From 4fc922b89c09c5e9db4744450c4582ec66be674c Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 29 Jun 2020 08:34:44 -0700 Subject: [PATCH 01/91] disable page load metrics task in baseline job too (cherry picked from commit 848c239bfff3eb4f3aca7e0d7f0164c8581c49f8) --- test/scripts/jenkins_xpack_visual_regression.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/scripts/jenkins_xpack_visual_regression.sh b/test/scripts/jenkins_xpack_visual_regression.sh index e406bb3e6106f2..b67c1c9060a6e2 100755 --- a/test/scripts/jenkins_xpack_visual_regression.sh +++ b/test/scripts/jenkins_xpack_visual_regression.sh @@ -19,5 +19,5 @@ yarn percy exec -t 500 -- -- \ --kibana-install-dir "$installDir" \ --config test/visual_regression/config.ts; -cd "$KIBANA_DIR" -source "test/scripts/jenkins_xpack_page_load_metrics.sh" +# cd "$KIBANA_DIR" +# source "test/scripts/jenkins_xpack_page_load_metrics.sh" From 97521eaee20a0b6627b0482531b10dc4b9e0637b Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Mon, 29 Jun 2020 11:49:38 -0500 Subject: [PATCH 02/91] [APM] Use licensing from context (#70118) (#70194) * [APM] Use licensing from context We added the usage of `featureUsage.notifyUsage` from the licensing plugin in #69455. This required us to use `getStartServices to add `licensing` to `context.plugins`. In #69838 `featureUsage` was added to `context.licensing`, so we don't need to add it to `context.plugins`. --- x-pack/plugins/apm/server/plugin.ts | 64 ++++++++----------- .../server/routes/create_api/index.test.ts | 3 +- .../plugins/apm/server/routes/service_map.ts | 5 +- x-pack/plugins/apm/server/routes/typings.ts | 3 - 4 files changed, 30 insertions(+), 45 deletions(-) diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index eb781ee0783075..deafda67b806d7 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -4,46 +4,42 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; +import { combineLatest, Observable } from 'rxjs'; +import { map, take } from 'rxjs/operators'; import { - PluginInitializerContext, - Plugin, CoreSetup, CoreStart, Logger, + Plugin, + PluginInitializerContext, } from 'src/core/server'; -import { Observable, combineLatest } from 'rxjs'; -import { map, take } from 'rxjs/operators'; -import { ObservabilityPluginSetup } from '../../observability/server'; -import { SecurityPluginSetup } from '../../security/server'; -import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; -import { TaskManagerSetupContract } from '../../task_manager/server'; -import { AlertingPlugin } from '../../alerts/server'; -import { ActionsPlugin } from '../../actions/server'; +import { APMConfig, APMXPackConfig, mergeConfigs } from '.'; import { APMOSSPluginSetup } from '../../../../src/plugins/apm_oss/server'; -import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index'; -import { createApmCustomLinkIndex } from './lib/settings/custom_link/create_custom_link_index'; -import { createApmApi } from './routes/create_apm_api'; -import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; -import { APMConfig, mergeConfigs, APMXPackConfig } from '.'; import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; +import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; +import { ActionsPlugin } from '../../actions/server'; +import { AlertingPlugin } from '../../alerts/server'; import { CloudSetup } from '../../cloud/server'; -import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client'; -import { - LicensingPluginSetup, - LicensingPluginStart, -} from '../../licensing/server'; -import { registerApmAlerts } from './lib/alerts/register_apm_alerts'; -import { createApmTelemetry } from './lib/apm_telemetry'; - import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; +import { LicensingPluginSetup } from '../../licensing/server'; +import { MlPluginSetup } from '../../ml/server'; +import { ObservabilityPluginSetup } from '../../observability/server'; +import { SecurityPluginSetup } from '../../security/server'; +import { TaskManagerSetupContract } from '../../task_manager/server'; import { APM_FEATURE, APM_SERVICE_MAPS_FEATURE_NAME, APM_SERVICE_MAPS_LICENSE_TYPE, } from './feature'; +import { registerApmAlerts } from './lib/alerts/register_apm_alerts'; +import { createApmTelemetry } from './lib/apm_telemetry'; +import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client'; +import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index'; +import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; +import { createApmCustomLinkIndex } from './lib/settings/custom_link/create_custom_link_index'; +import { createApmApi } from './routes/create_apm_api'; import { apmIndices, apmTelemetry } from './saved_objects'; import { createElasticCloudInstructions } from './tutorial/elastic_cloud'; -import { MlPluginSetup } from '../../ml/server'; export interface APMPluginSetup { config$: Observable; @@ -135,18 +131,14 @@ export class APMPlugin implements Plugin { APM_SERVICE_MAPS_LICENSE_TYPE ); - core.getStartServices().then(([_coreStart, pluginsStart]) => { - createApmApi().init(core, { - config$: mergedConfig$, - logger: this.logger!, - plugins: { - licensing: (pluginsStart as { licensing: LicensingPluginStart }) - .licensing, - observability: plugins.observability, - security: plugins.security, - ml: plugins.ml, - }, - }); + createApmApi().init(core, { + config$: mergedConfig$, + logger: this.logger!, + plugins: { + observability: plugins.observability, + security: plugins.security, + ml: plugins.ml, + }, }); return { diff --git a/x-pack/plugins/apm/server/routes/create_api/index.test.ts b/x-pack/plugins/apm/server/routes/create_api/index.test.ts index f5db936c00d3a7..3d3e26f680e0d2 100644 --- a/x-pack/plugins/apm/server/routes/create_api/index.test.ts +++ b/x-pack/plugins/apm/server/routes/create_api/index.test.ts @@ -9,7 +9,6 @@ import { CoreSetup, Logger } from 'src/core/server'; import { Params } from '../typings'; import { BehaviorSubject } from 'rxjs'; import { APMConfig } from '../..'; -import { LicensingPluginStart } from '../../../../licensing/server'; const getCoreMock = () => { const get = jest.fn(); @@ -41,7 +40,7 @@ const getCoreMock = () => { logger: ({ error: jest.fn(), } as unknown) as Logger, - plugins: { licensing: {} as LicensingPluginStart }, + plugins: {}, }, }; }; diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index 3937c18b3fe5e0..a3e2f708b0b22e 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -35,10 +35,7 @@ export const serviceMapRoute = createRoute(() => ({ if (!isValidPlatinumLicense(context.licensing.license)) { throw Boom.forbidden(invalidLicenseMessage); } - - context.plugins.licensing.featureUsage.notifyUsage( - APM_SERVICE_MAPS_FEATURE_NAME - ); + context.licensing.featureUsage.notifyUsage(APM_SERVICE_MAPS_FEATURE_NAME); const setup = await setupRequest(context, request); const { diff --git a/x-pack/plugins/apm/server/routes/typings.ts b/x-pack/plugins/apm/server/routes/typings.ts index f30a9d18d7aeab..b1815e88d29178 100644 --- a/x-pack/plugins/apm/server/routes/typings.ts +++ b/x-pack/plugins/apm/server/routes/typings.ts @@ -14,7 +14,6 @@ import { import { PickByValue, Optional } from 'utility-types'; import { Observable } from 'rxjs'; import { Server } from 'hapi'; -import { LicensingPluginStart } from '../../../licensing/server'; import { ObservabilityPluginSetup } from '../../../observability/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { FetchOptions } from '../../public/services/rest/callApi'; @@ -67,7 +66,6 @@ export type APMRequestHandlerContext< config: APMConfig; logger: Logger; plugins: { - licensing: LicensingPluginStart; observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; ml?: MlPluginSetup; @@ -116,7 +114,6 @@ export interface ServerAPI { config$: Observable; logger: Logger; plugins: { - licensing: LicensingPluginStart; observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; ml?: MlPluginSetup; From 1868b1e9fa569e992bb71a88244ed11d2449ee0c Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Mon, 29 Jun 2020 19:27:06 +0200 Subject: [PATCH 03/91] Bump react-router (#69608) (#70217) # Conflicts: # x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/overview.test.tsx.snap --- package.json | 9 +- packages/kbn-ui-shared-deps/package.json | 4 +- x-pack/package.json | 6 +- .../__snapshots__/cert_monitors.test.tsx.snap | 73 +- .../__snapshots__/cert_search.test.tsx.snap | 41 +- .../__snapshots__/cert_status.test.tsx.snap | 61 +- .../certificates_list.test.tsx.snap | 55 +- .../fingerprint_col.test.tsx.snap | 61 +- .../uptime_date_picker.test.tsx.snap | 37 +- .../duration_charts.test.tsx.snap | 145 ++-- .../monitor_bar_series.test.tsx.snap | 73 +- .../ping_histogram.test.tsx.snap | 333 ++++---- .../monitor_charts.test.tsx.snap | 41 +- .../ml_integerations.test.tsx.snap | 37 +- .../__snapshots__/ml_job_link.test.tsx.snap | 49 +- .../__snapshots__/ml_manage_job.test.tsx.snap | 45 +- .../ssl_certificate.test.tsx.snap | 43 +- .../__snapshots__/empty_state.test.tsx.snap | 65 +- .../filter_status_button.test.tsx.snap | 49 +- .../__snapshots__/monitor_list.test.tsx.snap | 768 +++++++++++------- .../__snapshots__/status_filter.test.tsx.snap | 37 +- .../monitor_list_drawer.test.tsx.snap | 206 +++-- .../certificate_form.test.tsx.snap | 55 +- .../__snapshots__/indices_form.test.tsx.snap | 55 +- .../__snapshots__/certificates.test.tsx.snap | 37 +- .../__snapshots__/monitor.test.tsx.snap | 37 +- .../__snapshots__/not_found.test.tsx.snap | 37 +- .../__snapshots__/overview.test.tsx.snap | 225 ++--- yarn.lock | 53 +- 29 files changed, 1910 insertions(+), 827 deletions(-) diff --git a/package.json b/package.json index 1a8b6e8aca3d27..69c414e6905882 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,6 @@ "resolutions": { "**/@types/node": ">=10.17.17 <10.20.0", "**/@types/react": "^16.9.36", - "**/@types/react-router": "^5.1.3", "**/@types/hapi": "^17.0.18", "**/@types/angular": "^1.6.56", "**/@types/hoist-non-react-statics": "^3.3.1", @@ -243,8 +242,8 @@ "react-monaco-editor": "~0.27.0", "react-redux": "^7.2.0", "react-resize-detector": "^4.2.0", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", "react-sizeme": "^2.3.6", "react-use": "^13.27.0", "reactcss": "1.2.3", @@ -373,8 +372,8 @@ "@types/react-grid-layout": "^0.16.7", "@types/react-redux": "^7.1.9", "@types/react-resize-detector": "^4.0.1", - "@types/react-router": "^5.1.3", - "@types/react-router-dom": "^5.1.3", + "@types/react-router": "^5.1.7", + "@types/react-router-dom": "^5.1.5", "@types/react-virtualized": "^9.18.7", "@types/recompose": "^0.30.6", "@types/redux-actions": "^2.6.1", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index fe4d3d06517d29..e070e35ababdde 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -26,8 +26,8 @@ "react": "^16.12.0", "react-dom": "^16.12.0", "react-intl": "^2.8.0", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", "regenerator-runtime": "^0.13.3", "rxjs": "^6.5.5", "symbol-observable": "^1.2.0", diff --git a/x-pack/package.json b/x-pack/package.json index 8765747154cc03..e297440ab0437a 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -100,7 +100,7 @@ "@types/react-beautiful-dnd": "^12.1.1", "@types/react-dom": "^16.9.8", "@types/react-redux": "^7.1.9", - "@types/react-router-dom": "^5.1.3", + "@types/react-router-dom": "^5.1.5", "@types/react-sticky": "^6.0.3", "@types/react-test-renderer": "^16.9.1", "@types/recompose": "^0.30.6", @@ -329,8 +329,8 @@ "react-portal": "^3.2.0", "react-redux": "^7.2.0", "react-reverse-portal": "^1.0.4", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", "react-shortcuts": "^2.0.0", "react-sticky": "^6.0.3", "react-syntax-highlighter": "^5.7.0", diff --git a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_monitors.test.tsx.snap b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_monitors.test.tsx.snap index a79fb0f0d3debe..bec7e111fbb28e 100644 --- a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_monitors.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_monitors.test.tsx.snap @@ -109,26 +109,61 @@ exports[`CertMonitors shallow renders expected elements for valid props 1`] = ` } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_search.test.tsx.snap b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_search.test.tsx.snap index 8d576fc116dae3..97f476a56135aa 100644 --- a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_search.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_search.test.tsx.snap @@ -90,8 +90,43 @@ exports[`CertificatesSearch shallow renders expected elements for valid props 1` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_status.test.tsx.snap b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_status.test.tsx.snap index f6a4b4598fe63d..d64434c48837cb 100644 --- a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_status.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/cert_status.test.tsx.snap @@ -91,24 +91,59 @@ exports[`CertStatus shallow renders expected elements for valid props 1`] = ` } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/certificates_list.test.tsx.snap b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/certificates_list.test.tsx.snap index fd90db793b26e0..dc808ffcdd22bc 100644 --- a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/certificates_list.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/certificates_list.test.tsx.snap @@ -51,20 +51,55 @@ exports[`CertificateList shallow renders expected elements for valid props 1`] = } } > - + + sort={ + Object { + "direction": "asc", + "field": "not_after", + } + } + /> + `; diff --git a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/fingerprint_col.test.tsx.snap b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/fingerprint_col.test.tsx.snap index b4e5a344122123..9a393940132946 100644 --- a/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/fingerprint_col.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/certificates/__tests__/__snapshots__/fingerprint_col.test.tsx.snap @@ -150,24 +150,59 @@ exports[`FingerprintCol shallow renders expected elements for valid props 1`] = } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/common/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap b/x-pack/plugins/uptime/public/components/common/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap index b1f6f5dfc4401d..4d23cebf7d5ca0 100644 --- a/x-pack/plugins/uptime/public/components/common/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/common/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap @@ -145,6 +145,41 @@ exports[`UptimeDatePicker component validates props with shallow render 1`] = ` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap b/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap index 96918ab68f7163..81cd399078e703 100644 --- a/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap @@ -51,62 +51,97 @@ exports[`MonitorCharts component renders the component without errors 1`] = ` } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap b/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap index 1db4a87b1c37b0..7316cfa368c6ec 100644 --- a/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap @@ -77,26 +77,61 @@ exports[`MonitorBarSeries component shallow renders a series when there are down } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap b/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap index 668e4e0c064a8b..fe20071ced4cb0 100644 --- a/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap @@ -85,160 +85,195 @@ exports[`PingHistogram component shallow renders the component without errors 1` } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap index dff5def46cbe03..8ca48b7e95ebe4 100644 --- a/x-pack/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap @@ -51,8 +51,43 @@ exports[`MonitorCharts component renders the component without errors 1`] = ` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap index 9ad61f50b05217..24c4e818a0592d 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap @@ -80,6 +80,41 @@ exports[`ML Integrations shallow renders without errors 1`] = ` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap index 9957f13fc13343..1fe7a4cdd3ee5c 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap @@ -68,15 +68,50 @@ exports[`ML JobLink shallow renders without errors 1`] = ` } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap index e9623c7aa78a2c..5f773d7b1b620d 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap @@ -80,10 +80,45 @@ exports[`Manage ML Job shallow renders without errors 1`] = ` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap index 5b63a09d4f7c4b..591b3f222d033f 100644 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap @@ -139,12 +139,47 @@ exports[`SSL Certificate component shallow renders 1`] = ` } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap index cdefa7db5688b9..6667da401d6a90 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap @@ -1372,25 +1372,60 @@ exports[`EmptyState component renders child components when count is truthy 1`] } } > - -
- Foo -
-
- Bar -
-
- Baz -
-
+ +
+ Foo +
+
+ Bar +
+
+ Baz +
+
+ `; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/filter_status_button.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/filter_status_button.test.tsx.snap index b5d1b1d8ff60ed..0c7dfd8f924538 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/filter_status_button.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/filter_status_button.test.tsx.snap @@ -75,12 +75,47 @@ exports[`FilterStatusButton shallow renders without errors for valid props 1`] = } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap index d593dcc21b5901..7fc6405aaa3031 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap @@ -51,21 +51,56 @@ exports[`MonitorList component MonitorListPagination component renders a no item } } > - + > + + `; @@ -120,83 +155,118 @@ exports[`MonitorList component MonitorListPagination component renders the pagin } } > - + + pageSize={10} + setPageSize={[MockFunction]} + /> + `; @@ -251,21 +321,56 @@ exports[`MonitorList component renders a no items message when no data is provid } } > - + > + + `; @@ -320,84 +425,119 @@ exports[`MonitorList component renders error list 1`] = ` } } > - + + pageSize={10} + setPageSize={[MockFunction]} + /> + `; @@ -452,83 +592,118 @@ exports[`MonitorList component renders loading state 1`] = ` } } > - + + pageSize={10} + setPageSize={[MockFunction]} + /> + `; @@ -1301,82 +1476,117 @@ exports[`MonitorList component shallow renders the monitor list 1`] = ` } } > - + + pageSize={10} + setPageSize={[MockFunction]} + /> + `; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/status_filter.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/status_filter.test.tsx.snap index e8b9326d360e8f..12f8cdf1dcdddc 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/status_filter.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/status_filter.test.tsx.snap @@ -123,6 +123,41 @@ exports[`StatusFilterComponent shallow renders without errors for valid props 1` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap index 4520b760be3794..877ba889ec1ff2 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap @@ -51,56 +51,91 @@ exports[`MonitorListDrawer component renders a MonitorListDrawer when there are } } > - + + /> + `; @@ -155,41 +190,76 @@ exports[`MonitorListDrawer component renders a MonitorListDrawer when there is o } } > - + + /> + `; diff --git a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap index 36351da6f14c9d..55c66183de946d 100644 --- a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap @@ -51,18 +51,53 @@ exports[`CertificateForm shallow renders expected elements for valid props 1`] = } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap index c5d077007e6502..2eb434ffbaf40d 100644 --- a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap @@ -51,18 +51,53 @@ exports[`CertificateForm shallow renders expected elements for valid props 1`] = } } > - + > + + `; diff --git a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/certificates.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/certificates.test.tsx.snap index 53b2ea27864bc0..e1009236ef4b83 100644 --- a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/certificates.test.tsx.snap +++ b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/certificates.test.tsx.snap @@ -51,6 +51,41 @@ exports[`CertificatesPage shallow renders expected elements for valid props 1`] } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap index 6064caa868bf82..cd92334cf72f5e 100644 --- a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap +++ b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/monitor.test.tsx.snap @@ -51,6 +51,41 @@ exports[`MonitorPage shallow renders expected elements for valid props 1`] = ` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/not_found.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/not_found.test.tsx.snap index a4d13963aaf778..df67e320d7aac8 100644 --- a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/not_found.test.tsx.snap +++ b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/not_found.test.tsx.snap @@ -51,6 +51,41 @@ exports[`NotFoundPage render component for valid props 1`] = ` } } > - + + + `; diff --git a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/overview.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/overview.test.tsx.snap index 6824b9e88803e4..e36f54b0bcfbc2 100644 --- a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/overview.test.tsx.snap +++ b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/overview.test.tsx.snap @@ -51,106 +51,141 @@ exports[`MonitorPage shallow renders expected elements for valid props 1`] = ` } } > - + > + + `; diff --git a/yarn.lock b/yarn.lock index 76efa90d30f48e..538110d42e0031 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1984,7 +1984,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.9.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== @@ -5772,19 +5772,19 @@ dependencies: "@types/react" "*" -"@types/react-router-dom@^5.1.3": - version "5.1.3" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.3.tgz#b5d28e7850bd274d944c0fbbe5d57e6b30d71196" - integrity sha512-pCq7AkOvjE65jkGS5fQwQhvUp4+4PVD9g39gXLZViP2UqFiFzsEpB3PKf0O6mdbKsewSK8N14/eegisa/0CwnA== +"@types/react-router-dom@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.5.tgz#7c334a2ea785dbad2b2dcdd83d2cf3d9973da090" + integrity sha512-ArBM4B1g3BWLGbaGvwBGO75GNFbLDUthrDojV2vHLih/Tq8M+tgvY1DSwkuNrPSwdp/GUL93WSEpTZs8nVyJLw== dependencies: "@types/history" "*" "@types/react" "*" "@types/react-router" "*" -"@types/react-router@*", "@types/react-router@^5.1.3": - version "5.1.3" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.3.tgz#7c7ca717399af64d8733d8cb338dd43641b96f2d" - integrity sha512-0gGhmerBqN8CzlnDmSgGNun3tuZFXerUclWkqEhozdLaJtfcJRUTGkKaEKk+/MpHd1KDS1+o2zb/3PkBUiv2qQ== +"@types/react-router@*", "@types/react-router@^5.1.7": + version "5.1.7" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.7.tgz#e9d12ed7dcfc79187e4d36667745b69a5aa11556" + integrity sha512-2ouP76VQafKjtuc0ShpwUebhHwJo0G6rhahW9Pb8au3tQTjYXd2jta4wv6U2tGLR/I42yuG00+UXjNYY0dTzbg== dependencies: "@types/history" "*" "@types/react" "*" @@ -21804,14 +21804,13 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= -mini-create-react-context@^0.3.0: - version "0.3.2" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189" - integrity sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw== +mini-create-react-context@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz#df60501c83151db69e28eac0ef08b4002efab040" + integrity sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA== dependencies: - "@babel/runtime" "^7.4.0" - gud "^1.0.0" - tiny-warning "^1.0.2" + "@babel/runtime" "^7.5.5" + tiny-warning "^1.0.3" mini-css-extract-plugin@0.7.0, mini-css-extract-plugin@^0.7.0: version "0.7.0" @@ -25945,16 +25944,16 @@ react-reverse-portal@^1.0.4: resolved "https://registry.yarnpkg.com/react-reverse-portal/-/react-reverse-portal-1.0.4.tgz#d127d2c9147549b25c4959aba1802eca4b144cd4" integrity sha512-WESex/wSjxHwdG7M0uwPNkdQXaLauXNHi4INQiRybmFIXVzAqgf/Ak2OzJ4MLf4UuCD/IzEwJOkML2SxnnontA== -react-router-dom@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" - integrity sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew== +react-router-dom@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" + integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA== dependencies: "@babel/runtime" "^7.1.2" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.1.2" + react-router "5.2.0" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" @@ -25963,16 +25962,16 @@ react-router-redux@^4.0.8: resolved "https://registry.yarnpkg.com/react-router-redux/-/react-router-redux-4.0.8.tgz#227403596b5151e182377dab835b5d45f0f8054e" integrity sha1-InQDWWtRUeGCN32rg1tdRfD4BU4= -react-router@5.1.2, react-router@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418" - integrity sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A== +react-router@5.2.0, react-router@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" + integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw== dependencies: "@babel/runtime" "^7.1.2" history "^4.9.0" hoist-non-react-statics "^3.1.0" loose-envify "^1.3.1" - mini-create-react-context "^0.3.0" + mini-create-react-context "^0.4.0" path-to-regexp "^1.7.0" prop-types "^15.6.2" react-is "^16.6.0" @@ -30195,7 +30194,7 @@ tiny-warning@^1.0.0: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.2.tgz#1dfae771ee1a04396bdfde27a3adcebc6b648b28" integrity sha512-rru86D9CpQRLvsFG5XFdy0KdLAvjdQDyZCsRcuu60WtzFylDM3eAWSxEVz5kzL2Gp544XiUvPbVKtOA/txLi9Q== -tiny-warning@^1.0.2: +tiny-warning@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== From 9303747b5463de6300363dd8131f3d334766fedf Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Mon, 29 Jun 2020 10:54:24 -0700 Subject: [PATCH 04/91] "Explore underlying data" in-chart action kibana.yml flag (#70045) (#70224) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 💡 rename folder to "explore_data" * style: 💄 check for "share" plugin in more semantic way "explore data" actions use Discover URL generator, which is registered in "share" plugin, which is optional plugin, so we check for its existance, because otherwise URL generator is not available. * refactor: 💡 move KibanaURL to a separate file * feat: 🎸 add "Explore underlying data" in-chart action * fix: 🐛 fix imports after refactor * feat: 🎸 add start.filtersFromContext to embeddable plugin * feat: 🎸 add type checkers to data plugin * feat: 🎸 better handle empty filters in Discover URL generator * feat: 🎸 implement .getUrl() method of explore data in-chart act * feat: 🎸 add embeddable.filtersAndTimeRangeFromContext() * feat: 🎸 improve getUrl() method of explore data action * test: 💍 update test mock * fix possible stale hashHistory.location in discover * style: 💄 ensureHashHistoryLocation -> syncHistoryLocations * docs: ✏️ update autogenerated docs * test: 💍 add in-chart "Explore underlying data" unit tests * test: 💍 add in-chart "Explore underlying data" functional tests * test: 💍 clean-up custom time range after panel action tests * chore: 🤖 fix embeddable plugin mocks * chore: 🤖 fix another mock * test: 💍 add support for new action to pie chart service * feat: 🎸 add kibana.yml to disable in-chart "explore data" actio Co-authored-by: Anton Dosov Co-authored-by: Elastic Machine Co-authored-by: Anton Dosov Co-authored-by: Elastic Machine --- x-pack/plugins/discover_enhanced/kibana.json | 5 ++-- .../discover_enhanced/public/plugin.ts | 14 ++++++++--- .../discover_enhanced/server/config.ts | 25 +++++++++++++++++++ .../plugins/discover_enhanced/server/index.ts | 12 +++++++++ 4 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/discover_enhanced/server/config.ts create mode 100644 x-pack/plugins/discover_enhanced/server/index.ts diff --git a/x-pack/plugins/discover_enhanced/kibana.json b/x-pack/plugins/discover_enhanced/kibana.json index 25b2a83baf98f8..704096ce7fcade 100644 --- a/x-pack/plugins/discover_enhanced/kibana.json +++ b/x-pack/plugins/discover_enhanced/kibana.json @@ -2,8 +2,9 @@ "id": "discoverEnhanced", "version": "8.0.0", "kibanaVersion": "kibana", - "server": false, + "server": true, "ui": true, "requiredPlugins": ["uiActions", "embeddable", "discover"], - "optionalPlugins": ["share"] + "optionalPlugins": ["share"], + "configPath": ["xpack", "discoverEnhanced"] } diff --git a/x-pack/plugins/discover_enhanced/public/plugin.ts b/x-pack/plugins/discover_enhanced/public/plugin.ts index ea3c1222eb369d..9613a9a8e3c8cc 100644 --- a/x-pack/plugins/discover_enhanced/public/plugin.ts +++ b/x-pack/plugins/discover_enhanced/public/plugin.ts @@ -53,7 +53,11 @@ export interface DiscoverEnhancedStartDependencies { export class DiscoverEnhancedPlugin implements Plugin { - constructor(public readonly initializerContext: PluginInitializerContext) {} + public readonly config: { actions: { exploreDataInChart: { enabled: boolean } } }; + + constructor(protected readonly context: PluginInitializerContext) { + this.config = context.config.get(); + } setup( core: CoreSetup, @@ -68,9 +72,11 @@ export class DiscoverEnhancedPlugin const exploreDataAction = new ExploreDataContextMenuAction(params); uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, exploreDataAction); - const exploreDataChartAction = new ExploreDataChartAction(params); - uiActions.addTriggerAction(SELECT_RANGE_TRIGGER, exploreDataChartAction); - uiActions.addTriggerAction(VALUE_CLICK_TRIGGER, exploreDataChartAction); + if (this.config.actions.exploreDataInChart.enabled) { + const exploreDataChartAction = new ExploreDataChartAction(params); + uiActions.addTriggerAction(SELECT_RANGE_TRIGGER, exploreDataChartAction); + uiActions.addTriggerAction(VALUE_CLICK_TRIGGER, exploreDataChartAction); + } } } diff --git a/x-pack/plugins/discover_enhanced/server/config.ts b/x-pack/plugins/discover_enhanced/server/config.ts new file mode 100644 index 00000000000000..becbdee1bfe408 --- /dev/null +++ b/x-pack/plugins/discover_enhanced/server/config.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from '../../../../src/core/server'; + +export const configSchema = schema.object({ + actions: schema.object({ + exploreDataInChart: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + }), + }), +}); + +export type ConfigSchema = TypeOf; + +export const config: PluginConfigDescriptor = { + schema: configSchema, + exposeToBrowser: { + actions: true, + }, +}; diff --git a/x-pack/plugins/discover_enhanced/server/index.ts b/x-pack/plugins/discover_enhanced/server/index.ts new file mode 100644 index 00000000000000..e361b9fb075eda --- /dev/null +++ b/x-pack/plugins/discover_enhanced/server/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { config } from './config'; + +export const plugin = () => ({ + setup() {}, + start() {}, +}); From a8718f835b103bd44083574c2347b0abffb72387 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 29 Jun 2020 13:57:12 -0400 Subject: [PATCH 05/91] [Ingest Manager] expose method to get agent and list agents to other plugins (#70087) (#70212) --- .../plugins/ingest_manager/server/plugin.ts | 11 ++++-- .../ingest_manager/server/services/index.ts | 34 ++++++++++++++++--- .../server/endpoint/mocks.ts | 3 ++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/ingest_manager/server/plugin.ts b/x-pack/plugins/ingest_manager/server/plugin.ts index 89f3c651eb71a2..4c4fdb2ba1e062 100644 --- a/x-pack/plugins/ingest_manager/server/plugin.ts +++ b/x-pack/plugins/ingest_manager/server/plugin.ts @@ -54,7 +54,12 @@ import { AgentService, datasourceService, } from './services'; -import { getAgentStatusById, authenticateAgentWithAccessToken } from './services/agents'; +import { + getAgentStatusById, + authenticateAgentWithAccessToken, + listAgents, + getAgent, +} from './services/agents'; import { CloudSetup } from '../../cloud/server'; import { agentCheckinState } from './services/agents/checkin/state'; @@ -236,7 +241,7 @@ export class IngestManagerPlugin plugins: { encryptedSavedObjects: EncryptedSavedObjectsPluginStart; } - ) { + ): Promise { await appContextService.start({ encryptedSavedObjectsStart: plugins.encryptedSavedObjects, encryptedSavedObjectsSetup: this.encryptedSavedObjectsSetup, @@ -255,6 +260,8 @@ export class IngestManagerPlugin return { esIndexPatternService: new ESIndexPatternSavedObjectService(), agentService: { + getAgent, + listAgents, getAgentStatusById, authenticateAgentWithAccessToken, }, diff --git a/x-pack/plugins/ingest_manager/server/services/index.ts b/x-pack/plugins/ingest_manager/server/services/index.ts index 149004f4818e1f..502f28a97bb2d0 100644 --- a/x-pack/plugins/ingest_manager/server/services/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/index.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedObjectsClientContract } from 'kibana/server'; -import { AgentStatus } from '../types'; +import { SavedObjectsClientContract, KibanaRequest } from 'kibana/server'; +import { AgentStatus, Agent } from '../types'; import * as settingsService from './settings'; export { ESIndexPatternSavedObjectService } from './es_index_pattern'; @@ -25,12 +25,38 @@ export interface ESIndexPatternService { * A service that provides exported functions that return information about an Agent */ export interface AgentService { + /** + * Get an Agent by id + */ + getAgent(soClient: SavedObjectsClientContract, agentId: string): Promise; + /** + * Authenticate an agent with access toekn + */ + authenticateAgentWithAccessToken( + soClient: SavedObjectsClientContract, + request: KibanaRequest + ): Promise; /** * Return the status by the Agent's id - * @param soClient - * @param agentId */ getAgentStatusById(soClient: SavedObjectsClientContract, agentId: string): Promise; + /** + * List agents + */ + listAgents( + soClient: SavedObjectsClientContract, + options: { + page: number; + perPage: number; + kuery?: string; + showInactive: boolean; + } + ): Promise<{ + agents: Agent[]; + total: number; + page: number; + perPage: number; + }>; } // Saved object services diff --git a/x-pack/plugins/security_solution/server/endpoint/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/mocks.ts index 5435eff4ef1507..aca8a4e0ce78f6 100644 --- a/x-pack/plugins/security_solution/server/endpoint/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/mocks.ts @@ -35,6 +35,9 @@ export const createMockEndpointAppContextServiceStartContract = (): jest.Mocked< export const createMockAgentService = (): jest.Mocked => { return { getAgentStatusById: jest.fn(), + authenticateAgentWithAccessToken: jest.fn(), + getAgent: jest.fn(), + listAgents: jest.fn(), }; }; From d20afbf9bb36cd299491f5723cbd9d63ab6a0e7b Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Mon, 29 Jun 2020 12:00:44 -0600 Subject: [PATCH 06/91] [data.search.aggs] Remove fieldFormats from AggConfig & AggConfigs (#69762) (#70225) --- .../data/common/field_formats/mocks.ts | 8 +- src/plugins/data/public/plugin.ts | 5 +- .../public/search/aggs/agg_config.test.ts | 145 +++--------------- .../data/public/search/aggs/agg_config.ts | 33 +--- .../public/search/aggs/agg_configs.test.ts | 52 +++---- .../data/public/search/aggs/agg_configs.ts | 17 +- .../data/public/search/aggs/agg_type.test.ts | 41 ----- .../data/public/search/aggs/agg_type.ts | 21 --- .../_terms_other_bucket_helper.test.ts | 4 +- .../create_filter/date_histogram.test.ts | 1 - .../buckets/create_filter/date_range.test.ts | 1 - .../buckets/create_filter/filters.test.ts | 1 - .../buckets/create_filter/histogram.test.ts | 21 ++- .../aggs/buckets/create_filter/histogram.ts | 23 +-- .../buckets/create_filter/ip_range.test.ts | 2 +- .../aggs/buckets/create_filter/range.test.ts | 29 +++- .../aggs/buckets/create_filter/range.ts | 19 ++- .../aggs/buckets/create_filter/terms.test.ts | 1 - .../search/aggs/buckets/date_histogram.ts | 17 +- .../search/aggs/buckets/date_range.test.ts | 1 - .../public/search/aggs/buckets/date_range.ts | 16 +- .../data/public/search/aggs/buckets/filter.ts | 1 + .../search/aggs/buckets/filters.test.ts | 1 - .../search/aggs/buckets/geo_hash.test.ts | 1 - .../public/search/aggs/buckets/geo_hash.ts | 1 + .../search/aggs/buckets/histogram.test.ts | 1 - .../public/search/aggs/buckets/histogram.ts | 2 +- .../public/search/aggs/buckets/ip_range.ts | 20 +-- .../public/search/aggs/buckets/range.test.ts | 35 ----- .../data/public/search/aggs/buckets/range.ts | 38 +---- .../aggs/buckets/significant_terms.test.ts | 1 - .../public/search/aggs/buckets/terms.test.ts | 4 +- .../data/public/search/aggs/buckets/terms.ts | 18 +-- .../public/search/aggs/metrics/bucket_avg.ts | 3 +- .../public/search/aggs/metrics/bucket_max.ts | 3 +- .../public/search/aggs/metrics/bucket_min.ts | 3 +- .../public/search/aggs/metrics/bucket_sum.ts | 3 +- .../public/search/aggs/metrics/cardinality.ts | 5 - .../data/public/search/aggs/metrics/count.ts | 6 - .../search/aggs/metrics/cumulative_sum.ts | 3 +- .../public/search/aggs/metrics/derivative.ts | 3 +- .../metrics/lib/parent_pipeline_agg_helper.ts | 16 +- .../lib/sibling_pipeline_agg_helper.ts | 9 -- .../public/search/aggs/metrics/median.test.ts | 1 - .../search/aggs/metrics/metric_agg_type.ts | 9 -- .../public/search/aggs/metrics/moving_avg.ts | 3 +- .../aggs/metrics/parent_pipeline.test.ts | 16 +- .../aggs/metrics/percentile_ranks.test.ts | 2 +- .../search/aggs/metrics/percentile_ranks.ts | 9 +- .../search/aggs/metrics/percentiles.test.ts | 2 +- .../public/search/aggs/metrics/serial_diff.ts | 3 +- .../aggs/metrics/sibling_pipeline.test.ts | 12 +- .../search/aggs/metrics/std_deviation.test.ts | 2 +- .../search/aggs/metrics/top_hit.test.ts | 2 +- src/plugins/data/public/search/aggs/mocks.ts | 2 - .../build_tabular_inspector_data.ts | 23 ++- .../search/expressions/create_filter.test.ts | 4 +- .../data/public/search/expressions/esaggs.ts | 13 +- .../data/public/search/search_service.ts | 3 - .../public/search/tabify/get_columns.test.ts | 7 +- .../search/tabify/response_writer.test.ts | 18 +-- .../data/public/search/tabify/tabify.test.ts | 7 +- .../public/components/table_vis_options.tsx | 2 +- test/functional/apps/visualize/_tile_map.js | 4 +- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 66 files changed, 203 insertions(+), 578 deletions(-) diff --git a/src/plugins/data/common/field_formats/mocks.ts b/src/plugins/data/common/field_formats/mocks.ts index 394d4c383032fb..9bbaefe2d146a8 100644 --- a/src/plugins/data/common/field_formats/mocks.ts +++ b/src/plugins/data/common/field_formats/mocks.ts @@ -17,7 +17,8 @@ * under the License. */ -import { IFieldFormatsRegistry } from '.'; +import { identity } from 'lodash'; +import { FieldFormat, IFieldFormatsRegistry } from '.'; export const fieldFormatsMock: IFieldFormatsRegistry = { getByFieldType: jest.fn(), @@ -35,6 +36,9 @@ export const fieldFormatsMock: IFieldFormatsRegistry = { init: jest.fn(), register: jest.fn(), parseDefaultTypeMap: jest.fn(), - deserialize: jest.fn(), + deserialize: jest.fn().mockImplementation(() => { + const DefaultFieldFormat = FieldFormat.from(identity); + return new DefaultFieldFormat(); + }), getTypeWithoutMetaParams: jest.fn(), }; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 83eb69c03eae6b..c3c3d4cb9f4d99 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -192,10 +192,7 @@ export class DataPublicPlugin implements Plugin { let indexPattern: IndexPattern; let typesRegistry: AggTypesRegistryStart; - let fieldFormats: FieldFormatsStart; beforeEach(() => { jest.restoreAllMocks(); mockDataServices(); - fieldFormats = fieldFormatsServiceMock.createStartContract(); indexPattern = stubIndexPatternWithFields as IndexPattern; typesRegistry = mockAggTypesRegistry(); }); describe('#toDsl', () => { it('calls #write()', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -64,7 +56,7 @@ describe('AggConfig', () => { }); it('uses the type name as the agg name', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -79,7 +71,7 @@ describe('AggConfig', () => { }); it('uses the params from #write() output as the agg params', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -109,7 +101,7 @@ describe('AggConfig', () => { params: {}, }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const histoConfig = ac.byName('date_histogram')[0]; const avgConfig = ac.byName('avg')[0]; @@ -219,8 +211,8 @@ describe('AggConfig', () => { testsIdentical.forEach((configState, index) => { it(`identical aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); }); }); @@ -260,8 +252,8 @@ describe('AggConfig', () => { testsIdenticalDifferentOrder.forEach((test, index) => { it(`identical aggregations (${index}) - init json is in different order`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); }); }); @@ -325,8 +317,8 @@ describe('AggConfig', () => { testsDifferent.forEach((test, index) => { it(`different aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(false); }); }); @@ -334,7 +326,7 @@ describe('AggConfig', () => { describe('#serialize', () => { it('includes the aggs id, params, type and schema', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'date_histogram', @@ -365,8 +357,8 @@ describe('AggConfig', () => { params: {}, }, ]; - const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); - const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry }); // this relies on the assumption that js-engines consistently loop over properties in insertion order. // most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications. @@ -394,7 +386,7 @@ describe('AggConfig', () => { params: { field: 'machine.os.keyword' }, }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs.map((agg) => agg.toSerializedFieldFormat())).toMatchInlineSnapshot(` Array [ @@ -456,7 +448,7 @@ describe('AggConfig', () => { }, }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs.map((agg) => agg.toSerializedFieldFormat())).toMatchInlineSnapshot(` Array [ @@ -478,20 +470,8 @@ describe('AggConfig', () => { }); describe('#toExpressionAst', () => { - beforeEach(() => { - fieldFormats.getDefaultInstance = (() => ({ - getConverterFor: (t?: string) => t || identity, - })) as any; - indexPattern.fields.getByName = (name) => - ({ - format: { - getConverterFor: (t?: string) => t || identity, - }, - } as IndexPatternField); - }); - it('works with primitive param types', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { enabled: true, type: 'terms', @@ -540,7 +520,7 @@ describe('AggConfig', () => { }); it('creates a subexpression for params of type "agg"', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'terms', params: { @@ -616,7 +596,7 @@ describe('AggConfig', () => { }, }); - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'range', params: { @@ -647,7 +627,7 @@ describe('AggConfig', () => { }); it('stringifies any other params which are an object', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'terms', params: { @@ -662,7 +642,7 @@ describe('AggConfig', () => { }); it(`returns undefined if an expressionName doesn't exist on the agg type`, () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); const configStates = { type: 'unknown type', params: {}, @@ -676,7 +656,7 @@ describe('AggConfig', () => { let aggConfig: AggConfig; beforeEach(() => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); aggConfig = ac.createAggConfig({ type: 'count' } as CreateAggConfigParams); }); @@ -702,85 +682,4 @@ describe('AggConfig', () => { expect(label).toBe(''); }); }); - - describe('#fieldFormatter - custom getFormat handler', () => { - it('returns formatter from getFormat handler', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); - const configStates = { - enabled: true, - type: 'count', - schema: 'metric', - params: { field: '@timestamp' }, - }; - const aggConfig = ac.createAggConfig(configStates); - - const fieldFormatter = aggConfig.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - }); - - // TODO: Converting these field formatter tests from browser tests to unit - // tests makes them much less helpful due to the extensive use of mocking. - // We should revisit these and rewrite them into something more useful. - describe('#fieldFormatter - no custom getFormat handler', () => { - let aggConfig: AggConfig; - - beforeEach(() => { - fieldFormats.getDefaultInstance = (() => ({ - getConverterFor: (t?: string) => t || identity, - })) as any; - indexPattern.fields.getByName = (name) => - ({ - format: { - getConverterFor: (t?: string) => t || identity, - }, - } as IndexPatternField); - - const configStates = { - enabled: true, - type: 'histogram', - schema: 'bucket', - params: { - field: 'bytes', - }, - }; - const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry, fieldFormats }); - aggConfig = ac.createAggConfig(configStates); - }); - - it("returns the field's formatter", () => { - aggConfig.params.field = { - format: { - getConverterFor: (t?: string) => t || identity, - }, - }; - expect(aggConfig.fieldFormatter().toString()).toBe( - aggConfig.getField().format.getConverterFor().toString() - ); - }); - - it('returns the string format if the field does not have a format', () => { - const agg = aggConfig; - agg.params.field = { type: 'number', format: null }; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - - it('returns the string format if there is no field', () => { - const agg = aggConfig; - delete agg.params.field; - const fieldFormatter = agg.fieldFormatter(); - expect(fieldFormatter).toBeDefined(); - expect(fieldFormatter('text')).toBe('text'); - }); - - it('returns the html converter if "html" is passed in', () => { - const field = indexPattern.fields.getByName('bytes'); - expect(aggConfig.fieldFormatter('html').toString()).toBe( - field!.format.getConverterFor('html').toString() - ); - }); - }); }); diff --git a/src/plugins/data/public/search/aggs/agg_config.ts b/src/plugins/data/public/search/aggs/agg_config.ts index a2b74eca584766..8650f5920e5202 100644 --- a/src/plugins/data/public/search/aggs/agg_config.ts +++ b/src/plugins/data/public/search/aggs/agg_config.ts @@ -30,8 +30,6 @@ import { writeParams } from './agg_params'; import { IAggConfigs } from './agg_configs'; import { FetchOptions } from '../fetch'; import { ISearchSource } from '../search_source'; -import { FieldFormatsContentType, KBN_FIELD_TYPES } from '../../../common'; -import { FieldFormatsStart } from '../../field_formats'; type State = string | number | boolean | null | undefined | SerializableState; @@ -52,10 +50,6 @@ export type AggConfigSerialized = Ensure< SerializableState >; -export interface AggConfigDependencies { - fieldFormats: FieldFormatsStart; -} - export type AggConfigOptions = Assign; /** @@ -116,13 +110,8 @@ export class AggConfig { private __type: IAggType; private __typeDecorations: any; private subAggs: AggConfig[] = []; - private readonly fieldFormats: FieldFormatsStart; - constructor( - aggConfigs: IAggConfigs, - opts: AggConfigOptions, - { fieldFormats }: AggConfigDependencies - ) { + constructor(aggConfigs: IAggConfigs, opts: AggConfigOptions) { this.aggConfigs = aggConfigs; this.id = String(opts.id || AggConfig.nextId(aggConfigs.aggs as any)); this.enabled = typeof opts.enabled === 'boolean' ? opts.enabled : true; @@ -143,8 +132,6 @@ export class AggConfig { // @ts-ignore this.__type = this.__type; - - this.fieldFormats = fieldFormats; } /** @@ -433,24 +420,6 @@ export class AggConfig { return this.aggConfigs.timeRange; } - fieldFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) { - const format = this.type && this.type.getFormat(this); - - if (format) { - return format.getConverterFor(contentType); - } - - return this.fieldOwnFormatter(contentType, defaultFormat); - } - - fieldOwnFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) { - const field = this.getField(); - let format = field && field.format; - if (!format) format = defaultFormat; - if (!format) format = this.fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); - return format.getConverterFor(contentType); - } - fieldName() { const field = this.getField(); return field ? field.name : ''; diff --git a/src/plugins/data/public/search/aggs/agg_configs.test.ts b/src/plugins/data/public/search/aggs/agg_configs.test.ts index 6e6fb3350d901f..121bb29f6f8edb 100644 --- a/src/plugins/data/public/search/aggs/agg_configs.test.ts +++ b/src/plugins/data/public/search/aggs/agg_configs.test.ts @@ -24,12 +24,10 @@ import { AggTypesRegistryStart } from './agg_types_registry'; import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; import { Field as IndexPatternField, IndexPattern } from '../../index_patterns'; import { stubIndexPattern, stubIndexPatternWithFields } from '../../../public/stubs'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('AggConfigs', () => { let indexPattern: IndexPattern; let typesRegistry: AggTypesRegistryStart; - const fieldFormats = fieldFormatsServiceMock.createStartContract(); beforeEach(() => { mockDataServices(); @@ -47,7 +45,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(1); }); @@ -72,7 +70,7 @@ describe('AggConfigs', () => { ]; const spy = jest.spyOn(AggConfig, 'ensureIds'); - new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(spy).toHaveBeenCalledTimes(1); expect(spy.mock.calls[0]).toEqual([configStates]); spy.mockRestore(); @@ -94,20 +92,16 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(2); ac.createAggConfig( - new AggConfig( - ac, - { - enabled: true, - type: typesRegistry.get('terms'), - params: {}, - schema: 'split', - }, - { fieldFormats } - ) + new AggConfig(ac, { + enabled: true, + type: typesRegistry.get('terms'), + params: {}, + schema: 'split', + }) ); expect(ac.aggs).toHaveLength(3); }); @@ -121,7 +115,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(1); ac.createAggConfig({ @@ -142,7 +136,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); expect(ac.aggs).toHaveLength(1); ac.createAggConfig( @@ -170,7 +164,7 @@ describe('AggConfigs', () => { { type: 'percentiles', enabled: true, params: {}, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const sorted = ac.getRequestAggs(); const aggs = indexBy(ac.aggs, (agg) => agg.type.name); @@ -193,7 +187,7 @@ describe('AggConfigs', () => { { type: 'count', enabled: true, params: {}, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const sorted = ac.getResponseAggs(); const aggs = indexBy(ac.aggs, (agg) => agg.type.name); @@ -210,7 +204,7 @@ describe('AggConfigs', () => { { type: 'percentiles', enabled: true, params: { percents: [1, 2, 3] }, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const sorted = ac.getResponseAggs(); const aggs = indexBy(ac.aggs, (agg) => agg.type.name); @@ -231,7 +225,7 @@ describe('AggConfigs', () => { it('uses the sorted aggs', () => { const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const spy = jest.spyOn(AggConfigs.prototype, 'getRequestAggs'); ac.toDsl(); expect(spy).toHaveBeenCalledTimes(1); @@ -245,10 +239,7 @@ describe('AggConfigs', () => { { enabled: true, type: 'count', params: {} }, ]; - const ac = new AggConfigs(indexPattern, configStates, { - typesRegistry, - fieldFormats, - }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const aggInfos = ac.aggs.map((aggConfig) => { const football = {}; @@ -291,7 +282,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const dsl = ac.toDsl(); const histo = ac.byName('date_histogram')[0]; const count = ac.byName('count')[0]; @@ -316,10 +307,7 @@ describe('AggConfigs', () => { { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, ]; - const ac = new AggConfigs(indexPattern, configStates, { - typesRegistry, - fieldFormats, - }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const dsl = ac.toDsl(); const histo = ac.byName('date_histogram')[0]; const metrics = ac.bySchemaName('metrics'); @@ -344,7 +332,7 @@ describe('AggConfigs', () => { { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const topLevelDsl = ac.toDsl(true); const buckets = ac.bySchemaName('buckets'); const metrics = ac.bySchemaName('metrics'); @@ -414,7 +402,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); const topLevelDsl = ac.toDsl(true)['2']; expect(Object.keys(topLevelDsl.aggs)).toContain('1'); diff --git a/src/plugins/data/public/search/aggs/agg_configs.ts b/src/plugins/data/public/search/aggs/agg_configs.ts index 6cc03be292d7b5..b272dfd3c7468e 100644 --- a/src/plugins/data/public/search/aggs/agg_configs.ts +++ b/src/plugins/data/public/search/aggs/agg_configs.ts @@ -28,7 +28,6 @@ import { IndexPattern } from '../../index_patterns'; import { ISearchSource } from '../search_source'; import { FetchOptions } from '../fetch'; import { TimeRange } from '../../../common'; -import { FieldFormatsStart } from '../../field_formats'; function removeParentAggs(obj: any) { for (const prop in obj) { @@ -48,7 +47,6 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) { export interface AggConfigsOptions { typesRegistry: AggTypesRegistryStart; - fieldFormats: FieldFormatsStart; } export type CreateAggConfigParams = Assign; @@ -70,7 +68,6 @@ export type IAggConfigs = AggConfigs; export class AggConfigs { public indexPattern: IndexPattern; public timeRange?: TimeRange; - private readonly fieldFormats: FieldFormatsStart; private readonly typesRegistry: AggTypesRegistryStart; aggs: IAggConfig[]; @@ -86,7 +83,6 @@ export class AggConfigs { this.aggs = []; this.indexPattern = indexPattern; - this.fieldFormats = opts.fieldFormats; configStates.forEach((params: any) => this.createAggConfig(params)); } @@ -117,7 +113,6 @@ export class AggConfigs { const aggConfigs = new AggConfigs(this.indexPattern, this.aggs.filter(filterAggs), { typesRegistry: this.typesRegistry, - fieldFormats: this.fieldFormats, }); return aggConfigs; @@ -134,14 +129,10 @@ export class AggConfigs { aggConfig = params; params.parent = this; } else { - aggConfig = new AggConfig( - this, - { - ...params, - type: typeof type === 'string' ? this.typesRegistry.get(type) : type, - }, - { fieldFormats: this.fieldFormats } - ); + aggConfig = new AggConfig(this, { + ...params, + type: typeof type === 'string' ? this.typesRegistry.get(type) : type, + }); } if (addToAggConfigs) { diff --git a/src/plugins/data/public/search/aggs/agg_type.test.ts b/src/plugins/data/public/search/aggs/agg_type.test.ts index cc45b935d45b54..99b1c4d8612192 100644 --- a/src/plugins/data/public/search/aggs/agg_type.test.ts +++ b/src/plugins/data/public/search/aggs/agg_type.test.ts @@ -159,47 +159,6 @@ describe('AggType Class', () => { }); }); - describe('getFormat', function () { - let aggConfig: IAggConfig; - let field: any; - - beforeEach(() => { - aggConfig = ({ - getField: jest.fn(() => field), - } as unknown) as IAggConfig; - }); - - test('returns the formatter for the aggConfig', () => { - const aggType = new AggType( - { - name: 'name', - title: 'title', - }, - dependencies - ); - - field = { - format: 'format', - }; - - expect(aggType.getFormat(aggConfig)).toBe('format'); - }); - - test('returns default formatter', () => { - const aggType = new AggType( - { - name: 'name', - title: 'title', - }, - dependencies - ); - - field = undefined; - - expect(aggType.getFormat(aggConfig)).toBe('default'); - }); - }); - describe('getSerializedFormat', () => { test('returns the default serialized field format if it exists', () => { const aggConfig = ({ diff --git a/src/plugins/data/public/search/aggs/agg_type.ts b/src/plugins/data/public/search/aggs/agg_type.ts index e909cd8134e83f..13655afdf469ea 100644 --- a/src/plugins/data/public/search/aggs/agg_type.ts +++ b/src/plugins/data/public/search/aggs/agg_type.ts @@ -28,7 +28,6 @@ import { IAggConfigs } from './agg_configs'; import { Adapters } from '../../../../../plugins/inspector/public'; import { BaseParamType } from './param_types/base'; import { AggParamType } from './param_types/agg'; -import { KBN_FIELD_TYPES, IFieldFormat } from '../../../common'; import { ISearchSource } from '../search_source'; import { GetInternalStartServicesFn } from '../../types'; @@ -58,7 +57,6 @@ export interface AggTypeConfig< inspectorAdapters: Adapters, abortSignal?: AbortSignal ) => Promise; - getFormat?: (agg: TAggConfig) => IFieldFormat; getSerializedFormat?: (agg: TAggConfig) => SerializedFieldFormat; getValue?: (agg: TAggConfig, bucket: any) => any; getKey?: (bucket: any, key: any, agg: TAggConfig) => any; @@ -197,16 +195,6 @@ export class AggType< inspectorAdapters: Adapters, abortSignal?: AbortSignal ) => Promise; - /** - * Pick a format for the values produced by this agg type, - * overridden by several metrics that always output a simple - * number - * - * @param {agg} agg - the agg to pick a format for - * @return {FieldFormat} - */ - getFormat: (agg: TAggConfig) => IFieldFormat; - /** * Get the serialized format for the values produced by this agg type, * overridden by several metrics that always output a simple number. @@ -283,15 +271,6 @@ export class AggType< this.decorateAggConfig = config.decorateAggConfig || (() => ({})); this.postFlightRequest = config.postFlightRequest || identity; - this.getFormat = - config.getFormat || - ((agg: TAggConfig) => { - const field = agg.getField(); - const { fieldFormats } = getInternalStartServices(); - - return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); - }); - this.getSerializedFormat = config.getSerializedFormat || ((agg: TAggConfig) => { diff --git a/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts b/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts index 44d99375bbd302..8e862b5692ca39 100644 --- a/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts @@ -26,7 +26,6 @@ import { AggConfigs, CreateAggConfigParams } from '../agg_configs'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketAggConfig } from './bucket_agg_type'; import { mockAggTypesRegistry } from '../test_helpers'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; const indexPattern = { id: '1234', @@ -220,10 +219,9 @@ const nestedOtherResponse = { describe('Terms Agg Other bucket helper', () => { const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = (aggs: CreateAggConfigParams[] = []) => { - return new AggConfigs(indexPattern, [...aggs], { typesRegistry, fieldFormats }); + return new AggConfigs(indexPattern, [...aggs], { typesRegistry }); }; describe('buildOtherBucketAgg', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts index 2f03b8ec671123..bcdc003707e752 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts @@ -82,7 +82,6 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getDateHistogramBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); const bucketKey = 1422579600000; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts index 0d66d9cfcdca2c..08f39e10b6006f 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts @@ -76,7 +76,6 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts index 0fdb07cc4198a5..c5ad1a61e6676f 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts @@ -73,7 +73,6 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts index 396d515f3b5809..3f9f5dd5672f0a 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts @@ -23,12 +23,21 @@ import { mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../bucket_agg_type'; import { BytesFormat, FieldFormatsGetConfigFn } from '../../../../../common'; +import { GetInternalStartServicesFn, InternalStartServices } from '../../../../types'; +import { FieldFormatsStart } from '../../../../field_formats'; import { fieldFormatsServiceMock } from '../../../../field_formats/mocks'; describe('AggConfig Filters', () => { + let getInternalStartServices: GetInternalStartServicesFn; + let fieldFormats: FieldFormatsStart; + + beforeEach(() => { + fieldFormats = fieldFormatsServiceMock.createStartContract(); + getInternalStartServices = () => (({ fieldFormats } as unknown) as InternalStartServices); + }); + describe('histogram', () => { const getConfig = (() => {}) as FieldFormatsGetConfigFn; - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = () => { const field = { name: 'bytes', @@ -57,21 +66,25 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry(), fieldFormats } + { typesRegistry: mockAggTypesRegistry() } ); }; test('should return an range filter for histogram', () => { const aggConfigs = getAggConfigs(); - const filter = createFilterHistogram(aggConfigs.aggs[0] as IBucketAggConfig, '2048'); + const filter = createFilterHistogram(getInternalStartServices)( + aggConfigs.aggs[0] as IBucketAggConfig, + '2048' + ); + expect(fieldFormats.deserialize).toHaveBeenCalledTimes(1); expect(filter).toHaveProperty('meta'); expect(filter.meta).toHaveProperty('index', '1234'); expect(filter).toHaveProperty('range'); expect(filter.range).toHaveProperty('bytes'); expect(filter.range.bytes).toHaveProperty('gte', 2048); expect(filter.range.bytes).toHaveProperty('lt', 3072); - expect(filter.meta).toHaveProperty('formattedValue', '2,048'); + expect(filter.meta).toHaveProperty('formattedValue'); }); }); }); diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts index f8e7747d49147c..f3626bc9130ad3 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.ts @@ -19,15 +19,20 @@ import { IBucketAggConfig } from '../bucket_agg_type'; import { buildRangeFilter, RangeFilterParams } from '../../../../../common'; +import { GetInternalStartServicesFn } from '../../../../types'; -export const createFilterHistogram = (aggConfig: IBucketAggConfig, key: string) => { - const value = parseInt(key, 10); - const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval }; +/** @internal */ +export const createFilterHistogram = (getInternalStartServices: GetInternalStartServicesFn) => { + return (aggConfig: IBucketAggConfig, key: string) => { + const { fieldFormats } = getInternalStartServices(); + const value = parseInt(key, 10); + const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval }; - return buildRangeFilter( - aggConfig.params.field, - params, - aggConfig.getIndexPattern(), - aggConfig.fieldFormatter()(key) - ); + return buildRangeFilter( + aggConfig.params.field, + params, + aggConfig.getIndexPattern(), + fieldFormats.deserialize(aggConfig.toSerializedFieldFormat()).convert(key) + ); + }; }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts index 990adde5f8a0bd..89a5fd65778912 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts @@ -55,7 +55,7 @@ describe('AggConfig Filters', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, { typesRegistry, fieldFormats }); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; test('should return a range filter for ip_range agg', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts index 564e7b4763c8d5..238e5737d8f474 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts @@ -24,19 +24,29 @@ import { AggConfigs } from '../../agg_configs'; import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../bucket_agg_type'; +import { FieldFormatsStart } from '../../../../field_formats'; import { fieldFormatsServiceMock } from '../../../../field_formats/mocks'; import { notificationServiceMock } from '../../../../../../../core/public/mocks'; -import { InternalStartServices } from '../../../../types'; +import { GetInternalStartServicesFn, InternalStartServices } from '../../../../types'; describe('AggConfig Filters', () => { describe('range', () => { let aggTypesDependencies: RangeBucketAggDependencies; + let getInternalStartServices: GetInternalStartServicesFn; + let fieldFormats: FieldFormatsStart; beforeEach(() => { + fieldFormats = fieldFormatsServiceMock.createStartContract(); + + getInternalStartServices = () => + (({ + fieldFormats, + notifications: notificationServiceMock.createStartContract(), + } as unknown) as InternalStartServices); + aggTypesDependencies = { getInternalStartServices: () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices), }; @@ -75,25 +85,28 @@ describe('AggConfig Filters', () => { ], { typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; test('should return a range filter for range agg', () => { const aggConfigs = getAggConfigs(); - const filter = createFilterRange(aggConfigs.aggs[0] as IBucketAggConfig, { - gte: 1024, - lt: 2048.0, - }); + const filter = createFilterRange(getInternalStartServices)( + aggConfigs.aggs[0] as IBucketAggConfig, + { + gte: 1024, + lt: 2048.0, + } + ); + expect(fieldFormats.deserialize).toHaveBeenCalledTimes(1); expect(filter).toHaveProperty('range'); expect(filter).toHaveProperty('meta'); expect(filter.meta).toHaveProperty('index', '1234'); expect(filter.range).toHaveProperty('bytes'); expect(filter.range.bytes).toHaveProperty('gte', 1024.0); expect(filter.range.bytes).toHaveProperty('lt', 2048.0); - expect(filter.meta).toHaveProperty('formattedValue', '≥ 1,024 and < 2,048'); + expect(filter.meta).toHaveProperty('formattedValue'); }); }); }); diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts index cbad8742bfab60..f9db2973af1369 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/range.ts @@ -19,12 +19,17 @@ import { IBucketAggConfig } from '../bucket_agg_type'; import { buildRangeFilter } from '../../../../../common'; +import { GetInternalStartServicesFn } from '../../../../types'; -export const createFilterRange = (aggConfig: IBucketAggConfig, params: any) => { - return buildRangeFilter( - aggConfig.params.field, - params, - aggConfig.getIndexPattern(), - aggConfig.fieldFormatter()(params) - ); +/** @internal */ +export const createFilterRange = (getInternalStartServices: GetInternalStartServicesFn) => { + return (aggConfig: IBucketAggConfig, params: any) => { + const { fieldFormats } = getInternalStartServices(); + return buildRangeFilter( + aggConfig.params.field, + params, + aggConfig.getIndexPattern(), + fieldFormats.deserialize(aggConfig.toSerializedFieldFormat()).convert(params) + ); + }; }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts index 36e4bef025ef9b..a45087916a395c 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts @@ -60,7 +60,6 @@ describe('AggConfig Filters', () => { return new AggConfigs(indexPattern, aggs, { typesRegistry: mockAggTypesRegistry([getTermsBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, }); }; diff --git a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts index fc42d43b2fea81..5b0f2921570c25 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts @@ -31,7 +31,7 @@ import { dateHistogramInterval, TimeRange } from '../../../../common'; import { writeParams } from '../agg_params'; import { isMetricAggType } from '../metrics/metric_agg_type'; -import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common'; +import { KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common'; import { TimefilterContract } from '../../../query'; import { QuerySetup } from '../../../query/query_service'; import { GetInternalStartServicesFn } from '../../../types'; @@ -137,21 +137,6 @@ export const getDateHistogramBucketAgg = ({ } as any, }; }, - getFormat(agg) { - const { fieldFormats } = getInternalStartServices(); - const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE); - - if (!DateFieldFormat) { - throw new Error('Unable to retrieve Date Field Format'); - } - - return new DateFieldFormat( - { - pattern: agg.buckets.getScaledDateFormat(), - }, - (key: string) => uiSettings.get(key) - ); - }, getSerializedFormat(agg) { return { id: 'date', diff --git a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts index e1881c3bbc7f4c..0829d6e9cdc9f7 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts @@ -78,7 +78,6 @@ describe('date_range params', () => { ], { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/date_range.ts b/src/plugins/data/public/search/aggs/buckets/date_range.ts index 3e14ab422ccbee..dbcf5517fb08fd 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_range.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_range.ts @@ -25,9 +25,9 @@ import { IUiSettingsClient } from 'src/core/public'; import { BUCKET_TYPES } from './bucket_agg_types'; import { BucketAggType, IBucketAggConfig } from './bucket_agg_type'; import { createFilterDateRange } from './create_filter/date_range'; -import { convertDateRangeToString, DateRangeKey } from './lib/date_range'; +import { DateRangeKey } from './lib/date_range'; -import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; @@ -58,18 +58,6 @@ export const getDateRangeBucketAgg = ({ getKey({ from, to }): DateRangeKey { return { from, to }; }, - getFormat(agg) { - const { fieldFormats } = getInternalStartServices(); - - const formatter = agg.fieldOwnFormatter( - TEXT_CONTEXT_TYPE, - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE) - ); - const DateRangeFormat = FieldFormat.from(function (range: DateRangeKey) { - return convertDateRangeToString(range, formatter); - }); - return new DateRangeFormat(); - }, getSerializedFormat(agg) { return { id: 'date_range', diff --git a/src/plugins/data/public/search/aggs/buckets/filter.ts b/src/plugins/data/public/search/aggs/buckets/filter.ts index 69157edad4f680..d048df9f0e43e8 100644 --- a/src/plugins/data/public/search/aggs/buckets/filter.ts +++ b/src/plugins/data/public/search/aggs/buckets/filter.ts @@ -41,6 +41,7 @@ export const getFilterBucketAgg = ({ getInternalStartServices }: FilterBucketAgg { name: BUCKET_TYPES.FILTER, title: filterTitle, + makeLabel: () => filterTitle, params: [ { name: 'geo_bounding_box', diff --git a/src/plugins/data/public/search/aggs/buckets/filters.test.ts b/src/plugins/data/public/search/aggs/buckets/filters.test.ts index 295e740a2a7809..7554e4081726cc 100644 --- a/src/plugins/data/public/search/aggs/buckets/filters.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/filters.test.ts @@ -71,7 +71,6 @@ describe('Filters Agg', () => { ], { typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts index 877a817984dc6f..d4c0a5b3288445 100644 --- a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts @@ -81,7 +81,6 @@ describe('Geohash Agg', () => { ], { typesRegistry: mockAggTypesRegistry(), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/geo_hash.ts b/src/plugins/data/public/search/aggs/buckets/geo_hash.ts index be339de5d7faea..fbe7c76681f816 100644 --- a/src/plugins/data/public/search/aggs/buckets/geo_hash.ts +++ b/src/plugins/data/public/search/aggs/buckets/geo_hash.ts @@ -54,6 +54,7 @@ export const getGeoHashBucketAgg = ({ getInternalStartServices }: GeoHashBucketA { name: BUCKET_TYPES.GEOHASH_GRID, title: geohashGridTitle, + makeLabel: () => geohashGridTitle, params: [ { name: 'field', diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts index 4756669f5b4b31..787603ee143613 100644 --- a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts @@ -74,7 +74,6 @@ describe('Histogram Agg', () => { ], { typesRegistry: mockAggTypesRegistry([getHistogramBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.ts b/src/plugins/data/public/search/aggs/buckets/histogram.ts index c1fad17f488db2..ce275e2dc1639a 100644 --- a/src/plugins/data/public/search/aggs/buckets/histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/histogram.ts @@ -67,7 +67,7 @@ export const getHistogramBucketAgg = ({ makeLabel(aggConfig) { return aggConfig.getFieldDisplayName(); }, - createFilter: createFilterHistogram, + createFilter: createFilterHistogram(getInternalStartServices), decorateAggConfig() { let autoBounds: AutoBounds; diff --git a/src/plugins/data/public/search/aggs/buckets/ip_range.ts b/src/plugins/data/public/search/aggs/buckets/ip_range.ts index b3e90bdf9b56a1..018fcb365b5850 100644 --- a/src/plugins/data/public/search/aggs/buckets/ip_range.ts +++ b/src/plugins/data/public/search/aggs/buckets/ip_range.ts @@ -23,13 +23,8 @@ import { BucketAggType } from './bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; import { createFilterIpRange } from './create_filter/ip_range'; -import { - convertIPRangeToString, - IpRangeKey, - RangeIpRangeAggKey, - CidrMaskIpRangeAggKey, -} from './lib/ip_range'; -import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common'; +import { IpRangeKey, RangeIpRangeAggKey, CidrMaskIpRangeAggKey } from './lib/ip_range'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; @@ -67,17 +62,6 @@ export const getIpRangeBucketAgg = ({ getInternalStartServices }: IpRangeBucketA } return { type: 'range', from: bucket.from, to: bucket.to }; }, - getFormat(agg) { - const { fieldFormats } = getInternalStartServices(); - const formatter = agg.fieldOwnFormatter( - TEXT_CONTEXT_TYPE, - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.IP) - ); - const IpRangeFormat = FieldFormat.from(function (range: IpRangeKey) { - return convertIPRangeToString(range, formatter); - }); - return new IpRangeFormat(); - }, getSerializedFormat(agg) { return { id: 'ip_range', diff --git a/src/plugins/data/public/search/aggs/buckets/range.test.ts b/src/plugins/data/public/search/aggs/buckets/range.test.ts index 2b8a36f2fbdbcb..fea5572b75795c 100644 --- a/src/plugins/data/public/search/aggs/buckets/range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/range.test.ts @@ -22,30 +22,9 @@ import { AggConfigs } from '../agg_configs'; import { mockDataServices, mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; import { FieldFormatsGetConfigFn, NumberFormat } from '../../../../common'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { notificationServiceMock } from '../../../../../../../src/core/public/mocks'; import { InternalStartServices } from '../../../types'; -const buckets = [ - { - to: 1024, - to_as_string: '1024.0', - doc_count: 20904, - }, - { - from: 1024, - from_as_string: '1024.0', - to: 2560, - to_as_string: '2560.0', - doc_count: 23358, - }, - { - from: 2560, - from_as_string: '2560.0', - doc_count: 174250, - }, -]; - describe('Range Agg', () => { let aggTypesDependencies: RangeBucketAggDependencies; @@ -53,7 +32,6 @@ describe('Range Agg', () => { aggTypesDependencies = { getInternalStartServices: () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices), }; @@ -99,23 +77,10 @@ describe('Range Agg', () => { ], { typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; - describe('formatting', () => { - test('formats bucket keys properly', () => { - const aggConfigs = getAggConfigs(); - const agg = aggConfigs.aggs[0]; - const format = (val: any) => agg.fieldFormatter()(agg.getKey(val)); - - expect(format(buckets[0])).toBe('≥ -∞ and < 1 KB'); - expect(format(buckets[1])).toBe('≥ 1 KB and < 2.5 KB'); - expect(format(buckets[2])).toBe('≥ 2.5 KB and < +∞'); - }); - }); - describe('getSerializedFormat', () => { test('generates a serialized field format in the expected shape', () => { const aggConfigs = getAggConfigs(); diff --git a/src/plugins/data/public/search/aggs/buckets/range.ts b/src/plugins/data/public/search/aggs/buckets/range.ts index 543e5d66b9fa81..92c5193d55a209 100644 --- a/src/plugins/data/public/search/aggs/buckets/range.ts +++ b/src/plugins/data/public/search/aggs/buckets/range.ts @@ -19,16 +19,13 @@ import { i18n } from '@kbn/i18n'; import { BucketAggType } from './bucket_agg_type'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { RangeKey } from './range_key'; import { createFilterRange } from './create_filter/range'; import { BUCKET_TYPES } from './bucket_agg_types'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; -const keyCaches = new WeakMap(); -const formats = new WeakMap(); - const rangeTitle = i18n.translate('data.search.aggs.buckets.rangeTitle', { defaultMessage: 'Range', }); @@ -45,12 +42,14 @@ export interface AggParamsRange extends BaseAggParams { }>; } -export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDependencies) => - new BucketAggType( +export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDependencies) => { + const keyCaches = new WeakMap(); + + return new BucketAggType( { name: BUCKET_TYPES.RANGE, title: rangeTitle, - createFilter: createFilterRange, + createFilter: createFilterRange(getInternalStartServices), makeLabel(aggConfig) { return i18n.translate('data.search.aggs.aggTypesLabel', { defaultMessage: '{fieldName} ranges', @@ -77,30 +76,6 @@ export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDe return key; }, - getFormat(agg) { - let aggFormat = formats.get(agg); - if (aggFormat) return aggFormat; - - const RangeFormat = FieldFormat.from((range: any) => { - const format = agg.fieldOwnFormatter(); - const gte = '\u2265'; - const lt = '\u003c'; - return i18n.translate('data.search.aggs.aggTypes.rangesFormatMessage', { - defaultMessage: '{gte} {from} and {lt} {to}', - values: { - gte, - from: format(range.gte), - lt, - to: format(range.lt), - }, - }); - }); - - aggFormat = new RangeFormat(); - - formats.set(agg, aggFormat); - return aggFormat; - }, getSerializedFormat(agg) { const format = agg.params.field ? agg.params.field.format.toJSON() : {}; return { @@ -132,3 +107,4 @@ export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDe }, { getInternalStartServices } ); +}; diff --git a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts index 156f7f8108482c..8fe833aa99cb2e 100644 --- a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts @@ -72,7 +72,6 @@ describe('Significant Terms Agg', () => { typesRegistry: mockAggTypesRegistry([ getSignificantTermsBucketAgg(aggTypesDependencies), ]), - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/terms.test.ts b/src/plugins/data/public/search/aggs/buckets/terms.test.ts index 9769efb6da7494..2c5be00c8afea5 100644 --- a/src/plugins/data/public/search/aggs/buckets/terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/terms.test.ts @@ -20,11 +20,9 @@ import { AggConfigs } from '../agg_configs'; import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; describe('Terms Agg', () => { describe('order agg editor UI', () => { - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = (params: Record = {}) => { const indexPattern = { id: '1234', @@ -49,7 +47,7 @@ describe('Terms Agg', () => { type: BUCKET_TYPES.TERMS, }, ], - { typesRegistry: mockAggTypesRegistry(), fieldFormats } + { typesRegistry: mockAggTypesRegistry() } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/terms.ts b/src/plugins/data/public/search/aggs/buckets/terms.ts index 1e8e9ab4ef9d09..57a5ebf72316c6 100644 --- a/src/plugins/data/public/search/aggs/buckets/terms.ts +++ b/src/plugins/data/public/search/aggs/buckets/terms.ts @@ -30,7 +30,7 @@ import { AggConfigSerialized, BaseAggParams, IAggConfigs } from '../types'; import { Adapters } from '../../../../../inspector/public'; import { ISearchSource } from '../../search_source'; -import { IFieldFormat, FieldFormatsContentType, KBN_FIELD_TYPES } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { getRequestInspectorStats, getResponseInspectorStats } from '../../expressions'; import { @@ -88,22 +88,6 @@ export const getTermsBucketAgg = ({ getInternalStartServices }: TermsBucketAggDe const params = agg.params; return agg.getFieldDisplayName() + ': ' + params.order.text; }, - getFormat(bucket): IFieldFormat { - return { - getConverterFor: (type: FieldFormatsContentType) => { - return (val: any) => { - if (val === '__other__') { - return bucket.params.otherBucketLabel; - } - if (val === '__missing__') { - return bucket.params.missingBucketLabel; - } - - return bucket.params.field.format.convert(val, type); - }; - }, - } as IFieldFormat; - }, getSerializedFormat(agg) { const format = agg.params.field ? agg.params.field.format.toJSON() : {}; return { diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts b/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts index 38312ec5cfa81c..a30e426dd23901 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts @@ -46,7 +46,7 @@ const averageBucketTitle = i18n.translate('data.search.aggs.metrics.averageBucke export const getBucketAvgMetricAgg = ({ getInternalStartServices, }: BucketAvgMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -55,7 +55,6 @@ export const getBucketAvgMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallAverageLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, getValue(agg, bucket) { const customMetric = agg.getParam('customMetric'); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_max.ts b/src/plugins/data/public/search/aggs/metrics/bucket_max.ts index e2c6a5105bac66..307c7ed3f9d386 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_max.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_max.ts @@ -45,7 +45,7 @@ const maxBucketTitle = i18n.translate('data.search.aggs.metrics.maxBucketTitle', export const getBucketMaxMetricAgg = ({ getInternalStartServices, }: BucketMaxMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -54,7 +54,6 @@ export const getBucketMaxMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallMaxLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_min.ts b/src/plugins/data/public/search/aggs/metrics/bucket_min.ts index c46a3eb9425d1f..bb4ed9d44b0b33 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_min.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_min.ts @@ -45,7 +45,7 @@ const minBucketTitle = i18n.translate('data.search.aggs.metrics.minBucketTitle', export const getBucketMinMetricAgg = ({ getInternalStartServices, }: BucketMinMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -54,7 +54,6 @@ export const getBucketMinMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallMinLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts b/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts index 57212ec9ff91b2..dd065b52acd129 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts @@ -45,7 +45,7 @@ const sumBucketTitle = i18n.translate('data.search.aggs.metrics.sumBucketTitle', export const getBucketSumMetricAgg = ({ getInternalStartServices, }: BucketSumMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper; + const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper; return new MetricAggType( { @@ -54,7 +54,6 @@ export const getBucketSumMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, overallSumLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/cardinality.ts b/src/plugins/data/public/search/aggs/metrics/cardinality.ts index 2855cc1b6b16eb..efc79a85595661 100644 --- a/src/plugins/data/public/search/aggs/metrics/cardinality.ts +++ b/src/plugins/data/public/search/aggs/metrics/cardinality.ts @@ -49,11 +49,6 @@ export const getCardinalityMetricAgg = ({ values: { field: aggConfig.getFieldDisplayName() }, }); }, - getFormat() { - const { fieldFormats } = getInternalStartServices(); - - return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); - }, getSerializedFormat(agg) { return { id: 'number', diff --git a/src/plugins/data/public/search/aggs/metrics/count.ts b/src/plugins/data/public/search/aggs/metrics/count.ts index 4c7b8139b01628..86faca053a9cf7 100644 --- a/src/plugins/data/public/search/aggs/metrics/count.ts +++ b/src/plugins/data/public/search/aggs/metrics/count.ts @@ -20,7 +20,6 @@ import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; -import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; export interface CountMetricAggDependencies { @@ -40,11 +39,6 @@ export const getCountMetricAgg = ({ getInternalStartServices }: CountMetricAggDe defaultMessage: 'Count', }); }, - getFormat() { - const { fieldFormats } = getInternalStartServices(); - - return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); - }, getSerializedFormat(agg) { return { id: 'number', diff --git a/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts b/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts index c392f44a7961ed..3de88bb71740f1 100644 --- a/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts +++ b/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts @@ -46,7 +46,7 @@ const cumulativeSumTitle = i18n.translate('data.search.aggs.metrics.cumulativeSu export const getCumulativeSumMetricAgg = ({ getInternalStartServices, }: CumulativeSumMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -55,7 +55,6 @@ export const getCumulativeSumMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, cumulativeSumLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/derivative.ts b/src/plugins/data/public/search/aggs/metrics/derivative.ts index f3c1cc9bc29773..c9507029080e61 100644 --- a/src/plugins/data/public/search/aggs/metrics/derivative.ts +++ b/src/plugins/data/public/search/aggs/metrics/derivative.ts @@ -46,7 +46,7 @@ const derivativeTitle = i18n.translate('data.search.aggs.metrics.derivativeTitle export const getDerivativeMetricAgg = ({ getInternalStartServices, }: DerivativeMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -57,7 +57,6 @@ export const getDerivativeMetricAgg = ({ }, subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts b/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts index 2a74a446ce84e0..73acd268600763 100644 --- a/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts +++ b/src/plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts @@ -18,14 +18,12 @@ */ import { i18n } from '@kbn/i18n'; -import { noop, identity } from 'lodash'; +import { noop } from 'lodash'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; import { parentPipelineAggWriter } from './parent_pipeline_agg_writer'; -import { FieldFormat } from '../../../../../common'; - const metricAggFilter = [ '!top_hits', '!percentiles', @@ -73,18 +71,6 @@ export const parentPipelineAggHelper = { ] as Array>; }, - getFormat(agg: IMetricAggConfig) { - let subAgg; - const customMetric = agg.getParam('customMetric'); - - if (customMetric) { - subAgg = customMetric; - } else { - subAgg = agg.aggConfigs.byId(agg.getParam('metricAgg')); - } - return subAgg ? subAgg.type.getFormat(subAgg) : new (FieldFormat.from(identity))(); - }, - getSerializedFormat(agg: IMetricAggConfig) { let subAgg; const customMetric = agg.getParam('customMetric'); diff --git a/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts b/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts index 8e3e0143bf9154..347ac76b8e27b9 100644 --- a/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts +++ b/src/plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts @@ -17,12 +17,10 @@ * under the License. */ -import { identity } from 'lodash'; import { i18n } from '@kbn/i18n'; import { siblingPipelineAggWriter } from './sibling_pipeline_agg_writer'; import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers'; import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type'; -import { FieldFormat } from '../../../../../common'; const metricAggFilter: string[] = [ '!top_hits', @@ -87,13 +85,6 @@ export const siblingPipelineAggHelper = { ] as Array>; }, - getFormat(agg: IMetricAggConfig) { - const customMetric = agg.getParam('customMetric'); - return customMetric - ? customMetric.type.getFormat(customMetric) - : new (FieldFormat.from(identity))(); - }, - getSerializedFormat(agg: IMetricAggConfig) { const customMetric = agg.getParam('customMetric'); return customMetric ? customMetric.type.getSerializedFormat(customMetric) : {}; diff --git a/src/plugins/data/public/search/aggs/metrics/median.test.ts b/src/plugins/data/public/search/aggs/metrics/median.test.ts index 71c48f04a3ca8a..b3721e2c1e679b 100644 --- a/src/plugins/data/public/search/aggs/metrics/median.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/median.test.ts @@ -63,7 +63,6 @@ describe('AggTypeMetricMedianProvider class', () => { ], { typesRegistry, - fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts b/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts index 83656db4ac5474..5c4ff91258fb00 100644 --- a/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts +++ b/src/plugins/data/public/search/aggs/metrics/metric_agg_type.ts @@ -22,7 +22,6 @@ import { AggType, AggTypeConfig } from '../agg_type'; import { AggParamType } from '../param_types/agg'; import { AggConfig } from '../agg_config'; import { METRIC_TYPES } from './metric_agg_types'; -import { KBN_FIELD_TYPES } from '../../../../common'; import { FieldTypes } from '../param_types'; import { GetInternalStartServicesFn } from '../../../types'; @@ -82,14 +81,6 @@ export class MetricAggType { - const { fieldFormats } = dependencies.getInternalStartServices(); - const field = agg.getField(); - return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER); - }); - this.subtype = config.subtype || i18n.translate('data.search.aggs.metrics.metricAggregationsSubtypeTitle', { diff --git a/src/plugins/data/public/search/aggs/metrics/moving_avg.ts b/src/plugins/data/public/search/aggs/metrics/moving_avg.ts index abad2782f9d201..61384ef1dc1066 100644 --- a/src/plugins/data/public/search/aggs/metrics/moving_avg.ts +++ b/src/plugins/data/public/search/aggs/metrics/moving_avg.ts @@ -48,7 +48,7 @@ const movingAvgLabel = i18n.translate('data.search.aggs.metrics.movingAvgLabel', export const getMovingAvgMetricAgg = ({ getInternalStartServices, }: MovingAvgMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -57,7 +57,6 @@ export const getMovingAvgMetricAgg = ({ title: movingAvgTitle, makeLabel: (agg) => makeNestedLabel(agg, movingAvgLabel), subtype, - getFormat, getSerializedFormat, params: [ ...params(), diff --git a/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts b/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts index 2201366cdf78b5..91149a3f29f94a 100644 --- a/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts @@ -24,14 +24,12 @@ import { getSerialDiffMetricAgg } from './serial_diff'; import { AggConfigs } from '../agg_configs'; import { mockAggTypesRegistry } from '../test_helpers'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { GetInternalStartServicesFn, InternalStartServices } from '../../../types'; import { notificationServiceMock } from '../../../../../../../src/core/public/mocks'; describe('parent pipeline aggs', function () { const getInternalStartServices: GetInternalStartServicesFn = () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices); @@ -76,9 +74,7 @@ describe('parent pipeline aggs', function () { const field = { name: 'field', format: { - type: { - id: 'bytes', - }, + toJSON: () => ({ id: 'bytes' }), }, }; const indexPattern = { @@ -111,7 +107,7 @@ describe('parent pipeline aggs', function () { schema: 'metric', }, ], - { typesRegistry, fieldFormats: getInternalStartServices().fieldFormats } + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -197,14 +193,14 @@ describe('parent pipeline aggs', function () { ); }); - it('should have correct formatter', () => { + it('should have correct serialized format', () => { init({ metricAgg: '3', }); - expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes'); }); - it('should have correct customMetric nested formatter', () => { + it('should have correct customMetric nested serialized format', () => { init({ metricAgg: 'custom', customMetric: { @@ -222,7 +218,7 @@ describe('parent pipeline aggs', function () { schema: 'orderAgg', }, }); - expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes'); }); it("should call modifyAggConfigOnSearchRequestStart for its customMetric's parameters", () => { diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts index df52c10a82495b..39e371763ed4b1 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts @@ -74,7 +74,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function () { }, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts index c5aee380b97762..1953c81a998740 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts @@ -22,7 +22,7 @@ import { MetricAggType } from './metric_agg_type'; import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; -import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../common'; +import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; @@ -96,13 +96,6 @@ export const getPercentileRanksMetricAgg = ({ return values.map((value: any) => new ValueAggConfig(value)); }, - getFormat() { - const { fieldFormats } = getInternalStartServices(); - return ( - fieldFormats.getInstance(FIELD_FORMAT_IDS.PERCENT) || - fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER) - ); - }, getSerializedFormat(agg) { return { id: 'percent', diff --git a/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts b/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts index 76382c01bcc108..52ab325ac5806b 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts @@ -67,7 +67,7 @@ describe('AggTypesMetricsPercentilesProvider class', () => { }, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/serial_diff.ts b/src/plugins/data/public/search/aggs/metrics/serial_diff.ts index 7cb1b194fed1c1..9ea01be11fe8f8 100644 --- a/src/plugins/data/public/search/aggs/metrics/serial_diff.ts +++ b/src/plugins/data/public/search/aggs/metrics/serial_diff.ts @@ -46,7 +46,7 @@ const serialDiffLabel = i18n.translate('data.search.aggs.metrics.serialDiffLabel export const getSerialDiffMetricAgg = ({ getInternalStartServices, }: SerialDiffMetricAggDependencies) => { - const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper; + const { subtype, params, getSerializedFormat } = parentPipelineAggHelper; return new MetricAggType( { @@ -55,7 +55,6 @@ export const getSerialDiffMetricAgg = ({ makeLabel: (agg) => makeNestedLabel(agg, serialDiffLabel), subtype, params: [...params()], - getFormat, getSerializedFormat, }, { diff --git a/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts b/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts index 56bd33b2b6345b..f08e850caadcec 100644 --- a/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts @@ -25,14 +25,12 @@ import { getBucketMaxMetricAgg } from './bucket_max'; import { AggConfigs } from '../agg_configs'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; import { mockAggTypesRegistry } from '../test_helpers'; -import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { GetInternalStartServicesFn, InternalStartServices } from '../../../types'; import { notificationServiceMock } from '../../../../../../../src/core/public/mocks'; describe('sibling pipeline aggs', () => { const getInternalStartServices: GetInternalStartServicesFn = () => (({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices); @@ -71,9 +69,7 @@ describe('sibling pipeline aggs', () => { const field = { name: 'field', format: { - type: { - id: 'bytes', - }, + toJSON: () => ({ id: 'bytes' }), }, }; const indexPattern = { @@ -112,7 +108,7 @@ describe('sibling pipeline aggs', () => { }, }, ], - { typesRegistry, fieldFormats: getInternalStartServices().fieldFormats } + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) @@ -155,7 +151,7 @@ describe('sibling pipeline aggs', () => { expect(aggDsl.parentAggs['2-bucket'].aggs['2-metric'].avg.field).toEqual('field'); }); - it('should have correct formatter', () => { + it('should have correct serialized field format', () => { init({ customMetric: { id: '5', @@ -171,7 +167,7 @@ describe('sibling pipeline aggs', () => { }, }); - expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes'); }); it("should call modifyAggConfigOnSearchRequestStart for nested aggs' parameters", () => { diff --git a/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts b/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts index 536764b2bcf0b8..2fa207e62771e3 100644 --- a/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts @@ -66,7 +66,7 @@ describe('AggTypeMetricStandardDeviationProvider class', () => { }, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); }; diff --git a/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts b/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts index 49e0a3e4b349ab..94a970a72a46f5 100644 --- a/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts @@ -91,7 +91,7 @@ describe('Top hit metric', () => { params, }, ], - { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } + { typesRegistry } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) diff --git a/src/plugins/data/public/search/aggs/mocks.ts b/src/plugins/data/public/search/aggs/mocks.ts index 16544fd8f46b08..7a5dcc9be45929 100644 --- a/src/plugins/data/public/search/aggs/mocks.ts +++ b/src/plugins/data/public/search/aggs/mocks.ts @@ -27,7 +27,6 @@ import { } from './'; import { SearchAggsSetup, SearchAggsStart } from './types'; import { mockAggTypesRegistry } from './test_helpers'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; const aggTypeBaseParamMock = () => ({ name: 'some_param', @@ -73,7 +72,6 @@ export const searchAggsStartMock = (): SearchAggsStart => ({ createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => { return new AggConfigs(indexPattern, configStates, { typesRegistry: mockAggTypesRegistry(), - fieldFormats: fieldFormatsServiceMock.createStartContract(), }); }), types: mockAggTypesRegistry(), diff --git a/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts b/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts index 906b8862d00aab..c4846a98f124fd 100644 --- a/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts +++ b/src/plugins/data/public/search/expressions/build_tabular_inspector_data.ts @@ -19,6 +19,7 @@ import { set } from 'lodash'; import { FormattedData } from '../../../../../plugins/inspector/public'; +import { FormatFactory } from '../../../common/field_formats/utils'; import { TabbedTable } from '../tabify'; import { createFilter } from './create_filter'; @@ -38,14 +39,30 @@ import { createFilter } from './create_filter'; */ export async function buildTabularInspectorData( table: TabbedTable, - queryFilter: { addFilters: (filter: any) => void } + { + queryFilter, + deserializeFieldFormat, + }: { + queryFilter: { addFilters: (filter: any) => void }; + deserializeFieldFormat: FormatFactory; + } ) { const aggConfigs = table.columns.map((column) => column.aggConfig); const rows = table.rows.map((row) => { return table.columns.reduce>((prev, cur, colIndex) => { const value = row[cur.id]; - const fieldFormatter = cur.aggConfig.fieldFormatter('text'); - prev[`col-${colIndex}-${cur.aggConfig.id}`] = new FormattedData(value, fieldFormatter(value)); + + let format = cur.aggConfig.toSerializedFieldFormat(); + if (Object.keys(format).length < 1) { + // If no format exists, fall back to string as a default + format = { id: 'string' }; + } + const fieldFormatter = deserializeFieldFormat(format); + + prev[`col-${colIndex}-${cur.aggConfig.id}`] = new FormattedData( + value, + fieldFormatter.convert(value) + ); return prev; }, {}); }); diff --git a/src/plugins/data/public/search/expressions/create_filter.test.ts b/src/plugins/data/public/search/expressions/create_filter.test.ts index 51b5e175761bd7..23da060cba2032 100644 --- a/src/plugins/data/public/search/expressions/create_filter.test.ts +++ b/src/plugins/data/public/search/expressions/create_filter.test.ts @@ -22,12 +22,10 @@ import { AggConfigs, IAggConfig } from '../aggs'; import { TabbedTable } from '../tabify'; import { isRangeFilter, BytesFormat, FieldFormatsGetConfigFn } from '../../../common'; import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('createFilter', () => { let table: TabbedTable; let aggConfig: IAggConfig; - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const typesRegistry = mockAggTypesRegistry(); @@ -60,7 +58,7 @@ describe('createFilter', () => { params, }, ], - { typesRegistry, fieldFormats } + { typesRegistry } ); }; diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 77475cd3ce88b9..d9ca378811e515 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -34,7 +34,12 @@ import { ISearchSource } from '../search_source'; import { tabifyAggResponse } from '../tabify'; import { Filter, Query, TimeRange, IIndexPattern, isRangeFilter } from '../../../common'; import { FilterManager, calculateBounds, getTime } from '../../query'; -import { getSearchService, getQueryService, getIndexPatterns } from '../../services'; +import { + getFieldFormats, + getIndexPatterns, + getQueryService, + getSearchService, +} from '../../services'; import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { getRequestInspectorStats, getResponseInspectorStats, serializeAggConfig } from './utils'; @@ -220,7 +225,11 @@ const handleCourierRequest = async ({ } inspectorAdapters.data.setTabularLoader( - () => buildTabularInspectorData((searchSource as any).tabifiedResponse, filterManager), + () => + buildTabularInspectorData((searchSource as any).tabifiedResponse, { + queryFilter: filterManager, + deserializeFieldFormat: getFieldFormats().deserialize, + }), { returnsFormattedValues: true } ); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index d5997c15817f69..992979ad0dbb0f 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -38,7 +38,6 @@ import { AggConfigs, getCalculateAutoTimeExpression, } from './aggs'; -import { FieldFormatsStart } from '../field_formats'; import { ISearchGeneric } from './i_search'; interface SearchServiceSetupDependencies { @@ -50,7 +49,6 @@ interface SearchServiceSetupDependencies { interface SearchServiceStartDependencies { indexPatterns: IndexPatternsContract; - fieldFormats: FieldFormatsStart; } /** @@ -158,7 +156,6 @@ export class SearchService implements Plugin { calculateAutoTimeExpression: getCalculateAutoTimeExpression(core.uiSettings), createAggConfigs: (indexPattern, configStates = [], schemas) => { return new AggConfigs(indexPattern, configStates, { - fieldFormats: dependencies.fieldFormats, typesRegistry: aggTypesStart, }); }, diff --git a/src/plugins/data/public/search/tabify/get_columns.test.ts b/src/plugins/data/public/search/tabify/get_columns.test.ts index b4498aca4079cf..0c5551d95690f2 100644 --- a/src/plugins/data/public/search/tabify/get_columns.test.ts +++ b/src/plugins/data/public/search/tabify/get_columns.test.ts @@ -21,7 +21,6 @@ import { tabifyGetColumns } from './get_columns'; import { TabbedAggColumn } from './types'; import { AggConfigs } from '../aggs'; import { mockAggTypesRegistry, mockDataServices } from '../aggs/test_helpers'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('get columns', () => { beforeEach(() => { @@ -29,7 +28,6 @@ describe('get columns', () => { }); const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const createAggConfigs = (aggs: any[] = []) => { const field = { @@ -45,10 +43,7 @@ describe('get columns', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, { - typesRegistry, - fieldFormats, - }); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; test('should inject the metric after each bucket if the vis is hierarchical', () => { diff --git a/src/plugins/data/public/search/tabify/response_writer.test.ts b/src/plugins/data/public/search/tabify/response_writer.test.ts index 3334d858ce54e9..94473d23ccc398 100644 --- a/src/plugins/data/public/search/tabify/response_writer.test.ts +++ b/src/plugins/data/public/search/tabify/response_writer.test.ts @@ -21,7 +21,6 @@ import { TabbedAggResponseWriter } from './response_writer'; import { AggConfigs, BUCKET_TYPES } from '../aggs'; import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; import { TabbedResponseWriterOptions } from './types'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('TabbedAggResponseWriter class', () => { beforeEach(() => { @@ -31,7 +30,6 @@ describe('TabbedAggResponseWriter class', () => { let responseWriter: TabbedAggResponseWriter; const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const splitAggConfig = [ { @@ -73,17 +71,11 @@ describe('TabbedAggResponseWriter class', () => { }, } as any; - return new TabbedAggResponseWriter( - new AggConfigs(indexPattern, aggs, { - typesRegistry, - fieldFormats, - }), - { - metricsAtAllLevels: false, - partialRows: false, - ...opts, - } - ); + return new TabbedAggResponseWriter(new AggConfigs(indexPattern, aggs, { typesRegistry }), { + metricsAtAllLevels: false, + partialRows: false, + ...opts, + }); }; describe('Constructor', () => { diff --git a/src/plugins/data/public/search/tabify/tabify.test.ts b/src/plugins/data/public/search/tabify/tabify.test.ts index f6691360cec312..0a1e99c8bb2001 100644 --- a/src/plugins/data/public/search/tabify/tabify.test.ts +++ b/src/plugins/data/public/search/tabify/tabify.test.ts @@ -22,11 +22,9 @@ import { IndexPattern } from '../../index_patterns'; import { AggConfigs, IAggConfig, IAggConfigs } from '../aggs'; import { mockAggTypesRegistry } from '../aggs/test_helpers'; import { metricOnly, threeTermBuckets } from 'fixtures/fake_hierarchical_data'; -import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('tabifyAggResponse Integration', () => { const typesRegistry = mockAggTypesRegistry(); - const fieldFormats = fieldFormatsServiceMock.createStartContract(); const createAggConfigs = (aggs: IAggConfig[] = []) => { const field = { @@ -42,10 +40,7 @@ describe('tabifyAggResponse Integration', () => { }, } as unknown) as IndexPattern; - return new AggConfigs(indexPattern, aggs, { - typesRegistry, - fieldFormats, - }); + return new AggConfigs(indexPattern, aggs, { typesRegistry }); }; const mockAggConfig = (agg: any): IAggConfig => (agg as unknown) as IAggConfig; diff --git a/src/plugins/vis_type_table/public/components/table_vis_options.tsx b/src/plugins/vis_type_table/public/components/table_vis_options.tsx index d220a6b2db8423..c4d333134237a6 100644 --- a/src/plugins/vis_type_table/public/components/table_vis_options.tsx +++ b/src/plugins/vis_type_table/public/components/table_vis_options.tsx @@ -46,7 +46,7 @@ function TableOptions({ }), }, ...tabifyGetColumns(aggs.getResponseAggs(), true) - .filter((col) => get(col.aggConfig.type.getFormat(col.aggConfig), 'type.id') === 'number') + .filter((col) => get(col.aggConfig.toSerializedFieldFormat(), 'id') === 'number') .map(({ name }) => ({ value: name, text: name })), ], [aggs] diff --git a/test/functional/apps/visualize/_tile_map.js b/test/functional/apps/visualize/_tile_map.js index 1a9ac5000b1bac..56585ccd725d80 100644 --- a/test/functional/apps/visualize/_tile_map.js +++ b/test/functional/apps/visualize/_tile_map.js @@ -207,7 +207,7 @@ export default function ({ getService, getPageObjects }) { const vizName1 = 'Visualization TileMap'; await PageObjects.visualize.loadSavedVisualization(vizName1); await inspector.open(); - await inspector.expectTableHeaders(['filter', 'geohash_grid', 'Count', 'Geo Centroid']); + await inspector.expectTableHeaders(['Filter', 'Geohash', 'Count', 'Geo Centroid']); await inspector.close(); }); @@ -216,7 +216,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visEditor.setIsFilteredByCollarCheckbox(false); await PageObjects.visEditor.clickGo(); await inspector.open(); - await inspector.expectTableHeaders(['geohash_grid', 'Count', 'Geo Centroid']); + await inspector.expectTableHeaders(['Geohash', 'Count', 'Geo Centroid']); await inspector.close(); }); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a41aeb60794284..29ea4426ac5f64 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -715,7 +715,6 @@ "data.search.aggs.aggGroups.bucketsText": "バケット", "data.search.aggs.aggGroups.metricsText": "メトリック", "data.search.aggs.aggGroups.noneText": "なし", - "data.search.aggs.aggTypes.rangesFormatMessage": "{gte} {from} と {lt} {to}", "data.search.aggs.aggTypesLabel": "{fieldName} の範囲", "data.search.aggs.buckets.dateHistogram.customLabel.help": "このアグリゲーションのカスタムラベルを表します", "data.search.aggs.buckets.dateHistogram.dropPartials.help": "このアグリゲーションでdrop_partialsを使用するかどうかを指定します", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index cf39b8eb12a710..84a4fb41cdd761 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -716,7 +716,6 @@ "data.search.aggs.aggGroups.bucketsText": "存储桶", "data.search.aggs.aggGroups.metricsText": "指标", "data.search.aggs.aggGroups.noneText": "无", - "data.search.aggs.aggTypes.rangesFormatMessage": "{gte} {from} 和 {lt} {to}", "data.search.aggs.aggTypesLabel": "{fieldName} 范围", "data.search.aggs.buckets.dateHistogram.customLabel.help": "表示此聚合的定制标签", "data.search.aggs.buckets.dateHistogram.dropPartials.help": "指定是否将 drop_partials 用于此聚合", From 96004e87e264dec5926c96e06d5d2d3992809db7 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 29 Jun 2020 14:09:46 -0400 Subject: [PATCH 07/91] [7.x] Hide unused resolver buttons (#70112) (#70155) Co-authored-by: Elastic Machine --- .../public/resolver/store/actions.ts | 10 ------ .../public/resolver/view/index.tsx | 4 +-- .../resolver/view/process_event_dot.tsx | 33 ++++++------------- .../public/resolver/view/submenu.tsx | 5 --- 4 files changed, 12 insertions(+), 40 deletions(-) diff --git a/x-pack/plugins/security_solution/public/resolver/store/actions.ts b/x-pack/plugins/security_solution/public/resolver/store/actions.ts index c633d791e8bf26..ae302d0e609116 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/actions.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/actions.ts @@ -141,15 +141,6 @@ interface UserSelectedRelatedEventCategory { }; } -/** - * This action should dispatch to indicate that the user chose to focus - * on examining alerts related to a particular ResolverEvent - */ -interface UserSelectedRelatedAlerts { - readonly type: 'userSelectedRelatedAlerts'; - readonly payload: ResolverEvent; -} - export type ResolverAction = | CameraAction | DataAction @@ -160,7 +151,6 @@ export type ResolverAction = | UserSelectedResolverNode | UserRequestedRelatedEventData | UserSelectedRelatedEventCategory - | UserSelectedRelatedAlerts | AppDetectedNewIdFromQueryParams | AppDisplayedDifferentPanel | AppDetectedMissingEventData; diff --git a/x-pack/plugins/security_solution/public/resolver/view/index.tsx b/x-pack/plugins/security_solution/public/resolver/view/index.tsx index 9b7114b56495c7..5c188fdc711560 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/index.tsx @@ -136,7 +136,7 @@ export const Resolver = React.memo(function Resolver({ projectionMatrix={projectionMatrix} /> ))} - {[...processNodePositions].map(([processEvent, position], index) => { + {[...processNodePositions].map(([processEvent, position]) => { const adjacentNodeMap = processToAdjacencyMap.get(processEvent); const processEntityId = entityId(processEvent); if (!adjacentNodeMap) { @@ -145,7 +145,7 @@ export const Resolver = React.memo(function Resolver({ } return ( { - dispatch({ - type: 'userSelectedRelatedAlerts', - payload: event, - }); - }, [dispatch, event]); - const history = useHistory(); const urlSearch = history.location.search; @@ -637,22 +630,16 @@ const ProcessEventDotComponents = React.memo( }} > - - - - + {grandTotal > 0 && ( + + )} diff --git a/x-pack/plugins/security_solution/public/resolver/view/submenu.tsx b/x-pack/plugins/security_solution/public/resolver/view/submenu.tsx index 8f972dd737af6a..d3bb6123ce04da 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/submenu.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/submenu.tsx @@ -31,11 +31,6 @@ export const subMenuAssets = { menuError: i18n.translate('xpack.securitySolution.endpoint.resolver.relatedRetrievalError', { defaultMessage: 'There was an error retrieving related events.', }), - relatedAlerts: { - title: i18n.translate('xpack.securitySolution.endpoint.resolver.relatedAlerts', { - defaultMessage: 'Related Alerts', - }), - }, relatedEvents: { title: i18n.translate('xpack.securitySolution.endpoint.resolver.relatedEvents', { defaultMessage: 'Events', From dd6b002a95ff5c4f1ceb0a276f780e84b1077db7 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 29 Jun 2020 12:12:20 -0600 Subject: [PATCH 08/91] remove no longer required div wrapper around ValidatedDualRange (#70188) (#70218) * remove no longer required div wrapper around ValidatedDualRange * tslint --- .../validated_range/validated_dual_range.tsx | 64 ++++++++----------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx b/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx index 8187e70b1bbd1a..63b9b48ec809eb 100644 --- a/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx +++ b/src/plugins/kibana_react/public/validated_range/validated_dual_range.tsx @@ -17,7 +17,7 @@ * under the License. */ import { i18n } from '@kbn/i18n'; -import React, { Component, createRef } from 'react'; +import React, { Component } from 'react'; import { EuiFormRow, EuiDualRange } from '@elastic/eui'; import { EuiFormRowDisplayKeys } from '@elastic/eui/src/components/form/form_row/form_row'; import { EuiDualRangeProps } from '@elastic/eui/src/components/form/range/dual_range'; @@ -72,18 +72,6 @@ export class ValidatedDualRange extends Component { return null; } - // Can remove after eui#3412 is resolved - componentDidMount() { - if (this.trackRef.current) { - const track = this.trackRef.current.querySelector('.euiRangeTrack'); - if (track) { - track.setAttribute('aria-hidden', 'true'); - } - } - } - - trackRef = createRef(); - // @ts-ignore state populated by getDerivedStateFromProps state: State = {}; @@ -119,34 +107,32 @@ export class ValidatedDualRange extends Component { } = this.props; return ( -
- + - - -
+ value={this.state.value} + onChange={this._onChange} + minInputProps={{ + 'aria-label': i18n.translate('kibana-react.dualRangeControl.minInputAriaLabel', { + defaultMessage: 'Range minimum', + }), + }} + maxInputProps={{ + 'aria-label': i18n.translate('kibana-react.dualRangeControl.maxInputAriaLabel', { + defaultMessage: 'Range maximum', + }), + }} + {...rest} + /> + ); } } From aceaa3170b1f0ca7b57280f32facf99985596e9a Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Mon, 29 Jun 2020 14:22:17 -0400 Subject: [PATCH 09/91] [7.x] Consolidate capabilities check for Stack Management (#69437) (#70222) Co-authored-by: Elastic Machine --- .../advanced_settings/public/plugin.ts | 13 ++-- .../redirect_no_index_pattern.tsx | 2 +- .../server/saved_objects/index_patterns.ts | 2 +- .../home/server/capabilities_provider.ts | 2 +- .../index_pattern_management/public/plugin.ts | 9 +-- .../management_sections_service.test.ts | 44 ++++++++++++- .../public/management_sections_service.ts | 20 +++++- src/plugins/management/public/plugin.ts | 2 +- src/plugins/management/public/types.ts | 8 ++- .../server/capabilities_provider.ts | 2 +- .../public/lib/in_app_url.test.ts | 4 +- .../public/lib/in_app_url.ts | 2 +- .../saved_objects_table.test.tsx.snap | 2 +- .../__snapshots__/relationships.test.tsx.snap | 2 +- .../__snapshots__/table.test.tsx.snap | 4 +- .../components/relationships.test.tsx | 4 +- .../objects_table/components/table.test.tsx | 4 +- .../saved_objects_table.test.tsx | 2 +- .../apis/saved_objects_management/find.ts | 2 +- .../saved_objects_management/relationships.ts | 4 +- .../__snapshots__/oss_features.test.ts.snap | 8 +-- .../plugins/features/server/oss_features.ts | 12 ++-- .../management/management_service.test.ts | 61 ------------------- .../public/management/management_service.tsx | 11 +--- x-pack/plugins/spaces/public/plugin.tsx | 4 -- .../advanced_settings_security.ts | 3 +- .../index_patterns_security.ts | 6 +- .../saved_objects_management_security.ts | 16 +++-- 28 files changed, 119 insertions(+), 136 deletions(-) diff --git a/src/plugins/advanced_settings/public/plugin.ts b/src/plugins/advanced_settings/public/plugin.ts index 2784b74ab726cf..8b3347f8d88f0e 100644 --- a/src/plugins/advanced_settings/public/plugin.ts +++ b/src/plugins/advanced_settings/public/plugin.ts @@ -17,8 +17,8 @@ * under the License. */ import { i18n } from '@kbn/i18n'; -import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; -import { ManagementApp, ManagementSectionId } from '../../management/public'; +import { CoreSetup, Plugin } from 'kibana/public'; +import { ManagementSectionId } from '../../management/public'; import { ComponentRegistry } from './component_registry'; import { AdvancedSettingsSetup, AdvancedSettingsStart, AdvancedSettingsPluginSetup } from './types'; @@ -30,11 +30,10 @@ const title = i18n.translate('advancedSettings.advancedSettingsLabel', { export class AdvancedSettingsPlugin implements Plugin { - private managementApp?: ManagementApp; public setup(core: CoreSetup, { management }: AdvancedSettingsPluginSetup) { const kibanaSection = management.sections.getSection(ManagementSectionId.Kibana); - this.managementApp = kibanaSection.registerApp({ + kibanaSection.registerApp({ id: 'settings', title, order: 3, @@ -51,11 +50,7 @@ export class AdvancedSettingsPlugin }; } - public start(core: CoreStart) { - if (!core.application.capabilities.management.kibana.settings) { - this.managementApp!.disable(); - } - + public start() { return { component: component.start, }; diff --git a/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx b/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx index e32a8e023cf402..7ed6525db6350e 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx +++ b/src/plugins/data/public/index_patterns/index_patterns/redirect_no_index_pattern.tsx @@ -30,7 +30,7 @@ export const onRedirectNoIndexPattern = ( navigateToApp: CoreStart['application']['navigateToApp'], overlays: CoreStart['overlays'] ) => () => { - const canManageIndexPatterns = capabilities.management.kibana.index_patterns; + const canManageIndexPatterns = capabilities.management.kibana.indexPatterns; const redirectTarget = canManageIndexPatterns ? '/management/kibana/indexPatterns' : '/home'; let timeoutId: NodeJS.Timeout | undefined; diff --git a/src/plugins/data/server/saved_objects/index_patterns.ts b/src/plugins/data/server/saved_objects/index_patterns.ts index ee02f38427914f..902cf2988f429f 100644 --- a/src/plugins/data/server/saved_objects/index_patterns.ts +++ b/src/plugins/data/server/saved_objects/index_patterns.ts @@ -37,7 +37,7 @@ export const indexPatternSavedObjectType: SavedObjectsType = { getInAppUrl(obj) { return { path: `/app/management/kibana/indexPatterns/patterns/${encodeURIComponent(obj.id)}`, - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }; }, }, diff --git a/src/plugins/home/server/capabilities_provider.ts b/src/plugins/home/server/capabilities_provider.ts index 1c662e2301e16c..5e86e0ca54bf79 100644 --- a/src/plugins/home/server/capabilities_provider.ts +++ b/src/plugins/home/server/capabilities_provider.ts @@ -24,6 +24,6 @@ export const capabilitiesProvider = () => ({ visualize: true, console: true, advanced_settings: true, - index_patterns: true, + indexPatterns: true, }, }); diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts index a98cc05a0a80af..6e93d23f8469ca 100644 --- a/src/plugins/index_pattern_management/public/plugin.ts +++ b/src/plugins/index_pattern_management/public/plugin.ts @@ -27,7 +27,7 @@ import { IndexPatternManagementServiceStart, } from './service'; -import { ManagementSetup, ManagementApp, ManagementSectionId } from '../../management/public'; +import { ManagementSetup, ManagementSectionId } from '../../management/public'; export interface IndexPatternManagementSetupDependencies { management: ManagementSetup; @@ -57,7 +57,6 @@ export class IndexPatternManagementPlugin IndexPatternManagementStartDependencies > { private readonly indexPatternManagementService = new IndexPatternManagementService(); - private managementApp?: ManagementApp; constructor(initializerContext: PluginInitializerContext) {} @@ -80,7 +79,7 @@ export class IndexPatternManagementPlugin return pathInApp && `/patterns${pathInApp}`; }); - this.managementApp = kibanaSection.registerApp({ + kibanaSection.registerApp({ id: IPM_APP_ID, title: sectionsHeader, order: 0, @@ -95,10 +94,6 @@ export class IndexPatternManagementPlugin } public start(core: CoreStart, plugins: IndexPatternManagementStartDependencies) { - if (!core.application.capabilities.management.kibana.index_patterns) { - this.managementApp!.disable(); - } - return this.indexPatternManagementService.start(); } diff --git a/src/plugins/management/public/management_sections_service.test.ts b/src/plugins/management/public/management_sections_service.test.ts index 2c5d04883235c7..fd56dd8a6ee274 100644 --- a/src/plugins/management/public/management_sections_service.test.ts +++ b/src/plugins/management/public/management_sections_service.test.ts @@ -27,9 +27,15 @@ describe('ManagementService', () => { managementService = new ManagementSectionsService(); }); + const capabilities = { + navLinks: {}, + catalogue: {}, + management: {}, + }; + test('Provides default sections', () => { managementService.setup(); - const start = managementService.start(); + const start = managementService.start({ capabilities }); expect(start.getAllSections().length).toEqual(6); expect(start.getSection(ManagementSectionId.Ingest)).toBeDefined(); @@ -48,7 +54,7 @@ describe('ManagementService', () => { expect(setup.getSection('test-section')).not.toBeUndefined(); // Start phase: - const start = managementService.start(); + const start = managementService.start({ capabilities }); expect(start.getSectionsEnabled().length).toEqual(7); @@ -56,4 +62,38 @@ describe('ManagementService', () => { expect(start.getSectionsEnabled().length).toEqual(6); }); + + test('Disables items that are not allowed by Capabilities', () => { + // Setup phase: + const setup = managementService.setup(); + const testSection = setup.register({ id: 'test-section', title: 'Test Section' }); + testSection.registerApp({ id: 'test-app-1', title: 'Test App 1', mount: jest.fn() }); + testSection.registerApp({ id: 'test-app-2', title: 'Test App 2', mount: jest.fn() }); + testSection.registerApp({ id: 'test-app-3', title: 'Test App 3', mount: jest.fn() }); + + expect(setup.getSection('test-section')).not.toBeUndefined(); + + // Start phase: + managementService.start({ + capabilities: { + navLinks: {}, + catalogue: {}, + management: { + ['test-section']: { + 'test-app-1': true, + 'test-app-2': false, + // test-app-3 intentionally left undefined. Should be enabled by default + }, + }, + }, + }); + + expect(testSection.apps).toHaveLength(3); + expect(testSection.getAppsEnabled().map((app) => app.id)).toMatchInlineSnapshot(` + Array [ + "test-app-1", + "test-app-3", + ] + `); + }); }); diff --git a/src/plugins/management/public/management_sections_service.ts b/src/plugins/management/public/management_sections_service.ts index 08a87b3e89f2ba..d8d148a9247fff 100644 --- a/src/plugins/management/public/management_sections_service.ts +++ b/src/plugins/management/public/management_sections_service.ts @@ -21,7 +21,12 @@ import { ReactElement } from 'react'; import { ManagementSection, RegisterManagementSectionArgs } from './utils'; import { managementSections } from './components/management_sections'; -import { ManagementSectionId, SectionsServiceSetup, SectionsServiceStart } from './types'; +import { + ManagementSectionId, + SectionsServiceSetup, + SectionsServiceStart, + SectionsServiceStartDeps, +} from './types'; export class ManagementSectionsService { private sections: Map = new Map(); @@ -55,7 +60,18 @@ export class ManagementSectionsService { }; } - start(): SectionsServiceStart { + start({ capabilities }: SectionsServiceStartDeps): SectionsServiceStart { + this.getAllSections().forEach((section) => { + if (capabilities.management.hasOwnProperty(section.id)) { + const sectionCapabilities = capabilities.management[section.id]; + section.apps.forEach((app) => { + if (sectionCapabilities.hasOwnProperty(app.id) && sectionCapabilities[app.id] !== true) { + app.disable(); + } + }); + } + }); + return { getSection: this.getSection, getAllSections: this.getAllSections, diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index 71656d7c0b83ba..dada4636e6add9 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -82,7 +82,7 @@ export class ManagementPlugin implements Plugin ManagementSection; + register: (args: Omit) => ManagementSection; getSection: (sectionId: ManagementSectionId | string) => ManagementSection; } diff --git a/src/plugins/management/server/capabilities_provider.ts b/src/plugins/management/server/capabilities_provider.ts index 9a69749c8233b4..254ac3ed04dd73 100644 --- a/src/plugins/management/server/capabilities_provider.ts +++ b/src/plugins/management/server/capabilities_provider.ts @@ -25,7 +25,7 @@ export const capabilitiesProvider = () => ({ */ kibana: { settings: true, - index_patterns: true, + indexPatterns: true, objects: true, }, }, diff --git a/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts b/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts index 09e08e6ec333b0..e83952e82c953e 100644 --- a/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts +++ b/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts @@ -70,7 +70,7 @@ describe('canViewInApp', () => { let uiCapabilities = createCapabilities({ management: { kibana: { - index_patterns: true, + indexPatterns: true, }, }, }); @@ -81,7 +81,7 @@ describe('canViewInApp', () => { uiCapabilities = createCapabilities({ management: { kibana: { - index_patterns: false, + indexPatterns: false, }, }, }); diff --git a/src/plugins/saved_objects_management/public/lib/in_app_url.ts b/src/plugins/saved_objects_management/public/lib/in_app_url.ts index 82146554afa6ff..0fcf52cba254b5 100644 --- a/src/plugins/saved_objects_management/public/lib/in_app_url.ts +++ b/src/plugins/saved_objects_management/public/lib/in_app_url.ts @@ -30,7 +30,7 @@ export function canViewInApp(uiCapabilities: Capabilities, type: string): boolea case 'index-pattern': case 'index-patterns': case 'indexPatterns': - return uiCapabilities.management.kibana.index_patterns as boolean; + return uiCapabilities.management.kibana.indexPatterns as boolean; case 'dashboard': case 'dashboards': return uiCapabilities.dashboard.show as boolean; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 884f39b97e2335..7d43158ad8878e 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -304,7 +304,7 @@ exports[`SavedObjectsTable should render normally 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "MyIndexPattern*", }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap index 6eb9e36394ee31..15e5cb89b622c6 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap @@ -456,7 +456,7 @@ exports[`Relationships should render searches normally 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/app/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "My Index Pattern", }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap index 92e4e637e0d3fe..56fddc075a50c9 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap @@ -178,7 +178,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "MyIndexPattern*", }, @@ -393,7 +393,7 @@ exports[`Table should render normally 1`] = ` "icon": "indexPatternApp", "inAppUrl": Object { "path": "/management/kibana/indexPatterns/patterns/1", - "uiCapabilitiesPath": "management.kibana.index_patterns", + "uiCapabilitiesPath": "management.kibana.indexPatterns", }, "title": "MyIndexPattern*", }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx index 9277d9b00305b1..2e545b372f781b 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx @@ -77,7 +77,7 @@ describe('Relationships', () => { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, @@ -113,7 +113,7 @@ describe('Relationships', () => { icon: 'indexPatternApp', inAppUrl: { path: '/app/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, title: 'My Index Pattern', }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index b9dad983cb42d4..6b25a1b0c1f256 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -41,7 +41,7 @@ const defaultProps: TableProps = { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, @@ -68,7 +68,7 @@ const defaultProps: TableProps = { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 27f4b06a707cdc..396fdb7f750c0e 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -158,7 +158,7 @@ describe('SavedObjectsTable', () => { editUrl: '#/management/kibana/indexPatterns/patterns/1', inAppUrl: { path: '/management/kibana/indexPatterns/patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, diff --git a/test/api_integration/apis/saved_objects_management/find.ts b/test/api_integration/apis/saved_objects_management/find.ts index 235d789a388df2..b5154d619685aa 100644 --- a/test/api_integration/apis/saved_objects_management/find.ts +++ b/test/api_integration/apis/saved_objects_management/find.ts @@ -287,7 +287,7 @@ export default function ({ getService }: FtrProviderContext) { inAppUrl: { path: '/app/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }); })); diff --git a/test/api_integration/apis/saved_objects_management/relationships.ts b/test/api_integration/apis/saved_objects_management/relationships.ts index 225fc5456e7436..a1ea65645c13fb 100644 --- a/test/api_integration/apis/saved_objects_management/relationships.ts +++ b/test/api_integration/apis/saved_objects_management/relationships.ts @@ -87,7 +87,7 @@ export default function ({ getService }: FtrProviderContext) { inAppUrl: { path: '/app/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, }, @@ -128,7 +128,7 @@ export default function ({ getService }: FtrProviderContext) { inAppUrl: { path: '/app/management/kibana/indexPatterns/patterns/8963ca30-3224-11e8-a572-ffca06da1357', - uiCapabilitiesPath: 'management.kibana.index_patterns', + uiCapabilitiesPath: 'management.kibana.indexPatterns', }, }, relationship: 'child', diff --git a/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap b/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap index 0999063945cb59..fe0a13fe702e55 100644 --- a/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap +++ b/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap @@ -240,11 +240,11 @@ Array [ "kibana", ], "catalogue": Array [ - "index_patterns", + "indexPatterns", ], "management": Object { "kibana": Array [ - "index_patterns", + "indexPatterns", ], }, "savedObject": Object { @@ -265,11 +265,11 @@ Array [ "kibana", ], "catalogue": Array [ - "index_patterns", + "indexPatterns", ], "management": Object { "kibana": Array [ - "index_patterns", + "indexPatterns", ], }, "savedObject": Object { diff --git a/x-pack/plugins/features/server/oss_features.ts b/x-pack/plugins/features/server/oss_features.ts index 1431ca30bc366c..8d40f51df5760f 100644 --- a/x-pack/plugins/features/server/oss_features.ts +++ b/x-pack/plugins/features/server/oss_features.ts @@ -294,16 +294,16 @@ export const buildOSSFeatures = ({ savedObjectTypes, includeTimelion }: BuildOSS order: 1600, icon: 'indexPatternApp', app: ['kibana'], - catalogue: ['index_patterns'], + catalogue: ['indexPatterns'], management: { - kibana: ['index_patterns'], + kibana: ['indexPatterns'], }, privileges: { all: { app: ['kibana'], - catalogue: ['index_patterns'], + catalogue: ['indexPatterns'], management: { - kibana: ['index_patterns'], + kibana: ['indexPatterns'], }, savedObject: { all: ['index-pattern'], @@ -313,9 +313,9 @@ export const buildOSSFeatures = ({ savedObjectTypes, includeTimelion }: BuildOSS }, read: { app: ['kibana'], - catalogue: ['index_patterns'], + catalogue: ['indexPatterns'], management: { - kibana: ['index_patterns'], + kibana: ['indexPatterns'], }, savedObject: { all: [], diff --git a/x-pack/plugins/spaces/public/management/management_service.test.ts b/x-pack/plugins/spaces/public/management/management_service.test.ts index 7d5ac444f5b746..eb543d44ecb4b6 100644 --- a/x-pack/plugins/spaces/public/management/management_service.test.ts +++ b/x-pack/plugins/spaces/public/management/management_service.test.ts @@ -9,7 +9,6 @@ import { coreMock } from 'src/core/public/mocks'; import { spacesManagerMock } from '../spaces_manager/mocks'; import { managementPluginMock } from '../../../../../src/plugins/management/public/mocks'; import { ManagementSection } from 'src/plugins/management/public'; -import { Capabilities } from 'kibana/public'; import { PluginsStart } from '../plugin'; import { CoreSetup } from 'src/core/public'; @@ -58,66 +57,6 @@ describe('ManagementService', () => { }); }); - describe('#start', () => { - it('disables the spaces management page if the user is not authorized', () => { - const mockSpacesManagementPage = { disable: jest.fn() }; - const mockKibanaSection = ({ - registerApp: jest.fn().mockReturnValue(mockSpacesManagementPage), - } as unknown) as ManagementSection; - - const deps = { - management: managementPluginMock.createSetupContract(), - getStartServices: coreMock.createSetup().getStartServices as CoreSetup< - PluginsStart - >['getStartServices'], - spacesManager: spacesManagerMock.create(), - }; - - deps.management.sections.getSection.mockImplementation((id) => { - if (id === 'kibana') return mockKibanaSection; - throw new Error(`unexpected getSection call: ${id}`); - }); - - const service = new ManagementService(); - service.setup(deps); - - const capabilities = ({ spaces: { manage: false } } as unknown) as Capabilities; - service.start({ capabilities }); - - expect(mockKibanaSection.registerApp).toHaveBeenCalledTimes(1); - expect(mockSpacesManagementPage.disable).toHaveBeenCalledTimes(1); - }); - - it('does not disable the spaces management page if the user is authorized', () => { - const mockSpacesManagementPage = { disable: jest.fn() }; - const mockKibanaSection = ({ - registerApp: jest.fn().mockReturnValue(mockSpacesManagementPage), - } as unknown) as ManagementSection; - - const deps = { - management: managementPluginMock.createSetupContract(), - getStartServices: coreMock.createSetup().getStartServices as CoreSetup< - PluginsStart - >['getStartServices'], - spacesManager: spacesManagerMock.create(), - }; - - deps.management.sections.getSection.mockImplementation((id) => { - if (id === 'kibana') return mockKibanaSection; - throw new Error(`unexpected getSection call: ${id}`); - }); - - const service = new ManagementService(); - service.setup(deps); - - const capabilities = ({ spaces: { manage: true } } as unknown) as Capabilities; - service.start({ capabilities }); - - expect(mockKibanaSection.registerApp).toHaveBeenCalledTimes(1); - expect(mockSpacesManagementPage.disable).toHaveBeenCalledTimes(0); - }); - }); - describe('#stop', () => { it('disables the spaces management page', () => { const mockSpacesManagementPage = { disable: jest.fn() }; diff --git a/x-pack/plugins/spaces/public/management/management_service.tsx b/x-pack/plugins/spaces/public/management/management_service.tsx index 297df076368495..4d5a1b32b31a37 100644 --- a/x-pack/plugins/spaces/public/management/management_service.tsx +++ b/x-pack/plugins/spaces/public/management/management_service.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { StartServicesAccessor, Capabilities } from 'src/core/public'; +import { StartServicesAccessor } from 'src/core/public'; import { ManagementSetup, ManagementApp, @@ -22,9 +22,6 @@ interface SetupDeps { securityLicense?: SecurityLicense; } -interface StartDeps { - capabilities: Capabilities; -} export class ManagementService { private registeredSpacesManagementApp?: ManagementApp; @@ -36,12 +33,6 @@ export class ManagementService { ); } - public start({ capabilities }: StartDeps) { - if (!capabilities.spaces.manage) { - this.disableSpacesApp(); - } - } - public stop() { this.disableSpacesApp(); } diff --git a/x-pack/plugins/spaces/public/plugin.tsx b/x-pack/plugins/spaces/public/plugin.tsx index 4097a2e3e05230..8589993a97e024 100644 --- a/x-pack/plugins/spaces/public/plugin.tsx +++ b/x-pack/plugins/spaces/public/plugin.tsx @@ -87,10 +87,6 @@ export class SpacesPlugin implements Plugin this.spacesManager.getActiveSpace(), diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index 2f8291991f3dd6..b7890ccf3db16e 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -138,8 +138,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/57377 - describe.skip('no advanced_settings privileges', () => { + describe('no advanced_settings privileges', function () { before(async () => { await security.role.create('no_advanced_settings_privileges_role', { elasticsearch: { diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index a6d2c13cd2b314..fd8a46d2996898 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -182,8 +182,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it(`doesn't show Index Patterns in management side-nav`, async () => { await PageObjects.settings.navigateTo(); - await testSubjects.existOrFail('kibana'); - await testSubjects.missingOrFail('index_patterns'); + await testSubjects.existOrFail('managementHome', { + timeout: config.get('timeouts.waitFor'), + }); + await testSubjects.missingOrFail('indexPatterns'); }); it(`does not allow navigation to Index Patterns; redirects to management home`, async () => { diff --git a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts index 819d03d8119468..28b8153ea4c2b2 100644 --- a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts +++ b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts @@ -310,19 +310,25 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); describe('listing', () => { - it('redirects to Kibana home', async () => { + it(`doesn't display management section`, async () => { + await PageObjects.settings.navigateTo(); + await testSubjects.existOrFail('managementHome'); // this ensures we've gotten to the management page + await testSubjects.missingOrFail('objects'); + }); + + it(`can't navigate to listing page`, async () => { await PageObjects.common.navigateToUrl('management', 'kibana/objects', { ensureCurrentUrl: false, shouldLoginIfPrompted: false, shouldUseHashForSubUrl: false, }); - await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('homeApp'); + + await testSubjects.existOrFail('managementHome'); }); }); describe('edit visualization', () => { - it('redirects to Kibana home', async () => { + it('redirects to management home', async () => { await PageObjects.common.navigateToUrl( 'management', 'kibana/objects/savedVisualizations/75c3e060-1e7c-11e9-8488-65449e65d0ed', @@ -333,7 +339,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { } ); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('homeApp'); + await testSubjects.existOrFail('managementHome'); }); }); }); From 4b0182ee690cf6c79586777cb5fe795d0b96911e Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 29 Jun 2020 14:49:18 -0400 Subject: [PATCH 10/91] Remove obsolete custom types from super date picker handlers. (#69038) (#69270) Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../components/common/uptime_date_picker.tsx | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/common/uptime_date_picker.tsx b/x-pack/plugins/uptime/public/components/common/uptime_date_picker.tsx index 4254004dba4e0a..1d0dcad73795bd 100644 --- a/x-pack/plugins/uptime/public/components/common/uptime_date_picker.tsx +++ b/x-pack/plugins/uptime/public/components/common/uptime_date_picker.tsx @@ -10,17 +10,6 @@ import { useUrlParams } from '../../hooks'; import { CLIENT_DEFAULTS } from '../../../common/constants'; import { UptimeRefreshContext, UptimeSettingsContext } from '../../contexts'; -// TODO: when EUI exports types for this, this should be replaced -interface SuperDateRangePickerRangeChangedEvent { - start: string; - end: string; -} - -interface SuperDateRangePickerRefreshChangedEvent { - isPaused: boolean; - refreshInterval?: number; -} - export interface CommonlyUsedRange { from: string; to: string; @@ -52,12 +41,12 @@ export const UptimeDatePicker = () => { commonlyUsedRanges={euiCommonlyUsedRanges} isPaused={autorefreshIsPaused} refreshInterval={autorefreshInterval} - onTimeChange={({ start, end }: SuperDateRangePickerRangeChangedEvent) => { + onTimeChange={({ start, end }) => { updateUrl({ dateRangeStart: start, dateRangeEnd: end }); refreshApp(); }} onRefresh={refreshApp} - onRefreshChange={({ isPaused, refreshInterval }: SuperDateRangePickerRefreshChangedEvent) => { + onRefreshChange={({ isPaused, refreshInterval }) => { updateUrl({ autorefreshInterval: refreshInterval === undefined ? autorefreshInterval : refreshInterval, From 16ccf8ed2a4eb723823775e82ba8d062fce451ed Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Mon, 29 Jun 2020 14:52:28 -0400 Subject: [PATCH 11/91] [SECURITY SOLUTION][INGEST] UX update for ingest manager edit/create datasource for endpoint (#70079) (#70213) [security solution][ingest]UX update for ingest manager edit/create datasource for endpoint Co-authored-by: Elastic Machine --- .../components/endpoint/link_to_app.tsx | 25 +++++-- .../configure_datasource.tsx | 68 ++++++++++++------- 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/link_to_app.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/link_to_app.tsx index d6d8859b280b85..a12611ea270357 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/link_to_app.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/link_to_app.tsx @@ -5,10 +5,10 @@ */ import React, { memo, MouseEventHandler } from 'react'; -import { EuiLink, EuiLinkProps } from '@elastic/eui'; +import { EuiLink, EuiLinkProps, EuiButton, EuiButtonProps } from '@elastic/eui'; import { useNavigateToAppEventHandler } from '../../hooks/endpoint/use_navigate_to_app_event_handler'; -type LinkToAppProps = EuiLinkProps & { +type LinkToAppProps = (EuiLinkProps | EuiButtonProps) & { /** the app id - normally the value of the `id` in that plugin's `kibana.json` */ appId: string; /** Any app specific path (route) */ @@ -16,6 +16,8 @@ type LinkToAppProps = EuiLinkProps & { // eslint-disable-next-line @typescript-eslint/no-explicit-any appState?: any; onClick?: MouseEventHandler; + /** Uses an EuiButton element for styling */ + asButton?: boolean; }; /** @@ -23,13 +25,22 @@ type LinkToAppProps = EuiLinkProps & { * a given app without causing a full browser refresh */ export const LinkToApp = memo( - ({ appId, appPath: path, appState: state, onClick, children, ...otherProps }) => { + ({ appId, appPath: path, appState: state, onClick, asButton, children, ...otherProps }) => { const handleOnClick = useNavigateToAppEventHandler(appId, { path, state, onClick }); + return ( - // eslint-disable-next-line @elastic/eui/href-or-on-click - - {children} - + <> + {asButton && asButton === true ? ( + + {children} + + ) : ( + // eslint-disable-next-line @elastic/eui/href-or-on-click + + {children} + + )} + ); } ); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx index 7b4dc36def1335..df1591bf78778a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx @@ -6,8 +6,8 @@ import React, { memo } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiEmptyPrompt, EuiText } from '@elastic/eui'; -import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public'; +import { EuiCallOut, EuiText, EuiTitle, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { LinkToApp } from '../../../../../common/components/endpoint/link_to_app'; import { CustomConfigureDatasourceContent, @@ -21,43 +21,65 @@ import { getPolicyDetailPath } from '../../../../common/routing'; */ export const ConfigureEndpointDatasource = memo( ({ from, datasourceId }: CustomConfigureDatasourceProps) => { - const { services } = useKibana(); let policyUrl = ''; if (from === 'edit' && datasourceId) { policyUrl = getPolicyDetailPath(datasourceId); } return ( - + <> + +

+ +

+
+ + +

{from === 'edit' ? ( - + <> - + + + + + ) : ( )}

- } - /> +
+ ); } ); From 58fee6c5c20028ba43782307d94f59afd48de76c Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Mon, 29 Jun 2020 15:48:43 -0400 Subject: [PATCH 12/91] [Lens] Fix cross cluster bug and optimize existence query (#70132) (#70237) Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../server/routes/existing_fields.test.ts | 15 ++++++++++++++ .../lens/server/routes/existing_fields.ts | 20 +++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/lens/server/routes/existing_fields.test.ts b/x-pack/plugins/lens/server/routes/existing_fields.test.ts index 33541c7206c532..728b78c8e97bc4 100644 --- a/x-pack/plugins/lens/server/routes/existing_fields.test.ts +++ b/x-pack/plugins/lens/server/routes/existing_fields.test.ts @@ -172,4 +172,19 @@ describe('buildFieldList', () => { script: '2+2', }); }); + + it('handles missing mappings', () => { + const fields = buildFieldList(indexPattern, {}, fieldDescriptors); + expect(fields.every((f) => f.isAlias === false)).toEqual(true); + }); + + it('handles empty fieldDescriptors by skipping multi-mappings', () => { + const fields = buildFieldList(indexPattern, mappings, []); + expect(fields.find((f) => f.name === 'baz')).toMatchObject({ + isAlias: false, + isScript: false, + name: 'baz', + path: ['baz'], + }); + }); }); diff --git a/x-pack/plugins/lens/server/routes/existing_fields.ts b/x-pack/plugins/lens/server/routes/existing_fields.ts index 461406591d4329..698680d32ea1b2 100644 --- a/x-pack/plugins/lens/server/routes/existing_fields.ts +++ b/x-pack/plugins/lens/server/routes/existing_fields.ts @@ -41,8 +41,7 @@ export interface Field { script?: string; } -// TODO: Pull this from kibana advanced settings -const metaFields = ['_source', '_id', '_type', '_index', '_score']; +const metaFields = ['_source', '_type']; export async function existingFieldsRoute(setup: CoreSetup) { const router = setup.http.createRouter(); @@ -137,6 +136,18 @@ async function fetchIndexPatternDefinition(indexPatternId: string, context: Requ indexPatternId ); const indexPatternTitle = indexPattern.attributes.title; + + if (indexPatternTitle.includes(':')) { + // Cross cluster search patterns include a colon, and we aren't able to fetch + // mapping information. + return { + indexPattern, + indexPatternTitle, + mappings: {}, + fieldDescriptors: [], + }; + } + // TODO: maybe don't use IndexPatternsFetcher at all, since we're only using it // to look up field values in the resulting documents. We can accomplish the same // using the mappings which we're also fetching here. @@ -166,10 +177,10 @@ async function fetchIndexPatternDefinition(indexPatternId: string, context: Requ */ export function buildFieldList( indexPattern: SavedObject, - mappings: MappingResult, + mappings: MappingResult | {}, fieldDescriptors: FieldDescriptor[] ): Field[] { - const aliasMap = Object.entries(Object.values(mappings)[0].mappings.properties) + const aliasMap = Object.entries(Object.values(mappings)[0]?.mappings.properties ?? {}) .map(([name, v]) => ({ ...v, name })) .filter((f) => f.type === 'alias') .reduce((acc, f) => { @@ -242,6 +253,7 @@ async function fetchIndexPatternStats({ body: { size: SAMPLE_SIZE, query, + sort: timeFieldName && fromDate && toDate ? [{ [timeFieldName]: 'desc' }] : [], // _source is required because we are also providing script fields. _source: '*', script_fields: scriptedFields.reduce((acc, field) => { From e5890d840d27b7e988a962c375b32b03ee8a77d3 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Mon, 29 Jun 2020 23:39:36 +0300 Subject: [PATCH 13/91] fix config update for root context (#70168) (#70226) Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../server/logging/logging_system.test.ts | 43 +++++++++++++++++++ src/core/server/logging/logging_system.ts | 4 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/core/server/logging/logging_system.test.ts b/src/core/server/logging/logging_system.test.ts index f73e40fe320dc3..ac52973081106e 100644 --- a/src/core/server/logging/logging_system.test.ts +++ b/src/core/server/logging/logging_system.test.ts @@ -230,6 +230,49 @@ test('setContextConfig() updates config with relative contexts', () => { ); }); +test('setContextConfig() updates config for a root context', () => { + const testsLogger = system.get('tests'); + const testsChildLogger = system.get('tests', 'child'); + const testsGrandchildLogger = system.get('tests', 'child', 'grandchild'); + + system.upgrade( + config.schema.validate({ + appenders: { default: { kind: 'console', layout: { kind: 'json' } } }, + root: { level: 'info' }, + }) + ); + + system.setContextConfig(['tests', 'child'], { + appenders: new Map([ + [ + 'custom', + { kind: 'console', layout: { kind: 'pattern', pattern: '[%level][%logger] %message' } }, + ], + ]), + loggers: [{ context: '', appenders: ['custom'], level: 'debug' }], + }); + + testsLogger.warn('tests log to default!'); + testsChildLogger.error('tests.child log to custom!'); + testsGrandchildLogger.debug('tests.child.grandchild log to custom!'); + + expect(mockConsoleLog).toHaveBeenCalledTimes(3); + // Parent context is unaffected + expect(JSON.parse(mockConsoleLog.mock.calls[0][0])).toMatchObject({ + context: 'tests', + message: 'tests log to default!', + level: 'WARN', + }); + // Customized contexts + expect(mockConsoleLog.mock.calls[1][0]).toMatchInlineSnapshot( + `"[ERROR][tests.child] tests.child log to custom!"` + ); + + expect(mockConsoleLog.mock.calls[2][0]).toMatchInlineSnapshot( + `"[DEBUG][tests.child.grandchild] tests.child.grandchild log to custom!"` + ); +}); + test('custom context configs are applied on subsequent calls to update()', () => { system.setContextConfig(['tests', 'child'], { appenders: new Map([ diff --git a/src/core/server/logging/logging_system.ts b/src/core/server/logging/logging_system.ts index 0bab9534d2d053..8aadab83bf7163 100644 --- a/src/core/server/logging/logging_system.ts +++ b/src/core/server/logging/logging_system.ts @@ -100,7 +100,9 @@ export class LoggingSystem implements LoggerFactory { // Automatically prepend the base context to the logger sub-contexts loggers: contextConfig.loggers.map((l) => ({ ...l, - context: LoggingConfig.getLoggerContext([context, l.context]), + context: LoggingConfig.getLoggerContext( + l.context.length > 0 ? [context, l.context] : [context] + ), })), }); From da0f779905c0b3c10cbaf2c6e0dffa57a814048a Mon Sep 17 00:00:00 2001 From: Robert Austin Date: Mon, 29 Jun 2020 16:54:11 -0400 Subject: [PATCH 14/91] [Security Solution] Resolver in Timeline (#69728) (#70242) Display Resolver in Security Solution's Timeline. --- .../common/endpoint/schema/resolver.ts | 16 + .../common/endpoint/types.ts | 5 + .../view/alert_details.test.tsx | 96 --- .../view/details/overview/index.tsx | 5 +- .../public/endpoint_alerts/view/resolver.tsx | 39 -- .../isometric_taxi_layout.test.ts.snap} | 154 +++-- .../index.ts} | 8 +- .../isometric_taxi_layout.test.ts | 152 +++++ .../isometric_taxi_layout.ts | 453 ++++++++++++++ .../public/resolver/models/resolver_tree.ts | 125 ++++ .../public/resolver/store/actions.ts | 24 +- .../resolver/store/camera/animation.test.ts | 3 +- .../public/resolver/store/camera/reducer.ts | 3 +- .../public/resolver/store/data/action.ts | 60 +- .../resolver/store/data/graphing.test.ts | 251 -------- .../public/resolver/store/data/index.ts | 8 - .../resolver/store/data/reducer.test.ts | 52 ++ .../public/resolver/store/data/reducer.ts | 81 ++- .../resolver/store/data/selectors.test.ts | 253 ++++++++ .../public/resolver/store/data/selectors.ts | 581 ++++-------------- .../store/data/visible_entities.test.ts | 5 +- .../public/resolver/store/index.ts | 10 +- .../public/resolver/store/middleware.ts | 127 ---- .../public/resolver/store/middleware/index.ts | 68 ++ .../store/middleware/resolver_tree_fetcher.ts | 103 ++++ .../public/resolver/store/reducer.ts | 3 +- .../public/resolver/store/selectors.ts | 22 +- .../public/resolver/types.ts | 60 +- .../public/resolver/view/graph_controls.tsx | 3 +- .../public/resolver/view/index.tsx | 180 +----- .../public/resolver/view/map.tsx | 125 ++++ .../public/resolver/view/panel.tsx | 11 +- .../public/resolver/view/styles.tsx | 60 ++ .../public/resolver/view/use_camera.test.tsx | 34 +- .../resolver/view/use_resolver_dispatch.ts | 2 +- .../view/use_state_syncing_actions.ts | 29 + .../components/graph_overlay/index.tsx | 17 +- .../timelines/components/timeline/styles.tsx | 2 +- .../server/endpoint/routes/resolver.ts | 14 + .../server/endpoint/routes/resolver/entity.ts | 86 +++ 40 files changed, 2002 insertions(+), 1328 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/endpoint_alerts/view/alert_details.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/endpoint_alerts/view/resolver.tsx rename x-pack/plugins/security_solution/public/resolver/{store/data/__snapshots__/graphing.test.ts.snap => models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap} (83%) rename x-pack/plugins/security_solution/public/resolver/models/{indexed_process_tree.ts => indexed_process_tree/index.ts} (95%) create mode 100644 x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.test.ts create mode 100644 x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts create mode 100644 x-pack/plugins/security_solution/public/resolver/models/resolver_tree.ts delete mode 100644 x-pack/plugins/security_solution/public/resolver/store/data/graphing.test.ts delete mode 100644 x-pack/plugins/security_solution/public/resolver/store/data/index.ts create mode 100644 x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.ts create mode 100644 x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts delete mode 100644 x-pack/plugins/security_solution/public/resolver/store/middleware.ts create mode 100644 x-pack/plugins/security_solution/public/resolver/store/middleware/index.ts create mode 100644 x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts create mode 100644 x-pack/plugins/security_solution/public/resolver/view/map.tsx create mode 100644 x-pack/plugins/security_solution/public/resolver/view/styles.tsx create mode 100644 x-pack/plugins/security_solution/public/resolver/view/use_state_syncing_actions.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity.ts diff --git a/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts b/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts index f5c3fd519c9c5a..398e2710b32531 100644 --- a/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts +++ b/x-pack/plugins/security_solution/common/endpoint/schema/resolver.ts @@ -71,3 +71,19 @@ export const validateChildren = { legacyEndpointID: schema.maybe(schema.string()), }), }; + +/** + * Used to validate GET requests for 'entities' + */ +export const validateEntities = { + query: schema.object({ + /** + * Return the process entities related to the document w/ the matching `_id`. + */ + _id: schema.string(), + /** + * Indices to search in. + */ + indices: schema.arrayOf(schema.string()), + }), +}; diff --git a/x-pack/plugins/security_solution/common/endpoint/types.ts b/x-pack/plugins/security_solution/common/endpoint/types.ts index 42f5f4b220da95..f71af34722dcf3 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types.ts @@ -511,6 +511,11 @@ export interface EndpointEvent { export type ResolverEvent = EndpointEvent | LegacyEndpointEvent; +/** + * The response body for the resolver '/entity' index API + */ +export type ResolverEntityIndex = Array<{ entity_id: string }>; + /** * Takes a @kbn/config-schema 'schema' type and returns a type that represents valid inputs. * Similar to `TypeOf`, but allows strings as input for `schema.number()` (which is inline diff --git a/x-pack/plugins/security_solution/public/endpoint_alerts/view/alert_details.test.tsx b/x-pack/plugins/security_solution/public/endpoint_alerts/view/alert_details.test.tsx deleted file mode 100644 index de939ad4f54c65..00000000000000 --- a/x-pack/plugins/security_solution/public/endpoint_alerts/view/alert_details.test.tsx +++ /dev/null @@ -1,96 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as reactTestingLibrary from '@testing-library/react'; -import { MemoryHistory } from 'history'; -import { Store } from 'redux'; - -import { mockAlertDetailsResult } from '../store/mock_alert_result_list'; -import { alertPageTestRender } from './test_helpers/render_alert_page'; -import { AppAction } from '../../common/store/actions'; -import { State } from '../../common/store/types'; - -describe('when the alert details flyout is open', () => { - let render: () => reactTestingLibrary.RenderResult; - let history: MemoryHistory; - let store: Store; - - beforeEach(async () => { - // Creates the render elements for the tests to use - ({ render, history, store } = alertPageTestRender()); - }); - describe('when the alerts details flyout is open', () => { - beforeEach(() => { - reactTestingLibrary.act(() => { - history.push({ - search: '?selected_alert=1', - }); - }); - }); - describe('when the data loads', () => { - beforeEach(() => { - reactTestingLibrary.act(() => { - const action: AppAction = { - type: 'serverReturnedAlertDetailsData', - payload: mockAlertDetailsResult(), - }; - store.dispatch(action); - }); - }); - it('should display take action button', async () => { - await render().findByTestId('alertDetailTakeActionDropdownButton'); - }); - describe('when the user clicks the take action button on the flyout', () => { - let renderResult: reactTestingLibrary.RenderResult; - beforeEach(async () => { - renderResult = render(); - const takeActionButton = await renderResult.findByTestId( - 'alertDetailTakeActionDropdownButton' - ); - if (takeActionButton) { - reactTestingLibrary.fireEvent.click(takeActionButton); - } - }); - it('should display the correct fields in the dropdown', async () => { - await renderResult.findByTestId('alertDetailTakeActionCloseAlertButton'); - await renderResult.findByTestId('alertDetailTakeActionWhitelistButton'); - }); - }); - describe('when the user navigates to the resolver tab', () => { - beforeEach(() => { - reactTestingLibrary.act(() => { - history.push({ - ...history.location, - search: '?selected_alert=1&active_details_tab=overviewResolver', - }); - }); - }); - it('should show the resolver view', async () => { - const resolver = await render().findByTestId('alertResolver'); - expect(resolver).toBeInTheDocument(); - }); - }); - describe('when the user navigates to the overview tab', () => { - let renderResult: reactTestingLibrary.RenderResult; - beforeEach(async () => { - renderResult = render(); - const overviewTab = await renderResult.findByTestId('overviewMetadata'); - if (overviewTab) { - reactTestingLibrary.fireEvent.click(overviewTab); - } - }); - it('should render all accordion panels', async () => { - await renderResult.findAllByTestId('alertDetailsAlertAccordion'); - await renderResult.findAllByTestId('alertDetailsHostAccordion'); - await renderResult.findAllByTestId('alertDetailsFileAccordion'); - await renderResult.findAllByTestId('alertDetailsHashAccordion'); - await renderResult.findAllByTestId('alertDetailsSourceProcessAccordion'); - await renderResult.findAllByTestId('alertDetailsSourceProcessTokenAccordion'); - }); - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx b/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx index 86c8e00c0a56fc..60adea44ab0ab1 100644 --- a/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx +++ b/x-pack/plugins/security_solution/public/endpoint_alerts/view/details/overview/index.tsx @@ -20,8 +20,6 @@ import { useAlertListSelector } from '../../hooks/use_alerts_selector'; import * as selectors from '../../../store/selectors'; import { MetadataPanel } from './metadata_panel'; import { FormattedDate } from '../../formatted_date'; -import { AlertDetailResolver } from '../../resolver'; -import { ResolverEvent } from '../../../../../common/endpoint/types'; import { TakeActionDropdown } from './take_action_dropdown'; import { urlFromQueryParams } from '../../url_from_query_params'; @@ -65,12 +63,11 @@ const AlertDetailsOverviewComponent = memo(() => { content: ( <> - ), }, ]; - }, [alertDetailsData]); + }, []); /* eslint-disable-next-line react-hooks/rules-of-hooks */ const activeTab = useMemo( diff --git a/x-pack/plugins/security_solution/public/endpoint_alerts/view/resolver.tsx b/x-pack/plugins/security_solution/public/endpoint_alerts/view/resolver.tsx deleted file mode 100644 index 92213a8bd3925b..00000000000000 --- a/x-pack/plugins/security_solution/public/endpoint_alerts/view/resolver.tsx +++ /dev/null @@ -1,39 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import styled from 'styled-components'; -import { Provider } from 'react-redux'; -import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; -import { ResolverEvent } from '../../../common/endpoint/types'; -import { StartServices } from '../../types'; -import { storeFactory } from '../../resolver/store'; -import { Resolver } from '../../resolver/view'; - -const AlertDetailResolverComponents = React.memo( - ({ className, selectedEvent }: { className?: string; selectedEvent?: ResolverEvent }) => { - const context = useKibana(); - const { store } = storeFactory(context); - - return ( -
- - - -
- ); - } -); - -AlertDetailResolverComponents.displayName = 'AlertDetailResolver'; - -export const AlertDetailResolver = styled(AlertDetailResolverComponents)` - height: 100%; - width: 100%; - display: flex; - flex-grow: 1; - min-height: calc(100vh - 505px); -`; diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/__snapshots__/graphing.test.ts.snap b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap similarity index 83% rename from x-pack/plugins/security_solution/public/resolver/store/data/__snapshots__/graphing.test.ts.snap rename to x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap index 8525ccd7b1548d..74efb41c4c595f 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/__snapshots__/graphing.test.ts.snap +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap @@ -56,12 +56,12 @@ Object { }, "points": Array [ Array [ - 0, - -229.43553924069099, + -98.99494936611666, + -286.5902999056318, ], Array [ - 395.9797974644666, - -0.8164965809277259, + 593.9696961966999, + 113.49302474895391, ], ], }, @@ -71,12 +71,12 @@ Object { }, "points": Array [ Array [ - 0, - -229.43553924069099, + -98.99494936611666, + -286.5902999056318, ], Array [ - 197.9898987322333, - -343.7450605705726, + 98.99494936611666, + -400.8998212355134, ], ], }, @@ -86,12 +86,27 @@ Object { }, "points": Array [ Array [ - 395.9797974644666, - -0.8164965809277259, + 296.98484809834997, + -57.97125724586854, ], + Array [ + 494.9747468305833, + -172.28077857575016, + ], + ], + }, + Object { + "metadata": Object { + "uniqueId": "", + }, + "points": Array [ Array [ 593.9696961966999, - -115.12601791080935, + 113.49302474895391, + ], + Array [ + 791.9595949289333, + -0.8164965809277259, ], ], }, @@ -101,12 +116,12 @@ Object { }, "points": Array [ Array [ - 197.9898987322333, - -343.7450605705726, + 98.99494936611666, + -400.8998212355134, ], Array [ - 395.9797974644666, - -458.05458190045425, + 296.98484809834997, + -515.2093425653951, ], ], }, @@ -116,12 +131,12 @@ Object { }, "points": Array [ Array [ - 296.98484809834997, - -515.2093425653951, + 197.9898987322333, + -572.3641032303359, ], Array [ - 494.9747468305833, - -400.8998212355134, + 395.9797974644666, + -458.05458190045425, ], ], }, @@ -131,12 +146,12 @@ Object { }, "points": Array [ Array [ - 296.98484809834997, - -515.2093425653951, + 197.9898987322333, + -572.3641032303359, ], Array [ - 494.9747468305833, - -629.5188638952767, + 395.9797974644666, + -686.6736245602175, ], ], }, @@ -146,12 +161,12 @@ Object { }, "points": Array [ Array [ - 494.9747468305833, - -400.8998212355134, + 395.9797974644666, + -458.05458190045425, ], Array [ - 692.9646455628166, - -515.2093425653951, + 593.9696961966999, + -572.3641032303359, ], ], }, @@ -161,12 +176,12 @@ Object { }, "points": Array [ Array [ - 593.9696961966999, - -115.12601791080935, + 494.9747468305833, + -172.28077857575016, ], Array [ - 791.9595949289333, - -229.43553924069096, + 692.9646455628166, + -286.5902999056318, ], ], }, @@ -176,12 +191,12 @@ Object { }, "points": Array [ Array [ - 692.9646455628166, - -286.5902999056318, + 593.9696961966999, + -343.7450605705726, ], Array [ - 890.9545442950499, - -172.28077857575016, + 791.9595949289333, + -229.43553924069096, ], ], }, @@ -191,12 +206,12 @@ Object { }, "points": Array [ Array [ - 692.9646455628166, - -286.5902999056318, + 593.9696961966999, + -343.7450605705726, ], Array [ - 890.9545442950499, - -400.89982123551346, + 791.9595949289333, + -458.05458190045425, ], ], }, @@ -206,12 +221,12 @@ Object { }, "points": Array [ Array [ - 890.9545442950499, - -172.28077857575016, + 791.9595949289333, + -229.43553924069096, ], Array [ - 1088.9444430272833, - -286.5902999056318, + 989.9494936611666, + -343.7450605705726, ], ], }, @@ -221,12 +236,12 @@ Object { }, "points": Array [ Array [ - 1088.9444430272833, - -286.5902999056318, + 989.9494936611666, + -343.7450605705726, ], Array [ - 1286.9343417595164, - -400.89982123551346, + 1187.9393923933999, + -458.05458190045425, ], ], }, @@ -263,8 +278,8 @@ Object { "unique_ppid": 0, }, } => Array [ - 197.9898987322333, - -343.7450605705726, + 98.99494936611666, + -400.8998212355134, ], Object { "@timestamp": 1582233383000, @@ -280,8 +295,25 @@ Object { "unique_ppid": 0, }, } => Array [ - 593.9696961966999, - -115.12601791080935, + 494.9747468305833, + -172.28077857575016, + ], + Object { + "@timestamp": 1582233383000, + "agent": Object { + "id": "", + "type": "", + "version": "", + }, + "endgame": Object { + "event_subtype_full": "termination_event", + "event_type_full": "process_event", + "unique_pid": 8, + "unique_ppid": 0, + }, + } => Array [ + 791.9595949289333, + -0.8164965809277259, ], Object { "@timestamp": 1582233383000, @@ -297,8 +329,8 @@ Object { "unique_ppid": 1, }, } => Array [ - 494.9747468305833, - -629.5188638952767, + 395.9797974644666, + -686.6736245602175, ], Object { "@timestamp": 1582233383000, @@ -314,8 +346,8 @@ Object { "unique_ppid": 1, }, } => Array [ - 692.9646455628166, - -515.2093425653951, + 593.9696961966999, + -572.3641032303359, ], Object { "@timestamp": 1582233383000, @@ -331,8 +363,8 @@ Object { "unique_ppid": 2, }, } => Array [ - 890.9545442950499, - -400.89982123551346, + 791.9595949289333, + -458.05458190045425, ], Object { "@timestamp": 1582233383000, @@ -348,8 +380,8 @@ Object { "unique_ppid": 2, }, } => Array [ - 1088.9444430272833, - -286.5902999056318, + 989.9494936611666, + -343.7450605705726, ], Object { "@timestamp": 1582233383000, @@ -365,8 +397,8 @@ Object { "unique_ppid": 6, }, } => Array [ - 1286.9343417595164, - -400.89982123551346, + 1187.9393923933999, + -458.05458190045425, ], }, } diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree.ts b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts similarity index 95% rename from x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree.ts rename to x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts index db00ca2d599687..b322de0f345263 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree.ts +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { uniquePidForProcess, uniqueParentPidForProcess } from './process_event'; -import { IndexedProcessTree, AdjacentProcessMap } from '../types'; -import { ResolverEvent } from '../../../common/endpoint/types'; -import { levelOrder as baseLevelOrder } from '../lib/tree_sequencers'; +import { uniquePidForProcess, uniqueParentPidForProcess } from '../process_event'; +import { IndexedProcessTree, AdjacentProcessMap } from '../../types'; +import { ResolverEvent } from '../../../../common/endpoint/types'; +import { levelOrder as baseLevelOrder } from '../../lib/tree_sequencers'; /** * Create a new IndexedProcessTree from an array of ProcessEvents diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.test.ts b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.test.ts new file mode 100644 index 00000000000000..72d8e878465f74 --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.test.ts @@ -0,0 +1,152 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { IsometricTaxiLayout } from '../../types'; +import { LegacyEndpointEvent } from '../../../../common/endpoint/types'; +import { isometricTaxiLayout } from './isometric_taxi_layout'; +import { mockProcessEvent } from '../../models/process_event_test_helpers'; +import { factory } from './index'; + +describe('resolver graph layout', () => { + let processA: LegacyEndpointEvent; + let processB: LegacyEndpointEvent; + let processC: LegacyEndpointEvent; + let processD: LegacyEndpointEvent; + let processE: LegacyEndpointEvent; + let processF: LegacyEndpointEvent; + let processG: LegacyEndpointEvent; + let processH: LegacyEndpointEvent; + let processI: LegacyEndpointEvent; + let events: LegacyEndpointEvent[]; + let layout: () => IsometricTaxiLayout; + + beforeEach(() => { + /* + * A + * ____|____ + * | | + * B C + * ___|___ ___|___ + * | | | | + * D E F G + * | + * H + * + */ + processA = mockProcessEvent({ + endgame: { + process_name: '', + event_type_full: 'process_event', + event_subtype_full: 'creation_event', + unique_pid: 0, + }, + }); + processB = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'already_running', + unique_pid: 1, + unique_ppid: 0, + }, + }); + processC = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'creation_event', + unique_pid: 2, + unique_ppid: 0, + }, + }); + processD = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'creation_event', + unique_pid: 3, + unique_ppid: 1, + }, + }); + processE = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'creation_event', + unique_pid: 4, + unique_ppid: 1, + }, + }); + processF = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'creation_event', + unique_pid: 5, + unique_ppid: 2, + }, + }); + processG = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'creation_event', + unique_pid: 6, + unique_ppid: 2, + }, + }); + processH = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'creation_event', + unique_pid: 7, + unique_ppid: 6, + }, + }); + processI = mockProcessEvent({ + endgame: { + event_type_full: 'process_event', + event_subtype_full: 'termination_event', + unique_pid: 8, + unique_ppid: 0, + }, + }); + layout = () => isometricTaxiLayout(factory(events)); + events = []; + }); + describe('when rendering no nodes', () => { + it('renders right', () => { + expect(layout()).toMatchSnapshot(); + }); + }); + describe('when rendering one node', () => { + beforeEach(() => { + events = [processA]; + }); + it('renders right', () => { + expect(layout()).toMatchSnapshot(); + }); + }); + describe('when rendering two nodes, one being the parent of the other', () => { + beforeEach(() => { + events = [processA, processB]; + }); + it('renders right', () => { + expect(layout()).toMatchSnapshot(); + }); + }); + describe('when rendering two forks, and one fork has an extra long tine', () => { + beforeEach(() => { + events = [ + processA, + processB, + processC, + processD, + processE, + processF, + processG, + processH, + processI, + ]; + }); + it('renders right', () => { + expect(layout()).toMatchSnapshot(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts new file mode 100644 index 00000000000000..9095f061ee73a7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/isometric_taxi_layout.ts @@ -0,0 +1,453 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import * as vector2 from '../../lib/vector2'; +import { + IndexedProcessTree, + Vector2, + EdgeLineSegment, + ProcessWidths, + ProcessPositions, + EdgeLineMetadata, + ProcessWithWidthMetadata, + Matrix3, + IsometricTaxiLayout, +} from '../../types'; +import * as event from '../../../../common/endpoint/models/event'; +import { ResolverEvent } from '../../../../common/endpoint/types'; +import * as model from './index'; +import { getFriendlyElapsedTime as elapsedTime } from '../../lib/date'; + +/** + * Graph the process tree + */ +export function isometricTaxiLayout(indexedProcessTree: IndexedProcessTree): IsometricTaxiLayout { + /** + * Walk the tree in reverse level order, calculating the 'width' of subtrees. + */ + const widths = widthsOfProcessSubtrees(indexedProcessTree); + + /** + * Walk the tree in level order. Using the precalculated widths, calculate the position of nodes. + * Nodes are positioned relative to their parents and preceding siblings. + */ + const positions = processPositions(indexedProcessTree, widths); + + /** + * With the widths and positions precalculated, we calculate edge line segments (arrays of vector2s) + * which connect them in a 'pitchfork' design. + */ + const edgeLineSegments = processEdgeLineSegments(indexedProcessTree, widths, positions); + + /** + * Transform the positions of nodes and edges so they seem like they are on an isometric grid. + */ + const transformedEdgeLineSegments: EdgeLineSegment[] = []; + const transformedPositions = new Map(); + + for (const [processEvent, position] of positions) { + transformedPositions.set( + processEvent, + vector2.applyMatrix3(position, isometricTransformMatrix) + ); + } + + for (const edgeLineSegment of edgeLineSegments) { + const { + points: [startPoint, endPoint], + } = edgeLineSegment; + + const transformedSegment: EdgeLineSegment = { + ...edgeLineSegment, + points: [ + vector2.applyMatrix3(startPoint, isometricTransformMatrix), + vector2.applyMatrix3(endPoint, isometricTransformMatrix), + ], + }; + + transformedEdgeLineSegments.push(transformedSegment); + } + + return { + processNodePositions: transformedPositions, + edgeLineSegments: transformedEdgeLineSegments, + }; +} + +/** + * In laying out the graph, we precalculate the 'width' of each subtree. The 'width' of the subtree is determined by its + * descedants and the rule that each process node must be at least 1 unit apart. Enforcing that all nodes are at least + * 1 unit apart on the x axis makes it easy to prevent the UI components from overlapping. There will always be space. + * + * Example widths: + * + * A and B each have a width of 0 + * + * A + * | + * B + * + * A has a width of 1. B and C have a width of 0. + * B and C must be 1 unit apart, so the A subtree has a width of 1. + * + * A + * ____|____ + * | | + * B C + * + * + * D, E, F, G, H all have a width of 0. + * B has a width of 1 since D->E must be 1 unit apart. + * Similarly, C has a width of 1 since F->G must be 1 unit apart. + * A has width of 3, since B has a width of 1, and C has a width of 1, and E->F must be at least + * 1 unit apart. + * A + * ____|____ + * | | + * B C + * ___|___ ___|___ + * | | | | + * D E F G + * | + * H + * + */ +function widthsOfProcessSubtrees(indexedProcessTree: IndexedProcessTree): ProcessWidths { + const widths = new Map(); + + if (model.size(indexedProcessTree) === 0) { + return widths; + } + + const processesInReverseLevelOrder = [...model.levelOrder(indexedProcessTree)].reverse(); + + for (const process of processesInReverseLevelOrder) { + const children = model.children(indexedProcessTree, process); + + const sumOfWidthOfChildren = function sumOfWidthOfChildren() { + return children.reduce(function sum(currentValue, child) { + /** + * `widths.get` will always return a number in this case. + * This loop sequences a tree in reverse level order. Width values are set for each node. + * Therefore a parent can always find a width for its children, since all of its children + * will have been handled already. + */ + return currentValue + widths.get(child)!; + }, 0); + }; + + const width = sumOfWidthOfChildren() + Math.max(0, children.length - 1) * distanceBetweenNodes; + widths.set(process, width); + } + + return widths; +} + +function processEdgeLineSegments( + indexedProcessTree: IndexedProcessTree, + widths: ProcessWidths, + positions: ProcessPositions +): EdgeLineSegment[] { + const edgeLineSegments: EdgeLineSegment[] = []; + for (const metadata of levelOrderWithWidths(indexedProcessTree, widths)) { + const edgeLineMetadata: EdgeLineMetadata = { uniqueId: '' }; + /** + * We only handle children, drawing lines back to their parents. The root has no parent, so we skip it + */ + if (metadata.parent === null) { + // eslint-disable-next-line no-continue + continue; + } + const { process, parent, parentWidth } = metadata; + const position = positions.get(process); + const parentPosition = positions.get(parent); + const parentId = event.entityId(parent); + const processEntityId = event.entityId(process); + const edgeLineId = parentId ? parentId + processEntityId : parentId; + + if (position === undefined || parentPosition === undefined) { + /** + * All positions have been precalculated, so if any are missing, it's an error. This will never happen. + */ + throw new Error(); + } + + const parentTime = event.eventTimestamp(parent); + const processTime = event.eventTimestamp(process); + if (parentTime && processTime) { + edgeLineMetadata.elapsedTime = elapsedTime(parentTime, processTime) ?? undefined; + } + edgeLineMetadata.uniqueId = edgeLineId; + + /** + * The point halfway between the parent and child on the y axis, we sometimes have a hard angle here in the edge line + */ + const midwayY = parentPosition[1] + (position[1] - parentPosition[1]) / 2; + + /** + * When drawing edge lines between a parent and children (when there are multiple children) we draw a pitchfork type + * design. The 'midway' line, runs along the x axis and joins all the children with a single descendant line from the parent. + * See the ascii diagram below. The underscore characters would be the midway line. + * + * A + * ____|____ + * | | + * B C + */ + const lineFromProcessToMidwayLine: EdgeLineSegment = { + points: [[position[0], midwayY], position], + metadata: edgeLineMetadata, + }; + + const siblings = model.children(indexedProcessTree, parent); + const isFirstChild = process === siblings[0]; + + if (metadata.isOnlyChild) { + // add a single line segment directly from parent to child. We don't do the 'pitchfork' in this case. + edgeLineSegments.push({ points: [parentPosition, position], metadata: edgeLineMetadata }); + } else if (isFirstChild) { + /** + * If the parent has multiple children, we draw the 'midway' line, and the line from the + * parent to the midway line, while handling the first child. + * + * Consider A the parent, and B the first child. We would draw somemthing like what's in the below diagram. The line from the + * midway line to C would be drawn when we handle C. + * + * A + * ____|____ + * | + * B C + */ + const { firstChildWidth, lastChildWidth } = metadata; + + const lineFromParentToMidwayLine: EdgeLineSegment = { + points: [parentPosition, [parentPosition[0], midwayY]], + metadata: { uniqueId: `parentToMid${edgeLineId}` }, + }; + + const widthOfMidline = parentWidth - firstChildWidth / 2 - lastChildWidth / 2; + + const minX = parentWidth / -2 + firstChildWidth / 2; + const maxX = minX + widthOfMidline; + + const midwayLine: EdgeLineSegment = { + points: [ + [ + // Position line relative to the parent's x component + parentPosition[0] + minX, + midwayY, + ], + [ + // Position line relative to the parent's x component + parentPosition[0] + maxX, + midwayY, + ], + ], + metadata: { uniqueId: `midway${edgeLineId}` }, + }; + + edgeLineSegments.push( + /* line from parent to midway line */ + lineFromParentToMidwayLine, + midwayLine, + lineFromProcessToMidwayLine + ); + } else { + // If this isn't the first child, it must have siblings (the first of which drew the midway line and line + // from the parent to the midway line + edgeLineSegments.push(lineFromProcessToMidwayLine); + } + } + return edgeLineSegments; +} + +function processPositions( + indexedProcessTree: IndexedProcessTree, + widths: ProcessWidths +): ProcessPositions { + const positions = new Map(); + /** + * This algorithm iterates the tree in level order. It keeps counters that are reset for each parent. + * By keeping track of the last parent node, we can know when we are dealing with a new set of siblings and + * reset the counters. + */ + let lastProcessedParentNode: ResolverEvent | undefined; + /** + * Nodes are positioned relative to their siblings. We walk this in level order, so we handle + * children left -> right. + * + * The width of preceding siblings is used to left align the node. + * The number of preceding siblings is important because each sibling must be 1 unit apart + * on the x axis. + */ + let numberOfPrecedingSiblings = 0; + let runningWidthOfPrecedingSiblings = 0; + + for (const metadata of levelOrderWithWidths(indexedProcessTree, widths)) { + // Handle root node + if (metadata.parent === null) { + const { process } = metadata; + /** + * Place the root node at (0, 0) for now. + */ + positions.set(process, [0, 0]); + } else { + const { process, parent, isOnlyChild, width, parentWidth } = metadata; + + // Reinit counters when parent changes + if (lastProcessedParentNode !== parent) { + numberOfPrecedingSiblings = 0; + runningWidthOfPrecedingSiblings = 0; + + // keep track of this so we know when to reinitialize + lastProcessedParentNode = parent; + } + + const parentPosition = positions.get(parent); + + if (parentPosition === undefined) { + /** + * Since this algorithm populates the `positions` map in level order, + * the parent node will have been processed already and the parent position + * will always be available. + * + * This will never happen. + */ + throw new Error(); + } + + /** + * The x 'offset' is added to the x value of the parent to determine the position of the node. + * We add `parentWidth / -2` in order to align the left side of this node with the left side of its parent. + * We add `numberOfPrecedingSiblings * distanceBetweenNodes` in order to keep each node 1 apart on the x axis. + * We add `runningWidthOfPrecedingSiblings` so that we don't overlap with our preceding siblings. We stack em up. + * We add `width / 2` so that we center the node horizontally (in case it has non-0 width.) + */ + const xOffset = + parentWidth / -2 + + numberOfPrecedingSiblings * distanceBetweenNodes + + runningWidthOfPrecedingSiblings + + width / 2; + + /** + * The y axis gains `-distanceBetweenNodes` as we move down the screen 1 unit at a time. + */ + let yDistanceBetweenNodes = -distanceBetweenNodes; + + if (!isOnlyChild) { + // Make space on leaves to show elapsed time + yDistanceBetweenNodes *= 2; + } + + const position = vector2.add([xOffset, yDistanceBetweenNodes], parentPosition); + + positions.set(process, position); + + numberOfPrecedingSiblings += 1; + runningWidthOfPrecedingSiblings += width; + } + } + + return positions; +} +function* levelOrderWithWidths( + tree: IndexedProcessTree, + widths: ProcessWidths +): Iterable { + for (const process of model.levelOrder(tree)) { + const parent = model.parent(tree, process); + const width = widths.get(process); + + if (width === undefined) { + /** + * All widths have been precalcluated, so this will not happen. + */ + throw new Error(); + } + + /** If the parent is undefined, we are processing the root. */ + if (parent === undefined) { + yield { + process, + width, + parent: null, + parentWidth: null, + isOnlyChild: null, + firstChildWidth: null, + lastChildWidth: null, + }; + } else { + const parentWidth = widths.get(parent); + + if (parentWidth === undefined) { + /** + * All widths have been precalcluated, so this will not happen. + */ + throw new Error(); + } + + const metadata: Partial = { + process, + width, + parent, + parentWidth, + }; + + const siblings = model.children(tree, parent); + if (siblings.length === 1) { + metadata.isOnlyChild = true; + metadata.lastChildWidth = width; + metadata.firstChildWidth = width; + } else { + const firstChildWidth = widths.get(siblings[0]); + const lastChildWidth = widths.get(siblings[siblings.length - 1]); + if (firstChildWidth === undefined || lastChildWidth === undefined) { + /** + * All widths have been precalcluated, so this will not happen. + */ + throw new Error(); + } + metadata.isOnlyChild = false; + metadata.firstChildWidth = firstChildWidth; + metadata.lastChildWidth = lastChildWidth; + } + + yield metadata as ProcessWithWidthMetadata; + } + } +} + +/** + * An isometric projection is a method for representing three dimensional objects in 2 dimensions. + * More information about isometric projections can be found here https://en.wikipedia.org/wiki/Isometric_projection. + * In our case, we obtain the isometric projection by rotating the objects 45 degrees in the plane of the screen + * and arctan(1/sqrt(2)) (~35.3 degrees) through the horizontal axis. + * + * A rotation by 45 degrees in the plane of the screen is given by: + * [ sqrt(2)/2 -sqrt(2)/2 0 + * sqrt(2)/2 sqrt(2)/2 0 + * 0 0 1] + * + * A rotation by arctan(1/sqrt(2)) through the horizantal axis is given by: + * [ 1 0 0 + * 0 sqrt(3)/3 -sqrt(6)/3 + * 0 sqrt(6)/3 sqrt(3)/3] + * + * We can multiply both of these matrices to get the final transformation below. + */ +/* prettier-ignore */ +const isometricTransformMatrix: Matrix3 = [ + Math.sqrt(2) / 2, -(Math.sqrt(2) / 2), 0, + Math.sqrt(6) / 6, Math.sqrt(6) / 6, -(Math.sqrt(6) / 3), + 0, 0, 1, +] + +const unit = 140; +const distanceBetweenNodesInUnits = 2; + +/** + * The distance in pixels (at scale 1) between nodes. Change this to space out nodes more + */ +const distanceBetweenNodes = distanceBetweenNodesInUnits * unit; diff --git a/x-pack/plugins/security_solution/public/resolver/models/resolver_tree.ts b/x-pack/plugins/security_solution/public/resolver/models/resolver_tree.ts new file mode 100644 index 00000000000000..cf32988a856b2c --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/models/resolver_tree.ts @@ -0,0 +1,125 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + ResolverTree, + ResolverEvent, + ResolverNodeStats, + ResolverLifecycleNode, +} from '../../../common/endpoint/types'; +import { uniquePidForProcess } from './process_event'; + +/** + * ResolverTree is a type returned by the server. + */ + +/** + * This returns the 'LifecycleNodes' of the tree. These nodes have + * the entityID and stats for a process. Used by `relatedEventsStats`. + */ +function lifecycleNodes(tree: ResolverTree): ResolverLifecycleNode[] { + return [tree, ...tree.children.childNodes, ...tree.ancestry.ancestors]; +} + +/** + * All the process events + */ +export function lifecycleEvents(tree: ResolverTree) { + const events: ResolverEvent[] = [...tree.lifecycle]; + for (const { lifecycle } of tree.children.childNodes) { + events.push(...lifecycle); + } + for (const { lifecycle } of tree.ancestry.ancestors) { + events.push(...lifecycle); + } + return events; +} + +/** + * This returns a map of entity_ids to stats for the related events and alerts. + */ +export function relatedEventsStats(tree: ResolverTree): Map { + const nodeStats: Map = new Map(); + for (const node of lifecycleNodes(tree)) { + if (node.stats) { + nodeStats.set(node.entityID, node.stats); + } + } + return nodeStats; +} + +/** + * ResolverTree type is returned by the server. It organizes events into a complex structure. The + * organization of events in the tree is done to associate metadata with the events. The client does not + * use this metadata. Instead, the client flattens the tree into an array. Therefore we can safely + * make a malformed ResolverTree for the purposes of the tests, so long as it is flattened in a predictable way. + */ +export function mock({ + events, + cursors = { childrenNextChild: null, ancestryNextAncestor: null }, +}: { + /** + * Events represented by the ResolverTree. + */ + events: ResolverEvent[]; + /** + * Optionally provide cursors for the 'children' and 'ancestry' edges. + */ + cursors?: { childrenNextChild: string | null; ancestryNextAncestor: string | null }; +}): ResolverTree | null { + if (events.length === 0) { + return null; + } + const first = events[0]; + return { + entityID: uniquePidForProcess(first), + // Required + children: { + childNodes: [], + nextChild: cursors.childrenNextChild, + }, + // Required + relatedEvents: { + events: [], + nextEvent: null, + }, + // Required + relatedAlerts: { + alerts: [], + nextAlert: null, + }, + // Required + ancestry: { + ancestors: [], + nextAncestor: cursors.ancestryNextAncestor, + }, + // Normally, this would have only certain events, but for testing purposes, it will have all events, since + // the position of events in the ResolverTree is irrelevant. + lifecycle: events, + // Required + stats: { + events: { + total: 0, + byCategory: {}, + }, + totalAlerts: 0, + }, + }; +} + +/** + * `true` if there are more children to fetch. + */ +export function hasMoreChildren(resolverTree: ResolverTree): boolean { + return resolverTree.children.nextChild !== null; +} + +/** + * `true` if there are more ancestors to fetch. + */ +export function hasMoreAncestors(resolverTree: ResolverTree): boolean { + return resolverTree.ancestry.nextAncestor !== null; +} diff --git a/x-pack/plugins/security_solution/public/resolver/store/actions.ts b/x-pack/plugins/security_solution/public/resolver/store/actions.ts index ae302d0e609116..5292cbb6445dce 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/actions.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/actions.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { CameraAction } from './camera'; -import { DataAction } from './data'; import { ResolverEvent } from '../../../common/endpoint/types'; +import { DataAction } from './data/action'; /** * When the user wants to bring a process node front-and-center on the map. @@ -53,26 +53,6 @@ interface AppDetectedNewIdFromQueryParams { }; } -/** - * Used when the alert list selects an alert and the flyout shows resolver. - */ -interface UserChangedSelectedEvent { - readonly type: 'userChangedSelectedEvent'; - readonly payload: { - /** - * Optional because they could have unselected the event. - */ - readonly selectedEvent?: ResolverEvent; - }; -} - -/** - * Triggered by middleware when the data for resolver needs to be loaded. Used to set state in redux to 'loading'. - */ -interface AppRequestedResolverData { - readonly type: 'appRequestedResolverData'; -} - /** * The action dispatched when the app requests related event data for one * subject (whose entity_id should be included as `payload`) @@ -145,8 +125,6 @@ export type ResolverAction = | CameraAction | DataAction | UserBroughtProcessIntoView - | UserChangedSelectedEvent - | AppRequestedResolverData | UserFocusedOnResolverNode | UserSelectedResolverNode | UserRequestedRelatedEventData diff --git a/x-pack/plugins/security_solution/public/resolver/store/camera/animation.test.ts b/x-pack/plugins/security_solution/public/resolver/store/camera/animation.test.ts index 92cbd95bcf5a86..50f4ffd0137dc1 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/camera/animation.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/camera/animation.test.ts @@ -6,10 +6,11 @@ import { createStore, Store, Reducer } from 'redux'; import { cameraReducer, cameraInitialState } from './reducer'; -import { CameraState, Vector2, ResolverAction } from '../../types'; +import { CameraState, Vector2 } from '../../types'; import * as selectors from './selectors'; import { animatePanning } from './methods'; import { lerp } from '../../lib/math'; +import { ResolverAction } from '../actions'; type TestAction = | ResolverAction diff --git a/x-pack/plugins/security_solution/public/resolver/store/camera/reducer.ts b/x-pack/plugins/security_solution/public/resolver/store/camera/reducer.ts index 0f6ae1b7d904a8..f64864edab5b33 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/camera/reducer.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/camera/reducer.ts @@ -11,8 +11,9 @@ import * as vector2 from '../../lib/vector2'; import * as selectors from './selectors'; import { clamp } from '../../lib/math'; -import { CameraState, ResolverAction, Vector2 } from '../../types'; +import { CameraState, Vector2 } from '../../types'; import { scaleToZoom } from './scale_to_zoom'; +import { ResolverAction } from '../actions'; /** * Used in tests. diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/action.ts b/x-pack/plugins/security_solution/public/resolver/store/data/action.ts index 3de6f08f5e0154..0d2a6936b4873d 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/action.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/action.ts @@ -4,23 +4,44 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - ResolverEvent, - ResolverNodeStats, - ResolverRelatedEvents, -} from '../../../../common/endpoint/types'; +import { ResolverRelatedEvents, ResolverTree } from '../../../../common/endpoint/types'; interface ServerReturnedResolverData { readonly type: 'serverReturnedResolverData'; readonly payload: { - readonly events: Readonly; - readonly stats: Readonly>; - readonly lineageLimits: { readonly children: string | null; readonly ancestors: string | null }; + /** + * The result of fetching data + */ + result: ResolverTree; + /** + * The database document ID that was used to fetch the resolver tree + */ + databaseDocumentID: string; }; } +interface AppRequestedResolverData { + readonly type: 'appRequestedResolverData'; + /** + * entity ID used to make the request. + */ + readonly payload: string; +} + interface ServerFailedToReturnResolverData { readonly type: 'serverFailedToReturnResolverData'; + /** + * entity ID used to make the failed request + */ + readonly payload: string; +} + +interface AppAbortedResolverDataRequest { + readonly type: 'appAbortedResolverDataRequest'; + /** + * entity ID used to make the aborted request + */ + readonly payload: string; } /** @@ -39,8 +60,29 @@ interface ServerReturnedRelatedEventData { readonly payload: ResolverRelatedEvents; } +/** + * Used by `useStateSyncingActions` hook. + * This is dispatched when external sources provide new parameters for Resolver. + * When the component receives a new 'databaseDocumentID' prop, this is fired. + */ +interface AppReceivedNewExternalProperties { + type: 'appReceivedNewExternalProperties'; + /** + * Defines the externally provided properties that Resolver acknowledges. + */ + payload: { + /** + * the `_id` of an ES document. This defines the origin of the Resolver graph. + */ + databaseDocumentID?: string; + }; +} + export type DataAction = | ServerReturnedResolverData | ServerFailedToReturnResolverData | ServerFailedToReturnRelatedEventData - | ServerReturnedRelatedEventData; + | ServerReturnedRelatedEventData + | AppReceivedNewExternalProperties + | AppRequestedResolverData + | AppAbortedResolverDataRequest; diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/graphing.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/graphing.test.ts deleted file mode 100644 index 163846e0414dbf..00000000000000 --- a/x-pack/plugins/security_solution/public/resolver/store/data/graphing.test.ts +++ /dev/null @@ -1,251 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Store, createStore } from 'redux'; -import { DataAction } from './action'; -import { dataReducer } from './reducer'; -import { DataState } from '../../types'; -import { LegacyEndpointEvent, ResolverEvent } from '../../../../common/endpoint/types'; -import { - graphableProcesses, - processNodePositionsAndEdgeLineSegments, - limitsReached, -} from './selectors'; -import { mockProcessEvent } from '../../models/process_event_test_helpers'; -import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; - -describe('resolver graph layout', () => { - let processA: LegacyEndpointEvent; - let processB: LegacyEndpointEvent; - let processC: LegacyEndpointEvent; - let processD: LegacyEndpointEvent; - let processE: LegacyEndpointEvent; - let processF: LegacyEndpointEvent; - let processG: LegacyEndpointEvent; - let processH: LegacyEndpointEvent; - let processI: LegacyEndpointEvent; - let store: Store; - - beforeEach(() => { - /* - * A - * ____|____ - * | | - * B C - * ___|___ ___|___ - * | | | | - * D E F G - * | - * H - * - */ - processA = mockProcessEvent({ - endgame: { - process_name: '', - event_type_full: 'process_event', - event_subtype_full: 'creation_event', - unique_pid: 0, - }, - }); - processB = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'already_running', - unique_pid: 1, - unique_ppid: 0, - }, - }); - processC = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'creation_event', - unique_pid: 2, - unique_ppid: 0, - }, - }); - processD = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'creation_event', - unique_pid: 3, - unique_ppid: 1, - }, - }); - processE = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'creation_event', - unique_pid: 4, - unique_ppid: 1, - }, - }); - processF = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'creation_event', - unique_pid: 5, - unique_ppid: 2, - }, - }); - processG = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'creation_event', - unique_pid: 6, - unique_ppid: 2, - }, - }); - processH = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'creation_event', - unique_pid: 7, - unique_ppid: 6, - }, - }); - processI = mockProcessEvent({ - endgame: { - event_type_full: 'process_event', - event_subtype_full: 'termination_event', - unique_pid: 8, - unique_ppid: 0, - }, - }); - store = createStore(dataReducer, undefined); - }); - describe('when rendering no nodes', () => { - beforeEach(() => { - const events: ResolverEvent[] = []; - const action: DataAction = { - type: 'serverReturnedResolverData', - payload: { events, stats: new Map(), lineageLimits: { children: null, ancestors: null } }, - }; - store.dispatch(action); - }); - it('the graphableProcesses list should only include nothing', () => { - const actual = graphableProcesses(store.getState()); - expect(actual).toEqual([]); - }); - it('renders right', () => { - expect(processNodePositionsAndEdgeLineSegments(store.getState())).toMatchSnapshot(); - }); - }); - describe('when rendering one node', () => { - beforeEach(() => { - const events = [processA]; - const action: DataAction = { - type: 'serverReturnedResolverData', - payload: { events, stats: new Map(), lineageLimits: { children: null, ancestors: null } }, - }; - store.dispatch(action); - }); - it('the graphableProcesses list should only include nothing', () => { - const actual = graphableProcesses(store.getState()); - expect(actual).toEqual([processA]); - }); - it('renders right', () => { - expect(processNodePositionsAndEdgeLineSegments(store.getState())).toMatchSnapshot(); - }); - }); - describe('when rendering two nodes, one being the parent of the other', () => { - beforeEach(() => { - const events = [processA, processB]; - const action: DataAction = { - type: 'serverReturnedResolverData', - payload: { events, stats: new Map(), lineageLimits: { children: null, ancestors: null } }, - }; - store.dispatch(action); - }); - it('the graphableProcesses list should only include nothing', () => { - const actual = graphableProcesses(store.getState()); - expect(actual).toEqual([processA, processB]); - }); - it('renders right', () => { - expect(processNodePositionsAndEdgeLineSegments(store.getState())).toMatchSnapshot(); - }); - }); - describe('when rendering two forks, and one fork has an extra long tine', () => { - beforeEach(() => { - const events = [ - processA, - processB, - processC, - processD, - processE, - processF, - processG, - processH, - processI, - ]; - const action: DataAction = { - type: 'serverReturnedResolverData', - payload: { events, stats: new Map(), lineageLimits: { children: null, ancestors: null } }, - }; - store.dispatch(action); - }); - it("the graphableProcesses list should only include events with 'processCreated' an 'processRan' eventType", () => { - const actual = graphableProcesses(store.getState()); - expect(actual).toEqual([ - processA, - processB, - processC, - processD, - processE, - processF, - processG, - processH, - ]); - }); - it('renders right', () => { - expect(processNodePositionsAndEdgeLineSegments(store.getState())).toMatchSnapshot(); - }); - }); -}); - -describe('resolver graph with too much lineage', () => { - let generator: EndpointDocGenerator; - let store: Store; - let allEvents: ResolverEvent[]; - let childrenCursor: string; - let ancestorCursor: string; - - beforeEach(() => { - generator = new EndpointDocGenerator('seed'); - allEvents = generator.generateTree({ ancestors: 1, generations: 2, children: 2 }).allEvents; - childrenCursor = 'aValidChildursor'; - ancestorCursor = 'aValidAncestorCursor'; - store = createStore(dataReducer, undefined); - }); - - describe('should select from state properly', () => { - it('should indicate there are too many ancestors', () => { - const action: DataAction = { - type: 'serverReturnedResolverData', - payload: { - events: allEvents, - stats: new Map(), - lineageLimits: { children: childrenCursor, ancestors: ancestorCursor }, - }, - }; - store.dispatch(action); - const { ancestors } = limitsReached(store.getState()); - expect(ancestors).toEqual(true); - }); - it('should indicate there are too many children', () => { - const action: DataAction = { - type: 'serverReturnedResolverData', - payload: { - events: allEvents, - stats: new Map(), - lineageLimits: { children: childrenCursor, ancestors: ancestorCursor }, - }, - }; - store.dispatch(action); - const { children } = limitsReached(store.getState()); - expect(children).toEqual(true); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/index.ts b/x-pack/plugins/security_solution/public/resolver/store/data/index.ts deleted file mode 100644 index 8db57c5d9681f4..00000000000000 --- a/x-pack/plugins/security_solution/public/resolver/store/data/index.ts +++ /dev/null @@ -1,8 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { dataReducer } from './reducer'; -export { DataAction } from './action'; diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.ts new file mode 100644 index 00000000000000..e6cd72ae0924be --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.test.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; + * you may not use this file except in compliance with the Elastic License. + */ +import { createStore, Store } from 'redux'; +import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; +import { mock as mockResolverTree } from '../../models/resolver_tree'; +import { dataReducer } from './reducer'; +import * as selectors from './selectors'; +import { DataState } from '../../types'; +import { DataAction } from './action'; + +/** + * Test the data reducer and selector. + */ +describe('Resolver Data Middleware', () => { + let store: Store; + + beforeEach(() => { + store = createStore(dataReducer, undefined); + }); + + describe('when data was received and the ancestry and children edges had cursors', () => { + beforeEach(() => { + const generator = new EndpointDocGenerator('seed'); + const tree = mockResolverTree({ + events: generator.generateTree({ ancestors: 1, generations: 2, children: 2 }).allEvents, + cursors: { + childrenNextChild: 'aValidChildursor', + ancestryNextAncestor: 'aValidAncestorCursor', + }, + }); + if (tree) { + const action: DataAction = { + type: 'serverReturnedResolverData', + payload: { + result: tree, + databaseDocumentID: '', + }, + }; + store.dispatch(action); + } + }); + it('should indicate there are additional ancestor', () => { + expect(selectors.hasMoreAncestors(store.getState())).toBe(true); + }); + it('should indicate there are additional children', () => { + expect(selectors.hasMoreChildren(store.getState())).toBe(true); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts index a36d43b70b87d7..45bf214005872c 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/reducer.ts @@ -5,41 +5,72 @@ */ import { Reducer } from 'redux'; -import { DataState, ResolverAction } from '../../types'; +import { DataState } from '../../types'; +import { ResolverAction } from '../actions'; -function initialState(): DataState { - return { - results: [], - relatedEventsStats: new Map(), - relatedEvents: new Map(), - relatedEventsReady: new Map(), - lineageLimits: { children: null, ancestors: null }, - isLoading: false, - hasError: false, - }; -} +const initialState: DataState = { + relatedEventsStats: new Map(), + relatedEvents: new Map(), + relatedEventsReady: new Map(), +}; -export const dataReducer: Reducer = (state = initialState(), action) => { - if (action.type === 'serverReturnedResolverData') { - return { +export const dataReducer: Reducer = (state = initialState, action) => { + if (action.type === 'appReceivedNewExternalProperties') { + const nextState: DataState = { ...state, - results: action.payload.events, - relatedEventsStats: action.payload.stats, - lineageLimits: action.payload.lineageLimits, - isLoading: false, - hasError: false, + databaseDocumentID: action.payload.databaseDocumentID, }; + return nextState; } else if (action.type === 'appRequestedResolverData') { + // keep track of what we're requesting, this way we know when to request and when not to. return { ...state, - isLoading: true, - hasError: false, + pendingRequestDatabaseDocumentID: action.payload, }; - } else if (action.type === 'serverFailedToReturnResolverData') { - return { + } else if (action.type === 'appAbortedResolverDataRequest') { + if (action.payload === state.pendingRequestDatabaseDocumentID) { + // the request we were awaiting was aborted + return { + ...state, + pendingRequestDatabaseDocumentID: undefined, + }; + } else { + return state; + } + } else if (action.type === 'serverReturnedResolverData') { + /** Only handle this if we are expecting a response */ + const nextState: DataState = { ...state, - hasError: true, + + /** + * Store the last received data, as well as the databaseDocumentID it relates to. + */ + lastResponse: { + result: action.payload.result, + databaseDocumentID: action.payload.databaseDocumentID, + successful: true, + }, + + // This assumes that if we just received something, there is no longer a pending request. + // This cannot model multiple in-flight requests + pendingRequestDatabaseDocumentID: undefined, }; + return nextState; + } else if (action.type === 'serverFailedToReturnResolverData') { + /** Only handle this if we are expecting a response */ + if (state.pendingRequestDatabaseDocumentID !== undefined) { + const nextState: DataState = { + ...state, + pendingRequestDatabaseDocumentID: undefined, + lastResponse: { + databaseDocumentID: state.pendingRequestDatabaseDocumentID, + successful: false, + }, + }; + return nextState; + } else { + return state; + } } else if ( action.type === 'userRequestedRelatedEventData' || action.type === 'appDetectedMissingEventData' diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts new file mode 100644 index 00000000000000..630dfe555548f3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.test.ts @@ -0,0 +1,253 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as selectors from './selectors'; +import { DataState } from '../../types'; +import { dataReducer } from './reducer'; +import { DataAction } from './action'; +import { createStore } from 'redux'; +describe('data state', () => { + let actions: DataAction[] = []; + + /** + * Get state, given an ordered collection of actions. + */ + const state: () => DataState = () => { + const store = createStore(dataReducer); + for (const action of actions) { + store.dispatch(action); + } + return store.getState(); + }; + + /** + * This prints out all of the properties of the data state. + * This way we can see the overall behavior of the selector easily. + */ + const viewAsAString = (dataState: DataState) => { + return [ + ['is loading', selectors.isLoading(dataState)], + ['has an error', selectors.hasError(dataState)], + ['has more children', selectors.hasMoreChildren(dataState)], + ['has more ancestors', selectors.hasMoreAncestors(dataState)], + ['document to fetch', selectors.databaseDocumentIDToFetch(dataState)], + ['requires a pending request to be aborted', selectors.databaseDocumentIDToAbort(dataState)], + ] + .map(([message, value]) => `${message}: ${JSON.stringify(value)}`) + .join('\n'); + }; + + it(`shouldn't initially be loading, or have an error, or have more children or ancestors, or have a document to fetch, or have a pending request that needs to be aborted.`, () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: false + has an error: false + has more children: false + has more ancestors: false + document to fetch: null + requires a pending request to be aborted: null" + `); + }); + + describe('when there is a databaseDocumentID but no pending request', () => { + const databaseDocumentID = 'databaseDocumentID'; + beforeEach(() => { + actions = [ + { + type: 'appReceivedNewExternalProperties', + payload: { databaseDocumentID }, + }, + ]; + }); + it('should need to fetch the databaseDocumentID', () => { + expect(selectors.databaseDocumentIDToFetch(state())).toBe(databaseDocumentID); + }); + it('should not be loading, have an error, have more children or ancestors, or have a pending request that needs to be aborted.', () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: false + has an error: false + has more children: false + has more ancestors: false + document to fetch: \\"databaseDocumentID\\" + requires a pending request to be aborted: null" + `); + }); + }); + describe('when there is a pending request but no databaseDocumentID', () => { + const databaseDocumentID = 'databaseDocumentID'; + beforeEach(() => { + actions = [ + { + type: 'appRequestedResolverData', + payload: databaseDocumentID, + }, + ]; + }); + it('should be loading', () => { + expect(selectors.isLoading(state())).toBe(true); + }); + it('should have a request to abort', () => { + expect(selectors.databaseDocumentIDToAbort(state())).toBe(databaseDocumentID); + }); + it('should not have an error, more children, more ancestors, or a document to fetch.', () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: true + has an error: false + has more children: false + has more ancestors: false + document to fetch: null + requires a pending request to be aborted: \\"databaseDocumentID\\"" + `); + }); + }); + describe('when there is a pending request for the current databaseDocumentID', () => { + const databaseDocumentID = 'databaseDocumentID'; + beforeEach(() => { + actions = [ + { + type: 'appReceivedNewExternalProperties', + payload: { databaseDocumentID }, + }, + { + type: 'appRequestedResolverData', + payload: databaseDocumentID, + }, + ]; + }); + it('should be loading', () => { + expect(selectors.isLoading(state())).toBe(true); + }); + it('should not have a request to abort', () => { + expect(selectors.databaseDocumentIDToAbort(state())).toBe(null); + }); + it('should not have an error, more children, more ancestors, a document to begin fetching, or a pending request that should be aborted.', () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: true + has an error: false + has more children: false + has more ancestors: false + document to fetch: null + requires a pending request to be aborted: null" + `); + }); + describe('when the pending request fails', () => { + beforeEach(() => { + actions.push({ + type: 'serverFailedToReturnResolverData', + payload: databaseDocumentID, + }); + }); + it('should not be loading', () => { + expect(selectors.isLoading(state())).toBe(false); + }); + it('should have an error', () => { + expect(selectors.hasError(state())).toBe(true); + }); + it('should not be loading, have more children, have more ancestors, have a document to fetch, or have a pending request that needs to be aborted.', () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: false + has an error: true + has more children: false + has more ancestors: false + document to fetch: null + requires a pending request to be aborted: null" + `); + }); + }); + }); + describe('when there is a pending request for a different databaseDocumentID than the current one', () => { + const firstDatabaseDocumentID = 'first databaseDocumentID'; + const secondDatabaseDocumentID = 'second databaseDocumentID'; + beforeEach(() => { + actions = [ + // receive the document ID, this would cause the middleware to starts the request + { + type: 'appReceivedNewExternalProperties', + payload: { databaseDocumentID: firstDatabaseDocumentID }, + }, + // this happens when the middleware starts the request + { + type: 'appRequestedResolverData', + payload: firstDatabaseDocumentID, + }, + // receive a different databaseDocumentID. this should cause the middleware to abort the existing request and start a new one + { + type: 'appReceivedNewExternalProperties', + payload: { databaseDocumentID: secondDatabaseDocumentID }, + }, + ]; + }); + it('should be loading', () => { + expect(selectors.isLoading(state())).toBe(true); + }); + it('should need to fetch the second databaseDocumentID', () => { + expect(selectors.databaseDocumentIDToFetch(state())).toBe(secondDatabaseDocumentID); + }); + it('should need to abort the request for the databaseDocumentID', () => { + expect(selectors.databaseDocumentIDToFetch(state())).toBe(secondDatabaseDocumentID); + }); + it('should not have an error, more children, or more ancestors.', () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: true + has an error: false + has more children: false + has more ancestors: false + document to fetch: \\"second databaseDocumentID\\" + requires a pending request to be aborted: \\"first databaseDocumentID\\"" + `); + }); + describe('and when the old request was aborted', () => { + beforeEach(() => { + actions.push({ + type: 'appAbortedResolverDataRequest', + payload: firstDatabaseDocumentID, + }); + }); + it('should not require a pending request to be aborted', () => { + expect(selectors.databaseDocumentIDToAbort(state())).toBe(null); + }); + it('should have a document to fetch', () => { + expect(selectors.databaseDocumentIDToFetch(state())).toBe(secondDatabaseDocumentID); + }); + it('should not be loading', () => { + expect(selectors.isLoading(state())).toBe(false); + }); + it('should not have an error, more children, or more ancestors.', () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: false + has an error: false + has more children: false + has more ancestors: false + document to fetch: \\"second databaseDocumentID\\" + requires a pending request to be aborted: null" + `); + }); + describe('and when the next request starts', () => { + beforeEach(() => { + actions.push({ + type: 'appRequestedResolverData', + payload: secondDatabaseDocumentID, + }); + }); + it('should not have a document ID to fetch', () => { + expect(selectors.databaseDocumentIDToFetch(state())).toBe(null); + }); + it('should be loading', () => { + expect(selectors.isLoading(state())).toBe(true); + }); + it('should not have an error, more children, more ancestors, or a pending request that needs to be aborted.', () => { + expect(viewAsAString(state())).toMatchInlineSnapshot(` + "is loading: true + has an error: false + has more children: false + has more ancestors: false + document to fetch: null + requires a pending request to be aborted: null" + `); + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts index 5654f1ca423f33..f15cb6427dccf9 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/selectors.ts @@ -8,449 +8,92 @@ import rbush from 'rbush'; import { createSelector } from 'reselect'; import { DataState, - IndexedProcessTree, - ProcessWidths, - ProcessPositions, - EdgeLineSegment, - ProcessWithWidthMetadata, - Matrix3, AdjacentProcessMap, Vector2, - EdgeLineMetadata, IndexedEntity, IndexedEdgeLineSegment, IndexedProcessNode, AABB, VisibleEntites, } from '../../types'; -import { ResolverEvent } from '../../../../common/endpoint/types'; -import * as event from '../../../../common/endpoint/models/event'; -import { add as vector2Add, applyMatrix3 } from '../../lib/vector2'; import { isGraphableProcess, isTerminatedProcess, uniquePidForProcess, } from '../../models/process_event'; -import { - factory as indexedProcessTreeFactory, - children as indexedProcessTreeChildren, - parent as indexedProcessTreeParent, - size, - levelOrder, -} from '../../models/indexed_process_tree'; -import { getFriendlyElapsedTime } from '../../lib/date'; +import { factory as indexedProcessTreeFactory } from '../../models/indexed_process_tree'; import { isEqual } from '../../lib/aabb'; -const unit = 140; -const distanceBetweenNodesInUnits = 2; - -export function isLoading(state: DataState) { - return state.isLoading; -} - -export function hasError(state: DataState) { - return state.hasError; -} +import { + ResolverEvent, + ResolverTree, + ResolverNodeStats, + ResolverRelatedEvents, +} from '../../../../common/endpoint/types'; +import * as resolverTreeModel from '../../models/resolver_tree'; +import { isometricTaxiLayout } from '../../models/indexed_process_tree/isometric_taxi_layout'; /** - * An isometric projection is a method for representing three dimensional objects in 2 dimensions. - * More information about isometric projections can be found here https://en.wikipedia.org/wiki/Isometric_projection. - * In our case, we obtain the isometric projection by rotating the objects 45 degrees in the plane of the screen - * and arctan(1/sqrt(2)) (~35.3 degrees) through the horizontal axis. - * - * A rotation by 45 degrees in the plane of the screen is given by: - * [ sqrt(2)/2 -sqrt(2)/2 0 - * sqrt(2)/2 sqrt(2)/2 0 - * 0 0 1] - * - * A rotation by arctan(1/sqrt(2)) through the horizantal axis is given by: - * [ 1 0 0 - * 0 sqrt(3)/3 -sqrt(6)/3 - * 0 sqrt(6)/3 sqrt(3)/3] - * - * We can multiply both of these matrices to get the final transformation below. + * If there is currently a request. */ -/* prettier-ignore */ -const isometricTransformMatrix: Matrix3 = [ - Math.sqrt(2) / 2, -(Math.sqrt(2) / 2), 0, - Math.sqrt(6) / 6, Math.sqrt(6) / 6, -(Math.sqrt(6) / 3), - 0, 0, 1, -] +export function isLoading(state: DataState): boolean { + return state.pendingRequestDatabaseDocumentID !== undefined; +} /** - * The distance in pixels (at scale 1) between nodes. Change this to space out nodes more + * If a request was made and it threw an error or returned a failure response code. */ -const distanceBetweenNodes = distanceBetweenNodesInUnits * unit; +export function hasError(state: DataState): boolean { + if (state.lastResponse && state.lastResponse.successful === false) { + return true; + } else { + return false; + } +} /** - * Process events that will be graphed. + * The last ResolverTree we received, if any. It may be stale (it might not be for the same databaseDocumentID that + * we're currently interested in. */ -export const graphableProcesses = createSelector( - ({ results }: DataState) => results, - function (results: DataState['results']) { - return results.filter(isGraphableProcess); +const resolverTree = (state: DataState): ResolverTree | undefined => { + if (state.lastResponse && state.lastResponse.successful) { + return state.lastResponse.result; + } else { + return undefined; } -); +}; /** * Process events that will be displayed as terminated. */ -export const terminatedProcesses = createSelector( - ({ results }: DataState) => results, - function (results: DataState['results']) { - return new Set( - results.filter(isTerminatedProcess).map((terminatedEvent) => { +export const terminatedProcesses = createSelector(resolverTree, function (tree?: ResolverTree) { + if (!tree) { + return new Set(); + } + return new Set( + resolverTreeModel + .lifecycleEvents(tree) + .filter(isTerminatedProcess) + .map((terminatedEvent) => { return uniquePidForProcess(terminatedEvent); }) - ); - } -); + ); +}); /** - * In laying out the graph, we precalculate the 'width' of each subtree. The 'width' of the subtree is determined by its - * descedants and the rule that each process node must be at least 1 unit apart. Enforcing that all nodes are at least - * 1 unit apart on the x axis makes it easy to prevent the UI components from overlapping. There will always be space. - * - * Example widths: - * - * A and B each have a width of 0 - * - * A - * | - * B - * - * A has a width of 1. B and C have a width of 0. - * B and C must be 1 unit apart, so the A subtree has a width of 1. - * - * A - * ____|____ - * | | - * B C - * - * - * D, E, F, G, H all have a width of 0. - * B has a width of 1 since D->E must be 1 unit apart. - * Similarly, C has a width of 1 since F->G must be 1 unit apart. - * A has width of 3, since B has a width of 1, and C has a width of 1, and E->F must be at least - * 1 unit apart. - * A - * ____|____ - * | | - * B C - * ___|___ ___|___ - * | | | | - * D E F G - * | - * H - * + * Process events that will be graphed. */ -function widthsOfProcessSubtrees(indexedProcessTree: IndexedProcessTree): ProcessWidths { - const widths = new Map(); - - if (size(indexedProcessTree) === 0) { - return widths; - } - - const processesInReverseLevelOrder = [...levelOrder(indexedProcessTree)].reverse(); - - for (const process of processesInReverseLevelOrder) { - const children = indexedProcessTreeChildren(indexedProcessTree, process); - - const sumOfWidthOfChildren = function sumOfWidthOfChildren() { - return children.reduce(function sum(currentValue, child) { - /** - * `widths.get` will always return a number in this case. - * This loop sequences a tree in reverse level order. Width values are set for each node. - * Therefore a parent can always find a width for its children, since all of its children - * will have been handled already. - */ - return currentValue + widths.get(child)!; - }, 0); - }; - - const width = sumOfWidthOfChildren() + Math.max(0, children.length - 1) * distanceBetweenNodes; - widths.set(process, width); - } - - return widths; -} - -function processEdgeLineSegments( - indexedProcessTree: IndexedProcessTree, - widths: ProcessWidths, - positions: ProcessPositions -): EdgeLineSegment[] { - const edgeLineSegments: EdgeLineSegment[] = []; - for (const metadata of levelOrderWithWidths(indexedProcessTree, widths)) { - const edgeLineMetadata: EdgeLineMetadata = { uniqueId: '' }; - /** - * We only handle children, drawing lines back to their parents. The root has no parent, so we skip it - */ - if (metadata.parent === null) { - // eslint-disable-next-line no-continue - continue; - } - const { process, parent, parentWidth } = metadata; - const position = positions.get(process); - const parentPosition = positions.get(parent); - const parentId = event.entityId(parent); - const processEntityId = event.entityId(process); - const edgeLineId = parentId ? parentId + processEntityId : parentId; - - if (position === undefined || parentPosition === undefined) { - /** - * All positions have been precalculated, so if any are missing, it's an error. This will never happen. - */ - throw new Error(); - } - - const parentTime = event.eventTimestamp(parent); - const processTime = event.eventTimestamp(process); - if (parentTime && processTime) { - const elapsedTime = getFriendlyElapsedTime(parentTime, processTime); - if (elapsedTime) edgeLineMetadata.elapsedTime = elapsedTime; - } - edgeLineMetadata.uniqueId = edgeLineId; - - /** - * The point halfway between the parent and child on the y axis, we sometimes have a hard angle here in the edge line - */ - const midwayY = parentPosition[1] + (position[1] - parentPosition[1]) / 2; - - /** - * When drawing edge lines between a parent and children (when there are multiple children) we draw a pitchfork type - * design. The 'midway' line, runs along the x axis and joins all the children with a single descendant line from the parent. - * See the ascii diagram below. The underscore characters would be the midway line. - * - * A - * ____|____ - * | | - * B C - */ - const lineFromProcessToMidwayLine: EdgeLineSegment = { - points: [[position[0], midwayY], position], - metadata: edgeLineMetadata, - }; - - const siblings = indexedProcessTreeChildren(indexedProcessTree, parent); - const isFirstChild = process === siblings[0]; - - if (metadata.isOnlyChild) { - // add a single line segment directly from parent to child. We don't do the 'pitchfork' in this case. - edgeLineSegments.push({ points: [parentPosition, position], metadata: edgeLineMetadata }); - } else if (isFirstChild) { - /** - * If the parent has multiple children, we draw the 'midway' line, and the line from the - * parent to the midway line, while handling the first child. - * - * Consider A the parent, and B the first child. We would draw somemthing like what's in the below diagram. The line from the - * midway line to C would be drawn when we handle C. - * - * A - * ____|____ - * | - * B C - */ - const { firstChildWidth, lastChildWidth } = metadata; - - const lineFromParentToMidwayLine: EdgeLineSegment = { - points: [parentPosition, [parentPosition[0], midwayY]], - metadata: { uniqueId: `parentToMid${edgeLineId}` }, - }; - - const widthOfMidline = parentWidth - firstChildWidth / 2 - lastChildWidth / 2; - - const minX = parentWidth / -2 + firstChildWidth / 2; - const maxX = minX + widthOfMidline; - - const midwayLine: EdgeLineSegment = { - points: [ - [ - // Position line relative to the parent's x component - parentPosition[0] + minX, - midwayY, - ], - [ - // Position line relative to the parent's x component - parentPosition[0] + maxX, - midwayY, - ], - ], - metadata: { uniqueId: `midway${edgeLineId}` }, - }; - - edgeLineSegments.push( - /* line from parent to midway line */ - lineFromParentToMidwayLine, - midwayLine, - lineFromProcessToMidwayLine - ); - } else { - // If this isn't the first child, it must have siblings (the first of which drew the midway line and line - // from the parent to the midway line - edgeLineSegments.push(lineFromProcessToMidwayLine); - } - } - return edgeLineSegments; -} - -function* levelOrderWithWidths( - tree: IndexedProcessTree, - widths: ProcessWidths -): Iterable { - for (const process of levelOrder(tree)) { - const parent = indexedProcessTreeParent(tree, process); - const width = widths.get(process); - - if (width === undefined) { - /** - * All widths have been precalcluated, so this will not happen. - */ - throw new Error(); - } - - /** If the parent is undefined, we are processing the root. */ - if (parent === undefined) { - yield { - process, - width, - parent: null, - parentWidth: null, - isOnlyChild: null, - firstChildWidth: null, - lastChildWidth: null, - }; - } else { - const parentWidth = widths.get(parent); - - if (parentWidth === undefined) { - /** - * All widths have been precalcluated, so this will not happen. - */ - throw new Error(); - } - - const metadata: Partial = { - process, - width, - parent, - parentWidth, - }; - - const siblings = indexedProcessTreeChildren(tree, parent); - if (siblings.length === 1) { - metadata.isOnlyChild = true; - metadata.lastChildWidth = width; - metadata.firstChildWidth = width; - } else { - const firstChildWidth = widths.get(siblings[0]); - const lastChildWidth = widths.get(siblings[siblings.length - 1]); - if (firstChildWidth === undefined || lastChildWidth === undefined) { - /** - * All widths have been precalcluated, so this will not happen. - */ - throw new Error(); - } - metadata.isOnlyChild = false; - metadata.firstChildWidth = firstChildWidth; - metadata.lastChildWidth = lastChildWidth; - } - - yield metadata as ProcessWithWidthMetadata; - } - } -} - -function processPositions( - indexedProcessTree: IndexedProcessTree, - widths: ProcessWidths -): ProcessPositions { - const positions = new Map(); - /** - * This algorithm iterates the tree in level order. It keeps counters that are reset for each parent. - * By keeping track of the last parent node, we can know when we are dealing with a new set of siblings and - * reset the counters. - */ - let lastProcessedParentNode: ResolverEvent | undefined; - /** - * Nodes are positioned relative to their siblings. We walk this in level order, so we handle - * children left -> right. - * - * The width of preceding siblings is used to left align the node. - * The number of preceding siblings is important because each sibling must be 1 unit apart - * on the x axis. - */ - let numberOfPrecedingSiblings = 0; - let runningWidthOfPrecedingSiblings = 0; - - for (const metadata of levelOrderWithWidths(indexedProcessTree, widths)) { - // Handle root node - if (metadata.parent === null) { - const { process } = metadata; - /** - * Place the root node at (0, 0) for now. - */ - positions.set(process, [0, 0]); - } else { - const { process, parent, isOnlyChild, width, parentWidth } = metadata; - - // Reinit counters when parent changes - if (lastProcessedParentNode !== parent) { - numberOfPrecedingSiblings = 0; - runningWidthOfPrecedingSiblings = 0; - - // keep track of this so we know when to reinitialize - lastProcessedParentNode = parent; - } - - const parentPosition = positions.get(parent); - - if (parentPosition === undefined) { - /** - * Since this algorithm populates the `positions` map in level order, - * the parent node will have been processed already and the parent position - * will always be available. - * - * This will never happen. - */ - throw new Error(); - } - - /** - * The x 'offset' is added to the x value of the parent to determine the position of the node. - * We add `parentWidth / -2` in order to align the left side of this node with the left side of its parent. - * We add `numberOfPrecedingSiblings * distanceBetweenNodes` in order to keep each node 1 apart on the x axis. - * We add `runningWidthOfPrecedingSiblings` so that we don't overlap with our preceding siblings. We stack em up. - * We add `width / 2` so that we center the node horizontally (in case it has non-0 width.) - */ - const xOffset = - parentWidth / -2 + - numberOfPrecedingSiblings * distanceBetweenNodes + - runningWidthOfPrecedingSiblings + - width / 2; - - /** - * The y axis gains `-distanceBetweenNodes` as we move down the screen 1 unit at a time. - */ - let yDistanceBetweenNodes = -distanceBetweenNodes; - - if (!isOnlyChild) { - // Make space on leaves to show elapsed time - yDistanceBetweenNodes *= 2; - } - - const position = vector2Add([xOffset, yDistanceBetweenNodes], parentPosition); - - positions.set(process, position); - - numberOfPrecedingSiblings += 1; - runningWidthOfPrecedingSiblings += width; - } +export const graphableProcesses = createSelector(resolverTree, function (tree?) { + if (tree) { + return resolverTreeModel.lifecycleEvents(tree).filter(isGraphableProcess); + } else { + return []; } +}); - return positions; -} - +/** + * The 'indexed process tree' contains the tree data, indexed in helpful ways. Used for O(1) access to stuff during graph layout. + */ export const indexedProcessTree = createSelector(graphableProcesses, function indexedTree( /* eslint-disable no-shadow */ graphableProcesses @@ -462,22 +105,28 @@ export const indexedProcessTree = createSelector(graphableProcesses, function in /** * This returns a map of entity_ids to stats about the related events and alerts. */ -export function relatedEventsStats(data: DataState) { - return data.relatedEventsStats; -} +export const relatedEventsStats: ( + state: DataState +) => Map | null = createSelector(resolverTree, (tree?: ResolverTree) => { + if (tree) { + return resolverTreeModel.relatedEventsStats(tree); + } else { + return null; + } +}); /** - * returns {Map} a map of entity_ids to related event data. + * returns a map of entity_ids to related event data. */ -export function relatedEventsByEntityId(data: DataState) { +export function relatedEventsByEntityId(data: DataState): Map { return data.relatedEvents; } /** - * returns {Map} a map of entity_ids to booleans indicating if it is waiting on related event + * returns a map of entity_ids to booleans indicating if it is waiting on related event * A value of `undefined` can be interpreted as `not yet requested` */ -export function relatedEventsReady(data: DataState) { +export function relatedEventsReady(data: DataState): Map { return data.relatedEventsReady; } @@ -502,6 +151,39 @@ export const processAdjacencies = createSelector( } ); +/** + * `true` if there were more children than we got in the last request. + */ +export function hasMoreChildren(state: DataState): boolean { + const tree = resolverTree(state); + return tree ? resolverTreeModel.hasMoreChildren(tree) : false; +} + +/** + * `true` if there were more ancestors than we got in the last request. + */ +export function hasMoreAncestors(state: DataState): boolean { + const tree = resolverTree(state); + return tree ? resolverTreeModel.hasMoreAncestors(tree) : false; +} + +/** + * If we need to fetch, this is the ID to fetch. + */ +export function databaseDocumentIDToFetch(state: DataState): string | null { + // If there is an ID, it must match either the last received version, or the pending version. + // Otherwise, we need to fetch it + // NB: this technique will not allow for refreshing of data. + if ( + state.databaseDocumentID !== undefined && + state.databaseDocumentID !== state.pendingRequestDatabaseDocumentID && + state.databaseDocumentID !== state.lastResponse?.databaseDocumentID + ) { + return state.databaseDocumentID; + } else { + return null; + } +} export const processNodePositionsAndEdgeLineSegments = createSelector( indexedProcessTree, function processNodePositionsAndEdgeLineSegments( @@ -509,53 +191,7 @@ export const processNodePositionsAndEdgeLineSegments = createSelector( indexedProcessTree /* eslint-enable no-shadow */ ) { - /** - * Walk the tree in reverse level order, calculating the 'width' of subtrees. - */ - const widths = widthsOfProcessSubtrees(indexedProcessTree); - - /** - * Walk the tree in level order. Using the precalculated widths, calculate the position of nodes. - * Nodes are positioned relative to their parents and preceding siblings. - */ - const positions = processPositions(indexedProcessTree, widths); - - /** - * With the widths and positions precalculated, we calculate edge line segments (arrays of vector2s) - * which connect them in a 'pitchfork' design. - */ - const edgeLineSegments = processEdgeLineSegments(indexedProcessTree, widths, positions); - - /** - * Transform the positions of nodes and edges so they seem like they are on an isometric grid. - */ - const transformedEdgeLineSegments: EdgeLineSegment[] = []; - const transformedPositions = new Map(); - - for (const [processEvent, position] of positions) { - transformedPositions.set(processEvent, applyMatrix3(position, isometricTransformMatrix)); - } - - for (const edgeLineSegment of edgeLineSegments) { - const { - points: [startPoint, endPoint], - } = edgeLineSegment; - - const transformedSegment: EdgeLineSegment = { - ...edgeLineSegment, - points: [ - applyMatrix3(startPoint, isometricTransformMatrix), - applyMatrix3(endPoint, isometricTransformMatrix), - ], - }; - - transformedEdgeLineSegments.push(transformedSegment); - } - - return { - processNodePositions: transformedPositions, - edgeLineSegments: transformedEdgeLineSegments, - }; + return isometricTaxiLayout(indexedProcessTree); } ); @@ -650,13 +286,18 @@ export const visibleProcessNodePositionsAndEdgeLineSegments = createSelector( } ); /** - * Returns the `children` and `ancestors` limits for the current graph, if any. - * - * @param state {DataState} the DataState from the reducer + * If there is a pending request that's for a entity ID that doesn't matche the `entityID`, then we should cancel it. */ -export const limitsReached = (state: DataState): { children: boolean; ancestors: boolean } => { - return { - children: state.lineageLimits.children !== null, - ancestors: state.lineageLimits.ancestors !== null, - }; -}; +export function databaseDocumentIDToAbort(state: DataState): string | null { + /** + * If there is a pending request, and its not for the current databaseDocumentID (even, if the current databaseDocumentID is undefined) then we should abort the request. + */ + if ( + state.pendingRequestDatabaseDocumentID !== undefined && + state.pendingRequestDatabaseDocumentID !== state.databaseDocumentID + ) { + return state.pendingRequestDatabaseDocumentID; + } else { + return null; + } +} diff --git a/x-pack/plugins/security_solution/public/resolver/store/data/visible_entities.test.ts b/x-pack/plugins/security_solution/public/resolver/store/data/visible_entities.test.ts index f10cfe0ba466a8..eb2b402a694a55 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/data/visible_entities.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/data/visible_entities.test.ts @@ -11,6 +11,7 @@ import { ResolverState } from '../../types'; import { LegacyEndpointEvent, ResolverEvent } from '../../../../common/endpoint/types'; import { visibleProcessNodePositionsAndEdgeLineSegments } from '../selectors'; import { mockProcessEvent } from '../../models/process_event_test_helpers'; +import { mock as mockResolverTree } from '../../models/resolver_tree'; describe('resolver visible entities', () => { let processA: LegacyEndpointEvent; @@ -111,7 +112,7 @@ describe('resolver visible entities', () => { ]; const action: ResolverAction = { type: 'serverReturnedResolverData', - payload: { events, stats: new Map(), lineageLimits: { children: '', ancestors: '' } }, + payload: { result: mockResolverTree({ events })!, databaseDocumentID: '' }, }; const cameraAction: ResolverAction = { type: 'userSetRasterSize', payload: [300, 200] }; store.dispatch(action); @@ -143,7 +144,7 @@ describe('resolver visible entities', () => { ]; const action: ResolverAction = { type: 'serverReturnedResolverData', - payload: { events, stats: new Map(), lineageLimits: { children: '', ancestors: '' } }, + payload: { result: mockResolverTree({ events })!, databaseDocumentID: '' }, }; const cameraAction: ResolverAction = { type: 'userSetRasterSize', payload: [2000, 2000] }; store.dispatch(action); diff --git a/x-pack/plugins/security_solution/public/resolver/store/index.ts b/x-pack/plugins/security_solution/public/resolver/store/index.ts index 203ecccb1d3696..9809e443d2d137 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/index.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/index.ts @@ -7,14 +7,15 @@ import { createStore, applyMiddleware, Store } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly'; import { KibanaReactContextValue } from '../../../../../../src/plugins/kibana_react/public'; -import { ResolverAction, ResolverState } from '../types'; +import { ResolverState } from '../types'; import { StartServices } from '../../types'; import { resolverReducer } from './reducer'; import { resolverMiddlewareFactory } from './middleware'; +import { ResolverAction } from './actions'; export const storeFactory = ( context?: KibanaReactContextValue -): { store: Store } => { +): Store => { const actionsBlacklist: Array = ['userMovedPointer']; const composeEnhancers = composeWithDevTools({ name: 'Resolver', @@ -22,8 +23,5 @@ export const storeFactory = ( }); const middlewareEnhancer = applyMiddleware(resolverMiddlewareFactory(context)); - const store = createStore(resolverReducer, composeEnhancers(middlewareEnhancer)); - return { - store, - }; + return createStore(resolverReducer, composeEnhancers(middlewareEnhancer)); }; diff --git a/x-pack/plugins/security_solution/public/resolver/store/middleware.ts b/x-pack/plugins/security_solution/public/resolver/store/middleware.ts deleted file mode 100644 index a1807255b5eafc..00000000000000 --- a/x-pack/plugins/security_solution/public/resolver/store/middleware.ts +++ /dev/null @@ -1,127 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Dispatch, MiddlewareAPI } from 'redux'; -import { KibanaReactContextValue } from '../../../../../../src/plugins/kibana_react/public'; -import { StartServices } from '../../types'; -import { ResolverState, ResolverAction } from '../types'; -import { - ResolverEvent, - ResolverChildren, - ResolverAncestry, - ResolverLifecycleNode, - ResolverNodeStats, - ResolverRelatedEvents, -} from '../../../common/endpoint/types'; -import * as event from '../../../common/endpoint/models/event'; - -type MiddlewareFactory = ( - context?: KibanaReactContextValue -) => ( - api: MiddlewareAPI, S> -) => (next: Dispatch) => (action: ResolverAction) => unknown; - -function getLifecycleEventsAndStats( - nodes: ResolverLifecycleNode[], - stats: Map -): ResolverEvent[] { - return nodes.reduce((flattenedEvents: ResolverEvent[], currentNode: ResolverLifecycleNode) => { - if (currentNode.lifecycle && currentNode.lifecycle.length > 0) { - flattenedEvents.push(...currentNode.lifecycle); - } - - if (currentNode.stats) { - stats.set(currentNode.entityID, currentNode.stats); - } - - return flattenedEvents; - }, []); -} - -export const resolverMiddlewareFactory: MiddlewareFactory = (context) => { - return (api) => (next) => async (action: ResolverAction) => { - next(action); - if (action.type === 'userChangedSelectedEvent') { - /** - * concurrently fetches a process's details, its ancestors, and its related events. - */ - if (context?.services.http && action.payload.selectedEvent) { - api.dispatch({ type: 'appRequestedResolverData' }); - try { - let lifecycle: ResolverEvent[]; - let children: ResolverChildren; - let ancestry: ResolverAncestry; - let entityId: string; - let stats: ResolverNodeStats; - if (event.isLegacyEvent(action.payload.selectedEvent)) { - entityId = action.payload.selectedEvent?.endgame?.unique_pid.toString(); - const legacyEndpointID = action.payload.selectedEvent?.agent?.id; - [{ lifecycle, children, ancestry, stats }] = await Promise.all([ - context.services.http.get(`/api/endpoint/resolver/${entityId}`, { - query: { legacyEndpointID, children: 5, ancestors: 5 }, - }), - ]); - } else { - entityId = action.payload.selectedEvent.process.entity_id; - [{ lifecycle, children, ancestry, stats }] = await Promise.all([ - context.services.http.get(`/api/endpoint/resolver/${entityId}`, { - query: { - children: 5, - ancestors: 5, - }, - }), - ]); - } - const nodeStats: Map = new Map(); - nodeStats.set(entityId, stats); - const lineageLimits = { children: children.nextChild, ancestors: ancestry.nextAncestor }; - - const events = [ - ...lifecycle, - ...getLifecycleEventsAndStats(children.childNodes, nodeStats), - ...getLifecycleEventsAndStats(ancestry.ancestors, nodeStats), - ]; - api.dispatch({ - type: 'serverReturnedResolverData', - payload: { - events, - stats: nodeStats, - lineageLimits, - }, - }); - } catch (error) { - api.dispatch({ - type: 'serverFailedToReturnResolverData', - }); - } - } - } else if ( - (action.type === 'userRequestedRelatedEventData' || - action.type === 'appDetectedMissingEventData') && - context - ) { - const entityIdToFetchFor = action.payload; - let result: ResolverRelatedEvents; - try { - result = await context.services.http.get( - `/api/endpoint/resolver/${entityIdToFetchFor}/events`, - { - query: { events: 100 }, - } - ); - api.dispatch({ - type: 'serverReturnedRelatedEventData', - payload: result, - }); - } catch (e) { - api.dispatch({ - type: 'serverFailedToReturnRelatedEventData', - payload: action.payload, - }); - } - } - }; -}; diff --git a/x-pack/plugins/security_solution/public/resolver/store/middleware/index.ts b/x-pack/plugins/security_solution/public/resolver/store/middleware/index.ts new file mode 100644 index 00000000000000..194b50256c6310 --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/store/middleware/index.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Dispatch, MiddlewareAPI } from 'redux'; +import { KibanaReactContextValue } from '../../../../../../../src/plugins/kibana_react/public'; +import { StartServices } from '../../../types'; +import { ResolverState } from '../../types'; +import { ResolverRelatedEvents } from '../../../../common/endpoint/types'; +import { ResolverTreeFetcher } from './resolver_tree_fetcher'; +import { ResolverAction } from '../actions'; + +type MiddlewareFactory = ( + context?: KibanaReactContextValue +) => ( + api: MiddlewareAPI, S> +) => (next: Dispatch) => (action: ResolverAction) => unknown; + +/** + * The redux middleware that the app uses to trigger side effects. + * All data fetching should be done here. + * For actions that the app triggers directly, use `app` as a prefix for the type. + * For actions that are triggered as a result of server interaction, use `server` as a prefix for the type. + */ +export const resolverMiddlewareFactory: MiddlewareFactory = (context) => { + return (api) => (next) => { + // This cannot work w/o `context`. + if (!context) { + return async (action: ResolverAction) => { + next(action); + }; + } + const resolverTreeFetcher = ResolverTreeFetcher(context, api); + return async (action: ResolverAction) => { + next(action); + + resolverTreeFetcher(); + + if ( + action.type === 'userRequestedRelatedEventData' || + action.type === 'appDetectedMissingEventData' + ) { + const entityIdToFetchFor = action.payload; + let result: ResolverRelatedEvents; + try { + result = await context.services.http.get( + `/api/endpoint/resolver/${entityIdToFetchFor}/events`, + { + query: { events: 100 }, + } + ); + + api.dispatch({ + type: 'serverReturnedRelatedEventData', + payload: result, + }); + } catch (e) { + api.dispatch({ + type: 'serverFailedToReturnRelatedEventData', + payload: action.payload, + }); + } + } + }; + }; +}; diff --git a/x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts b/x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts new file mode 100644 index 00000000000000..59e944d95e04b6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/store/middleware/resolver_tree_fetcher.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* eslint-disable no-duplicate-imports */ + +import { Dispatch, MiddlewareAPI } from 'redux'; +import { ResolverTree, ResolverEntityIndex } from '../../../../common/endpoint/types'; + +import { KibanaReactContextValue } from '../../../../../../../src/plugins/kibana_react/public'; +import { ResolverState } from '../../types'; +import * as selectors from '../selectors'; +import { StartServices } from '../../../types'; +import { DEFAULT_INDEX_KEY as defaultIndexKey } from '../../../../common/constants'; +import { ResolverAction } from '../actions'; +/** + * A function that handles syncing ResolverTree data w/ the current entity ID. + * This will make a request anytime the entityID changes (to something other than undefined.) + * If the entity ID changes while a request is in progress, the in-progress request will be cancelled. + * Call the returned function after each state transition. + * This is a factory because it is stateful and keeps that state in closure. + */ +export function ResolverTreeFetcher( + context: KibanaReactContextValue, + api: MiddlewareAPI, ResolverState> +): () => void { + let lastRequestAbortController: AbortController | undefined; + + // Call this after each state change. + // This fetches the ResolverTree for the current entityID + // if the entityID changes while + return async () => { + const state = api.getState(); + const databaseDocumentIDToFetch = selectors.databaseDocumentIDToFetch(state); + + if (selectors.databaseDocumentIDToAbort(state) && lastRequestAbortController) { + lastRequestAbortController.abort(); + // calling abort will cause an action to be fired + } else if (databaseDocumentIDToFetch !== null) { + lastRequestAbortController = new AbortController(); + let result: ResolverTree | undefined; + // Inform the state that we've made the request. Without this, the middleware will try to make the request again + // immediately. + api.dispatch({ + type: 'appRequestedResolverData', + payload: databaseDocumentIDToFetch, + }); + try { + const indices: string[] = context.services.uiSettings.get(defaultIndexKey); + const matchingEntities: ResolverEntityIndex = await context.services.http.get( + '/api/endpoint/resolver/entity', + { + signal: lastRequestAbortController.signal, + query: { + _id: databaseDocumentIDToFetch, + indices, + }, + } + ); + if (matchingEntities.length < 1) { + // If no entity_id could be found for the _id, bail out with a failure. + api.dispatch({ + type: 'serverFailedToReturnResolverData', + payload: databaseDocumentIDToFetch, + }); + return; + } + const entityIDToFetch = matchingEntities[0].entity_id; + result = await context.services.http.get(`/api/endpoint/resolver/${entityIDToFetch}`, { + signal: lastRequestAbortController.signal, + query: { + children: 5, + ancestors: 5, + }, + }); + } catch (error) { + // https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-AbortError + if (error instanceof DOMException && error.name === 'AbortError') { + api.dispatch({ + type: 'appAbortedResolverDataRequest', + payload: databaseDocumentIDToFetch, + }); + } else { + api.dispatch({ + type: 'serverFailedToReturnResolverData', + payload: databaseDocumentIDToFetch, + }); + } + } + if (result !== undefined) { + api.dispatch({ + type: 'serverReturnedResolverData', + payload: { + result, + databaseDocumentID: databaseDocumentIDToFetch, + }, + }); + } + } + }; +} diff --git a/x-pack/plugins/security_solution/public/resolver/store/reducer.ts b/x-pack/plugins/security_solution/public/resolver/store/reducer.ts index 77dffd79ea094a..65e53eb28549f9 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/reducer.ts @@ -8,7 +8,8 @@ import { htmlIdGenerator } from '@elastic/eui'; import { animateProcessIntoView } from './methods'; import { cameraReducer } from './camera/reducer'; import { dataReducer } from './data/reducer'; -import { ResolverState, ResolverAction, ResolverUIState } from '../types'; +import { ResolverAction } from './actions'; +import { ResolverState, ResolverUIState } from '../types'; import { uniquePidForProcess } from '../models/process_event'; /** diff --git a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts index 5599b7e8ab6138..55e0072c5227f9 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/selectors.ts @@ -56,6 +56,19 @@ export const processNodePositionsAndEdgeLineSegments = composeSelectors( dataSelectors.processNodePositionsAndEdgeLineSegments ); +/** + * If we need to fetch, this is the entity ID to fetch. + */ +export const databaseDocumentIDToFetch = composeSelectors( + dataStateSelector, + dataSelectors.databaseDocumentIDToFetch +); + +export const databaseDocumentIDToAbort = composeSelectors( + dataStateSelector, + dataSelectors.databaseDocumentIDToAbort +); + export const processAdjacencies = composeSelectors( dataStateSelector, dataSelectors.processAdjacencies @@ -158,15 +171,6 @@ export const graphableProcesses = composeSelectors( dataSelectors.graphableProcesses ); -/** - * Select the `ancestors` and `children` limits that were reached or exceeded - * during the request for the current tree. - */ -export const lineageLimitsReached = composeSelectors( - dataStateSelector, - dataSelectors.limitsReached -); - /** * Calls the `secondSelector` with the result of the `selector`. Use this when re-exporting a * concern-specific selector. `selector` should return the concern-specific state. diff --git a/x-pack/plugins/security_solution/public/resolver/types.ts b/x-pack/plugins/security_solution/public/resolver/types.ts index 0742fa2e305604..fe5b2276603a8c 100644 --- a/x-pack/plugins/security_solution/public/resolver/types.ts +++ b/x-pack/plugins/security_solution/public/resolver/types.ts @@ -7,11 +7,11 @@ import { Store } from 'redux'; import { BBox } from 'rbush'; import { ResolverAction } from './store/actions'; -export { ResolverAction } from './store/actions'; import { ResolverEvent, ResolverNodeStats, ResolverRelatedEvents, + ResolverTree, } from '../../common/endpoint/types'; /** @@ -176,15 +176,49 @@ export interface VisibleEntites { * State for `data` reducer which handles receiving Resolver data from the backend. */ export interface DataState { - readonly results: readonly ResolverEvent[]; - readonly relatedEventsStats: Readonly>; + readonly relatedEventsStats: Map; readonly relatedEvents: Map; readonly relatedEventsReady: Map; - readonly lineageLimits: Readonly<{ children: string | null; ancestors: string | null }>; - isLoading: boolean; - hasError: boolean; + /** + * The `_id` for an ES document. Used to select a process that we'll show the graph for. + */ + readonly databaseDocumentID?: string; + /** + * The id used for the pending request, if there is one. + */ + readonly pendingRequestDatabaseDocumentID?: string; + + /** + * The parameters and response from the last successful request. + */ + readonly lastResponse?: { + /** + * The id used in the request. + */ + readonly databaseDocumentID: string; + } & ( + | { + /** + * If a response with a success code was received, this is `true`. + */ + readonly successful: true; + /** + * The ResolverTree parsed from the response. + */ + readonly result: ResolverTree; + } + | { + /** + * If the request threw an exception or the response had a failure code, this will be false. + */ + readonly successful: false; + } + ); } +/** + * Represents an ordered pair. Used for x-y coordinates and the like. + */ export type Vector2 = readonly [number, number]; /** @@ -416,3 +450,17 @@ export type ResolverProcessType = | 'unknownEvent'; export type ResolverStore = Store; + +/** + * Describes the basic Resolver graph layout. + */ +export interface IsometricTaxiLayout { + /** + * A map of events to position. each event represents its own node. + */ + processNodePositions: Map; + /** + * A map of edgline segments, which graphically connect nodes. + */ + edgeLineSegments: EdgeLineSegment[]; +} diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx index 67c091627741ad..c2a7bbaacbf1d4 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx @@ -11,9 +11,10 @@ import styled from 'styled-components'; import { EuiRange, EuiPanel, EuiIcon } from '@elastic/eui'; import { useSelector, useDispatch } from 'react-redux'; import { SideEffectContext } from './side_effect_context'; -import { ResolverAction, Vector2 } from '../types'; +import { Vector2 } from '../types'; import * as selectors from '../store/selectors'; import { useResolverTheme } from './assets'; +import { ResolverAction } from '../store/actions'; interface StyledGraphControls { graphControlsBackground: string; diff --git a/x-pack/plugins/security_solution/public/resolver/view/index.tsx b/x-pack/plugins/security_solution/public/resolver/view/index.tsx index 5c188fdc711560..205180a40d62a4 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/index.tsx @@ -3,164 +3,44 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +/* eslint-disable react/display-name */ -import React, { useLayoutEffect, useContext } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import styled from 'styled-components'; -import { EuiLoadingSpinner } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import * as selectors from '../store/selectors'; -import { EdgeLine } from './edge_line'; -import { Panel } from './panel'; -import { GraphControls } from './graph_controls'; -import { ProcessEventDot } from './process_event_dot'; -import { useCamera } from './use_camera'; -import { SymbolDefinitions, useResolverTheme } from './assets'; -import { entityId } from '../../../common/endpoint/models/event'; -import { ResolverAction } from '../types'; -import { ResolverEvent } from '../../../common/endpoint/types'; -import { SideEffectContext } from './side_effect_context'; +import React, { useMemo } from 'react'; +import { Provider } from 'react-redux'; +import { ResolverMap } from './map'; +import { storeFactory } from '../store'; +import { StartServices } from '../../types'; +import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; -interface StyledResolver { - backgroundColor: string; -} - -const StyledResolver = styled.div` - /** - * Take up all availble space - */ - &, - .resolver-graph { - display: flex; - flex-grow: 1; - } - .loading-container { - display: flex; - align-items: center; - justify-content: center; - flex-grow: 1; - } +/** + * The top level, unconnected, Resolver component. + */ +export const Resolver = React.memo(function ({ + className, + databaseDocumentID, +}: { /** - * The placeholder components use absolute positioning. + * Used by `styled-components`. */ - position: relative; + className?: string; /** - * Prevent partially visible components from showing up outside the bounds of Resolver. + * The `_id` value of an event in ES. + * Used as the origin of the Resolver graph. */ - overflow: hidden; - contain: strict; - background-color: ${(props) => props.backgroundColor}; -`; - -const StyledPanel = styled(Panel)` - position: absolute; - left: 0; - top: 0; - bottom: 0; - overflow: auto; - width: 25em; - max-width: 50%; -`; - -const StyledResolverContainer = styled.div` - display: flex; - flex-grow: 1; - contain: layout; -`; - -export const Resolver = React.memo(function Resolver({ - className, - selectedEvent, -}: { - className?: string; - selectedEvent?: ResolverEvent; + databaseDocumentID?: string; }) { - const { timestamp } = useContext(SideEffectContext); - - const { processNodePositions, connectingEdgeLineSegments } = useSelector( - selectors.visibleProcessNodePositionsAndEdgeLineSegments - )(timestamp()); - - const dispatch: (action: ResolverAction) => unknown = useDispatch(); - const { processToAdjacencyMap } = useSelector(selectors.processAdjacencies); - const { projectionMatrix, ref, onMouseDown } = useCamera(); - const isLoading = useSelector(selectors.isLoading); - const hasError = useSelector(selectors.hasError); - const relatedEventsStats = useSelector(selectors.relatedEventsStats); - const activeDescendantId = useSelector(selectors.uiActiveDescendantId); - const terminatedProcesses = useSelector(selectors.terminatedProcesses); - const { colorMap } = useResolverTheme(); - - useLayoutEffect(() => { - dispatch({ - type: 'userChangedSelectedEvent', - payload: { selectedEvent }, - }); - }, [dispatch, selectedEvent]); + const context = useKibana(); + const store = useMemo(() => { + return storeFactory(context); + }, [context]); + /** + * Setup the store and use `Provider` here. This allows the ResolverMap component to + * dispatch actions and read from state. + */ return ( - - {isLoading ? ( -
- -
- ) : hasError ? ( -
-
- {' '} - -
-
- ) : ( - - {connectingEdgeLineSegments.map(({ points: [startPosition, endPosition], metadata }) => ( - - ))} - {[...processNodePositions].map(([processEvent, position]) => { - const adjacentNodeMap = processToAdjacencyMap.get(processEvent); - const processEntityId = entityId(processEvent); - if (!adjacentNodeMap) { - // This should never happen - throw new Error('Issue calculating adjacency node map.'); - } - return ( - - ); - })} - - )} - - - -
+ + + ); }); diff --git a/x-pack/plugins/security_solution/public/resolver/view/map.tsx b/x-pack/plugins/security_solution/public/resolver/view/map.tsx new file mode 100644 index 00000000000000..9022932c1594f9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/view/map.tsx @@ -0,0 +1,125 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +/* eslint-disable no-duplicate-imports */ + +/* eslint-disable react/display-name */ + +import React, { useContext } from 'react'; +import { useSelector } from 'react-redux'; +import { EuiLoadingSpinner } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import * as selectors from '../store/selectors'; +import { EdgeLine } from './edge_line'; +import { GraphControls } from './graph_controls'; +import { ProcessEventDot } from './process_event_dot'; +import { useCamera } from './use_camera'; +import { SymbolDefinitions, useResolverTheme } from './assets'; +import { useStateSyncingActions } from './use_state_syncing_actions'; +import { StyledMapContainer, StyledPanel, GraphContainer } from './styles'; +import { entityId } from '../../../common/endpoint/models/event'; +import { SideEffectContext } from './side_effect_context'; + +/** + * The highest level connected Resolver component. Needs a `Provider` in its ancestry to work. + */ +export const ResolverMap = React.memo(function ({ + className, + databaseDocumentID, +}: { + /** + * Used by `styled-components`. + */ + className?: string; + /** + * The `_id` value of an event in ES. + * Used as the origin of the Resolver graph. + */ + databaseDocumentID?: string; +}) { + /** + * This is responsible for dispatching actions that include any external data. + * `databaseDocumentID` + */ + useStateSyncingActions({ databaseDocumentID }); + + const { timestamp } = useContext(SideEffectContext); + const { processNodePositions, connectingEdgeLineSegments } = useSelector( + selectors.visibleProcessNodePositionsAndEdgeLineSegments + )(timestamp()); + const { processToAdjacencyMap } = useSelector(selectors.processAdjacencies); + const relatedEventsStats = useSelector(selectors.relatedEventsStats); + const terminatedProcesses = useSelector(selectors.terminatedProcesses); + const { projectionMatrix, ref, onMouseDown } = useCamera(); + const isLoading = useSelector(selectors.isLoading); + const hasError = useSelector(selectors.hasError); + const activeDescendantId = useSelector(selectors.uiActiveDescendantId); + const { colorMap } = useResolverTheme(); + + return ( + + {isLoading ? ( +
+ +
+ ) : hasError ? ( +
+
+ {' '} + +
+
+ ) : ( + + {connectingEdgeLineSegments.map(({ points: [startPosition, endPosition], metadata }) => ( + + ))} + {[...processNodePositions].map(([processEvent, position]) => { + const adjacentNodeMap = processToAdjacencyMap.get(processEvent); + const processEntityId = entityId(processEvent); + if (!adjacentNodeMap) { + // This should never happen + throw new Error('Issue calculating adjacency node map.'); + } + return ( + + ); + })} + + )} + + + +
+ ); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/view/panel.tsx b/x-pack/plugins/security_solution/public/resolver/view/panel.tsx index c8f6512077a6f5..2a2e7e87394a99 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panel.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panel.tsx @@ -22,7 +22,7 @@ import { displayNameRecord } from './process_event_dot'; import * as selectors from '../store/selectors'; import { useResolverDispatch } from './use_resolver_dispatch'; import * as event from '../../../common/endpoint/models/event'; -import { ResolverEvent } from '../../../common/endpoint/types'; +import { ResolverEvent, ResolverNodeStats } from '../../../common/endpoint/types'; import { SideEffectContext } from './side_effect_context'; import { ProcessEventListNarrowedByType } from './panels/panel_content_related_list'; import { EventCountsForProcess } from './panels/panel_content_related_counts'; @@ -141,15 +141,10 @@ const PanelContent = memo(function PanelContent() { [history, urlSearch] ); - // GO JONNY GO const relatedEventStats = useSelector(selectors.relatedEventsStats); const { crumbId, crumbEvent } = queryParams; - const relatedStatsForIdFromParams = useMemo(() => { - if (idFromParams) { - return relatedEventStats.get(idFromParams); - } - return undefined; - }, [relatedEventStats, idFromParams]); + const relatedStatsForIdFromParams: ResolverNodeStats | undefined = + idFromParams && relatedEventStats ? relatedEventStats.get(idFromParams) : undefined; /** * Determine which set of breadcrumbs to display based on the query parameters diff --git a/x-pack/plugins/security_solution/public/resolver/view/styles.tsx b/x-pack/plugins/security_solution/public/resolver/view/styles.tsx new file mode 100644 index 00000000000000..2a1e67f4a9fdce --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/view/styles.tsx @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import styled from 'styled-components'; +import { Panel } from './panel'; + +/** + * The top level DOM element for Resolver + * NB: `styled-components` may be used to wrap this. + */ +export const StyledMapContainer = styled.div<{ backgroundColor: string }>` + /** + * Take up all availble space + */ + &, + .resolver-graph { + display: flex; + flex-grow: 1; + } + .loading-container { + display: flex; + align-items: center; + justify-content: center; + flex-grow: 1; + } + /** + * The placeholder components use absolute positioning. + */ + position: relative; + /** + * Prevent partially visible components from showing up outside the bounds of Resolver. + */ + overflow: hidden; + contain: strict; + background-color: ${(props) => props.backgroundColor}; +`; + +/** + * The Panel, styled for use in `ResolverMap`. + */ +export const StyledPanel = styled(Panel)` + position: absolute; + left: 0; + top: 0; + bottom: 0; + overflow: auto; + width: 25em; + max-width: 50%; +`; + +/** + * Used by ResolverMap to contain the lines and nodes. + */ +export const GraphContainer = styled.div` + display: flex; + flex-grow: 1; + contain: layout; +`; diff --git a/x-pack/plugins/security_solution/public/resolver/view/use_camera.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/use_camera.test.tsx index dc7cb9a2ab1991..f772c20f8cf160 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/use_camera.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/use_camera.test.tsx @@ -11,12 +11,14 @@ import { useCamera, useAutoUpdatingClientRect } from './use_camera'; import { Provider } from 'react-redux'; import * as selectors from '../store/selectors'; import { storeFactory } from '../store'; -import { Matrix3, ResolverAction, ResolverStore, SideEffectSimulator } from '../types'; +import { Matrix3, ResolverStore, SideEffectSimulator } from '../types'; import { ResolverEvent } from '../../../common/endpoint/types'; import { SideEffectContext } from './side_effect_context'; import { applyMatrix3 } from '../lib/vector2'; import { sideEffectSimulator } from './side_effect_simulator'; import { mockProcessEvent } from '../models/process_event_test_helpers'; +import { mock as mockResolverTree } from '../models/resolver_tree'; +import { ResolverAction } from '../store/actions'; describe('useCamera on an unpainted element', () => { let element: HTMLElement; @@ -27,7 +29,7 @@ describe('useCamera on an unpainted element', () => { let simulator: SideEffectSimulator; beforeEach(async () => { - ({ store } = storeFactory()); + store = storeFactory(); const Test = function Test() { const camera = useCamera(); @@ -159,7 +161,7 @@ describe('useCamera on an unpainted element', () => { let process: ResolverEvent; beforeEach(() => { const events: ResolverEvent[] = []; - const numberOfEvents: number = Math.floor(Math.random() * 10 + 1); + const numberOfEvents: number = 10; for (let index = 0; index < numberOfEvents; index++) { const uniquePpid = index === 0 ? undefined : index - 1; @@ -174,23 +176,27 @@ describe('useCamera on an unpainted element', () => { }) ); } - const serverResponseAction: ResolverAction = { - type: 'serverReturnedResolverData', - payload: { - events, - stats: new Map(), - lineageLimits: { children: null, ancestors: null }, - }, - }; - act(() => { - store.dispatch(serverResponseAction); - }); + const tree = mockResolverTree({ events }); + if (tree !== null) { + const serverResponseAction: ResolverAction = { + type: 'serverReturnedResolverData', + payload: { result: tree, databaseDocumentID: '' }, + }; + act(() => { + store.dispatch(serverResponseAction); + }); + } else { + throw new Error('failed to create tree'); + } const processes: ResolverEvent[] = [ ...selectors .processNodePositionsAndEdgeLineSegments(store.getState()) .processNodePositions.keys(), ]; process = processes[processes.length - 1]; + if (!process) { + throw new Error('missing the process to bring into view'); + } simulator.controls.time = 0; const cameraAction: ResolverAction = { type: 'userBroughtProcessIntoView', diff --git a/x-pack/plugins/security_solution/public/resolver/view/use_resolver_dispatch.ts b/x-pack/plugins/security_solution/public/resolver/view/use_resolver_dispatch.ts index a993a4ed595e1b..90c3dadc56ba5a 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/use_resolver_dispatch.ts +++ b/x-pack/plugins/security_solution/public/resolver/view/use_resolver_dispatch.ts @@ -5,7 +5,7 @@ */ import { useDispatch } from 'react-redux'; -import { ResolverAction } from '../types'; +import { ResolverAction } from '../store/actions'; /** * Call `useDispatch`, but only accept `ResolverAction` actions. diff --git a/x-pack/plugins/security_solution/public/resolver/view/use_state_syncing_actions.ts b/x-pack/plugins/security_solution/public/resolver/view/use_state_syncing_actions.ts new file mode 100644 index 00000000000000..b8ea2049f5c49a --- /dev/null +++ b/x-pack/plugins/security_solution/public/resolver/view/use_state_syncing_actions.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useLayoutEffect } from 'react'; +import { useResolverDispatch } from './use_resolver_dispatch'; + +/** + * This is a hook that is meant to be used once at the top level of Resolver. + * It dispatches actions that keep the store in sync with external properties. + */ +export function useStateSyncingActions({ + databaseDocumentID, +}: { + /** + * The `_id` of an event in ES. Used to determine the origin of the Resolver graph. + */ + databaseDocumentID?: string; +}) { + const dispatch = useResolverDispatch(); + useLayoutEffect(() => { + dispatch({ + type: 'appReceivedNewExternalProperties', + payload: { databaseDocumentID }, + }); + }, [dispatch, databaseDocumentID]); +} diff --git a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx index fe38dd79176a5c..1c414246929ab4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/graph_overlay/index.tsx @@ -4,13 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiTitle, -} from '@elastic/eui'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { useCallback, useState } from 'react'; import { connect, ConnectedProps, useDispatch, useSelector } from 'react-redux'; @@ -31,6 +25,7 @@ import { setInsertTimeline, updateTimelineGraphEventId, } from '../../../timelines/store/timeline/actions'; +import { Resolver } from '../../../resolver/view'; import * as i18n from './translations'; @@ -39,6 +34,10 @@ const OverlayContainer = styled.div<{ bodyHeight?: number }>` width: 100%; `; +const StyledResolver = styled(Resolver)` + height: 100%; +`; + interface OwnProps { bodyHeight?: number; graphEventId?: string; @@ -117,9 +116,7 @@ const GraphOverlayComponent = ({ - - <>{`Resolver graph for event _id ${graphEventId}`} - + ({ overflow: auto; scrollbar-width: thin; flex: 1; - visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')}; + display: ${({ visible }) => (visible ? 'block' : 'none')}; &::-webkit-scrollbar { height: ${({ theme }) => theme.eui.euiScrollBar}; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts index 9b45a1a6c5354d..5c92b23d594de7 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver.ts @@ -12,12 +12,14 @@ import { validateChildren, validateAncestry, validateAlerts, + validateEntities, } from '../../../common/endpoint/schema/resolver'; import { handleEvents } from './resolver/events'; import { handleChildren } from './resolver/children'; import { handleAncestry } from './resolver/ancestry'; import { handleTree } from './resolver/tree'; import { handleAlerts } from './resolver/alerts'; +import { handleEntities } from './resolver/entity'; export function registerResolverRoutes(router: IRouter, endpointAppContext: EndpointAppContext) { const log = endpointAppContext.logFactory.get('resolver'); @@ -66,4 +68,16 @@ export function registerResolverRoutes(router: IRouter, endpointAppContext: Endp }, handleTree(log, endpointAppContext) ); + + /** + * Used to get details about an entity, aka process. + */ + router.get( + { + path: '/api/endpoint/resolver/entity', + validate: validateEntities, + options: { authRequired: true }, + }, + handleEntities() + ); } diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity.ts new file mode 100644 index 00000000000000..69b3780ec1683a --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { RequestHandler } from 'kibana/server'; +import { TypeOf } from '@kbn/config-schema'; +import { validateEntities } from '../../../../common/endpoint/schema/resolver'; +import { ResolverEntityIndex } from '../../../../common/endpoint/types'; + +/** + * This is used to get an 'entity_id' which is an internal-to-Resolver concept, from an `_id`, which + * is the artificial ID generated by ES for each document. + */ +export function handleEntities(): RequestHandler> { + return async (context, request, response) => { + const { + query: { _id, indices }, + } = request; + + /** + * A safe type for the response based on the semantics of the query. + * We specify _source, asking for `process.entity_id` and we only + * accept documents that have it. + * Also, we only request 1 document. + */ + interface ExpectedQueryResponse { + hits: { + hits: + | [] + | [ + { + _source: { + process: { + entity_id: string; + }; + }; + } + ]; + }; + } + + const queryResponse: ExpectedQueryResponse = await context.core.elasticsearch.legacy.client.callAsCurrentUser( + 'search', + { + index: indices, + body: { + // only return process.entity_id + _source: 'process.entity_id', + // only return 1 match at most + size: 1, + query: { + bool: { + filter: [ + { + // only return documents with the matching _id + ids: { + values: _id, + }, + }, + { + exists: { + // only return documents that have process.entity_id + field: 'process.entity_id', + }, + }, + ], + }, + }, + }, + } + ); + + const responseBody: ResolverEntityIndex = []; + for (const { + _source: { + process: { entity_id }, + }, + } of queryResponse.hits.hits) { + responseBody.push({ + entity_id, + }); + } + return response.ok({ body: responseBody }); + }; +} From 3e48426e9df7bcf420177c90d910ce237f70ccad Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Mon, 29 Jun 2020 22:58:08 +0200 Subject: [PATCH 15/91] [7.x] [APM] Run API tests as restricted user (#70050) (#70204) --- x-pack/plugins/apm/readme.md | 25 ++++- .../basic/tests/agent_configuration.ts | 11 +- .../basic/tests/annotations.ts | 6 +- .../basic/tests/custom_link.ts | 11 +- .../basic/tests/feature_controls.ts | 2 +- .../common/authentication.ts | 102 ++++++++++++++++++ .../test/apm_api_integration/common/config.ts | 42 +++++++- .../common/ftr_provider_context.ts | 14 ++- .../trial/tests/annotations.ts | 9 +- 9 files changed, 197 insertions(+), 25 deletions(-) create mode 100644 x-pack/test/apm_api_integration/common/authentication.ts diff --git a/x-pack/plugins/apm/readme.md b/x-pack/plugins/apm/readme.md index cb694712d7c97b..778b1f2ad2d91b 100644 --- a/x-pack/plugins/apm/readme.md +++ b/x-pack/plugins/apm/readme.md @@ -80,19 +80,38 @@ For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme) ### API integration tests +Our tests are separated in two suites: one suite runs with a basic license, and the other +with a trial license (the equivalent of gold+). This requires separate test servers and test runs. + **Start server** +Basic: + +``` +node scripts/functional_tests_server --config x-pack/test/apm_api_integration/basic/config.ts +``` + +Trial: + ``` -node scripts/functional_tests_server --config x-pack/test/api_integration/config.ts +node scripts/functional_tests_server --config x-pack/test/apm_api_integration/trial/config.ts ``` **Run tests** +Basic: + +``` +node scripts/functional_test_runner --config x-pack/test/apm_api_integration/basic/config.ts +``` + +Trial: + ``` -node scripts/functional_test_runner --config x-pack/test/api_integration/config.ts --grep='APM specs' +node scripts/functional_test_runner --config x-pack/test/apm_api_integration/trial/config.ts ``` -APM tests are located in `x-pack/test/api_integration/apis/apm`. +APM tests are located in `x-pack/test/apm_api_integration`. For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme) ### Linting diff --git a/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts b/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts index f6750a8eca24e7..9f39da2037f8ea 100644 --- a/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts +++ b/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts @@ -10,11 +10,12 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function agentConfigurationTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertestRead = getService('supertestAsApmReadUser'); + const supertestWrite = getService('supertestAsApmWriteUser'); const log = getService('log'); function searchConfigurations(configuration: any) { - return supertest + return supertestRead .post(`/api/apm/settings/agent-configuration/search`) .send(configuration) .set('kbn-xsrf', 'foo'); @@ -22,7 +23,7 @@ export default function agentConfigurationTests({ getService }: FtrProviderConte async function createConfiguration(config: AgentConfigurationIntake) { log.debug('creating configuration', config.service); - const res = await supertest + const res = await supertestWrite .put(`/api/apm/settings/agent-configuration`) .send(config) .set('kbn-xsrf', 'foo'); @@ -34,7 +35,7 @@ export default function agentConfigurationTests({ getService }: FtrProviderConte async function updateConfiguration(config: AgentConfigurationIntake) { log.debug('updating configuration', config.service); - const res = await supertest + const res = await supertestWrite .put(`/api/apm/settings/agent-configuration?overwrite=true`) .send(config) .set('kbn-xsrf', 'foo'); @@ -46,7 +47,7 @@ export default function agentConfigurationTests({ getService }: FtrProviderConte async function deleteConfiguration({ service }: AgentConfigurationIntake) { log.debug('deleting configuration', service); - const res = await supertest + const res = await supertestWrite .delete(`/api/apm/settings/agent-configuration`) .send({ service }) .set('kbn-xsrf', 'foo'); diff --git a/x-pack/test/apm_api_integration/basic/tests/annotations.ts b/x-pack/test/apm_api_integration/basic/tests/annotations.ts index d4b4892eaf91cd..c522ebcfb5c65e 100644 --- a/x-pack/test/apm_api_integration/basic/tests/annotations.ts +++ b/x-pack/test/apm_api_integration/basic/tests/annotations.ts @@ -10,15 +10,15 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function annotationApiTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertestWrite = getService('supertestAsApmAnnotationsWriteUser'); function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) { switch (method.toLowerCase()) { case 'post': - return supertest.post(url).send(data).set('kbn-xsrf', 'foo'); + return supertestWrite.post(url).send(data).set('kbn-xsrf', 'foo'); default: - throw new Error(`Unsupported methoed ${method}`); + throw new Error(`Unsupported method ${method}`); } } diff --git a/x-pack/test/apm_api_integration/basic/tests/custom_link.ts b/x-pack/test/apm_api_integration/basic/tests/custom_link.ts index 910c4797f39b76..77fdc83523ca64 100644 --- a/x-pack/test/apm_api_integration/basic/tests/custom_link.ts +++ b/x-pack/test/apm_api_integration/basic/tests/custom_link.ts @@ -10,7 +10,8 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function customLinksTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertestRead = getService('supertestAsApmReadUser'); + const supertestWrite = getService('supertestAsApmWriteUser'); const log = getService('log'); function searchCustomLinks(filters?: any) { @@ -18,12 +19,12 @@ export default function customLinksTests({ getService }: FtrProviderContext) { pathname: `/api/apm/settings/custom_links`, query: filters, }); - return supertest.get(path).set('kbn-xsrf', 'foo'); + return supertestRead.get(path).set('kbn-xsrf', 'foo'); } async function createCustomLink(customLink: CustomLink) { log.debug('creating configuration', customLink); - const res = await supertest + const res = await supertestWrite .post(`/api/apm/settings/custom_links`) .send(customLink) .set('kbn-xsrf', 'foo'); @@ -35,7 +36,7 @@ export default function customLinksTests({ getService }: FtrProviderContext) { async function updateCustomLink(id: string, customLink: CustomLink) { log.debug('updating configuration', id, customLink); - const res = await supertest + const res = await supertestWrite .put(`/api/apm/settings/custom_links/${id}`) .send(customLink) .set('kbn-xsrf', 'foo'); @@ -47,7 +48,7 @@ export default function customLinksTests({ getService }: FtrProviderContext) { async function deleteCustomLink(id: string) { log.debug('deleting configuration', id); - const res = await supertest + const res = await supertestWrite .delete(`/api/apm/settings/custom_links/${id}`) .set('kbn-xsrf', 'foo'); diff --git a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts index f3647c65106c92..42cbef69abbec9 100644 --- a/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts +++ b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function featureControlsTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertest = getService('supertestAsApmWriteUser'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const security = getService('security'); const spaces = getService('spaces'); diff --git a/x-pack/test/apm_api_integration/common/authentication.ts b/x-pack/test/apm_api_integration/common/authentication.ts new file mode 100644 index 00000000000000..9c34b4791114a4 --- /dev/null +++ b/x-pack/test/apm_api_integration/common/authentication.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PromiseReturnType } from '../../../plugins/apm/typings/common'; +import { SecurityServiceProvider } from '../../../../test/common/services/security'; + +type SecurityService = PromiseReturnType; + +export enum ApmUser { + apmReadUser = 'apm_read_user', + apmWriteUser = 'apm_write_user', + apmAnnotationsWriteUser = 'apm_annotations_write_user', +} + +const roles = { + [ApmUser.apmReadUser]: { + elasticsearch: { + cluster: [], + indices: [ + { names: ['observability-annotations'], privileges: ['read', 'view_index_metadata'] }, + ], + }, + kibana: [ + { + base: [], + feature: { + apm: ['read'], + }, + spaces: ['*'], + }, + ], + }, + [ApmUser.apmWriteUser]: { + elasticsearch: { + cluster: [], + indices: [ + { names: ['observability-annotations'], privileges: ['read', 'view_index_metadata'] }, + ], + }, + kibana: [ + { + base: [], + feature: { + apm: ['all'], + }, + spaces: ['*'], + }, + ], + }, + [ApmUser.apmAnnotationsWriteUser]: { + elasticsearch: { + cluster: [], + indices: [ + { + names: ['observability-annotations'], + privileges: [ + 'read', + 'view_index_metadata', + 'index', + 'manage', + 'create_index', + 'create_doc', + ], + }, + ], + }, + }, +}; + +const users = { + [ApmUser.apmReadUser]: { + roles: ['apm_user', ApmUser.apmReadUser], + }, + [ApmUser.apmWriteUser]: { + roles: ['apm_user', ApmUser.apmWriteUser], + }, + [ApmUser.apmAnnotationsWriteUser]: { + roles: ['apm_user', ApmUser.apmWriteUser, ApmUser.apmAnnotationsWriteUser], + }, +}; + +export async function createApmUser(security: SecurityService, apmUser: ApmUser) { + const role = roles[apmUser]; + const user = users[apmUser]; + + if (!role || !user) { + throw new Error(`No configuration found for ${apmUser}`); + } + + await security.role.create(apmUser, role); + + await security.user.create(apmUser, { + full_name: apmUser, + password: APM_TEST_PASSWORD, + roles: user.roles, + }); +} + +export const APM_TEST_PASSWORD = 'changeme'; diff --git a/x-pack/test/apm_api_integration/common/config.ts b/x-pack/test/apm_api_integration/common/config.ts index 83dc597829a3cd..e4dc2a78ae0189 100644 --- a/x-pack/test/apm_api_integration/common/config.ts +++ b/x-pack/test/apm_api_integration/common/config.ts @@ -5,6 +5,11 @@ */ import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; +import supertestAsPromised from 'supertest-as-promised'; +import { format, UrlObject } from 'url'; +import { InheritedFtrProviderContext, InheritedServices } from './ftr_provider_context'; +import { PromiseReturnType } from '../../../plugins/apm/typings/common'; +import { createApmUser, APM_TEST_PASSWORD, ApmUser } from './authentication'; interface Settings { license: 'basic' | 'trial'; @@ -12,6 +17,22 @@ interface Settings { name: string; } +const supertestAsApmUser = (kibanaServer: UrlObject, apmUser: ApmUser) => async ( + context: InheritedFtrProviderContext +) => { + const security = context.getService('security'); + await security.init(); + + await createApmUser(security, apmUser); + + const url = format({ + ...kibanaServer, + auth: `${apmUser}:${APM_TEST_PASSWORD}`, + }); + + return supertestAsPromised(url); +}; + export function createTestConfig(settings: Settings) { const { testFiles, license, name } = settings; @@ -20,14 +41,27 @@ export function createTestConfig(settings: Settings) { require.resolve('../../api_integration/config.ts') ); + const services = xPackAPITestsConfig.get('services') as InheritedServices; + const servers = xPackAPITestsConfig.get('servers'); + + const supertestAsApmReadUser = supertestAsApmUser(servers.kibana, ApmUser.apmReadUser); + return { testFiles, - servers: xPackAPITestsConfig.get('servers'), - services: xPackAPITestsConfig.get('services'), + servers, + services: { + ...services, + supertest: supertestAsApmReadUser, + supertestAsApmReadUser, + supertestAsApmWriteUser: supertestAsApmUser(servers.kibana, ApmUser.apmWriteUser), + supertestAsApmAnnotationsWriteUser: supertestAsApmUser( + servers.kibana, + ApmUser.apmAnnotationsWriteUser + ), + }, junit: { reportName: name, }, - esTestCluster: { ...xPackAPITestsConfig.get('esTestCluster'), license, @@ -36,3 +70,5 @@ export function createTestConfig(settings: Settings) { }; }; } + +export type ApmServices = PromiseReturnType>['services']; diff --git a/x-pack/test/apm_api_integration/common/ftr_provider_context.ts b/x-pack/test/apm_api_integration/common/ftr_provider_context.ts index 90600816d17114..aee3d556605aa6 100644 --- a/x-pack/test/apm_api_integration/common/ftr_provider_context.ts +++ b/x-pack/test/apm_api_integration/common/ftr_provider_context.ts @@ -4,4 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -export { FtrProviderContext } from '../../api_integration/ftr_provider_context'; +import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; +import { FtrProviderContext as InheritedFtrProviderContext } from '../../api_integration/ftr_provider_context'; +import { ApmServices } from './config'; + +export type InheritedServices = InheritedFtrProviderContext extends GenericFtrProviderContext< + infer TServices, + {} +> + ? TServices + : {}; + +export { InheritedFtrProviderContext }; +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/apm_api_integration/trial/tests/annotations.ts b/x-pack/test/apm_api_integration/trial/tests/annotations.ts index 0913d0c4b90bb6..d5b6b8342e5ab2 100644 --- a/x-pack/test/apm_api_integration/trial/tests/annotations.ts +++ b/x-pack/test/apm_api_integration/trial/tests/annotations.ts @@ -13,7 +13,8 @@ const DEFAULT_INDEX_NAME = 'observability-annotations'; // eslint-disable-next-line import/no-default-export export default function annotationApiTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const supertestRead = getService('supertestAsApmReadUser'); + const supertestWrite = getService('supertestAsApmAnnotationsWriteUser'); const es = getService('es'); function expectContainsObj(source: JsonObject, expected: JsonObject) { @@ -30,13 +31,13 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) { switch (method.toLowerCase()) { case 'get': - return supertest.get(url).set('kbn-xsrf', 'foo'); + return supertestRead.get(url).set('kbn-xsrf', 'foo'); case 'post': - return supertest.post(url).send(data).set('kbn-xsrf', 'foo'); + return supertestWrite.post(url).send(data).set('kbn-xsrf', 'foo'); default: - throw new Error(`Unsupported methoed ${method}`); + throw new Error(`Unsupported method ${method}`); } } From e0e276e1e4ac4ebce24792a172408dc0dc7061d2 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Mon, 29 Jun 2020 15:21:38 -0600 Subject: [PATCH 16/91] [data.search.aggs] Remove date histogram dependency on timefilter (#69858) (#70249) --- ...bana-plugin-plugins-data-server.gettime.md | 27 +++++++++++++++ .../kibana-plugin-plugins-data-server.md | 1 + src/plugins/data/common/index.ts | 1 - src/plugins/data/common/query/index.ts | 1 + .../query/timefilter/get_time.test.ts | 0 .../query/timefilter/get_time.ts | 8 +++-- .../common/{ => query}/timefilter/index.ts | 3 +- .../{ => query}/timefilter/is_time_range.ts | 0 .../common/{ => query}/timefilter/types.ts | 7 ++++ src/plugins/data/common/query/types.ts | 2 ++ src/plugins/data/common/types.ts | 1 - src/plugins/data/public/index.ts | 2 +- src/plugins/data/public/plugin.ts | 1 - .../data/public/query/timefilter/index.ts | 1 - .../query/timefilter/lib/get_force_now.ts | 34 +++++++++++++++++++ .../query/timefilter/lib/parse_querystring.ts | 1 + .../public/query/timefilter/timefilter.ts | 16 ++------- .../data/public/query/timefilter/types.ts | 7 ++-- .../data/public/search/aggs/agg_types.ts | 15 ++++---- .../create_filter/date_histogram.test.ts | 5 ++- .../search/aggs/buckets/date_histogram.ts | 34 ++++++++++--------- .../data/public/search/aggs/index.test.ts | 5 ++- .../test_helpers/mock_agg_types_registry.ts | 5 ++- .../data/public/search/expressions/esaggs.ts | 12 +++++-- .../data/public/search/search_service.ts | 17 +++++++--- src/plugins/data/server/index.ts | 1 + src/plugins/data/server/server.api.md | 8 +++++ 27 files changed, 149 insertions(+), 66 deletions(-) create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.gettime.md rename src/plugins/data/{public => common}/query/timefilter/get_time.test.ts (100%) rename src/plugins/data/{public => common}/query/timefilter/get_time.ts (90%) rename src/plugins/data/common/{ => query}/timefilter/index.ts (92%) rename src/plugins/data/common/{ => query}/timefilter/is_time_range.ts (100%) rename src/plugins/data/common/{ => query}/timefilter/types.ts (88%) create mode 100644 src/plugins/data/public/query/timefilter/lib/get_force_now.ts diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.gettime.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.gettime.md new file mode 100644 index 00000000000000..54e7cf92f500cf --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.gettime.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [getTime](./kibana-plugin-plugins-data-server.gettime.md) + +## getTime() function + +Signature: + +```typescript +export declare function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, options?: { + forceNow?: Date; + fieldName?: string; +}): import("../..").RangeFilter | undefined; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| indexPattern | IIndexPattern | undefined | | +| timeRange | TimeRange | | +| options | {
forceNow?: Date;
fieldName?: string;
} | | + +Returns: + +`import("../..").RangeFilter | undefined` + diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index f492ba2843a697..c80112fb17dde5 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -23,6 +23,7 @@ | Function | Description | | --- | --- | | [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | | [shouldReadFieldFromDocValues(aggregatable, esType)](./kibana-plugin-plugins-data-server.shouldreadfieldfromdocvalues.md) | | diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts index b40e02b709d301..0fb45fcc739d45 100644 --- a/src/plugins/data/common/index.ts +++ b/src/plugins/data/common/index.ts @@ -26,6 +26,5 @@ export * from './kbn_field_types'; export * from './query'; export * from './search'; export * from './search/aggs'; -export * from './timefilter'; export * from './types'; export * from './utils'; diff --git a/src/plugins/data/common/query/index.ts b/src/plugins/data/common/query/index.ts index 4e90f6f8bb83ec..b0dfbbb82355e0 100644 --- a/src/plugins/data/common/query/index.ts +++ b/src/plugins/data/common/query/index.ts @@ -18,5 +18,6 @@ */ export * from './filter_manager'; +export * from './timefilter'; export * from './types'; export * from './is_query'; diff --git a/src/plugins/data/public/query/timefilter/get_time.test.ts b/src/plugins/data/common/query/timefilter/get_time.test.ts similarity index 100% rename from src/plugins/data/public/query/timefilter/get_time.test.ts rename to src/plugins/data/common/query/timefilter/get_time.test.ts diff --git a/src/plugins/data/public/query/timefilter/get_time.ts b/src/plugins/data/common/query/timefilter/get_time.ts similarity index 90% rename from src/plugins/data/public/query/timefilter/get_time.ts rename to src/plugins/data/common/query/timefilter/get_time.ts index 3706972ce4a2ef..6e4eda95accc73 100644 --- a/src/plugins/data/public/query/timefilter/get_time.ts +++ b/src/plugins/data/common/query/timefilter/get_time.ts @@ -18,14 +18,16 @@ */ import dateMath from '@elastic/datemath'; -import { IIndexPattern } from '../..'; -import { TimeRange, buildRangeFilter } from '../../../common'; +import { buildRangeFilter, IIndexPattern, TimeRange, TimeRangeBounds } from '../..'; interface CalculateBoundsOptions { forceNow?: Date; } -export function calculateBounds(timeRange: TimeRange, options: CalculateBoundsOptions = {}) { +export function calculateBounds( + timeRange: TimeRange, + options: CalculateBoundsOptions = {} +): TimeRangeBounds { return { min: dateMath.parse(timeRange.from, { forceNow: options.forceNow }), max: dateMath.parse(timeRange.to, { roundUp: true, forceNow: options.forceNow }), diff --git a/src/plugins/data/common/timefilter/index.ts b/src/plugins/data/common/query/timefilter/index.ts similarity index 92% rename from src/plugins/data/common/timefilter/index.ts rename to src/plugins/data/common/query/timefilter/index.ts index e0c509e119fda1..55739511a0ef54 100644 --- a/src/plugins/data/common/timefilter/index.ts +++ b/src/plugins/data/common/query/timefilter/index.ts @@ -17,4 +17,5 @@ * under the License. */ -export { isTimeRange } from './is_time_range'; +export * from './get_time'; +export * from './is_time_range'; diff --git a/src/plugins/data/common/timefilter/is_time_range.ts b/src/plugins/data/common/query/timefilter/is_time_range.ts similarity index 100% rename from src/plugins/data/common/timefilter/is_time_range.ts rename to src/plugins/data/common/query/timefilter/is_time_range.ts diff --git a/src/plugins/data/common/timefilter/types.ts b/src/plugins/data/common/query/timefilter/types.ts similarity index 88% rename from src/plugins/data/common/timefilter/types.ts rename to src/plugins/data/common/query/timefilter/types.ts index b197b16e67dd11..60008ce6054e1b 100644 --- a/src/plugins/data/common/timefilter/types.ts +++ b/src/plugins/data/common/query/timefilter/types.ts @@ -17,6 +17,8 @@ * under the License. */ +import { Moment } from 'moment'; + export interface RefreshInterval { pause: boolean; value: number; @@ -27,3 +29,8 @@ export interface TimeRange { to: string; mode?: 'absolute' | 'relative'; } + +export interface TimeRangeBounds { + min: Moment | undefined; + max: Moment | undefined; +} diff --git a/src/plugins/data/common/query/types.ts b/src/plugins/data/common/query/types.ts index 61b5d5b2b7b4ad..6b34a1baf293bc 100644 --- a/src/plugins/data/common/query/types.ts +++ b/src/plugins/data/common/query/types.ts @@ -17,6 +17,8 @@ * under the License. */ +export * from './timefilter/types'; + export interface Query { query: string | { [key: string]: any }; language: string; diff --git a/src/plugins/data/common/types.ts b/src/plugins/data/common/types.ts index 93629c3dbaf626..e2ec1a031b0ca7 100644 --- a/src/plugins/data/common/types.ts +++ b/src/plugins/data/common/types.ts @@ -17,7 +17,6 @@ * under the License. */ -export * from './timefilter/types'; export * from './query/types'; export * from './kbn_field_types/types'; export * from './index_patterns/types'; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 030d462141b09e..2f4978da1ebd8d 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -420,7 +420,6 @@ export { connectToQueryState, syncQueryStateWithUrl, QueryState, - getTime, getQueryLog, getDefaultQuery, FilterManager, @@ -434,6 +433,7 @@ export { } from './query'; export { + getTime, // kbn field types castEsToKbnFieldTypeName, getKbnTypeNames, diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index c3c3d4cb9f4d99..c53fd2d36898c0 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -150,7 +150,6 @@ export class DataPublicPlugin implements Plugin { - const forceNow = parseQueryString().forceNow as string; - if (!forceNow) { - return; - } - - const ticks = Date.parse(forceNow); - if (isNaN(ticks)) { - throw new Error(`forceNow query parameter, ${forceNow}, can't be parsed by Date.parse`); - } - return new Date(ticks); + return getForceNow(); }; } diff --git a/src/plugins/data/public/query/timefilter/types.ts b/src/plugins/data/public/query/timefilter/types.ts index 8b8deea43f808e..d47a9cbb3bd609 100644 --- a/src/plugins/data/public/query/timefilter/types.ts +++ b/src/plugins/data/public/query/timefilter/types.ts @@ -16,7 +16,9 @@ * specific language governing permissions and limitations * under the License. */ + import { Moment } from 'moment'; + import { TimeRange, RefreshInterval } from '../../../common'; export interface TimefilterConfig { @@ -32,7 +34,4 @@ export type InputTimeRange = to: Moment; }; -export interface TimeRangeBounds { - min: Moment | undefined; - max: Moment | undefined; -} +export { TimeRangeBounds } from '../../../common'; diff --git a/src/plugins/data/public/search/aggs/agg_types.ts b/src/plugins/data/public/search/aggs/agg_types.ts index 2af29d36002460..68542b66e6c358 100644 --- a/src/plugins/data/public/search/aggs/agg_types.ts +++ b/src/plugins/data/public/search/aggs/agg_types.ts @@ -18,7 +18,8 @@ */ import { IUiSettingsClient } from 'src/core/public'; -import { QuerySetup } from '../../query/query_service'; +import { TimeRange, TimeRangeBounds } from '../../../common'; +import { GetInternalStartServicesFn } from '../../types'; import { getCountMetricAgg } from './metrics/count'; import { getAvgMetricAgg } from './metrics/avg'; @@ -54,18 +55,16 @@ import { getBucketAvgMetricAgg } from './metrics/bucket_avg'; import { getBucketMinMetricAgg } from './metrics/bucket_min'; import { getBucketMaxMetricAgg } from './metrics/bucket_max'; -import { GetInternalStartServicesFn } from '../../types'; - export interface AggTypesDependencies { - uiSettings: IUiSettingsClient; - query: QuerySetup; + calculateBounds: (timeRange: TimeRange) => TimeRangeBounds; getInternalStartServices: GetInternalStartServicesFn; + uiSettings: IUiSettingsClient; } export const getAggTypes = ({ - uiSettings, - query, + calculateBounds, getInternalStartServices, + uiSettings, }: AggTypesDependencies) => ({ metrics: [ getCountMetricAgg({ getInternalStartServices }), @@ -91,7 +90,7 @@ export const getAggTypes = ({ getGeoCentroidMetricAgg({ getInternalStartServices }), ], buckets: [ - getDateHistogramBucketAgg({ uiSettings, query, getInternalStartServices }), + getDateHistogramBucketAgg({ calculateBounds, uiSettings, getInternalStartServices }), getHistogramBucketAgg({ uiSettings, getInternalStartServices }), getRangeBucketAgg({ getInternalStartServices }), getDateRangeBucketAgg({ uiSettings, getInternalStartServices }), diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts index bcdc003707e752..518bdbfe0c1352 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts @@ -30,7 +30,6 @@ import { import { BUCKET_TYPES } from '../bucket_agg_types'; import { RangeFilter } from '../../../../../common'; import { coreMock, notificationServiceMock } from '../../../../../../../core/public/mocks'; -import { queryServiceMock } from '../../../../query/mocks'; import { fieldFormatsServiceMock } from '../../../../field_formats/mocks'; import { InternalStartServices } from '../../../../types'; @@ -46,13 +45,13 @@ describe('AggConfig Filters', () => { const { uiSettings } = coreMock.createSetup(); aggTypesDependencies = { - uiSettings, - query: queryServiceMock.createSetupContract(), + calculateBounds: jest.fn(), getInternalStartServices: () => (({ fieldFormats: fieldFormatsServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), } as unknown) as InternalStartServices), + uiSettings, }; mockDataServices(); diff --git a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts index 5b0f2921570c25..e4c4bc0cedc3c4 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts @@ -27,28 +27,30 @@ import { BucketAggType, IBucketAggConfig } from './bucket_agg_type'; import { BUCKET_TYPES } from './bucket_agg_types'; import { createFilterDateHistogram } from './create_filter/date_histogram'; import { intervalOptions } from './_interval_options'; -import { dateHistogramInterval, TimeRange } from '../../../../common'; import { writeParams } from '../agg_params'; import { isMetricAggType } from '../metrics/metric_agg_type'; -import { KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common'; -import { TimefilterContract } from '../../../query'; -import { QuerySetup } from '../../../query/query_service'; +import { + dateHistogramInterval, + KBN_FIELD_TYPES, + TimeRange, + TimeRangeBounds, + UI_SETTINGS, +} from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; import { BaseAggParams } from '../types'; import { ExtendedBounds } from './lib/extended_bounds'; -const detectedTimezone = moment.tz.guess(); -const tzOffset = moment().format('Z'); +type CalculateBoundsFn = (timeRange: TimeRange) => TimeRangeBounds; const updateTimeBuckets = ( agg: IBucketDateHistogramAggConfig, - timefilter: TimefilterContract, + calculateBounds: CalculateBoundsFn, customBuckets?: IBucketDateHistogramAggConfig['buckets'] ) => { const bounds = agg.params.timeRange && (agg.fieldIsTimeField() || agg.params.interval === 'auto') - ? timefilter.calculateBounds(agg.params.timeRange) + ? calculateBounds(agg.params.timeRange) : undefined; const buckets = customBuckets || agg.buckets; buckets.setBounds(bounds); @@ -56,9 +58,9 @@ const updateTimeBuckets = ( }; export interface DateHistogramBucketAggDependencies { - uiSettings: IUiSettingsClient; - query: QuerySetup; + calculateBounds: CalculateBoundsFn; getInternalStartServices: GetInternalStartServicesFn; + uiSettings: IUiSettingsClient; } export interface IBucketDateHistogramAggConfig extends IBucketAggConfig { @@ -83,9 +85,9 @@ export interface AggParamsDateHistogram extends BaseAggParams { } export const getDateHistogramBucketAgg = ({ - uiSettings, - query, + calculateBounds, getInternalStartServices, + uiSettings, }: DateHistogramBucketAggDependencies) => new BucketAggType( { @@ -123,14 +125,13 @@ export const getDateHistogramBucketAgg = ({ get() { if (buckets) return buckets; - const { timefilter } = query.timefilter; buckets = new TimeBuckets({ 'histogram:maxBars': uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS), 'histogram:barTarget': uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET), dateFormat: uiSettings.get('dateFormat'), 'dateFormat:scaled': uiSettings.get('dateFormat:scaled'), }); - updateTimeBuckets(this, timefilter, buckets); + updateTimeBuckets(this, calculateBounds, buckets); return buckets; }, @@ -195,8 +196,7 @@ export const getDateHistogramBucketAgg = ({ default: 'auto', options: intervalOptions, write(agg, output, aggs) { - const { timefilter } = query.timefilter; - updateTimeBuckets(agg, timefilter); + updateTimeBuckets(agg, calculateBounds); const { useNormalizedEsInterval, scaleMetricValues } = agg.params; const interval = agg.buckets.getInterval(useNormalizedEsInterval); @@ -257,6 +257,8 @@ export const getDateHistogramBucketAgg = ({ if (!tz) { // If the index pattern typeMeta data, didn't had a time zone assigned for the selected field use the configured tz const isDefaultTimezone = uiSettings.isDefault('dateFormat:tz'); + const detectedTimezone = moment.tz.guess(); + const tzOffset = moment().format('Z'); tz = isDefaultTimezone ? detectedTimezone || tzOffset : uiSettings.get('dateFormat:tz'); diff --git a/src/plugins/data/public/search/aggs/index.test.ts b/src/plugins/data/public/search/aggs/index.test.ts index 4864a8b9d013bb..73068326ca97ee 100644 --- a/src/plugins/data/public/search/aggs/index.test.ts +++ b/src/plugins/data/public/search/aggs/index.test.ts @@ -22,7 +22,6 @@ import { getAggTypes } from './index'; import { isBucketAggType } from './buckets/bucket_agg_type'; import { isMetricAggType } from './metrics/metric_agg_type'; -import { QueryStart } from '../../query'; import { FieldFormatsStart } from '../../field_formats'; import { InternalStartServices } from '../../types'; @@ -31,13 +30,13 @@ describe('AggTypesComponent', () => { const coreStart = coreMock.createSetup(); const aggTypes = getAggTypes({ - uiSettings: coreSetup.uiSettings, - query: {} as QueryStart, + calculateBounds: jest.fn(), getInternalStartServices: () => (({ notifications: coreStart.notifications, fieldFormats: {} as FieldFormatsStart, } as unknown) as InternalStartServices), + uiSettings: coreSetup.uiSettings, }); const { buckets, metrics } = aggTypes; diff --git a/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts b/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts index 836aaad2cda0c3..385d0cd6c6b396 100644 --- a/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts +++ b/src/plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts @@ -22,7 +22,6 @@ import { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry'; import { getAggTypes } from '../agg_types'; import { BucketAggType } from '../buckets/bucket_agg_type'; import { MetricAggType } from '../metrics/metric_agg_type'; -import { queryServiceMock } from '../../../query/mocks'; import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; import { InternalStartServices } from '../../../types'; import { TimeBucketsConfig } from '../buckets/lib/time_buckets/time_buckets'; @@ -79,8 +78,7 @@ export function mockAggTypesRegistry | MetricAggTyp coreSetup.uiSettings.get = mockUiSettings; const aggTypes = getAggTypes({ - uiSettings: coreSetup.uiSettings, - query: queryServiceMock.createSetupContract(), + calculateBounds: jest.fn(), getInternalStartServices: () => (({ fieldFormats: fieldFormatsServiceMock.createStartContract(), @@ -88,6 +86,7 @@ export function mockAggTypesRegistry | MetricAggTyp uiSettings: coreStart.uiSettings, injectedMetadata: coreStart.injectedMetadata, } as unknown) as InternalStartServices), + uiSettings: coreSetup.uiSettings, }); aggTypes.buckets.forEach((type) => registrySetup.registerBucket(type)); diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index d9ca378811e515..e9daec0b4191b6 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -32,8 +32,16 @@ import { Adapters } from '../../../../../plugins/inspector/public'; import { IAggConfigs } from '../aggs'; import { ISearchSource } from '../search_source'; import { tabifyAggResponse } from '../tabify'; -import { Filter, Query, TimeRange, IIndexPattern, isRangeFilter } from '../../../common'; -import { FilterManager, calculateBounds, getTime } from '../../query'; +import { + calculateBounds, + Filter, + getTime, + IIndexPattern, + isRangeFilter, + Query, + TimeRange, +} from '../../../common'; +import { FilterManager } from '../../query'; import { getFieldFormats, getIndexPatterns, diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 992979ad0dbb0f..134dc89c2421a0 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -25,10 +25,11 @@ import { ExpressionsSetup } from '../../../../plugins/expressions/public'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; import { TStrategyTypes } from './strategy_types'; import { getEsClient, LegacyApiCaller } from './legacy'; +import { getForceNow } from '../query/timefilter/lib/get_force_now'; +import { calculateBounds, TimeRange } from '../../common/query'; import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search'; import { esSearchStrategyProvider } from './es_search'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; -import { QuerySetup } from '../query'; import { GetInternalStartServicesFn } from '../types'; import { SearchInterceptor } from './search_interceptor'; import { @@ -44,7 +45,6 @@ interface SearchServiceSetupDependencies { expressions: ExpressionsSetup; getInternalStartServices: GetInternalStartServicesFn; packageInfo: PackageInfo; - query: QuerySetup; } interface SearchServiceStartDependencies { @@ -83,9 +83,16 @@ export class SearchService implements Plugin { return strategy; }; + /** + * getForceNow uses window.location, so we must have a separate implementation + * of calculateBounds on the client and the server. + */ + private calculateBounds = (timeRange: TimeRange) => + calculateBounds(timeRange, { forceNow: getForceNow() }); + public setup( core: CoreSetup, - { expressions, packageInfo, query, getInternalStartServices }: SearchServiceSetupDependencies + { expressions, packageInfo, getInternalStartServices }: SearchServiceSetupDependencies ): ISearchSetup { this.esClient = getEsClient(core.injectedMetadata, core.http, packageInfo); @@ -98,9 +105,9 @@ export class SearchService implements Plugin { // register each agg type const aggTypes = getAggTypes({ - query, - uiSettings: core.uiSettings, + calculateBounds: this.calculateBounds, getInternalStartServices, + uiSettings: core.uiSettings, }); aggTypes.buckets.forEach((b) => aggTypesSetup.registerBucket(b)); aggTypes.metrics.forEach((m) => aggTypesSetup.registerMetric(m)); diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 19d028c1d41e1b..6a4eb38b552ffb 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -202,6 +202,7 @@ export { castEsToKbnFieldTypeName, // query Filter, + getTime, Query, // timefilter RefreshInterval, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index f2a40fd48d7c1e..8c6137e95333d4 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -335,6 +335,14 @@ export function getDefaultSearchParams(config: SharedGlobalConfig): { restTotalHitsAsInt: boolean; }; +// Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, options?: { + forceNow?: Date; + fieldName?: string; +}): import("../..").RangeFilter | undefined; + // @internal export function getTotalLoaded({ total, failed, successful }: ShardsResponse): { total: number; From ecd2082e73b11f73ca8b65e189a239641c8a4931 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Mon, 29 Jun 2020 23:24:04 +0200 Subject: [PATCH 17/91] [7.x] Move and rename legacy elasticsearch client (#69797) (#70221) * Move and rename legacy elasticsearch client (#69797) * move last snapshot to inline * move legacy files to legacy subfolder * move request types out of legacy * export Headers from http instead of elasticsearch * renaming - first pass * renaming - second pass * fix core mocks * adapt new calls * update generated doc * fix IT test mocks * fix new usages # Conflicts: # src/core/server/saved_objects/service/lib/repository.ts # x-pack/plugins/event_log/server/es/context.test.ts # x-pack/plugins/oss_telemetry/server/test_utils/index.ts # x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts * fix usages --- ...ibana-plugin-core-server.callapioptions.md | 21 - ...core-server.clusterclient._constructor_.md | 22 - ...ugin-core-server.clusterclient.asscoped.md | 24 - ...server.clusterclient.callasinternaluser.md | 13 - ...kibana-plugin-core-server.clusterclient.md | 35 - ...n-core-server.elasticsearcherror._code_.md | 11 - ...a-plugin-core-server.elasticsearcherror.md | 19 - ...searcherrorhelpers.isnotauthorizederror.md | 22 - ...server.elasticsearchservicesetup.legacy.md | 4 +- ...n-core-server.elasticsearchservicesetup.md | 2 +- ...server.elasticsearchservicestart.legacy.md | 4 +- ...n-core-server.elasticsearchservicestart.md | 2 +- ...lugin-core-server.ilegacyclusterclient.md} | 8 +- ...core-server.ilegacycustomclusterclient.md} | 8 +- ...core-server.ilegacyscopedclusterclient.md} | 8 +- ...ana-plugin-core-server.legacyapicaller.md} | 6 +- ...plugin-core-server.legacycallapioptions.md | 21 + ...ore-server.legacycallapioptions.signal.md} | 4 +- ...ver.legacycallapioptions.wrap401errors.md} | 4 +- ...erver.legacyclusterclient._constructor_.md | 22 + ...ore-server.legacyclusterclient.asscoped.md | 24 + ....legacyclusterclient.callasinternaluser.md | 13 + ...-core-server.legacyclusterclient.close.md} | 4 +- ...-plugin-core-server.legacyclusterclient.md | 32 + ...server.legacyelasticsearchclientconfig.md} | 6 +- ...-server.legacyelasticsearcherror._code_.md | 11 + ...in-core-server.legacyelasticsearcherror.md | 19 + ...rrorhelpers.decoratenotauthorizederror.md} | 8 +- ...searcherrorhelpers.isnotauthorizederror.md | 22 + ...server.legacyelasticsearcherrorhelpers.md} | 10 +- ...legacyscopedclusterclient._constructor_.md | 22 + ...yscopedclusterclient.callascurrentuser.md} | 10 +- ...scopedclusterclient.callasinternaluser.md} | 10 +- ...n-core-server.legacyscopedclusterclient.md | 26 + .../core/server/kibana-plugin-core-server.md | 22 +- ...-core-server.requesthandlercontext.core.md | 2 +- ...lugin-core-server.requesthandlercontext.md | 4 +- ...erver.scopedclusterclient._constructor_.md | 22 - ...-plugin-core-server.scopedclusterclient.md | 29 - ...rver.indexpatternsfetcher._constructor_.md | 4 +- .../elasticsearch_config.test.ts.snap | 3 - .../elasticsearch_config.test.ts | 4 +- .../elasticsearch_service.mock.ts | 19 +- .../elasticsearch_service.test.mocks.ts | 2 +- .../elasticsearch/elasticsearch_service.ts | 40 +- src/core/server/elasticsearch/index.ts | 19 +- .../elasticsearch/{ => legacy}/api_types.ts | 244 +++---- .../{ => legacy}/cluster_client.test.mocks.ts | 2 +- .../{ => legacy}/cluster_client.test.ts | 45 +- .../{ => legacy}/cluster_client.ts | 82 +-- .../elasticsearch_client_config.test.ts | 6 +- .../elasticsearch_client_config.ts | 14 +- .../elasticsearch/{ => legacy}/errors.test.ts | 24 +- .../elasticsearch/{ => legacy}/errors.ts | 12 +- src/core/server/elasticsearch/legacy/index.ts | 28 + .../{ => legacy}/retry_call_cluster.test.ts | 2 +- .../{ => legacy}/retry_call_cluster.ts | 22 +- .../scoped_cluster_client.test.ts | 11 +- .../{ => legacy}/scoped_cluster_client.ts | 27 +- src/core/server/elasticsearch/types.ts | 47 +- .../version_check/ensure_es_version.ts | 4 +- src/core/server/http/index.ts | 1 + .../core_service.test.mocks.ts | 4 +- src/core/server/index.ts | 28 +- .../saved_objects/saved_objects_service.ts | 10 +- .../saved_objects/service/lib/repository.ts | 17 +- src/core/server/server.api.md | 608 +++++++++--------- .../integration_tests/lib/servers.ts | 6 +- .../core_plugins/elasticsearch/lib/cluster.ts | 8 +- .../fetcher/index_patterns_fetcher.ts | 6 +- .../index_patterns/fetcher/lib/es_api.ts | 6 +- .../field_capabilities/field_capabilities.ts | 4 +- .../fetcher/lib/resolve_time_pattern.ts | 4 +- .../usage_collector/fetch.test.ts | 6 +- .../kql_telemetry/usage_collector/fetch.ts | 4 +- src/plugins/data/server/server.api.md | 4 +- src/plugins/expressions/server/legacy.ts | 4 +- .../kibana/get_saved_object_counts.ts | 4 +- src/plugins/telemetry/server/fetcher.ts | 4 +- .../telemetry_collection/get_cluster_info.ts | 4 +- .../telemetry_collection/get_cluster_stats.ts | 4 +- .../server/telemetry_collection/get_kibana.ts | 4 +- .../telemetry_collection/get_local_license.ts | 6 +- .../register_collection.ts | 4 +- .../server/types.ts | 8 +- .../server/collector/collector.ts | 4 +- .../server/collector/collector_set.ts | 6 +- .../strategies/abstract_search_strategy.ts | 6 +- .../validation_telemetry_service.ts | 4 +- .../database/kibana_database_adapter.ts | 4 +- .../plugins/actions/server/actions_client.ts | 8 +- x-pack/plugins/actions/server/plugin.ts | 4 +- x-pack/plugins/actions/server/types.ts | 10 +- .../actions/server/usage/actions_telemetry.ts | 6 +- x-pack/plugins/actions/server/usage/task.ts | 4 +- .../index_threshold/routes/fields.ts | 4 +- .../index_threshold/routes/indices.ts | 6 +- .../plugins/alerting_builtins/server/types.ts | 4 +- x-pack/plugins/alerts/server/plugin.ts | 4 +- .../server/routes/_mock_handler_arguments.ts | 4 +- x-pack/plugins/alerts/server/types.ts | 10 +- .../alerts/server/usage/alerts_telemetry.ts | 6 +- x-pack/plugins/alerts/server/usage/task.ts | 4 +- .../collect_data_telemetry/index.ts | 4 +- .../get_dynamic_index_pattern.ts | 4 +- .../annotations/get_stored_annotations.ts | 4 +- .../server/lib/services/annotations/index.ts | 4 +- .../create_agent_config_index.ts | 4 +- .../custom_link/create_custom_link_index.ts | 4 +- .../server/plugin.ts | 12 +- .../server/search/es_search_strategy.ts | 6 +- .../server/es/cluster_client_adapter.test.ts | 4 +- .../server/es/cluster_client_adapter.ts | 4 +- .../event_log/server/es/context.test.ts | 4 +- x-pack/plugins/event_log/server/es/context.ts | 4 +- .../event_log/server/event_log_client.ts | 4 +- .../event_log/server/event_log_service.ts | 4 +- .../server/event_log_start_service.ts | 4 +- x-pack/plugins/event_log/server/plugin.ts | 4 +- x-pack/plugins/global_search/server/types.ts | 4 +- .../server/plugin.ts | 10 +- .../api/index/register_add_policy_route.ts | 4 +- .../routes/api/index/register_remove_route.ts | 4 +- .../routes/api/index/register_retry_route.ts | 4 +- .../api/nodes/register_details_route.ts | 4 +- .../routes/api/nodes/register_list_route.ts | 4 +- .../api/policies/register_create_route.ts | 8 +- .../api/policies/register_delete_route.ts | 7 +- .../api/policies/register_fetch_route.ts | 6 +- .../templates/register_add_policy_route.ts | 9 +- .../api/templates/register_fetch_route.ts | 4 +- .../plugins/index_management/server/plugin.ts | 8 +- .../plugins/index_management/server/types.ts | 4 +- .../framework/kibana_framework_adapter.ts | 4 +- ...review_inventory_metric_threshold_alert.ts | 4 +- .../preview_metric_threshold_alert.ts | 4 +- .../log_entry_categories_analysis.ts | 6 +- .../ingest_manager/server/types/index.tsx | 4 +- .../lens/server/routes/existing_fields.ts | 4 +- x-pack/plugins/lens/server/usage/task.ts | 6 +- .../lens/server/usage/visualization_counts.ts | 4 +- .../license_management/server/types.ts | 6 +- .../plugins/licensing/server/plugin.test.ts | 4 +- x-pack/plugins/licensing/server/plugin.ts | 20 +- x-pack/plugins/licensing/server/types.ts | 6 +- .../lists/common/get_call_cluster.mock.ts | 4 +- .../server/services/items/create_list_item.ts | 4 +- .../services/items/create_list_items_bulk.ts | 4 +- .../server/services/items/delete_list_item.ts | 4 +- .../items/delete_list_item_by_value.ts | 4 +- .../server/services/items/find_list_item.ts | 4 +- .../server/services/items/get_list_item.ts | 4 +- .../services/items/get_list_item_by_value.ts | 4 +- .../services/items/get_list_item_by_values.ts | 4 +- .../server/services/items/update_list_item.ts | 4 +- .../items/write_lines_to_bulk_list_items.ts | 6 +- .../items/write_list_items_to_stream.ts | 8 +- .../server/services/lists/create_list.ts | 4 +- .../server/services/lists/delete_list.ts | 4 +- .../lists/server/services/lists/find_list.ts | 4 +- .../lists/server/services/lists/get_list.ts | 4 +- .../server/services/lists/list_client.ts | 4 +- .../services/lists/list_client_types.ts | 4 +- .../server/services/lists/update_list.ts | 4 +- .../services/utils/get_search_after_scroll.ts | 4 +- .../services/utils/scroll_to_start_page.ts | 4 +- x-pack/plugins/lists/server/types.ts | 4 +- .../fetch_all_from_scroll.ts | 4 +- x-pack/plugins/logstash/server/plugin.ts | 4 +- .../server/routes/pipelines/delete.ts | 4 +- .../logstash/server/routes/pipelines/list.ts | 4 +- x-pack/plugins/logstash/server/types.ts | 4 +- .../lib/capabilities/check_capabilities.ts | 4 +- .../ml/server/lib/capabilities/upgrade.ts | 6 +- .../ml/server/lib/check_annotations/index.ts | 4 +- .../annotation_service/annotation.test.ts | 6 +- .../models/annotation_service/annotation.ts | 4 +- .../server/models/annotation_service/index.ts | 4 +- .../bucket_span_estimator.d.ts | 6 +- .../bucket_span_estimator.test.ts | 6 +- .../calculate_model_memory_limit.ts | 6 +- .../models/calendar/calendar_manager.ts | 6 +- .../server/models/calendar/event_manager.ts | 4 +- .../data_recognizer/data_recognizer.test.ts | 4 +- .../models/data_recognizer/data_recognizer.ts | 4 +- .../models/data_visualizer/data_visualizer.ts | 6 +- .../models/fields_service/fields_service.ts | 4 +- .../file_data_visualizer.ts | 4 +- .../file_data_visualizer/import_data.ts | 4 +- .../ml/server/models/filter/filter_manager.ts | 6 +- .../job_audit_messages.d.ts | 4 +- .../ml/server/models/job_service/datafeeds.ts | 4 +- .../ml/server/models/job_service/groups.ts | 4 +- .../ml/server/models/job_service/index.ts | 4 +- .../ml/server/models/job_service/jobs.ts | 4 +- .../models/job_service/model_snapshots.ts | 4 +- .../job_validation/job_validation.test.ts | 4 +- .../models/job_validation/job_validation.ts | 6 +- .../validate_cardinality.test.ts | 4 +- .../job_validation/validate_cardinality.ts | 6 +- .../validate_influencers.test.ts | 31 +- .../job_validation/validate_influencers.ts | 4 +- .../validate_model_memory_limit.test.ts | 4 +- .../validate_model_memory_limit.ts | 4 +- .../validate_time_range.test.ts | 4 +- .../job_validation/validate_time_range.ts | 6 +- .../models/results_service/results_service.ts | 4 +- x-pack/plugins/ml/server/plugin.ts | 8 +- .../providers/anomaly_detectors.ts | 6 +- .../shared_services/providers/job_service.ts | 6 +- .../shared_services/providers/modules.ts | 11 +- .../providers/results_service.ts | 8 +- .../shared_services/providers/system.ts | 6 +- .../monitoring/server/alerts/cluster_state.ts | 4 +- .../server/alerts/license_expiration.ts | 4 +- .../server/es_client/instantiate_client.ts | 7 +- .../server/lib/alerts/get_prepared_alert.ts | 6 +- .../monitoring/server/license_service.ts | 4 +- x-pack/plugins/monitoring/server/plugin.ts | 10 +- .../register_monitoring_collection.ts | 4 +- .../annotations/create_annotations_client.ts | 4 +- .../server/utils/create_or_update_index.ts | 8 +- .../lib/tasks/visualizations/task_runner.ts | 6 +- .../oss_telemetry/server/test_utils/index.ts | 12 +- x-pack/plugins/rollup/server/plugin.ts | 14 +- x-pack/plugins/rollup/server/types.ts | 4 +- .../server/authentication/api_keys.test.ts | 8 +- .../server/authentication/api_keys.ts | 6 +- .../server/authentication/authenticator.ts | 4 +- .../server/authentication/index.test.ts | 10 +- .../security/server/authentication/index.ts | 4 +- .../server/authentication/providers/base.ts | 4 +- .../authentication/providers/basic.test.ts | 4 +- .../authentication/providers/http.test.ts | 8 +- .../authentication/providers/kerberos.test.ts | 26 +- .../authentication/providers/kerberos.ts | 12 +- .../authentication/providers/oidc.test.ts | 16 +- .../authentication/providers/pki.test.ts | 18 +- .../authentication/providers/saml.test.ts | 20 +- .../authentication/providers/token.test.ts | 18 +- .../server/authentication/tokens.test.ts | 9 +- .../security/server/authentication/tokens.ts | 6 +- .../authorization/authorization_service.ts | 8 +- .../server/authorization/check_privileges.ts | 4 +- .../register_privileges_with_cluster.test.ts | 6 +- .../register_privileges_with_cluster.ts | 4 +- x-pack/plugins/security/server/plugin.test.ts | 4 +- x-pack/plugins/security/server/plugin.ts | 4 +- .../plugins/security/server/routes/index.ts | 4 +- .../routes/role_mapping/feature_check.test.ts | 4 +- .../routes/role_mapping/feature_check.ts | 4 +- .../routes/users/change_password.test.ts | 8 +- .../endpoint/alerts/handlers/alerts.test.ts | 6 +- .../endpoint/alerts/handlers/lib/index.ts | 4 +- .../server/endpoint/mocks.ts | 4 +- .../endpoint/routes/metadata/metadata.test.ts | 10 +- .../routes/metadata/support/unenroll.test.ts | 6 +- .../routes/metadata/support/unenroll.ts | 10 +- .../endpoint/routes/policy/handlers.test.ts | 4 +- .../server/endpoint/routes/policy/service.ts | 4 +- .../endpoint/routes/resolver/queries/base.ts | 4 +- .../routes/resolver/queries/multi_searcher.ts | 4 +- .../endpoint/routes/resolver/utils/fetch.ts | 4 +- .../signals/find_ml_signals.ts | 4 +- .../server/lib/detection_engine/types.ts | 4 +- .../plugins/snapshot_restore/server/plugin.ts | 8 +- .../plugins/snapshot_restore/server/types.ts | 4 +- .../spaces_usage_collector.ts | 4 +- .../task_manager/server/task_manager.ts | 4 +- x-pack/plugins/transform/server/plugin.ts | 8 +- .../upgrade_assistant/server/lib/apm/index.ts | 4 +- .../server/lib/es_deprecation_logging_apis.ts | 6 +- .../server/lib/es_indices_state_check.ts | 4 +- .../server/lib/es_migration_apis.ts | 5 +- .../server/lib/es_version_precheck.test.ts | 4 +- .../server/lib/es_version_precheck.ts | 4 +- .../server/lib/query_default_field.test.ts | 4 +- .../server/lib/query_default_field.ts | 4 +- .../server/lib/reindexing/reindex_actions.ts | 8 +- .../server/lib/reindexing/reindex_service.ts | 4 +- .../server/lib/reindexing/worker.ts | 9 +- .../lib/telemetry/usage_collector.test.ts | 4 +- .../server/lib/telemetry/usage_collector.ts | 6 +- .../routes/reindex_indices/reindex_handler.ts | 4 +- .../lib/adapters/framework/adapter_types.ts | 4 +- .../__tests__/get_monitor_status.test.ts | 4 +- .../server/lib/requests/get_index_pattern.ts | 6 +- .../lib/requests/search/query_context.ts | 4 +- .../plugins/uptime/server/rest_api/types.ts | 4 +- .../fetch_all_from_scroll.ts | 4 +- x-pack/plugins/watcher/server/plugin.ts | 8 +- .../routes/api/indices/register_get_route.ts | 4 +- .../routes/api/register_list_fields_route.ts | 4 +- .../routes/api/register_load_history_route.ts | 4 +- .../api/settings/register_load_route.ts | 4 +- .../action/register_acknowledge_route.ts | 8 +- .../api/watch/register_activate_route.ts | 4 +- .../api/watch/register_deactivate_route.ts | 4 +- .../routes/api/watch/register_delete_route.ts | 4 +- .../api/watch/register_execute_route.ts | 4 +- .../api/watch/register_history_route.ts | 4 +- .../routes/api/watch/register_load_route.ts | 4 +- .../api/watch/register_visualize_route.ts | 4 +- .../api/watches/register_delete_route.ts | 4 +- .../routes/api/watches/register_list_route.ts | 4 +- .../api_integration/apis/lens/telemetry.ts | 6 +- 306 files changed, 1675 insertions(+), 1548 deletions(-) delete mode 100644 docs/development/core/server/kibana-plugin-core-server.callapioptions.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.clusterclient._constructor_.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.clusterclient.asscoped.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.clusterclient.callasinternaluser.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.clusterclient.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.elasticsearcherror._code_.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.elasticsearcherror.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md rename docs/development/core/server/{kibana-plugin-core-server.iclusterclient.md => kibana-plugin-core-server.ilegacyclusterclient.md} (56%) rename docs/development/core/server/{kibana-plugin-core-server.icustomclusterclient.md => kibana-plugin-core-server.ilegacycustomclusterclient.md} (53%) rename docs/development/core/server/{kibana-plugin-core-server.iscopedclusterclient.md => kibana-plugin-core-server.ilegacyscopedclusterclient.md} (56%) rename docs/development/core/server/{kibana-plugin-core-server.apicaller.md => kibana-plugin-core-server.legacyapicaller.md} (54%) create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.md rename docs/development/core/server/{kibana-plugin-core-server.callapioptions.signal.md => kibana-plugin-core-server.legacycallapioptions.signal.md} (57%) rename docs/development/core/server/{kibana-plugin-core-server.callapioptions.wrap401errors.md => kibana-plugin-core-server.legacycallapioptions.wrap401errors.md} (69%) create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyclusterclient._constructor_.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.asscoped.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md rename docs/development/core/server/{kibana-plugin-core-server.clusterclient.close.md => kibana-plugin-core-server.legacyclusterclient.close.md} (64%) create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.md rename docs/development/core/server/{kibana-plugin-core-server.elasticsearchclientconfig.md => kibana-plugin-core-server.legacyelasticsearchclientconfig.md} (52%) create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror._code_.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md rename docs/development/core/server/{kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md => kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md} (52%) create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md rename docs/development/core/server/{kibana-plugin-core-server.elasticsearcherrorhelpers.md => kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md} (65%) create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md rename docs/development/core/server/{kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md => kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md} (58%) rename docs/development/core/server/{kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md => kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md} (55%) create mode 100644 docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.scopedclusterclient._constructor_.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.md delete mode 100644 src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap rename src/core/server/elasticsearch/{ => legacy}/api_types.ts (54%) rename src/core/server/elasticsearch/{ => legacy}/cluster_client.test.mocks.ts (95%) rename src/core/server/elasticsearch/{ => legacy}/cluster_client.test.ts (91%) rename src/core/server/elasticsearch/{ => legacy}/cluster_client.ts (77%) rename src/core/server/elasticsearch/{ => legacy}/elasticsearch_client_config.test.ts (98%) rename src/core/server/elasticsearch/{ => legacy}/elasticsearch_client_config.ts (93%) rename src/core/server/elasticsearch/{ => legacy}/errors.test.ts (68%) rename src/core/server/elasticsearch/{ => legacy}/errors.ts (88%) create mode 100644 src/core/server/elasticsearch/legacy/index.ts rename src/core/server/elasticsearch/{ => legacy}/retry_call_cluster.test.ts (98%) rename src/core/server/elasticsearch/{ => legacy}/retry_call_cluster.ts (88%) rename src/core/server/elasticsearch/{ => legacy}/scoped_cluster_client.test.ts (95%) rename src/core/server/elasticsearch/{ => legacy}/scoped_cluster_client.ts (85%) diff --git a/docs/development/core/server/kibana-plugin-core-server.callapioptions.md b/docs/development/core/server/kibana-plugin-core-server.callapioptions.md deleted file mode 100644 index 03f74424acf99b..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.callapioptions.md +++ /dev/null @@ -1,21 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) - -## CallAPIOptions interface - -The set of options that defines how API call should be made and result be processed. - -Signature: - -```typescript -export interface CallAPIOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [signal](./kibana-plugin-core-server.callapioptions.signal.md) | AbortSignal | A signal object that allows you to abort the request via an AbortController object. | -| [wrap401Errors](./kibana-plugin-core-server.callapioptions.wrap401errors.md) | boolean | Indicates whether 401 Unauthorized errors returned from the Elasticsearch API should be wrapped into Boom error instances with properly set WWW-Authenticate header that could have been returned by the API itself. If API didn't specify that then Basic realm="Authorization Required" is used as WWW-Authenticate. | - diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient._constructor_.md deleted file mode 100644 index d4b2f80443acb6..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient._constructor_.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [(constructor)](./kibana-plugin-core-server.clusterclient._constructor_.md) - -## ClusterClient.(constructor) - -Constructs a new instance of the `ClusterClient` class - -Signature: - -```typescript -constructor(config: ElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| config | ElasticsearchClientConfig | | -| log | Logger | | -| getAuthHeaders | GetAuthHeaders | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.asscoped.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient.asscoped.md deleted file mode 100644 index dd1dcffc5a969f..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.asscoped.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [asScoped](./kibana-plugin-core-server.clusterclient.asscoped.md) - -## ClusterClient.asScoped() method - -Creates an instance of [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional `callAsCurrentUser` method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. - -Signature: - -```typescript -asScoped(request?: ScopeableRequest): IScopedClusterClient; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | ScopeableRequest | Request the IScopedClusterClient instance will be scoped to. Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform | - -Returns: - -`IScopedClusterClient` - diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient.callasinternaluser.md deleted file mode 100644 index ae9a9b46b52b6b..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.callasinternaluser.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.clusterclient.callasinternaluser.md) - -## ClusterClient.callAsInternalUser property - -Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). - -Signature: - -```typescript -callAsInternalUser: APICaller; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.md b/docs/development/core/server/kibana-plugin-core-server.clusterclient.md deleted file mode 100644 index 0f6b2512a6d94c..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.md +++ /dev/null @@ -1,35 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) - -## ClusterClient class - -Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). - -See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). - -Signature: - -```typescript -export declare class ClusterClient implements IClusterClient -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(config, log, getAuthHeaders)](./kibana-plugin-core-server.clusterclient._constructor_.md) | | Constructs a new instance of the ClusterClient class | - -## Properties - -| Property | Modifiers | Type | Description | -| --- | --- | --- | --- | -| [callAsInternalUser](./kibana-plugin-core-server.clusterclient.callasinternaluser.md) | | APICaller | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [asScoped(request)](./kibana-plugin-core-server.clusterclient.asscoped.md) | | Creates an instance of [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) based on the configuration the current cluster client that exposes additional callAsCurrentUser method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. | -| [close()](./kibana-plugin-core-server.clusterclient.close.md) | | Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. | - diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror._code_.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror._code_.md deleted file mode 100644 index d2b07e8d116bab..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror._code_.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) > [\[code\]](./kibana-plugin-core-server.elasticsearcherror._code_.md) - -## ElasticsearchError.\[code\] property - -Signature: - -```typescript -[code]?: string; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror.md deleted file mode 100644 index 42079c02689c53..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherror.md +++ /dev/null @@ -1,19 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) - -## ElasticsearchError interface - - -Signature: - -```typescript -export interface ElasticsearchError extends Boom -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [\[code\]](./kibana-plugin-core-server.elasticsearcherror._code_.md) | string | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md deleted file mode 100644 index d85ae4f9ab5303..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md) - -## ElasticsearchErrorHelpers.isNotAuthorizedError() method - -Signature: - -```typescript -static isNotAuthorizedError(error: any): error is ElasticsearchError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| error | any | | - -Returns: - -`error is ElasticsearchError` - diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md index e8c4c63dc6a964..c683f0ba33189f 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.legacy.md @@ -13,7 +13,7 @@ ```typescript legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md index c1e23527e95163..0dd41a6154a1e8 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicesetup.md @@ -15,5 +15,5 @@ export interface ElasticsearchServiceSetup | Property | Type | Description | | --- | --- | --- | -| [legacy](./kibana-plugin-core-server.elasticsearchservicesetup.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ICustomClusterClient;
readonly client: IClusterClient;
} | | +| [legacy](./kibana-plugin-core-server.elasticsearchservicesetup.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<LegacyElasticsearchClientConfig>) => ILegacyCustomClusterClient;
readonly client: ILegacyClusterClient;
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md index 667a36091f2326..5f346d7887c2af 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.legacy.md @@ -13,7 +13,7 @@ ```typescript legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md index 39c794af2c881f..e059acdbd52fa2 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchservicestart.md @@ -15,5 +15,5 @@ export interface ElasticsearchServiceStart | Property | Type | Description | | --- | --- | --- | -| [legacy](./kibana-plugin-core-server.elasticsearchservicestart.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<ElasticsearchClientConfig>) => ICustomClusterClient;
readonly client: IClusterClient;
} | | +| [legacy](./kibana-plugin-core-server.elasticsearchservicestart.legacy.md) | {
readonly createClient: (type: string, clientConfig?: Partial<LegacyElasticsearchClientConfig>) => ILegacyCustomClusterClient;
readonly client: ILegacyClusterClient;
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.iclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.ilegacyclusterclient.md similarity index 56% rename from docs/development/core/server/kibana-plugin-core-server.iclusterclient.md rename to docs/development/core/server/kibana-plugin-core-server.ilegacyclusterclient.md index 28fbdf17cf31c9..c70a5ac07c6ad8 100644 --- a/docs/development/core/server/kibana-plugin-core-server.iclusterclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.ilegacyclusterclient.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IClusterClient](./kibana-plugin-core-server.iclusterclient.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ILegacyClusterClient](./kibana-plugin-core-server.ilegacyclusterclient.md) -## IClusterClient type +## ILegacyClusterClient type Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). -See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). +See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). Signature: ```typescript -export declare type IClusterClient = Pick; +export declare type ILegacyClusterClient = Pick; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.icustomclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.ilegacycustomclusterclient.md similarity index 53% rename from docs/development/core/server/kibana-plugin-core-server.icustomclusterclient.md rename to docs/development/core/server/kibana-plugin-core-server.ilegacycustomclusterclient.md index 3d379e1231cb15..a3cb8f13150212 100644 --- a/docs/development/core/server/kibana-plugin-core-server.icustomclusterclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.ilegacycustomclusterclient.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ICustomClusterClient](./kibana-plugin-core-server.icustomclusterclient.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ILegacyCustomClusterClient](./kibana-plugin-core-server.ilegacycustomclusterclient.md) -## ICustomClusterClient type +## ILegacyCustomClusterClient type Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via `asScoped(...)`). -See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). +See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). Signature: ```typescript -export declare type ICustomClusterClient = Pick; +export declare type ILegacyCustomClusterClient = Pick; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.ilegacyscopedclusterclient.md similarity index 56% rename from docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md rename to docs/development/core/server/kibana-plugin-core-server.ilegacyscopedclusterclient.md index 378836ee461f38..1263b85acb4983 100644 --- a/docs/development/core/server/kibana-plugin-core-server.iscopedclusterclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.ilegacyscopedclusterclient.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) -## IScopedClusterClient type +## ILegacyScopedClusterClient type Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. -See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). +See [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md). Signature: ```typescript -export declare type IScopedClusterClient = Pick; +export declare type ILegacyScopedClusterClient = Pick; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.apicaller.md b/docs/development/core/server/kibana-plugin-core-server.legacyapicaller.md similarity index 54% rename from docs/development/core/server/kibana-plugin-core-server.apicaller.md rename to docs/development/core/server/kibana-plugin-core-server.legacyapicaller.md index 4da23b3f821c5b..e6c2878d2b3556 100644 --- a/docs/development/core/server/kibana-plugin-core-server.apicaller.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyapicaller.md @@ -1,12 +1,12 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [APICaller](./kibana-plugin-core-server.apicaller.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md) -## APICaller interface +## LegacyAPICaller interface Signature: ```typescript -export interface APICaller +export interface LegacyAPICaller ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.md b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.md new file mode 100644 index 00000000000000..9ebe2fc57a54bf --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) + +## LegacyCallAPIOptions interface + +The set of options that defines how API call should be made and result be processed. + +Signature: + +```typescript +export interface LegacyCallAPIOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [signal](./kibana-plugin-core-server.legacycallapioptions.signal.md) | AbortSignal | A signal object that allows you to abort the request via an AbortController object. | +| [wrap401Errors](./kibana-plugin-core-server.legacycallapioptions.wrap401errors.md) | boolean | Indicates whether 401 Unauthorized errors returned from the Elasticsearch API should be wrapped into Boom error instances with properly set WWW-Authenticate header that could have been returned by the API itself. If API didn't specify that then Basic realm="Authorization Required" is used as WWW-Authenticate. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.callapioptions.signal.md b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.signal.md similarity index 57% rename from docs/development/core/server/kibana-plugin-core-server.callapioptions.signal.md rename to docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.signal.md index 8b35924826f151..7d795a59e41a54 100644 --- a/docs/development/core/server/kibana-plugin-core-server.callapioptions.signal.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.signal.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) > [signal](./kibana-plugin-core-server.callapioptions.signal.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) > [signal](./kibana-plugin-core-server.legacycallapioptions.signal.md) -## CallAPIOptions.signal property +## LegacyCallAPIOptions.signal property A signal object that allows you to abort the request via an AbortController object. diff --git a/docs/development/core/server/kibana-plugin-core-server.callapioptions.wrap401errors.md b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.wrap401errors.md similarity index 69% rename from docs/development/core/server/kibana-plugin-core-server.callapioptions.wrap401errors.md rename to docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.wrap401errors.md index 2a5b8054819a3a..38fac54db77a42 100644 --- a/docs/development/core/server/kibana-plugin-core-server.callapioptions.wrap401errors.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacycallapioptions.wrap401errors.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) > [wrap401Errors](./kibana-plugin-core-server.callapioptions.wrap401errors.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) > [wrap401Errors](./kibana-plugin-core-server.legacycallapioptions.wrap401errors.md) -## CallAPIOptions.wrap401Errors property +## LegacyCallAPIOptions.wrap401Errors property Indicates whether `401 Unauthorized` errors returned from the Elasticsearch API should be wrapped into `Boom` error instances with properly set `WWW-Authenticate` header that could have been returned by the API itself. If API didn't specify that then `Basic realm="Authorization Required"` is used as `WWW-Authenticate`. diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient._constructor_.md new file mode 100644 index 00000000000000..823f34bd7dd237 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [(constructor)](./kibana-plugin-core-server.legacyclusterclient._constructor_.md) + +## LegacyClusterClient.(constructor) + +Constructs a new instance of the `LegacyClusterClient` class + +Signature: + +```typescript +constructor(config: LegacyElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | LegacyElasticsearchClientConfig | | +| log | Logger | | +| getAuthHeaders | GetAuthHeaders | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.asscoped.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.asscoped.md new file mode 100644 index 00000000000000..1c25fc1d072b61 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.asscoped.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [asScoped](./kibana-plugin-core-server.legacyclusterclient.asscoped.md) + +## LegacyClusterClient.asScoped() method + +Creates an instance of [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) based on the configuration the current cluster client that exposes additional `callAsCurrentUser` method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. + +Signature: + +```typescript +asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | ScopeableRequest | Request the IScopedClusterClient instance will be scoped to. Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform | + +Returns: + +`ILegacyScopedClusterClient` + diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md new file mode 100644 index 00000000000000..2e235485711c6e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md) + +## LegacyClusterClient.callAsInternalUser property + +Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). + +Signature: + +```typescript +callAsInternalUser: LegacyAPICaller; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.clusterclient.close.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.close.md similarity index 64% rename from docs/development/core/server/kibana-plugin-core-server.clusterclient.close.md rename to docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.close.md index 68a1bd4b9d7cf2..88a5ffce5bb17c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.clusterclient.close.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.close.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ClusterClient](./kibana-plugin-core-server.clusterclient.md) > [close](./kibana-plugin-core-server.clusterclient.close.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) > [close](./kibana-plugin-core-server.legacyclusterclient.close.md) -## ClusterClient.close() method +## LegacyClusterClient.close() method Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.md new file mode 100644 index 00000000000000..4f218ae552c99b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyclusterclient.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) + +## LegacyClusterClient class + + +Signature: + +```typescript +export declare class LegacyClusterClient implements ILegacyClusterClient +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(config, log, getAuthHeaders)](./kibana-plugin-core-server.legacyclusterclient._constructor_.md) | | Constructs a new instance of the LegacyClusterClient class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [callAsInternalUser](./kibana-plugin-core-server.legacyclusterclient.callasinternaluser.md) | | LegacyAPICaller | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [asScoped(request)](./kibana-plugin-core-server.legacyclusterclient.asscoped.md) | | Creates an instance of [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) based on the configuration the current cluster client that exposes additional callAsCurrentUser method scoped to the provided req. Consumers shouldn't worry about closing scoped client instances, these will be automatically closed as soon as the original cluster client isn't needed anymore and closed. | +| [close()](./kibana-plugin-core-server.legacyclusterclient.close.md) | | Closes the cluster client. After that client cannot be used and one should create a new client instance to be able to interact with Elasticsearch API. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md similarity index 52% rename from docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md rename to docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md index 703b07808aca3b..62b0f216c863c0 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclientconfig.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearchclientconfig.md @@ -1,14 +1,14 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchClientConfig](./kibana-plugin-core-server.legacyelasticsearchclientconfig.md) -## ElasticsearchClientConfig type +## LegacyElasticsearchClientConfig type Signature: ```typescript -export declare type ElasticsearchClientConfig = Pick & Pick & { +export declare type LegacyElasticsearchClientConfig = Pick & Pick & { pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror._code_.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror._code_.md new file mode 100644 index 00000000000000..05530ceb0d568b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror._code_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchError](./kibana-plugin-core-server.legacyelasticsearcherror.md) > [\[code\]](./kibana-plugin-core-server.legacyelasticsearcherror._code_.md) + +## LegacyElasticsearchError.\[code\] property + +Signature: + +```typescript +[code]?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md new file mode 100644 index 00000000000000..f760780504e55f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherror.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchError](./kibana-plugin-core-server.legacyelasticsearcherror.md) + +## LegacyElasticsearchError interface + + +Signature: + +```typescript +export interface LegacyElasticsearchError extends Boom +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [\[code\]](./kibana-plugin-core-server.legacyelasticsearcherror._code_.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md similarity index 52% rename from docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md rename to docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md index 2b2eeceb4e3c9d..bd802a39e9339f 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md @@ -1,13 +1,13 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) > [decorateNotAuthorizedError](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md) -## ElasticsearchErrorHelpers.decorateNotAuthorizedError() method +## LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError() method Signature: ```typescript -static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchError; +static decorateNotAuthorizedError(error: Error, reason?: string): LegacyElasticsearchError; ``` ## Parameters @@ -19,5 +19,5 @@ static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchE Returns: -`ElasticsearchError` +`LegacyElasticsearchError` diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md new file mode 100644 index 00000000000000..f647916149458e --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) > [isNotAuthorizedError](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md) + +## LegacyElasticsearchErrorHelpers.isNotAuthorizedError() method + +Signature: + +```typescript +static isNotAuthorizedError(error: any): error is LegacyElasticsearchError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | any | | + +Returns: + +`error is LegacyElasticsearchError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.md b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md similarity index 65% rename from docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.md rename to docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md index e9c205e3dfa2c4..e20dcd4ed253eb 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrorhelpers.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) -## ElasticsearchErrorHelpers class +## LegacyElasticsearchErrorHelpers class Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as `body.error.header[WWW-Authenticate]` Signature: ```typescript -export declare class ElasticsearchErrorHelpers +export declare class LegacyElasticsearchErrorHelpers ``` ## Example @@ -30,6 +30,6 @@ try { | Method | Modifiers | Description | | --- | --- | --- | -| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-core-server.elasticsearcherrorhelpers.decoratenotauthorizederror.md) | static | | -| [isNotAuthorizedError(error)](./kibana-plugin-core-server.elasticsearcherrorhelpers.isnotauthorizederror.md) | static | | +| [decorateNotAuthorizedError(error, reason)](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.decoratenotauthorizederror.md) | static | | +| [isNotAuthorizedError(error)](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.isnotauthorizederror.md) | static | | diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md new file mode 100644 index 00000000000000..bd1cd1e9f3d9b3 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) > [(constructor)](./kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md) + +## LegacyScopedClusterClient.(constructor) + +Constructs a new instance of the `LegacyScopedClusterClient` class + +Signature: + +```typescript +constructor(internalAPICaller: LegacyAPICaller, scopedAPICaller: LegacyAPICaller, headers?: Headers | undefined); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| internalAPICaller | LegacyAPICaller | | +| scopedAPICaller | LegacyAPICaller | | +| headers | Headers | undefined | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md similarity index 58% rename from docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md rename to docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md index 68c0f8e6be1be0..9130f9adde76e0 100644 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) > [callAsCurrentUser](./kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) > [callAsCurrentUser](./kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md) -## ScopedClusterClient.callAsCurrentUser() method +## LegacyScopedClusterClient.callAsCurrentUser() method -Calls specified `endpoint` with provided `clientParams` on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-core-server.apicaller.md). +Calls specified `endpoint` with provided `clientParams` on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). Signature: ```typescript -callAsCurrentUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; +callAsCurrentUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; ``` ## Parameters @@ -18,7 +18,7 @@ callAsCurrentUser(endpoint: string, clientParams?: Record, options? | --- | --- | --- | | endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | | clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | -| options | CallAPIOptions | Options that affect the way we call the API and process the result. | +| options | LegacyCallAPIOptions | Options that affect the way we call the API and process the result. | Returns: diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md similarity index 55% rename from docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md rename to docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md index e769fd692a4d1d..bf95782299e720 100644 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md @@ -1,15 +1,15 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) > [callAsInternalUser](./kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md) -## ScopedClusterClient.callAsInternalUser() method +## LegacyScopedClusterClient.callAsInternalUser() method -Calls specified `endpoint` with provided `clientParams` on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). +Calls specified `endpoint` with provided `clientParams` on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). Signature: ```typescript -callAsInternalUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; +callAsInternalUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; ``` ## Parameters @@ -18,7 +18,7 @@ callAsInternalUser(endpoint: string, clientParams?: Record, options | --- | --- | --- | | endpoint | string | String descriptor of the endpoint e.g. cluster.getSettings or ping. | | clientParams | Record<string, any> | A dictionary of parameters that will be passed directly to the Elasticsearch JS client. | -| options | CallAPIOptions | Options that affect the way we call the API and process the result. | +| options | LegacyCallAPIOptions | Options that affect the way we call the API and process the result. | Returns: diff --git a/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.md new file mode 100644 index 00000000000000..f3d8a69b8ed053 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.legacyscopedclusterclient.md @@ -0,0 +1,26 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) + +## LegacyScopedClusterClient class + + +Signature: + +```typescript +export declare class LegacyScopedClusterClient implements ILegacyScopedClusterClient +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(internalAPICaller, scopedAPICaller, headers)](./kibana-plugin-core-server.legacyscopedclusterclient._constructor_.md) | | Constructs a new instance of the LegacyScopedClusterClient class | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [callAsCurrentUser(endpoint, clientParams, options)](./kibana-plugin-core-server.legacyscopedclusterclient.callascurrentuser.md) | | Calls specified endpoint with provided clientParams on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). | +| [callAsInternalUser(endpoint, clientParams, options)](./kibana-plugin-core-server.legacyscopedclusterclient.callasinternaluser.md) | | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md). | + diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index b7b0d8f7ed686d..cbba61e16798bb 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -17,18 +17,18 @@ The plugin integrates with the core system via lifecycle events: `setup` | Class | Description | | --- | --- | | [BasePath](./kibana-plugin-core-server.basepath.md) | Access or manipulate the Kibana base path | -| [ClusterClient](./kibana-plugin-core-server.clusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | | [CspConfig](./kibana-plugin-core-server.cspconfig.md) | CSP configuration for use in Kibana. | | [ElasticsearchConfig](./kibana-plugin-core-server.elasticsearchconfig.md) | Wrapper of config schema. | -| [ElasticsearchErrorHelpers](./kibana-plugin-core-server.elasticsearcherrorhelpers.md) | Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as body.error.header[WWW-Authenticate] | | [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md) | Kibana specific abstraction for an incoming request. | +| [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md) | | +| [LegacyElasticsearchErrorHelpers](./kibana-plugin-core-server.legacyelasticsearcherrorhelpers.md) | Helpers for working with errors returned from the Elasticsearch service.Since the internal data of errors are subject to change, consumers of the Elasticsearch service should always use these helpers to classify errors instead of checking error internals such as body.error.header[WWW-Authenticate] | +| [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md) | | | [RouteValidationError](./kibana-plugin-core-server.routevalidationerror.md) | Error to return when the validation is not successful. | | [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) | | | [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | | | [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | | | [SavedObjectsSerializer](./kibana-plugin-core-server.savedobjectsserializer.md) | A serializer that can be used to manually convert [raw](./kibana-plugin-core-server.savedobjectsrawdoc.md) or [sanitized](./kibana-plugin-core-server.savedobjectsanitizeddoc.md) documents to the other kind. | | [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) | Registry holding information about all the registered [saved object types](./kibana-plugin-core-server.savedobjectstype.md). | -| [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). | ## Enumerations @@ -54,7 +54,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | Interface | Description | | --- | --- | -| [APICaller](./kibana-plugin-core-server.apicaller.md) | | | [AssistanceAPIResponse](./kibana-plugin-core-server.assistanceapiresponse.md) | | | [AssistantAPIClientParams](./kibana-plugin-core-server.assistantapiclientparams.md) | | | [Authenticated](./kibana-plugin-core-server.authenticated.md) | | @@ -63,7 +62,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AuthRedirectedParams](./kibana-plugin-core-server.authredirectedparams.md) | Result of auth redirection. | | [AuthResultParams](./kibana-plugin-core-server.authresultparams.md) | Result of successful authentication. | | [AuthToolkit](./kibana-plugin-core-server.authtoolkit.md) | A tool set defining an outcome of Auth interceptor for incoming request. | -| [CallAPIOptions](./kibana-plugin-core-server.callapioptions.md) | The set of options that defines how API call should be made and result be processed. | | [Capabilities](./kibana-plugin-core-server.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | | [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) | APIs to manage the [Capabilities](./kibana-plugin-core-server.capabilities.md) that will be used by the application.Plugins relying on capabilities to toggle some of their features should register them during the setup phase using the registerProvider method.Plugins having the responsibility to restrict capabilities depending on a given context should register their capabilities switcher using the registerSwitcher method.Refers to the methods documentation for complete description and examples. | | [CapabilitiesStart](./kibana-plugin-core-server.capabilitiesstart.md) | APIs to access the application [Capabilities](./kibana-plugin-core-server.capabilities.md). | @@ -78,7 +76,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DeprecationInfo](./kibana-plugin-core-server.deprecationinfo.md) | | | [DeprecationSettings](./kibana-plugin-core-server.deprecationsettings.md) | UiSettings deprecation field options. | | [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. | -| [ElasticsearchError](./kibana-plugin-core-server.elasticsearcherror.md) | | | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | | [ElasticsearchStatusMeta](./kibana-plugin-core-server.elasticsearchstatusmeta.md) | | @@ -104,6 +101,9 @@ The plugin integrates with the core system via lifecycle events: `setup` | [IUiSettingsClient](./kibana-plugin-core-server.iuisettingsclient.md) | Server-side client that provides access to the advanced settings stored in elasticsearch. The settings provide control over the behavior of the Kibana application. For example, a user can specify how to display numeric or date fields. Users can adjust the settings via Management UI. | | [KibanaRequestEvents](./kibana-plugin-core-server.kibanarequestevents.md) | Request events. | | [KibanaRequestRoute](./kibana-plugin-core-server.kibanarequestroute.md) | Request specific route information exposed to a handler. | +| [LegacyAPICaller](./kibana-plugin-core-server.legacyapicaller.md) | | +| [LegacyCallAPIOptions](./kibana-plugin-core-server.legacycallapioptions.md) | The set of options that defines how API call should be made and result be processed. | +| [LegacyElasticsearchError](./kibana-plugin-core-server.legacyelasticsearcherror.md) | | | [LegacyRequest](./kibana-plugin-core-server.legacyrequest.md) | | | [LegacyServiceSetupDeps](./kibana-plugin-core-server.legacyservicesetupdeps.md) | | | [LegacyServiceStartDeps](./kibana-plugin-core-server.legacyservicestartdeps.md) | | @@ -128,7 +128,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PluginConfigDescriptor](./kibana-plugin-core-server.pluginconfigdescriptor.md) | Describes a plugin configuration properties. | | [PluginInitializerContext](./kibana-plugin-core-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | | [PluginManifest](./kibana-plugin-core-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | -| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | +| [RequestHandlerContext](./kibana-plugin-core-server.requesthandlercontext.md) | Plugin specific context passed to a route handler.Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.legacyscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request | | [RouteConfig](./kibana-plugin-core-server.routeconfig.md) | Route specific configuration. | | [RouteConfigOptions](./kibana-plugin-core-server.routeconfigoptions.md) | Additional route options. | | [RouteConfigOptionsBody](./kibana-plugin-core-server.routeconfigoptionsbody.md) | Additional body options for a route | @@ -222,7 +222,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ConfigDeprecationProvider](./kibana-plugin-core-server.configdeprecationprovider.md) | A provider that should returns a list of [ConfigDeprecation](./kibana-plugin-core-server.configdeprecation.md).See [ConfigDeprecationFactory](./kibana-plugin-core-server.configdeprecationfactory.md) for more usage examples. | | [ConfigPath](./kibana-plugin-core-server.configpath.md) | | | [DestructiveRouteMethod](./kibana-plugin-core-server.destructiveroutemethod.md) | Set of HTTP methods changing the state of the server. | -| [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) | | | [Freezable](./kibana-plugin-core-server.freezable.md) | | | [GetAuthHeaders](./kibana-plugin-core-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | | [GetAuthState](./kibana-plugin-core-server.getauthstate.md) | Gets authentication state for a request. Returned by auth interceptor. | @@ -234,16 +233,17 @@ The plugin integrates with the core system via lifecycle events: `setup` | [HttpResourcesResponseOptions](./kibana-plugin-core-server.httpresourcesresponseoptions.md) | HTTP Resources response parameters | | [HttpResponsePayload](./kibana-plugin-core-server.httpresponsepayload.md) | Data send to the client as a response payload. | | [IBasePath](./kibana-plugin-core-server.ibasepath.md) | Access or manipulate the Kibana base path[BasePath](./kibana-plugin-core-server.basepath.md) | -| [IClusterClient](./kibana-plugin-core-server.iclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | | [IContextProvider](./kibana-plugin-core-server.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | -| [ICustomClusterClient](./kibana-plugin-core-server.icustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [ClusterClient](./kibana-plugin-core-server.clusterclient.md). | +| [ILegacyClusterClient](./kibana-plugin-core-server.ilegacyclusterclient.md) | Represents an Elasticsearch cluster API client created by the platform. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). | +| [ILegacyCustomClusterClient](./kibana-plugin-core-server.ilegacycustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). | +| [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md). | | [IsAuthenticated](./kibana-plugin-core-server.isauthenticated.md) | Returns authentication status for a request. | | [ISavedObjectsRepository](./kibana-plugin-core-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | | [ISavedObjectTypeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) | See [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) for documentation. | -| [IScopedClusterClient](./kibana-plugin-core-server.iscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). | | [KibanaRequestRouteOptions](./kibana-plugin-core-server.kibanarequestrouteoptions.md) | Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. | | [KibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) | Creates an object containing request response payload, HTTP headers, error details, and other data transmitted to the client. | | [KnownHeaders](./kibana-plugin-core-server.knownheaders.md) | Set of well-known HTTP headers. | +| [LegacyElasticsearchClientConfig](./kibana-plugin-core-server.legacyelasticsearchclientconfig.md) | | | [LifecycleResponseFactory](./kibana-plugin-core-server.lifecycleresponsefactory.md) | Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. | | [LoggerConfigType](./kibana-plugin-core-server.loggerconfigtype.md) | | | [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-core-server.migration_assistance_index_action.md) | | diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md index 7b887d6d421e4c..b09fb121b8a632 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md @@ -14,7 +14,7 @@ core: { }; elasticsearch: { legacy: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; }; }; uiSettings: { diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md index 99be0676bcda3d..55d6e931ac1584 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md @@ -6,7 +6,7 @@ Plugin specific context passed to a route handler. -Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.scopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request +Provides the following clients and services: - [savedObjects.client](./kibana-plugin-core-server.savedobjectsclient.md) - Saved Objects client which uses the credentials of the incoming request - [savedObjects.typeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) - Type registry containing all the registered types. - [elasticsearch.legacy.client](./kibana-plugin-core-server.legacyscopedclusterclient.md) - Elasticsearch data client which uses the credentials of the incoming request - [uiSettings.client](./kibana-plugin-core-server.iuisettingsclient.md) - uiSettings client which uses the credentials of the incoming request Signature: @@ -18,5 +18,5 @@ export interface RequestHandlerContext | Property | Type | Description | | --- | --- | --- | -| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
};
elasticsearch: {
legacy: {
client: IScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | +| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
};
elasticsearch: {
legacy: {
client: ILegacyScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient._constructor_.md deleted file mode 100644 index d4d1d442a57f98..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient._constructor_.md +++ /dev/null @@ -1,22 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) > [(constructor)](./kibana-plugin-core-server.scopedclusterclient._constructor_.md) - -## ScopedClusterClient.(constructor) - -Constructs a new instance of the `ScopedClusterClient` class - -Signature: - -```typescript -constructor(internalAPICaller: APICaller, scopedAPICaller: APICaller, headers?: Headers | undefined); -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| internalAPICaller | APICaller | | -| scopedAPICaller | APICaller | | -| headers | Headers | undefined | | - diff --git a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.md b/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.md deleted file mode 100644 index 058d65b587dbed..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.scopedclusterclient.md +++ /dev/null @@ -1,29 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md) - -## ScopedClusterClient class - -Serves the same purpose as "normal" `ClusterClient` but exposes additional `callAsCurrentUser` method that doesn't use credentials of the Kibana internal user (as `callAsInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API. - -See [ScopedClusterClient](./kibana-plugin-core-server.scopedclusterclient.md). - -Signature: - -```typescript -export declare class ScopedClusterClient implements IScopedClusterClient -``` - -## Constructors - -| Constructor | Modifiers | Description | -| --- | --- | --- | -| [(constructor)(internalAPICaller, scopedAPICaller, headers)](./kibana-plugin-core-server.scopedclusterclient._constructor_.md) | | Constructs a new instance of the ScopedClusterClient class | - -## Methods - -| Method | Modifiers | Description | -| --- | --- | --- | -| [callAsCurrentUser(endpoint, clientParams, options)](./kibana-plugin-core-server.scopedclusterclient.callascurrentuser.md) | | Calls specified endpoint with provided clientParams on behalf of the user initiated request to the Kibana server (via HTTP request headers). See [APICaller](./kibana-plugin-core-server.apicaller.md). | -| [callAsInternalUser(endpoint, clientParams, options)](./kibana-plugin-core-server.scopedclusterclient.callasinternaluser.md) | | Calls specified endpoint with provided clientParams on behalf of the Kibana internal user. See [APICaller](./kibana-plugin-core-server.apicaller.md). | - diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md index f9bbcc5a356e13..d36ebd0745e8d0 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.indexpatternsfetcher._constructor_.md @@ -9,12 +9,12 @@ Constructs a new instance of the `IndexPatternsFetcher` class Signature: ```typescript -constructor(callDataCluster: APICaller); +constructor(callDataCluster: LegacyAPICaller); ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| callDataCluster | APICaller | | +| callDataCluster | LegacyAPICaller | | diff --git a/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap b/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap deleted file mode 100644 index 75627f311d9a58..00000000000000 --- a/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`#username throws if equal to "elastic", only while running from source 1`] = `"[username]: value of \\"elastic\\" is forbidden. This is a superuser account that can obfuscate privilege-related issues. You should use the \\"kibana_system\\" user instead."`; diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts index d070ee41e5fa7b..06b862d2454d86 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts @@ -367,6 +367,8 @@ test('#username throws if equal to "elastic", only while running from source', ( const obj = { username: 'elastic', }; - expect(() => config.schema.validate(obj, { dist: false })).toThrowErrorMatchingSnapshot(); + expect(() => config.schema.validate(obj, { dist: false })).toThrowErrorMatchingInlineSnapshot( + `"[username]: value of \\"elastic\\" is forbidden. This is a superuser account that can obfuscate privilege-related issues. You should use the \\"kibana_system\\" user instead."` + ); expect(() => config.schema.validate(obj, { dist: true })).not.toThrow(); }); diff --git a/src/core/server/elasticsearch/elasticsearch_service.mock.ts b/src/core/server/elasticsearch/elasticsearch_service.mock.ts index 55e60f5987604e..fdfc48fa9f754b 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.mock.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.mock.ts @@ -19,26 +19,29 @@ import { BehaviorSubject } from 'rxjs'; import { Client } from 'elasticsearch'; -import { IClusterClient, ICustomClusterClient } from './cluster_client'; -import { IScopedClusterClient } from './scoped_cluster_client'; +import { + ILegacyClusterClient, + ILegacyCustomClusterClient, + ILegacyScopedClusterClient, +} from './legacy'; import { ElasticsearchConfig } from './elasticsearch_config'; import { ElasticsearchService } from './elasticsearch_service'; import { InternalElasticsearchServiceSetup, ElasticsearchStatusMeta } from './types'; import { NodesVersionCompatibility } from './version_check/ensure_es_version'; import { ServiceStatus, ServiceStatusLevels } from '../status'; -const createScopedClusterClientMock = (): jest.Mocked => ({ +const createScopedClusterClientMock = (): jest.Mocked => ({ callAsInternalUser: jest.fn(), callAsCurrentUser: jest.fn(), }); -const createCustomClusterClientMock = (): jest.Mocked => ({ +const createCustomClusterClientMock = (): jest.Mocked => ({ ...createClusterClientMock(), close: jest.fn(), }); function createClusterClientMock() { - const client: jest.Mocked = { + const client: jest.Mocked = { callAsInternalUser: jest.fn(), asScoped: jest.fn(), }; @@ -48,8 +51,8 @@ function createClusterClientMock() { interface MockedElasticSearchServiceSetup { legacy: { - createClient: jest.Mock; - client: jest.Mocked; + createClient: jest.Mock; + client: jest.Mocked; }; } @@ -81,7 +84,7 @@ const createStartContractMock = () => { type MockedInternalElasticSearchServiceSetup = jest.Mocked< InternalElasticsearchServiceSetup & { - legacy: { client: jest.Mocked }; + legacy: { client: jest.Mocked }; } >; const createInternalSetupContractMock = () => { diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts index e87913a3c5e4ff..c30230a7847a0e 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.test.mocks.ts @@ -18,4 +18,4 @@ */ export const MockClusterClient = jest.fn(); -jest.mock('./cluster_client', () => ({ ClusterClient: MockClusterClient })); +jest.mock('./legacy/cluster_client', () => ({ LegacyClusterClient: MockClusterClient })); diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index 26001bf83924fb..f47b33dd410f6c 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -34,23 +34,26 @@ import { merge } from '../../utils'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { - ClusterClient, - ScopeableRequest, - IClusterClient, - ICustomClusterClient, -} from './cluster_client'; -import { ElasticsearchClientConfig } from './elasticsearch_client_config'; + LegacyClusterClient, + ILegacyClusterClient, + ILegacyCustomClusterClient, + LegacyElasticsearchClientConfig, + LegacyCallAPIOptions, +} from './legacy'; import { ElasticsearchConfig, ElasticsearchConfigType } from './elasticsearch_config'; import { InternalHttpServiceSetup, GetAuthHeaders } from '../http/'; -import { InternalElasticsearchServiceSetup, ElasticsearchServiceStart } from './types'; -import { CallAPIOptions } from './api_types'; +import { + InternalElasticsearchServiceSetup, + ElasticsearchServiceStart, + ScopeableRequest, +} from './types'; import { pollEsNodesVersion } from './version_check/ensure_es_version'; import { calculateStatus$ } from './status'; /** @internal */ interface CoreClusterClients { config: ElasticsearchConfig; - client: ClusterClient; + client: LegacyClusterClient; } interface SetupDeps { @@ -67,9 +70,9 @@ export class ElasticsearchService private kibanaVersion: string; private createClient?: ( type: string, - clientConfig?: Partial - ) => ICustomClusterClient; - private client?: IClusterClient; + clientConfig?: Partial + ) => ILegacyCustomClusterClient; + private client?: ILegacyClusterClient; constructor(private readonly coreContext: CoreContext) { this.kibanaVersion = coreContext.env.packageInfo.version; @@ -123,7 +126,7 @@ export class ElasticsearchService async callAsInternalUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { const _client = await client$.pipe(take(1)).toPromise(); return await _client.callAsInternalUser(endpoint, clientParams, options); @@ -134,7 +137,7 @@ export class ElasticsearchService async callAsCurrentUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { const _client = await client$.pipe(take(1)).toPromise(); return await _client @@ -155,7 +158,10 @@ export class ElasticsearchService kibanaVersion: this.kibanaVersion, }).pipe(takeUntil(this.stop$), shareReplay({ refCount: true, bufferSize: 1 })); - this.createClient = (type: string, clientConfig: Partial = {}) => { + this.createClient = ( + type: string, + clientConfig: Partial = {} + ) => { const finalConfig = merge({}, config, clientConfig); return this.createClusterClient(type, finalConfig, deps.http.getAuthHeaders); }; @@ -193,10 +199,10 @@ export class ElasticsearchService private createClusterClient( type: string, - config: ElasticsearchClientConfig, + config: LegacyElasticsearchClientConfig, getAuthHeaders?: GetAuthHeaders ) { - return new ClusterClient( + return new LegacyClusterClient( config, this.coreContext.logger.get('elasticsearch', type), getAuthHeaders diff --git a/src/core/server/elasticsearch/index.ts b/src/core/server/elasticsearch/index.ts index 2e45f710c4dcfd..f5f5f5cc7b6f88 100644 --- a/src/core/server/elasticsearch/index.ts +++ b/src/core/server/elasticsearch/index.ts @@ -18,17 +18,14 @@ */ export { ElasticsearchService } from './elasticsearch_service'; +export { config, configSchema, ElasticsearchConfig } from './elasticsearch_config'; +export { NodesVersionCompatibility } from './version_check/ensure_es_version'; export { - ClusterClient, + ElasticsearchServiceSetup, + ElasticsearchServiceStart, + ElasticsearchStatusMeta, + InternalElasticsearchServiceSetup, FakeRequest, - IClusterClient, - ICustomClusterClient, ScopeableRequest, -} from './cluster_client'; -export { IScopedClusterClient, ScopedClusterClient, Headers } from './scoped_cluster_client'; -export { ElasticsearchClientConfig } from './elasticsearch_client_config'; -export { config, configSchema, ElasticsearchConfig } from './elasticsearch_config'; -export { ElasticsearchError, ElasticsearchErrorHelpers } from './errors'; -export * from './api_types'; -export * from './types'; -export { NodesVersionCompatibility } from './version_check/ensure_es_version'; +} from './types'; +export * from './legacy'; diff --git a/src/core/server/elasticsearch/api_types.ts b/src/core/server/elasticsearch/legacy/api_types.ts similarity index 54% rename from src/core/server/elasticsearch/api_types.ts rename to src/core/server/elasticsearch/legacy/api_types.ts index 5f2b61eb4935fd..b9699ab290e3fc 100644 --- a/src/core/server/elasticsearch/api_types.ts +++ b/src/core/server/elasticsearch/legacy/api_types.ts @@ -151,7 +151,7 @@ import { * * @public */ -export interface CallAPIOptions { +export interface LegacyCallAPIOptions { /** * Indicates whether `401 Unauthorized` errors returned from the Elasticsearch API * should be wrapped into `Boom` error instances with properly set `WWW-Authenticate` @@ -166,154 +166,154 @@ export interface CallAPIOptions { } /** @public */ -export interface APICaller { +export interface LegacyAPICaller { /* eslint-disable */ - (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'clearScroll', params: ClearScrollParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'count', params: CountParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'create', params: CreateDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'delete', params: DeleteDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'deleteScript', params: DeleteScriptParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'exists', params: ExistsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'explain', params: ExplainParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'fieldStats', params: FieldStatsParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'clearScroll', params: ClearScrollParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'count', params: CountParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'create', params: CreateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'delete', params: DeleteDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'deleteScript', params: DeleteScriptParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'exists', params: ExistsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'explain', params: ExplainParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'fieldStats', params: FieldStatsParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'get', params: GetParams, options?: CallAPIOptions): Promise>; - (endpoint: 'getScript', params: GetScriptParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'getSource', params: GetSourceParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'getTemplate', params: GetTemplateParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'get', params: GetParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'getScript', params: GetScriptParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'getSource', params: GetSourceParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'getTemplate', params: GetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'index', params: IndexDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'info', params: InfoParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'index', params: IndexDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'info', params: InfoParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'mget', params: MGetParams, options?: CallAPIOptions): Promise>; - (endpoint: 'msearch', params: MSearchParams, options?: CallAPIOptions): Promise>; - (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: CallAPIOptions): Promise>; - (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ping', params: PingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'putScript', params: PutScriptParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'putTemplate', params: PutTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'reindex', params: ReindexParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'mget', params: MGetParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'msearch', params: MSearchParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ping', params: PingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'putScript', params: PutScriptParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'putTemplate', params: PutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'reindex', params: ReindexParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; // Generic types cannot be properly looked up with ReturnType. Hard code these explicitly. - (endpoint: 'scroll', params: ScrollParams, options?: CallAPIOptions): Promise>; - (endpoint: 'search', params: SearchParams, options?: CallAPIOptions): Promise>; - (endpoint: 'searchShards', params: SearchShardsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'suggest', params: SuggestParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'termvectors', params: TermvectorsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'update', params: UpdateDocumentParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'scroll', params: ScrollParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'search', params: SearchParams, options?: LegacyCallAPIOptions): Promise>; + (endpoint: 'searchShards', params: SearchShardsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'suggest', params: SuggestParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'termvectors', params: TermvectorsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'update', params: UpdateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; // cat namespace - (endpoint: 'cat.aliases', params: CatAliasesParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.allocation', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.count', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.health', params: CatHealthParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.help', params: CatHelpParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.indices', params: CatIndicesParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.master', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.nodes', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.plugins', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.repositories', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.segments', params: CatSegmentsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.shards', params: CatShardsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.tasks', params: CatTasksParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'cat.aliases', params: CatAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.allocation', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.count', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.health', params: CatHealthParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.help', params: CatHelpParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.indices', params: CatIndicesParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.master', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.nodes', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.plugins', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.repositories', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.segments', params: CatSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.shards', params: CatShardsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.tasks', params: CatTasksParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: LegacyCallAPIOptions): ReturnType; // cluster namespace - (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.health', params: ClusterHealthParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.state', params: ClusterStateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.health', params: ClusterHealthParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.state', params: ClusterStateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: LegacyCallAPIOptions): ReturnType; // indices namespace - (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.close', params: IndicesCloseParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.create', params: IndicesCreateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.exists', params: IndicesExistsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.flush', params: IndicesFlushParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.get', params: IndicesGetParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.open', params: IndicesOpenParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.stats', params: IndicesStatsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.close', params: IndicesCloseParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.create', params: IndicesCreateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.exists', params: IndicesExistsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.flush', params: IndicesFlushParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.get', params: IndicesGetParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.open', params: IndicesOpenParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.stats', params: IndicesStatsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: LegacyCallAPIOptions): ReturnType; // ingest namepsace - (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: LegacyCallAPIOptions): ReturnType; // nodes namespace - (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'nodes.info', params: NodesInfoParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'nodes.stats', params: NodesStatsParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'nodes.info', params: NodesInfoParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'nodes.stats', params: NodesStatsParams, options?: LegacyCallAPIOptions): ReturnType; // snapshot namespace - (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; // tasks namespace - (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'tasks.get', params: TasksGetParams, options?: CallAPIOptions): ReturnType; - (endpoint: 'tasks.list', params: TasksListParams, options?: CallAPIOptions): ReturnType; + (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'tasks.get', params: TasksGetParams, options?: LegacyCallAPIOptions): ReturnType; + (endpoint: 'tasks.list', params: TasksListParams, options?: LegacyCallAPIOptions): ReturnType; // other APIs accessed via transport.request - (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: CallAPIOptions): Promise< + (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: LegacyCallAPIOptions): Promise< AssistanceAPIResponse >; - (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: CallAPIOptions): Promise< + (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: LegacyCallAPIOptions): Promise< DeprecationAPIResponse >; // Catch-all definition - (endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; + (endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; /* eslint-enable */ } diff --git a/src/core/server/elasticsearch/cluster_client.test.mocks.ts b/src/core/server/elasticsearch/legacy/cluster_client.test.mocks.ts similarity index 95% rename from src/core/server/elasticsearch/cluster_client.test.mocks.ts rename to src/core/server/elasticsearch/legacy/cluster_client.test.mocks.ts index 6873117aecc35e..08585c2305e9bf 100644 --- a/src/core/server/elasticsearch/cluster_client.test.mocks.ts +++ b/src/core/server/elasticsearch/legacy/cluster_client.test.mocks.ts @@ -29,7 +29,7 @@ jest.mock('elasticsearch', () => { export const MockScopedClusterClient = jest.fn(); jest.mock('./scoped_cluster_client', () => ({ - ScopedClusterClient: MockScopedClusterClient, + LegacyScopedClusterClient: MockScopedClusterClient, })); export const mockParseElasticsearchClientConfig = jest.fn(); diff --git a/src/core/server/elasticsearch/cluster_client.test.ts b/src/core/server/elasticsearch/legacy/cluster_client.test.ts similarity index 91% rename from src/core/server/elasticsearch/cluster_client.test.ts rename to src/core/server/elasticsearch/legacy/cluster_client.test.ts index 820272bdf14b81..9ab4862a1ab4c5 100644 --- a/src/core/server/elasticsearch/cluster_client.test.ts +++ b/src/core/server/elasticsearch/legacy/cluster_client.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { ElasticsearchConfig } from './elasticsearch_config'; +import { ElasticsearchConfig } from '../elasticsearch_config'; import { MockClient, @@ -27,10 +27,10 @@ import { import { errors } from 'elasticsearch'; import { get } from 'lodash'; -import { Logger } from '../logging'; -import { loggingSystemMock } from '../logging/logging_system.mock'; -import { httpServerMock } from '../http/http_server.mocks'; -import { ClusterClient } from './cluster_client'; +import { Logger } from '../../logging'; +import { loggingSystemMock } from '../../logging/logging_system.mock'; +import { httpServerMock } from '../../http/http_server.mocks'; +import { LegacyClusterClient } from './cluster_client'; const logger = loggingSystemMock.create(); afterEach(() => jest.clearAllMocks()); @@ -42,7 +42,7 @@ test('#constructor creates client with parsed config', () => { const mockEsConfig = { apiVersion: 'es-version' } as any; const mockLogger = logger.get(); - const clusterClient = new ClusterClient(mockEsConfig, mockLogger); + const clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); expect(clusterClient).toBeDefined(); expect(mockParseElasticsearchClientConfig).toHaveBeenCalledTimes(1); @@ -58,7 +58,7 @@ describe('#callAsInternalUser', () => { ping: jest.Mock; security: { authenticate: jest.Mock }; }; - let clusterClient: ClusterClient; + let clusterClient: LegacyClusterClient; beforeEach(() => { mockEsClientInstance = { @@ -68,7 +68,7 @@ describe('#callAsInternalUser', () => { }; MockClient.mockImplementation(() => mockEsClientInstance); - clusterClient = new ClusterClient({ apiVersion: 'es-version' } as any, logger.get()); + clusterClient = new LegacyClusterClient({ apiVersion: 'es-version' } as any, logger.get()); }); test('fails if cluster client is closed', async () => { @@ -220,7 +220,7 @@ describe('#asScoped', () => { let mockEsClientInstance: { ping: jest.Mock; close: jest.Mock }; let mockScopedEsClientInstance: { ping: jest.Mock; close: jest.Mock }; - let clusterClient: ClusterClient; + let clusterClient: LegacyClusterClient; let mockLogger: Logger; let mockEsConfig: ElasticsearchConfig; @@ -237,7 +237,7 @@ describe('#asScoped', () => { requestHeadersWhitelist: ['one', 'two'], } as any; - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); jest.clearAllMocks(); }); @@ -272,7 +272,7 @@ describe('#asScoped', () => { test('properly configures `ignoreCertAndKey` for various configurations', () => { // Config without SSL. - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); mockParseElasticsearchClientConfig.mockClear(); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); @@ -285,7 +285,7 @@ describe('#asScoped', () => { // Config ssl.alwaysPresentCertificate === false mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: false } } as any; - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); mockParseElasticsearchClientConfig.mockClear(); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); @@ -298,7 +298,7 @@ describe('#asScoped', () => { // Config ssl.alwaysPresentCertificate === true mockEsConfig = { ...mockEsConfig, ssl: { alwaysPresentCertificate: true } } as any; - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); mockParseElasticsearchClientConfig.mockClear(); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1' } })); @@ -341,7 +341,7 @@ describe('#asScoped', () => { }); test('does not fail when scope to not defined request', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient.asScoped(); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -352,7 +352,7 @@ describe('#asScoped', () => { }); test('does not fail when scope to a request without headers', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient.asScoped({} as any); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -363,7 +363,10 @@ describe('#asScoped', () => { }); test('calls getAuthHeaders and filters results for a real request', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger, () => ({ one: '1', three: '3' })); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, () => ({ + one: '1', + three: '3', + })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { two: '2' } })); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -374,7 +377,7 @@ describe('#asScoped', () => { }); test('getAuthHeaders results rewrite extends a request headers', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger, () => ({ one: 'foo' })); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, () => ({ one: 'foo' })); clusterClient.asScoped(httpServerMock.createRawRequest({ headers: { one: '1', two: '2' } })); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); expect(MockScopedClusterClient).toHaveBeenCalledWith( @@ -386,14 +389,14 @@ describe('#asScoped', () => { test("doesn't call getAuthHeaders for a fake request", async () => { const getAuthHeaders = jest.fn(); - clusterClient = new ClusterClient(mockEsConfig, mockLogger, getAuthHeaders); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger, getAuthHeaders); clusterClient.asScoped({ headers: { one: '1', two: '2', three: '3' } }); expect(getAuthHeaders).not.toHaveBeenCalled(); }); test('filters a fake request headers', async () => { - clusterClient = new ClusterClient(mockEsConfig, mockLogger); + clusterClient = new LegacyClusterClient(mockEsConfig, mockLogger); clusterClient.asScoped({ headers: { one: '1', two: '2', three: '3' } }); expect(MockScopedClusterClient).toHaveBeenCalledTimes(1); @@ -409,7 +412,7 @@ describe('#close', () => { let mockEsClientInstance: { close: jest.Mock }; let mockScopedEsClientInstance: { close: jest.Mock }; - let clusterClient: ClusterClient; + let clusterClient: LegacyClusterClient; beforeEach(() => { mockEsClientInstance = { close: jest.fn() }; @@ -418,7 +421,7 @@ describe('#close', () => { () => mockScopedEsClientInstance ); - clusterClient = new ClusterClient( + clusterClient = new LegacyClusterClient( { apiVersion: 'es-version', requestHeadersWhitelist: [] } as any, logger.get() ); diff --git a/src/core/server/elasticsearch/cluster_client.ts b/src/core/server/elasticsearch/legacy/cluster_client.ts similarity index 77% rename from src/core/server/elasticsearch/cluster_client.ts rename to src/core/server/elasticsearch/legacy/cluster_client.ts index 2352677b8d3e0a..8e2d20a8972fc9 100644 --- a/src/core/server/elasticsearch/cluster_client.ts +++ b/src/core/server/elasticsearch/legacy/cluster_client.ts @@ -19,16 +19,17 @@ import { Client } from 'elasticsearch'; import { get } from 'lodash'; -import { ElasticsearchErrorHelpers } from './errors'; -import { GetAuthHeaders, isRealRequest, LegacyRequest } from '../http'; -import { filterHeaders, Headers, KibanaRequest, ensureRawRequest } from '../http/router'; -import { Logger } from '../logging'; +import { LegacyElasticsearchErrorHelpers } from './errors'; +import { GetAuthHeaders, isRealRequest } from '../../http'; +import { filterHeaders, ensureRawRequest } from '../../http/router'; +import { Logger } from '../../logging'; +import { ScopeableRequest } from '../types'; import { - ElasticsearchClientConfig, + LegacyElasticsearchClientConfig, parseElasticsearchClientConfig, } from './elasticsearch_client_config'; -import { ScopedClusterClient, IScopedClusterClient } from './scoped_cluster_client'; -import { CallAPIOptions, APICaller } from './api_types'; +import { LegacyScopedClusterClient, ILegacyScopedClusterClient } from './scoped_cluster_client'; +import { LegacyCallAPIOptions, LegacyAPICaller } from './api_types'; /** * Support Legacy platform request for the period of migration. @@ -50,7 +51,7 @@ const callAPI = async ( client: Client, endpoint: string, clientParams: Record = {}, - options: CallAPIOptions = { wrap401Errors: true } + options: LegacyCallAPIOptions = { wrap401Errors: true } ) => { const clientPath = endpoint.split('.'); const api: any = get(client, clientPath); @@ -75,55 +76,40 @@ const callAPI = async ( throw err; } - throw ElasticsearchErrorHelpers.decorateNotAuthorizedError(err); + throw LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(err); } }; -/** - * Fake request object created manually by Kibana plugins. - * @public - */ -export interface FakeRequest { - /** Headers used for authentication against Elasticsearch */ - headers: Headers; -} - /** * Represents an Elasticsearch cluster API client created by the platform. * It allows to call API on behalf of the internal Kibana user and * the actual user that is derived from the request headers (via `asScoped(...)`). * - * See {@link ClusterClient}. + * See {@link LegacyClusterClient}. * * @public */ -export type IClusterClient = Pick; +export type ILegacyClusterClient = Pick; /** * Represents an Elasticsearch cluster API client created by a plugin. * It allows to call API on behalf of the internal Kibana user and * the actual user that is derived from the request headers (via `asScoped(...)`). * - * See {@link ClusterClient}. - * - * @public - */ -export type ICustomClusterClient = Pick; - -/** - A user credentials container. - * It accommodates the necessary auth credentials to impersonate the current user. + * See {@link LegacyClusterClient}. * * @public - * See {@link KibanaRequest}. */ -export type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; +export type ILegacyCustomClusterClient = Pick< + LegacyClusterClient, + 'callAsInternalUser' | 'close' | 'asScoped' +>; /** * {@inheritDoc IClusterClient} * @public */ -export class ClusterClient implements IClusterClient { +export class LegacyClusterClient implements ILegacyClusterClient { /** * Raw Elasticsearch JS client that acts on behalf of the Kibana internal user. */ @@ -141,7 +127,7 @@ export class ClusterClient implements IClusterClient { private isClosed = false; constructor( - private readonly config: ElasticsearchClientConfig, + private readonly config: LegacyElasticsearchClientConfig, private readonly log: Logger, private readonly getAuthHeaders: GetAuthHeaders = noop ) { @@ -151,20 +137,24 @@ export class ClusterClient implements IClusterClient { /** * Calls specified endpoint with provided clientParams on behalf of the * Kibana internal user. - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. * @param options - Options that affect the way we call the API and process the result. */ - public callAsInternalUser: APICaller = async ( + public callAsInternalUser: LegacyAPICaller = async ( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { this.assertIsNotClosed(); - return await (callAPI.bind(null, this.client) as APICaller)(endpoint, clientParams, options); + return await (callAPI.bind(null, this.client) as LegacyAPICaller)( + endpoint, + clientParams, + options + ); }; /** @@ -185,7 +175,7 @@ export class ClusterClient implements IClusterClient { } /** - * Creates an instance of {@link IScopedClusterClient} based on the configuration the + * Creates an instance of {@link ILegacyScopedClusterClient} based on the configuration the * current cluster client that exposes additional `callAsCurrentUser` method * scoped to the provided req. Consumers shouldn't worry about closing * scoped client instances, these will be automatically closed as soon as the @@ -194,7 +184,7 @@ export class ClusterClient implements IClusterClient { * @param request - Request the `IScopedClusterClient` instance will be scoped to. * Supports request optionality, Legacy.Request & FakeRequest for BWC with LegacyPlatform */ - public asScoped(request?: ScopeableRequest): IScopedClusterClient { + public asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient { // It'd have been quite expensive to create and configure client for every incoming // request since it involves parsing of the config, reading of the SSL certificate and // key files etc. Moreover scoped client needs two Elasticsearch JS clients at the same @@ -210,7 +200,7 @@ export class ClusterClient implements IClusterClient { ); } - return new ScopedClusterClient( + return new LegacyScopedClusterClient( this.callAsInternalUser, this.callAsCurrentUser, filterHeaders(this.getHeaders(request), this.config.requestHeadersWhitelist) @@ -220,20 +210,20 @@ export class ClusterClient implements IClusterClient { /** * Calls specified endpoint with provided clientParams on behalf of the * user initiated request to the Kibana server (via HTTP request headers). - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. * @param options - Options that affect the way we call the API and process the result. */ - private callAsCurrentUser: APICaller = async ( + private callAsCurrentUser: LegacyAPICaller = async ( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { this.assertIsNotClosed(); - return await (callAPI.bind(null, this.scopedClient!) as APICaller)( + return await (callAPI.bind(null, this.scopedClient!) as LegacyAPICaller)( endpoint, clientParams, options @@ -246,9 +236,7 @@ export class ClusterClient implements IClusterClient { } } - private getHeaders( - request?: KibanaRequest | LegacyRequest | FakeRequest - ): Record { + private getHeaders(request?: ScopeableRequest): Record { if (!isRealRequest(request)) { return request && request.headers ? request.headers : {}; } diff --git a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts similarity index 98% rename from src/core/server/elasticsearch/elasticsearch_client_config.test.ts rename to src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts index 77d1e41c9ad833..d6b65da7726d26 100644 --- a/src/core/server/elasticsearch/elasticsearch_client_config.test.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.test.ts @@ -18,9 +18,9 @@ */ import { duration } from 'moment'; -import { loggingSystemMock } from '../logging/logging_system.mock'; +import { loggingSystemMock } from '../../logging/logging_system.mock'; import { - ElasticsearchClientConfig, + LegacyElasticsearchClientConfig, parseElasticsearchClientConfig, } from './elasticsearch_client_config'; const logger = loggingSystemMock.create(); @@ -64,7 +64,7 @@ Object { }); test('parses fully specified config', () => { - const elasticsearchConfig: ElasticsearchClientConfig = { + const elasticsearchConfig: LegacyElasticsearchClientConfig = { apiVersion: 'v7.0.0', customHeaders: { xsrf: 'something' }, logQueries: true, diff --git a/src/core/server/elasticsearch/elasticsearch_client_config.ts b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts similarity index 93% rename from src/core/server/elasticsearch/elasticsearch_client_config.ts rename to src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts index 287d835c40351b..260a60ac74f118 100644 --- a/src/core/server/elasticsearch/elasticsearch_client_config.ts +++ b/src/core/server/elasticsearch/legacy/elasticsearch_client_config.ts @@ -22,9 +22,9 @@ import { cloneDeep } from 'lodash'; import { Duration } from 'moment'; import { checkServerIdentity } from 'tls'; import url from 'url'; -import { pick } from '../../utils'; -import { Logger } from '../logging'; -import { ElasticsearchConfig } from './elasticsearch_config'; +import { pick } from '../../../utils'; +import { Logger } from '../../logging'; +import { ElasticsearchConfig } from '../elasticsearch_config'; /** * @privateRemarks Config that consumers can pass to the Elasticsearch JS client is complex and includes @@ -33,7 +33,7 @@ import { ElasticsearchConfig } from './elasticsearch_config'; * * @public */ -export type ElasticsearchClientConfig = Pick & +export type LegacyElasticsearchClientConfig = Pick & Pick< ElasticsearchConfig, | 'apiVersion' @@ -53,7 +53,7 @@ export type ElasticsearchClientConfig = Pick { describe('NotAuthorized error', () => { describe('decorateNotAuthorizedError', () => { it('returns original object', () => { const error = new Error(); - expect(ElasticsearchErrorHelpers.decorateNotAuthorizedError(error)).toBe(error); + expect(LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(error)).toBe(error); }); it('makes the error identifiable as a NotAuthorized error', () => { const error = new Error(); - expect(ElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(false); - ElasticsearchErrorHelpers.decorateNotAuthorizedError(error); - expect(ElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(true); + expect(LegacyElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(false); + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(error); + expect(LegacyElasticsearchErrorHelpers.isNotAuthorizedError(error)).toBe(true); }); it('adds boom properties', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); expect(typeof error.output).toBe('object'); expect(error.output.statusCode).toBe(401); }); it('preserves boom properties of input', () => { const error = Boom.notFound(); - ElasticsearchErrorHelpers.decorateNotAuthorizedError(error); + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(error); expect(error.output.statusCode).toBe(404); }); describe('error.output', () => { it('defaults to message of error', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error('foobar')); + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( + new Error('foobar') + ); expect(error.output.payload).toHaveProperty('message', 'foobar'); }); it('prefixes message with passed reason', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new Error('foobar'), 'biz' ); expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); }); it('sets statusCode to 401', () => { - const error = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error('foo')); + const error = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( + new Error('foo') + ); expect(error.output).toHaveProperty('statusCode', 401); }); }); diff --git a/src/core/server/elasticsearch/errors.ts b/src/core/server/elasticsearch/legacy/errors.ts similarity index 88% rename from src/core/server/elasticsearch/errors.ts rename to src/core/server/elasticsearch/legacy/errors.ts index 6852b8632ebf12..f81903d76547a3 100644 --- a/src/core/server/elasticsearch/errors.ts +++ b/src/core/server/elasticsearch/legacy/errors.ts @@ -27,11 +27,11 @@ enum ErrorCode { } /** @public */ -export interface ElasticsearchError extends Boom { +export interface LegacyElasticsearchError extends Boom { [code]?: string; } -function isElasticsearchError(error: any): error is ElasticsearchError { +function isElasticsearchError(error: any): error is LegacyElasticsearchError { return Boolean(error && error[code]); } @@ -40,7 +40,7 @@ function decorate( errorCode: ErrorCode, statusCode: number, message?: string -): ElasticsearchError { +): LegacyElasticsearchError { if (isElasticsearchError(error)) { return error; } @@ -50,7 +50,7 @@ function decorate( message, // keep status and messages if Boom error object already has them override: false, - }) as ElasticsearchError; + }) as LegacyElasticsearchError; boom[code] = errorCode; @@ -74,8 +74,8 @@ function decorate( * } * ``` */ -export class ElasticsearchErrorHelpers { - public static isNotAuthorizedError(error: any): error is ElasticsearchError { +export class LegacyElasticsearchErrorHelpers { + public static isNotAuthorizedError(error: any): error is LegacyElasticsearchError { return isElasticsearchError(error) && error[code] === ErrorCode.NOT_AUTHORIZED; } diff --git a/src/core/server/elasticsearch/legacy/index.ts b/src/core/server/elasticsearch/legacy/index.ts new file mode 100644 index 00000000000000..165980b9f45223 --- /dev/null +++ b/src/core/server/elasticsearch/legacy/index.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +export { + LegacyClusterClient, + ILegacyClusterClient, + ILegacyCustomClusterClient, +} from './cluster_client'; +export { ILegacyScopedClusterClient, LegacyScopedClusterClient } from './scoped_cluster_client'; +export { LegacyElasticsearchClientConfig } from './elasticsearch_client_config'; +export { retryCallCluster, migrationsRetryCallCluster } from './retry_call_cluster'; +export { LegacyElasticsearchError, LegacyElasticsearchErrorHelpers } from './errors'; +export * from './api_types'; diff --git a/src/core/server/elasticsearch/retry_call_cluster.test.ts b/src/core/server/elasticsearch/legacy/retry_call_cluster.test.ts similarity index 98% rename from src/core/server/elasticsearch/retry_call_cluster.test.ts rename to src/core/server/elasticsearch/legacy/retry_call_cluster.test.ts index 18ffa95048c4d9..62789a4fe952d7 100644 --- a/src/core/server/elasticsearch/retry_call_cluster.test.ts +++ b/src/core/server/elasticsearch/legacy/retry_call_cluster.test.ts @@ -19,7 +19,7 @@ import * as legacyElasticsearch from 'elasticsearch'; import { retryCallCluster, migrationsRetryCallCluster } from './retry_call_cluster'; -import { loggingSystemMock } from '../logging/logging_system.mock'; +import { loggingSystemMock } from '../../logging/logging_system.mock'; describe('retryCallCluster', () => { it('retries ES API calls that rejects with NoConnections', () => { diff --git a/src/core/server/elasticsearch/retry_call_cluster.ts b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts similarity index 88% rename from src/core/server/elasticsearch/retry_call_cluster.ts rename to src/core/server/elasticsearch/legacy/retry_call_cluster.ts index aa3e39d948593a..b12ecc889eb2d7 100644 --- a/src/core/server/elasticsearch/retry_call_cluster.ts +++ b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts @@ -21,9 +21,9 @@ import { retryWhen, concatMap } from 'rxjs/operators'; import { defer, throwError, iif, timer } from 'rxjs'; import * as legacyElasticsearch from 'elasticsearch'; -import { CallAPIOptions } from '.'; -import { APICaller } from './api_types'; -import { Logger } from '../logging'; +import { LegacyCallAPIOptions } from '.'; +import { LegacyAPICaller } from './api_types'; +import { Logger } from '../../logging'; const esErrors = legacyElasticsearch.errors; @@ -39,12 +39,16 @@ const esErrors = legacyElasticsearch.errors; * @param delay */ export function migrationsRetryCallCluster( - apiCaller: APICaller, + apiCaller: LegacyAPICaller, log: Logger, delay: number = 2500 ) { const previousErrors: string[] = []; - return (endpoint: string, clientParams: Record = {}, options?: CallAPIOptions) => { + return ( + endpoint: string, + clientParams: Record = {}, + options?: LegacyCallAPIOptions + ) => { return defer(() => apiCaller(endpoint, clientParams, options)) .pipe( retryWhen((error$) => @@ -86,8 +90,12 @@ export function migrationsRetryCallCluster( * * @param apiCaller */ -export function retryCallCluster(apiCaller: APICaller) { - return (endpoint: string, clientParams: Record = {}, options?: CallAPIOptions) => { +export function retryCallCluster(apiCaller: LegacyAPICaller) { + return ( + endpoint: string, + clientParams: Record = {}, + options?: LegacyCallAPIOptions + ) => { return defer(() => apiCaller(endpoint, clientParams, options)) .pipe( retryWhen((errors) => diff --git a/src/core/server/elasticsearch/scoped_cluster_client.test.ts b/src/core/server/elasticsearch/legacy/scoped_cluster_client.test.ts similarity index 95% rename from src/core/server/elasticsearch/scoped_cluster_client.test.ts rename to src/core/server/elasticsearch/legacy/scoped_cluster_client.test.ts index 63113de1469537..6275832faec9b8 100644 --- a/src/core/server/elasticsearch/scoped_cluster_client.test.ts +++ b/src/core/server/elasticsearch/legacy/scoped_cluster_client.test.ts @@ -17,15 +17,15 @@ * under the License. */ -import { ScopedClusterClient } from './scoped_cluster_client'; +import { LegacyScopedClusterClient } from './scoped_cluster_client'; let internalAPICaller: jest.Mock; let scopedAPICaller: jest.Mock; -let clusterClient: ScopedClusterClient; +let clusterClient: LegacyScopedClusterClient; beforeEach(() => { internalAPICaller = jest.fn(); scopedAPICaller = jest.fn(); - clusterClient = new ScopedClusterClient(internalAPICaller, scopedAPICaller, { one: '1' }); + clusterClient = new LegacyScopedClusterClient(internalAPICaller, scopedAPICaller, { one: '1' }); }); afterEach(() => jest.clearAllMocks()); @@ -172,7 +172,10 @@ describe('#callAsCurrentUser', () => { const mockResponse = { data: 'response' }; scopedAPICaller.mockResolvedValue(mockResponse); - const clusterClientWithoutHeaders = new ScopedClusterClient(internalAPICaller, scopedAPICaller); + const clusterClientWithoutHeaders = new LegacyScopedClusterClient( + internalAPICaller, + scopedAPICaller + ); await expect(clusterClientWithoutHeaders.callAsCurrentUser('ping')).resolves.toBe(mockResponse); expect(scopedAPICaller).toHaveBeenCalledTimes(1); diff --git a/src/core/server/elasticsearch/scoped_cluster_client.ts b/src/core/server/elasticsearch/legacy/scoped_cluster_client.ts similarity index 85% rename from src/core/server/elasticsearch/scoped_cluster_client.ts rename to src/core/server/elasticsearch/legacy/scoped_cluster_client.ts index 4b64bfba151907..e62409ff00c7ed 100644 --- a/src/core/server/elasticsearch/scoped_cluster_client.ts +++ b/src/core/server/elasticsearch/legacy/scoped_cluster_client.ts @@ -18,11 +18,8 @@ */ import { intersection, isObject } from 'lodash'; -import { Headers } from '../http/router'; -import { APICaller, CallAPIOptions } from './api_types'; - -/** @public */ -export { Headers }; +import { Headers } from '../../http/router'; +import { LegacyAPICaller, LegacyCallAPIOptions } from './api_types'; /** * Serves the same purpose as "normal" `ClusterClient` but exposes additional @@ -30,12 +27,12 @@ export { Headers }; * user (as `callAsInternalUser` does) to request Elasticsearch API, but rather * passes HTTP headers extracted from the current user request to the API. * - * See {@link ScopedClusterClient}. + * See {@link LegacyScopedClusterClient}. * * @public */ -export type IScopedClusterClient = Pick< - ScopedClusterClient, +export type ILegacyScopedClusterClient = Pick< + LegacyScopedClusterClient, 'callAsCurrentUser' | 'callAsInternalUser' >; @@ -43,10 +40,10 @@ export type IScopedClusterClient = Pick< * {@inheritDoc IScopedClusterClient} * @public */ -export class ScopedClusterClient implements IScopedClusterClient { +export class LegacyScopedClusterClient implements ILegacyScopedClusterClient { constructor( - private readonly internalAPICaller: APICaller, - private readonly scopedAPICaller: APICaller, + private readonly internalAPICaller: LegacyAPICaller, + private readonly scopedAPICaller: LegacyAPICaller, private readonly headers?: Headers ) { this.callAsCurrentUser = this.callAsCurrentUser.bind(this); @@ -56,7 +53,7 @@ export class ScopedClusterClient implements IScopedClusterClient { /** * Calls specified `endpoint` with provided `clientParams` on behalf of the * Kibana internal user. - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. @@ -65,7 +62,7 @@ export class ScopedClusterClient implements IScopedClusterClient { public callAsInternalUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { return this.internalAPICaller(endpoint, clientParams, options); } @@ -73,7 +70,7 @@ export class ScopedClusterClient implements IScopedClusterClient { /** * Calls specified `endpoint` with provided `clientParams` on behalf of the * user initiated request to the Kibana server (via HTTP request headers). - * See {@link APICaller}. + * See {@link LegacyAPICaller}. * * @param endpoint - String descriptor of the endpoint e.g. `cluster.getSettings` or `ping`. * @param clientParams - A dictionary of parameters that will be passed directly to the Elasticsearch JS client. @@ -82,7 +79,7 @@ export class ScopedClusterClient implements IScopedClusterClient { public callAsCurrentUser( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) { const defaultHeaders = this.headers; if (defaultHeaders !== undefined) { diff --git a/src/core/server/elasticsearch/types.ts b/src/core/server/elasticsearch/types.ts index 6fef08fc298ffa..2b4ba4b0a0a550 100644 --- a/src/core/server/elasticsearch/types.ts +++ b/src/core/server/elasticsearch/types.ts @@ -18,9 +18,14 @@ */ import { Observable } from 'rxjs'; +import { Headers } from '../http/router'; +import { LegacyRequest, KibanaRequest } from '../http'; import { ElasticsearchConfig } from './elasticsearch_config'; -import { ElasticsearchClientConfig } from './elasticsearch_client_config'; -import { IClusterClient, ICustomClusterClient } from './cluster_client'; +import { + LegacyElasticsearchClientConfig, + ILegacyClusterClient, + ILegacyCustomClusterClient, +} from './legacy'; import { NodesVersionCompatibility } from './version_check/ensure_es_version'; import { ServiceStatus } from '../status'; @@ -38,7 +43,7 @@ export interface ElasticsearchServiceSetup { * @deprecated * Use {@link ElasticsearchServiceStart.legacy | ElasticsearchServiceStart.legacy.createClient} instead. * - * Create application specific Elasticsearch cluster API client with customized config. See {@link IClusterClient}. + * Create application specific Elasticsearch cluster API client with customized config. See {@link ILegacyClusterClient}. * * @param type Unique identifier of the client * @param clientConfig A config consists of Elasticsearch JS client options and @@ -56,22 +61,22 @@ export interface ElasticsearchServiceSetup { */ readonly createClient: ( type: string, - clientConfig?: Partial - ) => ICustomClusterClient; + clientConfig?: Partial + ) => ILegacyCustomClusterClient; /** * @deprecated * Use {@link ElasticsearchServiceStart.legacy | ElasticsearchServiceStart.legacy.client} instead. * * All Elasticsearch config value changes are processed under the hood. - * See {@link IClusterClient}. + * See {@link ILegacyClusterClient}. * * @example * ```js * const client = core.elasticsearch.legacy.client; * ``` */ - readonly client: IClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -86,7 +91,7 @@ export interface ElasticsearchServiceStart { * */ legacy: { /** - * Create application specific Elasticsearch cluster API client with customized config. See {@link IClusterClient}. + * Create application specific Elasticsearch cluster API client with customized config. See {@link ILegacyClusterClient}. * * @param type Unique identifier of the client * @param clientConfig A config consists of Elasticsearch JS client options and @@ -104,19 +109,19 @@ export interface ElasticsearchServiceStart { */ readonly createClient: ( type: string, - clientConfig?: Partial - ) => ICustomClusterClient; + clientConfig?: Partial + ) => ILegacyCustomClusterClient; /** * A pre-configured Elasticsearch client. All Elasticsearch config value changes are processed under the hood. - * See {@link IClusterClient}. + * See {@link ILegacyClusterClient}. * * @example * ```js * const client = core.elasticsearch.client; * ``` */ - readonly client: IClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -135,3 +140,21 @@ export interface ElasticsearchStatusMeta { warningNodes: NodesVersionCompatibility['warningNodes']; incompatibleNodes: NodesVersionCompatibility['incompatibleNodes']; } + +/** + * Fake request object created manually by Kibana plugins. + * @public + */ +export interface FakeRequest { + /** Headers used for authentication against Elasticsearch */ + headers: Headers; +} + +/** + A user credentials container. + * It accommodates the necessary auth credentials to impersonate the current user. + * + * @public + * See {@link KibanaRequest}. + */ +export type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; diff --git a/src/core/server/elasticsearch/version_check/ensure_es_version.ts b/src/core/server/elasticsearch/version_check/ensure_es_version.ts index 776298e5869a0d..3f562dac22a028 100644 --- a/src/core/server/elasticsearch/version_check/ensure_es_version.ts +++ b/src/core/server/elasticsearch/version_check/ensure_es_version.ts @@ -29,10 +29,10 @@ import { esVersionEqualsKibana, } from './es_kibana_version_compatability'; import { Logger } from '../../logging'; -import { APICaller } from '..'; +import { LegacyAPICaller } from '..'; export interface PollEsNodesVersionOptions { - callWithInternalUser: APICaller; + callWithInternalUser: LegacyAPICaller; log: Logger; kibanaVersion: string; ignoreVersionMismatch: boolean; diff --git a/src/core/server/http/index.ts b/src/core/server/http/index.ts index ca9dfde2e71dce..65d633260a7911 100644 --- a/src/core/server/http/index.ts +++ b/src/core/server/http/index.ts @@ -25,6 +25,7 @@ export { CustomHttpResponseOptions, IKibanaSocket, isRealRequest, + Headers, HttpResponseOptions, HttpResponsePayload, ErrorHttpResponseOptions, diff --git a/src/core/server/http/integration_tests/core_service.test.mocks.ts b/src/core/server/http/integration_tests/core_service.test.mocks.ts index 8e782970e2a8e4..6f9b4b96eae9d6 100644 --- a/src/core/server/http/integration_tests/core_service.test.mocks.ts +++ b/src/core/server/http/integration_tests/core_service.test.mocks.ts @@ -19,8 +19,8 @@ import { elasticsearchServiceMock } from '../../elasticsearch/elasticsearch_service.mock'; export const clusterClientMock = jest.fn(); -jest.doMock('../../elasticsearch/scoped_cluster_client', () => ({ - ScopedClusterClient: clusterClientMock.mockImplementation(function () { +jest.doMock('../../elasticsearch/legacy/scoped_cluster_client', () => ({ + LegacyScopedClusterClient: clusterClientMock.mockImplementation(function () { return elasticsearchServiceMock.createScopedClusterClient(); }), })); diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 7520111bf33ac5..91c33fac41646b 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -41,7 +41,7 @@ import { ElasticsearchServiceSetup, - IScopedClusterClient, + ILegacyScopedClusterClient, configSchema as elasticsearchConfigSchema, ElasticsearchServiceStart, } from './elasticsearch'; @@ -91,25 +91,24 @@ export { export { CoreId } from './core_context'; export { CspConfig, ICspConfig } from './csp'; export { - ClusterClient, - IClusterClient, - ICustomClusterClient, - Headers, - ScopedClusterClient, - IScopedClusterClient, + LegacyClusterClient, + ILegacyClusterClient, + ILegacyCustomClusterClient, + LegacyScopedClusterClient, + ILegacyScopedClusterClient, ElasticsearchConfig, - ElasticsearchClientConfig, - ElasticsearchError, - ElasticsearchErrorHelpers, + LegacyElasticsearchClientConfig, + LegacyElasticsearchError, + LegacyElasticsearchErrorHelpers, ElasticsearchServiceSetup, ElasticsearchServiceStart, ElasticsearchStatusMeta, NodesVersionCompatibility, - APICaller, + LegacyAPICaller, FakeRequest, ScopeableRequest, } from './elasticsearch'; -export * from './elasticsearch/api_types'; +export * from './elasticsearch/legacy/api_types'; export { AuthenticationHandler, AuthHeaders, @@ -127,6 +126,7 @@ export { CustomHttpResponseOptions, GetAuthHeaders, GetAuthState, + Headers, HttpAuth, HttpResponseOptions, HttpResponsePayload, @@ -356,7 +356,7 @@ export { * which uses the credentials of the incoming request * - {@link ISavedObjectTypeRegistry | savedObjects.typeRegistry} - Type registry containing * all the registered types. - * - {@link ScopedClusterClient | elasticsearch.legacy.client} - Elasticsearch + * - {@link LegacyScopedClusterClient | elasticsearch.legacy.client} - Elasticsearch * data client which uses the credentials of the incoming request * - {@link IUiSettingsClient | uiSettings.client} - uiSettings client * which uses the credentials of the incoming request @@ -371,7 +371,7 @@ export interface RequestHandlerContext { }; elasticsearch: { legacy: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; }; }; uiSettings: { diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index 48b1e12fc187ed..c2d4f49d7ee2ac 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -30,13 +30,13 @@ import { KibanaMigrator, IKibanaMigrator } from './migrations'; import { CoreContext } from '../core_context'; import { LegacyServiceDiscoverPlugins } from '../legacy'; import { - APICaller, + LegacyAPICaller, ElasticsearchServiceStart, - IClusterClient, + ILegacyClusterClient, InternalElasticsearchServiceSetup, } from '../elasticsearch'; import { KibanaConfigType } from '../kibana_config'; -import { migrationsRetryCallCluster } from '../elasticsearch/retry_call_cluster'; +import { migrationsRetryCallCluster } from '../elasticsearch/legacy'; import { SavedObjectsConfigType, SavedObjectsMigrationConfigType, @@ -434,7 +434,7 @@ export class SavedObjectsService await migrator.runMigrations(); } - const createRepository = (callCluster: APICaller, includedHiddenTypes: string[] = []) => { + const createRepository = (callCluster: LegacyAPICaller, includedHiddenTypes: string[] = []) => { return SavedObjectsRepository.createRepository( migrator, this.typeRegistry, @@ -484,7 +484,7 @@ export class SavedObjectsService private createMigrator( kibanaConfig: KibanaConfigType, savedObjectsConfig: SavedObjectsMigrationConfigType, - esClient: IClusterClient, + esClient: ILegacyClusterClient, migrationsRetryDelay?: number ): KibanaMigrator { return new KibanaMigrator({ diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index eeb822b780594b..f24195c0f295e3 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -19,8 +19,9 @@ import { omit } from 'lodash'; import uuid from 'uuid'; -import { retryCallCluster } from '../../../elasticsearch/retry_call_cluster'; -import { APICaller } from '../../../elasticsearch/'; +import { retryCallCluster } from '../../../elasticsearch/legacy'; +import { LegacyAPICaller } from '../../../elasticsearch/'; + import { getRootPropertiesObjects, IndexMapping } from '../../mappings'; import { getSearchDsl } from './search_dsl'; import { includedFields } from './included_fields'; @@ -73,7 +74,7 @@ const isRight = (either: Either): either is Right => either.tag === 'Right'; export interface SavedObjectsRepositoryOptions { index: string; mappings: IndexMapping; - callCluster: APICaller; + callCluster: LegacyAPICaller; typeRegistry: SavedObjectTypeRegistry; serializer: SavedObjectsSerializer; migrator: KibanaMigrator; @@ -116,7 +117,7 @@ export class SavedObjectsRepository { private _mappings: IndexMapping; private _registry: SavedObjectTypeRegistry; private _allowedTypes: string[]; - private _unwrappedCallCluster: APICaller; + private _unwrappedCallCluster: LegacyAPICaller; private _serializer: SavedObjectsSerializer; /** @@ -131,7 +132,7 @@ export class SavedObjectsRepository { migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, - callCluster: APICaller, + callCluster: LegacyAPICaller, includedHiddenTypes: string[] = [], injectedConstructor: any = SavedObjectsRepository ): ISavedObjectsRepository { @@ -187,7 +188,7 @@ export class SavedObjectsRepository { } this._allowedTypes = allowedTypes; - this._unwrappedCallCluster = async (...args: Parameters) => { + this._unwrappedCallCluster = async (...args: Parameters) => { await migrator.runMigrations(); return callCluster(...args); }; @@ -1299,7 +1300,7 @@ export class SavedObjectsRepository { }; } - private async _writeToCluster(...args: Parameters) { + private async _writeToCluster(...args: Parameters) { try { return await this._callCluster(...args); } catch (err) { @@ -1307,7 +1308,7 @@ export class SavedObjectsRepository { } } - private async _callCluster(...args: Parameters) { + private async _callCluster(...args: Parameters) { try { return await this._unwrappedCallCluster(...args); } catch (err) { diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index b79ce1da322510..e8399a48b3bf20 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -144,250 +144,6 @@ import { UpdateDocumentByQueryParams } from 'elasticsearch'; import { UpdateDocumentParams } from 'elasticsearch'; import { Url } from 'url'; -// @public (undocumented) -export interface APICaller { - // (undocumented) - (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'clearScroll', params: ClearScrollParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'count', params: CountParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'create', params: CreateDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'delete', params: DeleteDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'deleteScript', params: DeleteScriptParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'exists', params: ExistsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'explain', params: ExplainParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'fieldStats', params: FieldStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'get', params: GetParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'getScript', params: GetScriptParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'getSource', params: GetSourceParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'getTemplate', params: GetTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'index', params: IndexDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'info', params: InfoParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'mget', params: MGetParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'msearch', params: MSearchParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ping', params: PingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'putScript', params: PutScriptParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'putTemplate', params: PutTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'reindex', params: ReindexParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'scroll', params: ScrollParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'search', params: SearchParams, options?: CallAPIOptions): Promise>; - // (undocumented) - (endpoint: 'searchShards', params: SearchShardsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'suggest', params: SuggestParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'termvectors', params: TermvectorsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'update', params: UpdateDocumentParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.aliases', params: CatAliasesParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.allocation', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.count', params: CatAllocationParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.health', params: CatHealthParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.help', params: CatHelpParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.indices', params: CatIndicesParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.master', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.nodes', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.plugins', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.repositories', params: CatCommonParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.segments', params: CatSegmentsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.shards', params: CatShardsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.tasks', params: CatTasksParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.health', params: ClusterHealthParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.state', params: ClusterStateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.close', params: IndicesCloseParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.create', params: IndicesCreateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.exists', params: IndicesExistsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.flush', params: IndicesFlushParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.get', params: IndicesGetParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.open', params: IndicesOpenParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.stats', params: IndicesStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'nodes.info', params: NodesInfoParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'nodes.stats', params: NodesStatsParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'tasks.get', params: TasksGetParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'tasks.list', params: TasksListParams, options?: CallAPIOptions): ReturnType; - // (undocumented) - (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: CallAPIOptions): Promise; - // (undocumented) - (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: CallAPIOptions): Promise; - // (undocumented) - (endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; -} - // Warning: (ae-forgotten-export) The symbol "appendersSchema" needs to be exported by the entry point index.d.ts // // @public (undocumented) @@ -497,12 +253,6 @@ export class BasePath { // @internal (undocumented) export function bootstrap({ configs, cliArgs, applyConfigOverrides, features, }: BootstrapArgs): Promise; -// @public -export interface CallAPIOptions { - signal?: AbortSignal; - wrap401Errors?: boolean; -} - // @public export interface Capabilities { [key: string]: Record>; @@ -530,14 +280,6 @@ export interface CapabilitiesStart { // @public export type CapabilitiesSwitcher = (request: KibanaRequest, uiCapabilities: Capabilities) => Partial | Promise>; -// @public -export class ClusterClient implements IClusterClient { - constructor(config: ElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); - asScoped(request?: ScopeableRequest): IScopedClusterClient; - callAsInternalUser: APICaller; - close(): void; - } - // @alpha export const config: { elasticsearch: { @@ -851,14 +593,6 @@ export interface DiscoveredPlugin { readonly requiredPlugins: readonly PluginName[]; } -// @public (undocumented) -export type ElasticsearchClientConfig = Pick & Pick & { - pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; - requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; - sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; - ssl?: Partial; -}; - // @public export class ElasticsearchConfig { constructor(rawConfig: ElasticsearchConfigType); @@ -884,26 +618,12 @@ export class ElasticsearchConfig { readonly username?: string; } -// @public (undocumented) -export interface ElasticsearchError extends Boom { - // (undocumented) - [code]?: string; -} - -// @public -export class ElasticsearchErrorHelpers { - // (undocumented) - static decorateNotAuthorizedError(error: Error, reason?: string): ElasticsearchError; - // (undocumented) - static isNotAuthorizedError(error: any): error is ElasticsearchError; -} - // @public (undocumented) export interface ElasticsearchServiceSetup { // @deprecated (undocumented) legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -911,8 +631,8 @@ export interface ElasticsearchServiceSetup { export interface ElasticsearchServiceStart { // @deprecated (undocumented) legacy: { - readonly createClient: (type: string, clientConfig?: Partial) => ICustomClusterClient; - readonly client: IClusterClient; + readonly createClient: (type: string, clientConfig?: Partial) => ILegacyCustomClusterClient; + readonly client: ILegacyClusterClient; }; } @@ -1056,9 +776,6 @@ export interface HttpServiceStart { // @public export type IBasePath = Pick; -// @public -export type IClusterClient = Pick; - // @public export interface IContextContainer> { createHandler(pluginOpaqueId: PluginOpaqueId, handler: THandler): (...rest: HandlerParameters) => ShallowPromise>; @@ -1078,9 +795,6 @@ export interface ICspConfig { readonly warnLegacyBrowsers: boolean; } -// @public -export type ICustomClusterClient = Pick; - // @public export interface IKibanaResponse { // (undocumented) @@ -1102,6 +816,15 @@ export interface IKibanaSocket { getPeerCertificate(detailed?: boolean): PeerCertificate | DetailedPeerCertificate | null; } +// @public +export type ILegacyClusterClient = Pick; + +// @public +export type ILegacyCustomClusterClient = Pick; + +// @public +export type ILegacyScopedClusterClient = Pick; + // @public (undocumented) export interface ImageValidation { // (undocumented) @@ -1155,9 +878,6 @@ export type ISavedObjectsRepository = Pick; -// @public -export type IScopedClusterClient = Pick; - // @public export function isRelativeUrl(candidatePath: string): boolean; @@ -1247,6 +967,266 @@ export const kibanaResponseFactory: { // @public export type KnownHeaders = KnownKeys; +// @public (undocumented) +export interface LegacyAPICaller { + // (undocumented) + (endpoint: 'bulk', params: BulkIndexDocumentsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'clearScroll', params: ClearScrollParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'count', params: CountParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'create', params: CreateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'delete', params: DeleteDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'deleteByQuery', params: DeleteDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'deleteScript', params: DeleteScriptParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'deleteTemplate', params: DeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'exists', params: ExistsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'explain', params: ExplainParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'fieldStats', params: FieldStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'get', params: GetParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'getScript', params: GetScriptParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'getSource', params: GetSourceParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'getTemplate', params: GetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'index', params: IndexDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'info', params: InfoParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'mget', params: MGetParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'msearch', params: MSearchParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'msearchTemplate', params: MSearchTemplateParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'mtermvectors', params: MTermVectorsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ping', params: PingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'putScript', params: PutScriptParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'putTemplate', params: PutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'reindex', params: ReindexParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'reindexRethrottle', params: ReindexRethrottleParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'renderSearchTemplate', params: RenderSearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'scroll', params: ScrollParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'search', params: SearchParams, options?: LegacyCallAPIOptions): Promise>; + // (undocumented) + (endpoint: 'searchShards', params: SearchShardsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'searchTemplate', params: SearchTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'suggest', params: SuggestParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'termvectors', params: TermvectorsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'update', params: UpdateDocumentParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'updateByQuery', params: UpdateDocumentByQueryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.aliases', params: CatAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.allocation', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.count', params: CatAllocationParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.fielddata', params: CatFielddataParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.health', params: CatHealthParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.help', params: CatHelpParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.indices', params: CatIndicesParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.master', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.nodeattrs', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.nodes', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.pendingTasks', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.plugins', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.recovery', params: CatRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.repositories', params: CatCommonParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.segments', params: CatSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.shards', params: CatShardsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.snapshots', params: CatSnapshotsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.tasks', params: CatTasksParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cat.threadPool', params: CatThreadPoolParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.allocationExplain', params: ClusterAllocationExplainParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.getSettings', params: ClusterGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.health', params: ClusterHealthParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.pendingTasks', params: ClusterPendingTasksParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.putSettings', params: ClusterPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.reroute', params: ClusterRerouteParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.state', params: ClusterStateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'cluster.stats', params: ClusterStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.analyze', params: IndicesAnalyzeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.clearCache', params: IndicesClearCacheParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.close', params: IndicesCloseParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.create', params: IndicesCreateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.delete', params: IndicesDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.deleteAlias', params: IndicesDeleteAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.deleteTemplate', params: IndicesDeleteTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.exists', params: IndicesExistsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.existsAlias', params: IndicesExistsAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.existsTemplate', params: IndicesExistsTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.existsType', params: IndicesExistsTypeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.flush', params: IndicesFlushParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.flushSynced', params: IndicesFlushSyncedParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.forcemerge', params: IndicesForcemergeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.get', params: IndicesGetParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getAlias', params: IndicesGetAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getFieldMapping', params: IndicesGetFieldMappingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getMapping', params: IndicesGetMappingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getSettings', params: IndicesGetSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getTemplate', params: IndicesGetTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.getUpgrade', params: IndicesGetUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.open', params: IndicesOpenParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putAlias', params: IndicesPutAliasParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putMapping', params: IndicesPutMappingParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putSettings', params: IndicesPutSettingsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.putTemplate', params: IndicesPutTemplateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.recovery', params: IndicesRecoveryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.refresh', params: IndicesRefreshParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.rollover', params: IndicesRolloverParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.segments', params: IndicesSegmentsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.shardStores', params: IndicesShardStoresParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.shrink', params: IndicesShrinkParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.stats', params: IndicesStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.updateAliases', params: IndicesUpdateAliasesParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.upgrade', params: IndicesUpgradeParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'indices.validateQuery', params: IndicesValidateQueryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.deletePipeline', params: IngestDeletePipelineParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.getPipeline', params: IngestGetPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.putPipeline', params: IngestPutPipelineParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'ingest.simulate', params: IngestSimulateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'nodes.hotThreads', params: NodesHotThreadsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'nodes.info', params: NodesInfoParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'nodes.stats', params: NodesStatsParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.create', params: SnapshotCreateParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.createRepository', params: SnapshotCreateRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.delete', params: SnapshotDeleteParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.deleteRepository', params: SnapshotDeleteRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.get', params: SnapshotGetParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.getRepository', params: SnapshotGetRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.restore', params: SnapshotRestoreParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.status', params: SnapshotStatusParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'snapshot.verifyRepository', params: SnapshotVerifyRepositoryParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'tasks.cancel', params: TasksCancelParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'tasks.get', params: TasksGetParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'tasks.list', params: TasksListParams, options?: LegacyCallAPIOptions): ReturnType; + // (undocumented) + (endpoint: 'transport.request', clientParams: AssistantAPIClientParams, options?: LegacyCallAPIOptions): Promise; + // (undocumented) + (endpoint: 'transport.request', clientParams: DeprecationAPIClientParams, options?: LegacyCallAPIOptions): Promise; + // (undocumented) + (endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; +} + +// @public +export interface LegacyCallAPIOptions { + signal?: AbortSignal; + wrap401Errors?: boolean; +} + +// Warning: (ae-unresolved-inheritdoc-reference) The @inheritDoc reference could not be resolved: The package "kibana" does not have an export "IClusterClient" +// +// @public (undocumented) +export class LegacyClusterClient implements ILegacyClusterClient { + constructor(config: LegacyElasticsearchClientConfig, log: Logger, getAuthHeaders?: GetAuthHeaders); + asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient; + callAsInternalUser: LegacyAPICaller; + close(): void; + } + // @internal @deprecated export interface LegacyConfig { // (undocumented) @@ -1261,6 +1241,28 @@ export interface LegacyConfig { set(config: LegacyVars): void; } +// @public (undocumented) +export type LegacyElasticsearchClientConfig = Pick & Pick & { + pingTimeout?: ElasticsearchConfig['pingTimeout'] | ConfigOptions['pingTimeout']; + requestTimeout?: ElasticsearchConfig['requestTimeout'] | ConfigOptions['requestTimeout']; + sniffInterval?: ElasticsearchConfig['sniffInterval'] | ConfigOptions['sniffInterval']; + ssl?: Partial; +}; + +// @public (undocumented) +export interface LegacyElasticsearchError extends Boom { + // (undocumented) + [code]?: string; +} + +// @public +export class LegacyElasticsearchErrorHelpers { + // (undocumented) + static decorateNotAuthorizedError(error: Error, reason?: string): LegacyElasticsearchError; + // (undocumented) + static isNotAuthorizedError(error: any): error is LegacyElasticsearchError; +} + // Warning: (ae-forgotten-export) The symbol "ILegacyInternals" needs to be exported by the entry point index.d.ts // // @internal @deprecated (undocumented) @@ -1280,6 +1282,15 @@ export class LegacyInternals implements ILegacyInternals { export interface LegacyRequest extends Request { } +// Warning: (ae-unresolved-inheritdoc-reference) The @inheritDoc reference could not be resolved: The package "kibana" does not have an export "IScopedClusterClient" +// +// @public (undocumented) +export class LegacyScopedClusterClient implements ILegacyScopedClusterClient { + constructor(internalAPICaller: LegacyAPICaller, scopedAPICaller: LegacyAPICaller, headers?: Headers | undefined); + callAsCurrentUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; + callAsInternalUser(endpoint: string, clientParams?: Record, options?: LegacyCallAPIOptions): Promise; + } + // Warning: (ae-forgotten-export) The symbol "LegacyPlugins" needs to be exported by the entry point index.d.ts // // @internal @deprecated (undocumented) @@ -1679,7 +1690,7 @@ export interface RequestHandlerContext { }; elasticsearch: { legacy: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; }; }; uiSettings: { @@ -2325,7 +2336,7 @@ export class SavedObjectsRepository { // Warning: (ae-forgotten-export) The symbol "KibanaMigrator" needs to be exported by the entry point index.d.ts // // @internal - static createRepository(migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, callCluster: APICaller, includedHiddenTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository; + static createRepository(migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, callCluster: LegacyAPICaller, includedHiddenTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository; delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise; deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; @@ -2480,13 +2491,6 @@ export type SavedObjectUnsanitizedDoc = SavedObjectDoc & Partial // @public export type ScopeableRequest = KibanaRequest | LegacyRequest | FakeRequest; -// @public -export class ScopedClusterClient implements IScopedClusterClient { - constructor(internalAPICaller: APICaller, scopedAPICaller: APICaller, headers?: Headers | undefined); - callAsCurrentUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; - callAsInternalUser(endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; - } - // @public export interface ServiceStatus | unknown = unknown> { detail?: string; 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 486abd5a0c7908..ea462291059a51 100644 --- a/src/core/server/ui_settings/integration_tests/lib/servers.ts +++ b/src/core/server/ui_settings/integration_tests/lib/servers.ts @@ -25,7 +25,7 @@ import { TestKibanaUtils, TestUtils, } from '../../../../../test_utils/kbn_server'; -import { APICaller } from '../../../elasticsearch/'; +import { LegacyAPICaller } from '../../../elasticsearch/'; import { httpServerMock } from '../../../http/http_server.mocks'; let servers: TestUtils; @@ -37,7 +37,7 @@ let kbnServer: TestKibanaUtils['kbnServer']; interface AllServices { kbnServer: TestKibanaUtils['kbnServer']; savedObjectsClient: SavedObjectsClientContract; - callCluster: APICaller; + callCluster: LegacyAPICaller; uiSettings: IUiSettingsClient; deleteKibanaIndex: typeof deleteKibanaIndex; } @@ -62,7 +62,7 @@ export async function startServers() { kbnServer = kbn.kbnServer; } -async function deleteKibanaIndex(callCluster: APICaller) { +async function deleteKibanaIndex(callCluster: LegacyAPICaller) { const kibanaIndices = await callCluster('cat.indices', { index: '.kibana*', format: 'json' }); const indexNames = kibanaIndices.map((x: any) => x.index); if (!indexNames.length) { diff --git a/src/legacy/core_plugins/elasticsearch/lib/cluster.ts b/src/legacy/core_plugins/elasticsearch/lib/cluster.ts index a595fffb3c2350..0e7692f6be7555 100644 --- a/src/legacy/core_plugins/elasticsearch/lib/cluster.ts +++ b/src/legacy/core_plugins/elasticsearch/lib/cluster.ts @@ -19,18 +19,18 @@ import { Request } from 'hapi'; import { errors } from 'elasticsearch'; -import { CallAPIOptions, ClusterClient, FakeRequest } from 'kibana/server'; +import { LegacyCallAPIOptions, LegacyClusterClient, FakeRequest } from 'kibana/server'; export class Cluster { public readonly errors = errors; - constructor(private readonly clusterClient: ClusterClient) {} + constructor(private readonly clusterClient: LegacyClusterClient) {} public callWithRequest = async ( req: Request | FakeRequest, endpoint: string, clientParams?: Record, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { return await this.clusterClient .asScoped(req) @@ -40,7 +40,7 @@ export class Cluster { public callWithInternalUser = async ( endpoint: string, clientParams?: Record, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => { return await this.clusterClient.callAsInternalUser(endpoint, clientParams, options); }; diff --git a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts index f563976cae9b82..ff9d67152e268d 100644 --- a/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data/server/index_patterns/fetcher/index_patterns_fetcher.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { getFieldCapabilities, resolveTimePattern, createNoMatchingIndicesError } from './lib'; @@ -37,9 +37,9 @@ interface FieldSubType { } export class IndexPatternsFetcher { - private _callDataCluster: APICaller; + private _callDataCluster: LegacyAPICaller; - constructor(callDataCluster: APICaller) { + constructor(callDataCluster: LegacyAPICaller) { this._callDataCluster = callDataCluster; } diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts index 734e845e857693..0738a16034d467 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/es_api.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { convertEsError } from './errors'; import { FieldCapsResponse } from './field_capabilities'; @@ -46,7 +46,7 @@ export interface IndexAliasResponse { * @return {Promise} */ export async function callIndexAliasApi( - callCluster: APICaller, + callCluster: LegacyAPICaller, indices: string[] | string ): Promise { try { @@ -71,7 +71,7 @@ export async function callIndexAliasApi( * @param {Array|String} indices * @return {Promise} */ -export async function callFieldCapsApi(callCluster: APICaller, indices: string[] | string) { +export async function callFieldCapsApi(callCluster: LegacyAPICaller, indices: string[] | string) { try { return (await callCluster('fieldCaps', { index: indices, diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts index d8c94664322049..502364cdcba327 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/field_capabilities/field_capabilities.ts @@ -19,7 +19,7 @@ import { defaults, indexBy, sortBy } from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { callFieldCapsApi } from '../es_api'; import { FieldCapsResponse, readFieldCapsResponse } from './field_caps_response'; import { mergeOverrides } from './overrides'; @@ -39,7 +39,7 @@ export function concatIfUniq(arr: T[], value: T) { * @return {Promise>} */ export async function getFieldCapabilities( - callCluster: APICaller, + callCluster: LegacyAPICaller, indices: string | string[] = [], metaFields: string[] = [] ) { diff --git a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts index 764307bef0ba64..a01d34dbe9df6c 100644 --- a/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts +++ b/src/plugins/data/server/index_patterns/fetcher/lib/resolve_time_pattern.ts @@ -20,7 +20,7 @@ import { chain } from 'lodash'; import moment from 'moment'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { timePatternToWildcard } from './time_pattern_to_wildcard'; import { callIndexAliasApi, IndicesAliasResponse } from './es_api'; @@ -36,7 +36,7 @@ import { callIndexAliasApi, IndicesAliasResponse } from './es_api'; * and the indices that actually match the time * pattern (matches); */ -export async function resolveTimePattern(callCluster: APICaller, timePattern: string) { +export async function resolveTimePattern(callCluster: LegacyAPICaller, timePattern: string) { const aliases = await callIndexAliasApi(callCluster, timePatternToWildcard(timePattern)); const allIndexDetails = chain(aliases) diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts index 0ff1cea923845f..c905342f01cf11 100644 --- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.test.ts @@ -18,7 +18,7 @@ */ import { fetchProvider } from './fetch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; jest.mock('../../../common', () => ({ DEFAULT_QUERY_LANGUAGE: 'lucene', @@ -28,7 +28,7 @@ jest.mock('../../../common', () => ({ })); let fetch: ReturnType; -let callCluster: APICaller; +let callCluster: LegacyAPICaller; function setupMockCallCluster( optCount: { optInCount?: number; optOutCount?: number } | null, @@ -79,7 +79,7 @@ function setupMockCallCluster( } throw new Error('invalid call'); - }) as unknown) as APICaller; + }) as unknown) as LegacyAPICaller; } describe('makeKQLUsageCollector', () => { diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts index 29f9be903a36f1..109d6f812334df 100644 --- a/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts +++ b/src/plugins/data/server/kql_telemetry/usage_collector/fetch.ts @@ -18,7 +18,7 @@ */ import { get } from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { DEFAULT_QUERY_LANGUAGE, UI_SETTINGS } from '../../../common'; const defaultSearchQueryLanguageSetting = DEFAULT_QUERY_LANGUAGE; @@ -30,7 +30,7 @@ export interface Usage { } export function fetchProvider(index: string) { - return async (callCluster: APICaller): Promise => { + return async (callCluster: LegacyAPICaller): Promise => { const [response, config] = await Promise.all([ callCluster('get', { index, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 8c6137e95333d4..1961fe331c5820 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -4,7 +4,6 @@ ```ts -import { APICaller as APICaller_2 } from 'kibana/server'; import Boom from 'boom'; import { BulkIndexDocumentsParams } from 'elasticsearch'; import { CatAliasesParams } from 'elasticsearch'; @@ -92,6 +91,7 @@ import { IngestGetPipelineParams } from 'elasticsearch'; import { IngestPutPipelineParams } from 'elasticsearch'; import { IngestSimulateParams } from 'elasticsearch'; import { KibanaConfigType as KibanaConfigType_2 } from 'src/core/server/kibana_config'; +import { LegacyAPICaller as LegacyAPICaller_2 } from 'kibana/server'; import { Logger as Logger_2 } from 'kibana/server'; import { MGetParams } from 'elasticsearch'; import { MGetResponse } from 'elasticsearch'; @@ -487,7 +487,7 @@ export const indexPatterns: { // // @public (undocumented) export class IndexPatternsFetcher { - constructor(callDataCluster: APICaller_2); + constructor(callDataCluster: LegacyAPICaller_2); getFieldsForTimePattern(options: { pattern: string; metaFields: string[]; diff --git a/src/plugins/expressions/server/legacy.ts b/src/plugins/expressions/server/legacy.ts index 4dd9419e59e2dd..8ff08542f18f85 100644 --- a/src/plugins/expressions/server/legacy.ts +++ b/src/plugins/expressions/server/legacy.ts @@ -26,7 +26,7 @@ import { register, registryFactory, Registry, Fn } from '@kbn/interpreter/common import Boom from 'boom'; import { schema } from '@kbn/config-schema'; -import { CoreSetup, Logger, APICaller } from 'src/core/server'; +import { CoreSetup, Logger, LegacyAPICaller } from 'src/core/server'; import { ExpressionsServerSetupDependencies } from './plugin'; import { typeSpecs, ExpressionType } from '../common'; import { serializeProvider } from '../common'; @@ -98,7 +98,7 @@ export const createLegacyServerEndpoints = ( * @param {*} fnCall - Describes the function being run `{ functionName, args, context }` */ async function runFunction( - handlers: { environment: string; elasticsearchClient: APICaller }, + handlers: { environment: string; elasticsearchClient: LegacyAPICaller }, fnCall: any ) { const { functionName, args, context } = fnCall; diff --git a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts index 804c8b0ed2026e..1adc0dc6896fda 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/kibana/get_saved_object_counts.ts @@ -27,7 +27,7 @@ */ import { snakeCase } from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; const TYPES = [ 'dashboard', @@ -45,7 +45,7 @@ export interface KibanaSavedObjectCounts { } export async function getSavedObjectsCounts( - callCluster: APICaller, + callCluster: LegacyAPICaller, kibanaIndex: string // Typically '.kibana'. We might need a way to obtain it from the SavedObjects client (or the SavedObjects client to provide a way to run aggregations?) ): Promise { const savedObjectCountSearchParams = { diff --git a/src/plugins/telemetry/server/fetcher.ts b/src/plugins/telemetry/server/fetcher.ts index 9422df60305184..75cfac721bcd3b 100644 --- a/src/plugins/telemetry/server/fetcher.ts +++ b/src/plugins/telemetry/server/fetcher.ts @@ -29,7 +29,7 @@ import { SavedObjectsClientContract, SavedObjectsClient, CoreStart, - ICustomClusterClient, + ILegacyCustomClusterClient, } from '../../../core/server'; import { getTelemetryOptIn, @@ -63,7 +63,7 @@ export class FetcherTask { private isSending = false; private internalRepository?: SavedObjectsClientContract; private telemetryCollectionManager?: TelemetryCollectionManagerPluginStart; - private elasticsearchClient?: ICustomClusterClient; + private elasticsearchClient?: ILegacyCustomClusterClient; constructor(initializerContext: PluginInitializerContext) { this.config$ = initializerContext.config.create(); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts index d5f0d2d8c9598d..4a33356ee97614 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_info.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; // This can be removed when the ES client improves the types export interface ESClusterInfo { @@ -43,6 +43,6 @@ export interface ESClusterInfo { * * @param {function} callCluster The callWithInternalUser handler (exposed for testing) */ -export function getClusterInfo(callCluster: APICaller) { +export function getClusterInfo(callCluster: LegacyAPICaller) { return callCluster('info'); } diff --git a/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts index 89e2cae7779856..d7c0110a99c6fd 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_cluster_stats.ts @@ -18,14 +18,14 @@ */ import { ClusterDetailsGetter } from 'src/plugins/telemetry_collection_manager/server'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { TIMEOUT } from './constants'; /** * Get the cluster stats from the connected cluster. * * This is the equivalent to GET /_cluster/stats?timeout=30s. */ -export async function getClusterStats(callCluster: APICaller) { +export async function getClusterStats(callCluster: LegacyAPICaller) { return await callCluster('cluster.stats', { timeout: TIMEOUT, }); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts index 645c5a4be8a6cb..5d27774a630a59 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_kibana.ts @@ -19,7 +19,7 @@ import { omit } from 'lodash'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { StatsCollectionContext } from 'src/plugins/telemetry_collection_manager/server'; export interface KibanaUsageStats { @@ -83,7 +83,7 @@ export function handleKibanaStats( export async function getKibana( usageCollection: UsageCollectionSetup, - callWithInternalUser: APICaller + callWithInternalUser: LegacyAPICaller ): Promise { const usage = await usageCollection.bulkFetch(callWithInternalUser); return usageCollection.toObject(usage); diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts index 0ba6fcc154d8bd..d41904c6d8e0e8 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_license.ts @@ -17,12 +17,12 @@ * under the License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ESLicense, LicenseGetter } from 'src/plugins/telemetry_collection_manager/server'; let cachedLicense: ESLicense | undefined; -function fetchLicense(callCluster: APICaller, local: boolean) { +function fetchLicense(callCluster: LegacyAPICaller, local: boolean) { return callCluster<{ license: ESLicense }>('transport.request', { method: 'GET', path: '/_license', @@ -41,7 +41,7 @@ function fetchLicense(callCluster: APICaller, local: boolean) { * * Like any X-Pack related API, X-Pack must installed for this to work. */ -async function getLicenseFromLocalOrMaster(callCluster: APICaller) { +async function getLicenseFromLocalOrMaster(callCluster: LegacyAPICaller) { // Fetching the local license is cheaper than getting it from the master and good enough const { license } = await fetchLicense(callCluster, true).catch(async (err) => { if (cachedLicense) { diff --git a/src/plugins/telemetry/server/telemetry_collection/register_collection.ts b/src/plugins/telemetry/server/telemetry_collection/register_collection.ts index 833fd9f7fd5bca..438fcadad92555 100644 --- a/src/plugins/telemetry/server/telemetry_collection/register_collection.ts +++ b/src/plugins/telemetry/server/telemetry_collection/register_collection.ts @@ -36,7 +36,7 @@ * under the License. */ -import { IClusterClient } from 'kibana/server'; +import { ILegacyClusterClient } from 'kibana/server'; import { TelemetryCollectionManagerPluginSetup } from 'src/plugins/telemetry_collection_manager/server'; import { getLocalStats } from './get_local_stats'; import { getClusterUuids } from './get_cluster_stats'; @@ -44,7 +44,7 @@ import { getLocalLicense } from './get_local_license'; export function registerCollection( telemetryCollectionManager: TelemetryCollectionManagerPluginSetup, - esCluster: IClusterClient + esCluster: ILegacyClusterClient ) { telemetryCollectionManager.setCollection({ esCluster, diff --git a/src/plugins/telemetry_collection_manager/server/types.ts b/src/plugins/telemetry_collection_manager/server/types.ts index d3a47694d38a76..16f96c07fd8ead 100644 --- a/src/plugins/telemetry_collection_manager/server/types.ts +++ b/src/plugins/telemetry_collection_manager/server/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller, Logger, KibanaRequest, IClusterClient } from 'kibana/server'; +import { LegacyAPICaller, Logger, KibanaRequest, ILegacyClusterClient } from 'kibana/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { TelemetryCollectionManagerPlugin } from './plugin'; @@ -64,7 +64,7 @@ export interface ClusterDetails { export interface StatsCollectionConfig { usageCollection: UsageCollectionSetup; - callCluster: APICaller; + callCluster: LegacyAPICaller; start: string | number; end: string | number; } @@ -129,7 +129,7 @@ export interface CollectionConfig< > { title: string; priority: number; - esCluster: IClusterClient; + esCluster: ILegacyClusterClient; statsGetter: StatsGetter; clusterDetailsGetter: ClusterDetailsGetter; licenseGetter: LicenseGetter; @@ -144,6 +144,6 @@ export interface Collection< statsGetter: StatsGetter; licenseGetter: LicenseGetter; clusterDetailsGetter: ClusterDetailsGetter; - esCluster: IClusterClient; + esCluster: ILegacyClusterClient; title: string; } diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts index 00d55ef1c06db5..9ae63b9f50e429 100644 --- a/src/plugins/usage_collection/server/collector/collector.ts +++ b/src/plugins/usage_collection/server/collector/collector.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Logger, APICaller } from 'kibana/server'; +import { Logger, LegacyAPICaller } from 'kibana/server'; export type CollectorFormatForBulkUpload = (result: T) => { type: string; payload: U }; @@ -48,7 +48,7 @@ export interface CollectorOptions { type: string; init?: Function; schema?: MakeSchemaFrom; - fetch: (callCluster: APICaller) => Promise | T; + fetch: (callCluster: LegacyAPICaller) => Promise | T; /* * A hook for allowing the fetched data payload to be organized into a typed * data model for internal bulk upload. See defaultFormatterForBulkUpload for diff --git a/src/plugins/usage_collection/server/collector/collector_set.ts b/src/plugins/usage_collection/server/collector/collector_set.ts index 04ba7452f99e2d..b6308d66033885 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.ts @@ -18,7 +18,7 @@ */ import { snakeCase } from 'lodash'; -import { Logger, APICaller } from 'kibana/server'; +import { Logger, LegacyAPICaller } from 'kibana/server'; import { Collector, CollectorOptions } from './collector'; import { UsageCollector } from './usage_collector'; @@ -112,7 +112,7 @@ export class CollectorSet { }; public bulkFetch = async ( - callCluster: APICaller, + callCluster: LegacyAPICaller, collectors: Array> = this.collectors ) => { const responses = []; @@ -140,7 +140,7 @@ export class CollectorSet { return this.makeCollectorSetFromArray(filtered); }; - public bulkFetchUsage = async (callCluster: APICaller) => { + public bulkFetchUsage = async (callCluster: LegacyAPICaller) => { const usageCollectors = this.getFilteredCollectorSet((c) => c instanceof UsageCollector); return await this.bulkFetch(callCluster, usageCollectors.collectors); }; diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index a2146e493d4edf..0b1c6e6e204141 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -18,7 +18,7 @@ */ import { - APICaller, + LegacyAPICaller, FakeRequest, IUiSettingsClient, SavedObjectsClientContract, @@ -53,12 +53,12 @@ export type ReqFacade = FakeRequest & { }; export class AbstractSearchStrategy { - public getCallWithRequestInstance: (req: ReqFacade) => APICaller; + public getCallWithRequestInstance: (req: ReqFacade) => LegacyAPICaller; public getSearchRequest: (req: ReqFacade) => any; constructor( server: any, - callWithRequestFactory: (server: any, req: ReqFacade) => APICaller, + callWithRequestFactory: (server: any, req: ReqFacade) => LegacyAPICaller, SearchRequest: any ) { this.getCallWithRequestInstance = (req) => callWithRequestFactory(server, req); diff --git a/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts b/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts index 22e427bed24c3c..a5f095a4c4f3d1 100644 --- a/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts +++ b/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts @@ -17,7 +17,7 @@ * under the License. */ -import { APICaller, CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server'; +import { LegacyAPICaller, CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server'; import { UsageCollectionSetup } from '../../../usage_collection/server'; import { tsvbTelemetrySavedObjectType } from '../saved_objects'; @@ -49,7 +49,7 @@ export class ValidationTelemetryService implements Plugin({ type: 'tsvb-validation', isReady: () => this.kibanaIndex !== '', - fetch: async (callCluster: APICaller) => { + fetch: async (callCluster: LegacyAPICaller) => { try { const response = await callCluster('get', { index: this.kibanaIndex, diff --git a/x-pack/legacy/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts b/x-pack/legacy/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts index baccbe416f3980..213b728a2c163a 100644 --- a/x-pack/legacy/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts +++ b/x-pack/legacy/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ElasticsearchServiceStart, IClusterClient } from 'src/core/server'; +import { ElasticsearchServiceStart, ILegacyClusterClient } from 'src/core/server'; import { FrameworkUser } from '../framework/adapter_types'; import { internalAuthData } from './../framework/adapter_types'; import { @@ -23,7 +23,7 @@ import { } from './adapter_types'; export class KibanaDatabaseAdapter implements DatabaseAdapter { - private es: IClusterClient; + private es: ILegacyClusterClient; constructor(elasticsearch: ElasticsearchServiceStart) { this.es = elasticsearch.legacy.client; diff --git a/x-pack/plugins/actions/server/actions_client.ts b/x-pack/plugins/actions/server/actions_client.ts index a2feac83cba9f5..a512d314fb7e25 100644 --- a/x-pack/plugins/actions/server/actions_client.ts +++ b/x-pack/plugins/actions/server/actions_client.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; import { - IScopedClusterClient, + ILegacyScopedClusterClient, SavedObjectsClientContract, SavedObjectAttributes, SavedObject, @@ -50,7 +50,7 @@ interface CreateOptions { interface ConstructorOptions { defaultKibanaIndex: string; - scopedClusterClient: IScopedClusterClient; + scopedClusterClient: ILegacyScopedClusterClient; actionTypeRegistry: ActionTypeRegistry; savedObjectsClient: SavedObjectsClientContract; preconfiguredActions: PreConfiguredAction[]; @@ -66,7 +66,7 @@ interface UpdateOptions { export class ActionsClient { private readonly defaultKibanaIndex: string; - private readonly scopedClusterClient: IScopedClusterClient; + private readonly scopedClusterClient: ILegacyScopedClusterClient; private readonly savedObjectsClient: SavedObjectsClientContract; private readonly actionTypeRegistry: ActionTypeRegistry; private readonly preconfiguredActions: PreConfiguredAction[]; @@ -298,7 +298,7 @@ function actionFromSavedObject(savedObject: SavedObject): ActionResul async function injectExtraFindData( defaultKibanaIndex: string, - scopedClusterClient: IScopedClusterClient, + scopedClusterClient: ILegacyScopedClusterClient, actionResults: ActionResult[] ): Promise { const aggs: Record = {}; diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index ad3fa97ee0c366..eae2595136627d 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -17,7 +17,7 @@ import { RequestHandler, IContextProvider, ElasticsearchServiceStart, - IClusterClient, + ILegacyClusterClient, SavedObjectsClientContract, } from '../../../../src/core/server'; @@ -307,7 +307,7 @@ export class ActionsPlugin implements Plugin, Plugi return (request) => ({ callCluster: elasticsearch.legacy.client.asScoped(request).callAsCurrentUser, savedObjectsClient: getScopedClient(request), - getScopedCallCluster(clusterClient: IClusterClient) { + getScopedCallCluster(clusterClient: ILegacyClusterClient) { return clusterClient.asScoped(request).callAsCurrentUser; }, }); diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index 093d22c2c1a710..ca5da2779139e9 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -9,8 +9,8 @@ import { PluginSetupContract, PluginStartContract } from './plugin'; import { ActionsClient } from './actions_client'; import { LicenseType } from '../../licensing/common/types'; import { - IClusterClient, - IScopedClusterClient, + ILegacyClusterClient, + ILegacyScopedClusterClient, KibanaRequest, SavedObjectsClientContract, SavedObjectAttributes, @@ -23,9 +23,11 @@ export type GetBasePathFunction = (spaceId?: string) => string; export type SpaceIdToNamespaceFunction = (spaceId?: string) => string | undefined; export interface Services { - callCluster: IScopedClusterClient['callAsCurrentUser']; + callCluster: ILegacyScopedClusterClient['callAsCurrentUser']; savedObjectsClient: SavedObjectsClientContract; - getScopedCallCluster(clusterClient: IClusterClient): IScopedClusterClient['callAsCurrentUser']; + getScopedCallCluster( + clusterClient: ILegacyClusterClient + ): ILegacyScopedClusterClient['callAsCurrentUser']; } declare module 'src/core/server' { diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index 6996ba629f8da9..2815b5fbe6a5e4 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; -export async function getTotalCount(callCluster: APICaller, kibanaIndex: string) { +export async function getTotalCount(callCluster: LegacyAPICaller, kibanaIndex: string) { const scriptedMetric = { scripted_metric: { init_script: 'state.types = [:]', @@ -66,7 +66,7 @@ export async function getTotalCount(callCluster: APICaller, kibanaIndex: string) }; } -export async function getInUseTotalCount(callCluster: APICaller, kibanaIndex: string) { +export async function getInUseTotalCount(callCluster: LegacyAPICaller, kibanaIndex: string) { const scriptedMetric = { scripted_metric: { init_script: 'state.connectorIds = new HashMap(); state.total = 0;', diff --git a/x-pack/plugins/actions/server/usage/task.ts b/x-pack/plugins/actions/server/usage/task.ts index 862a170ca13436..050f0021a32c1f 100644 --- a/x-pack/plugins/actions/server/usage/task.ts +++ b/x-pack/plugins/actions/server/usage/task.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, CoreSetup, APICaller } from 'kibana/server'; +import { Logger, CoreSetup, LegacyAPICaller } from 'kibana/server'; import moment from 'moment'; import { RunContext, @@ -62,7 +62,7 @@ async function scheduleTasks(logger: Logger, taskManager: TaskManagerStartContra export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex: string) { return ({ taskInstance }: RunContext) => { const { state } = taskInstance; - const callCluster = (...args: Parameters) => { + const callCluster = (...args: Parameters) => { return core.getStartServices().then(([{ elasticsearch: { legacy: { client } } }]) => client.callAsInternalUser(...args) ); diff --git a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/fields.ts b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/fields.ts index 1ef289d74a05e8..ea1e17002c4a5c 100644 --- a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/fields.ts +++ b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/fields.ts @@ -14,7 +14,7 @@ import { KibanaRequest, IKibanaResponse, KibanaResponseFactory, - IScopedClusterClient, + ILegacyScopedClusterClient, } from 'kibana/server'; import { Service } from '../../../types'; @@ -93,7 +93,7 @@ interface Field { } async function getRawFields( - dataClient: IScopedClusterClient, + dataClient: ILegacyScopedClusterClient, indexes: string[] ): Promise { const params = { diff --git a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/indices.ts b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/indices.ts index dcf117aafa6fb5..c94705829ec602 100644 --- a/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/indices.ts +++ b/x-pack/plugins/alerting_builtins/server/alert_types/index_threshold/routes/indices.ts @@ -16,7 +16,7 @@ import { KibanaRequest, IKibanaResponse, KibanaResponseFactory, - IScopedClusterClient, + ILegacyScopedClusterClient, } from 'kibana/server'; import { SearchResponse } from 'elasticsearch'; import { Service } from '../../../types'; @@ -84,7 +84,7 @@ function uniqueCombined(list1: string[], list2: string[], limit: number) { } async function getIndicesFromPattern( - dataClient: IScopedClusterClient, + dataClient: ILegacyScopedClusterClient, pattern: string ): Promise { const params = { @@ -114,7 +114,7 @@ async function getIndicesFromPattern( } async function getAliasesFromPattern( - dataClient: IScopedClusterClient, + dataClient: ILegacyScopedClusterClient, pattern: string ): Promise { const params = { diff --git a/x-pack/plugins/alerting_builtins/server/types.ts b/x-pack/plugins/alerting_builtins/server/types.ts index 95d34371a6d1e6..1fb5314ca4fd9e 100644 --- a/x-pack/plugins/alerting_builtins/server/types.ts +++ b/x-pack/plugins/alerting_builtins/server/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, ScopedClusterClient } from '../../../../src/core/server'; +import { Logger, LegacyScopedClusterClient } from '../../../../src/core/server'; import { PluginSetupContract as AlertingSetup } from '../../alerts/server'; import { getService as getServiceIndexThreshold } from './alert_types/index_threshold'; @@ -31,4 +31,4 @@ export interface Service extends IService { logger: Logger; } -export type CallCluster = ScopedClusterClient['callAsCurrentUser']; +export type CallCluster = LegacyScopedClusterClient['callAsCurrentUser']; diff --git a/x-pack/plugins/alerts/server/plugin.ts b/x-pack/plugins/alerts/server/plugin.ts index 324bc9fbfb72bf..23a5dc51d04754 100644 --- a/x-pack/plugins/alerts/server/plugin.ts +++ b/x-pack/plugins/alerts/server/plugin.ts @@ -29,7 +29,7 @@ import { RequestHandler, SharedGlobalConfig, ElasticsearchServiceStart, - IClusterClient, + ILegacyClusterClient, } from '../../../../src/core/server'; import { @@ -273,7 +273,7 @@ export class AlertingPlugin { return (request) => ({ callCluster: elasticsearch.legacy.client.asScoped(request).callAsCurrentUser, savedObjectsClient: this.getScopedClientWithAlertSavedObjectType(savedObjects, request), - getScopedCallCluster(clusterClient: IClusterClient) { + getScopedCallCluster(clusterClient: ILegacyClusterClient) { return clusterClient.asScoped(request).callAsCurrentUser; }, }); diff --git a/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts index 9c98040ea09bb4..7d86d4fde7e61b 100644 --- a/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts @@ -8,7 +8,7 @@ import { RequestHandlerContext, KibanaRequest, KibanaResponseFactory, - IClusterClient, + ILegacyClusterClient, } from 'kibana/server'; import { identity } from 'lodash'; import { httpServerMock } from '../../../../../src/core/server/mocks'; @@ -24,7 +24,7 @@ export function mockHandlerArguments( }: { alertsClient?: AlertsClientMock; listTypes?: AlertType[]; - esClient?: jest.Mocked; + esClient?: jest.Mocked; }, req: unknown, res?: Array> diff --git a/x-pack/plugins/alerts/server/types.ts b/x-pack/plugins/alerts/server/types.ts index d0070eb9a299ef..24dfb391f0791f 100644 --- a/x-pack/plugins/alerts/server/types.ts +++ b/x-pack/plugins/alerts/server/types.ts @@ -11,8 +11,8 @@ import { Alert, AlertActionParams, ActionGroup } from '../common'; import { AlertsClient } from './alerts_client'; export * from '../common'; import { - IClusterClient, - IScopedClusterClient, + ILegacyClusterClient, + ILegacyScopedClusterClient, KibanaRequest, SavedObjectAttributes, SavedObjectsClientContract, @@ -38,9 +38,11 @@ declare module 'src/core/server' { } export interface Services { - callCluster: IScopedClusterClient['callAsCurrentUser']; + callCluster: ILegacyScopedClusterClient['callAsCurrentUser']; savedObjectsClient: SavedObjectsClientContract; - getScopedCallCluster(clusterClient: IClusterClient): IScopedClusterClient['callAsCurrentUser']; + getScopedCallCluster( + clusterClient: ILegacyClusterClient + ): ILegacyScopedClusterClient['callAsCurrentUser']; } export interface AlertServices extends Services { diff --git a/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts b/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts index 2edf1c10618646..389178de3e5d0d 100644 --- a/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts +++ b/x-pack/plugins/alerts/server/usage/alerts_telemetry.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { SearchResponse } from 'elasticsearch'; const alertTypeMetric = { @@ -33,7 +33,7 @@ const alertTypeMetric = { }, }; -export async function getTotalCountAggregations(callCluster: APICaller, kibanaInex: string) { +export async function getTotalCountAggregations(callCluster: LegacyAPICaller, kibanaInex: string) { const throttleTimeMetric = { scripted_metric: { init_script: 'state.min = 0; state.max = 0; state.totalSum = 0; state.totalCount = 0;', @@ -286,7 +286,7 @@ export async function getTotalCountAggregations(callCluster: APICaller, kibanaIn }; } -export async function getTotalCountInUse(callCluster: APICaller, kibanaInex: string) { +export async function getTotalCountInUse(callCluster: LegacyAPICaller, kibanaInex: string) { const searchResult: SearchResponse = await callCluster('search', { index: kibanaInex, rest_total_hits_as_int: true, diff --git a/x-pack/plugins/alerts/server/usage/task.ts b/x-pack/plugins/alerts/server/usage/task.ts index 395f0c107c984f..5909351321385b 100644 --- a/x-pack/plugins/alerts/server/usage/task.ts +++ b/x-pack/plugins/alerts/server/usage/task.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, CoreSetup, APICaller } from 'kibana/server'; +import { Logger, CoreSetup, LegacyAPICaller } from 'kibana/server'; import moment from 'moment'; import { RunContext, @@ -65,7 +65,7 @@ async function scheduleTasks(logger: Logger, taskManager: TaskManagerStartContra export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex: string) { return ({ taskInstance }: RunContext) => { const { state } = taskInstance; - const callCluster = (...args: Parameters) => { + const callCluster = (...args: Parameters) => { return core.getStartServices().then(([{ elasticsearch: { legacy: { client } } }]) => client.callAsInternalUser(...args) ); 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 fab39da505a352..e53a0e24b4723d 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { merge } from 'lodash'; -import { Logger, CallAPIOptions } from 'kibana/server'; +import { Logger, LegacyCallAPIOptions } from 'kibana/server'; import { IndicesStatsParams, Client } from 'elasticsearch'; import { ESSearchRequest, @@ -21,7 +21,7 @@ type TelemetryTaskExecutor = (params: { ): Promise>; indicesStats( params: IndicesStatsParams, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ): ReturnType; transportRequest: (params: { path: string; diff --git a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts index 6251bd7bd66017..ee03e77de35805 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts @@ -5,7 +5,7 @@ */ import LRU from 'lru-cache'; -import { APICaller } from '../../../../../../src/core/server'; +import { LegacyAPICaller } from '../../../../../../src/core/server'; import { IndexPatternsFetcher, IIndexPattern, @@ -37,7 +37,7 @@ export const getDynamicIndexPattern = async ({ } const indexPatternsFetcher = new IndexPatternsFetcher( - (...rest: Parameters) => + (...rest: Parameters) => context.core.elasticsearch.legacy.client.callAsCurrentUser(...rest) ); 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 e77307a3f9db13..75aeb27ea21225 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, Logger } from 'kibana/server'; +import { LegacyAPICaller, Logger } from 'kibana/server'; import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; import { ESSearchResponse } from '../../../../typings/elasticsearch'; import { ScopedAnnotationsClient } from '../../../../../observability/server'; @@ -24,7 +24,7 @@ export async function getStoredAnnotations({ setup: Setup & SetupTimeRange; serviceName: string; environment?: string; - apiCaller: APICaller; + apiCaller: LegacyAPICaller; annotationsClient: ScopedAnnotationsClient; logger: Logger; }): Promise { diff --git a/x-pack/plugins/apm/server/lib/services/annotations/index.ts b/x-pack/plugins/apm/server/lib/services/annotations/index.ts index e2b6e74d4d65a5..a5f8e595ccf54d 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/index.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, Logger } from 'kibana/server'; +import { LegacyAPICaller, Logger } from 'kibana/server'; import { ScopedAnnotationsClient } from '../../../../../observability/server'; import { getDerivedServiceAnnotations } from './get_derived_service_annotations'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; @@ -21,7 +21,7 @@ export async function getServiceAnnotations({ environment?: string; setup: Setup & SetupTimeRange; annotationsClient?: ScopedAnnotationsClient; - apiCaller: APICaller; + apiCaller: LegacyAPICaller; logger: Logger; }) { // start fetching derived annotations (based on transactions), but don't wait on it 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 d480342bbef11f..83117db1167b5d 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, Logger } from 'src/core/server'; +import { ILegacyClusterClient, Logger } from 'src/core/server'; import { createOrUpdateIndex, MappingsDefinition, @@ -17,7 +17,7 @@ export async function createApmAgentConfigurationIndex({ config, logger, }: { - esClient: IClusterClient; + esClient: ILegacyClusterClient; config: APMConfig; logger: Logger; }) { 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 a690e7fd8665a6..2bfe0d620e4e8e 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, Logger } from 'src/core/server'; +import { ILegacyClusterClient, Logger } from 'src/core/server'; import { createOrUpdateIndex, MappingsDefinition, @@ -17,7 +17,7 @@ export const createApmCustomLinkIndex = async ({ config, logger, }: { - esClient: IClusterClient; + esClient: ILegacyClusterClient; config: APMConfig; logger: Logger; }) => { diff --git a/x-pack/plugins/cross_cluster_replication/server/plugin.ts b/x-pack/plugins/cross_cluster_replication/server/plugin.ts index d9fe296553f38c..e39b4dfd471a82 100644 --- a/x-pack/plugins/cross_cluster_replication/server/plugin.ts +++ b/x-pack/plugins/cross_cluster_replication/server/plugin.ts @@ -15,12 +15,12 @@ import { first } from 'rxjs/operators'; import { i18n } from '@kbn/i18n'; import { CoreSetup, - ICustomClusterClient, + ILegacyCustomClusterClient, Plugin, Logger, PluginInitializerContext, - APICaller, - IScopedClusterClient, + LegacyAPICaller, + ILegacyScopedClusterClient, } from 'src/core/server'; import { Index } from '../../index_management/server'; @@ -34,7 +34,7 @@ import { isEsError } from './shared_imports'; import { formatEsError } from './lib/format_es_error'; interface CrossClusterReplicationContext { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; } async function getCustomEsClient(getStartServices: CoreSetup['getStartServices']) { @@ -44,7 +44,7 @@ async function getCustomEsClient(getStartServices: CoreSetup['getStartServices'] return core.elasticsearch.legacy.createClient('crossClusterReplication', esClientConfig); } -const ccrDataEnricher = async (indicesList: Index[], callWithRequest: APICaller) => { +const ccrDataEnricher = async (indicesList: Index[], callWithRequest: LegacyAPICaller) => { if (!indicesList?.length) { return indicesList; } @@ -77,7 +77,7 @@ export class CrossClusterReplicationServerPlugin implements Plugin; private readonly license: License; private readonly logger: Logger; - private ccrEsClient?: ICustomClusterClient; + private ccrEsClient?: ILegacyCustomClusterClient; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 9083ab24a4521a..aa8b0bfc66639d 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -8,7 +8,7 @@ import { first } from 'rxjs/operators'; import { mapKeys, snakeCase } from 'lodash'; import { SearchResponse } from 'elasticsearch'; import { Observable } from 'rxjs'; -import { APICaller, SharedGlobalConfig } from '../../../../../src/core/server'; +import { LegacyAPICaller, SharedGlobalConfig } from '../../../../../src/core/server'; import { ES_SEARCH_STRATEGY } from '../../../../../src/plugins/data/common'; import { ISearch, @@ -59,7 +59,7 @@ export const enhancedEsSearchStrategyProvider = ( }; async function asyncSearch( - caller: APICaller, + caller: LegacyAPICaller, request: IEnhancedEsSearchRequest, options?: ISearchOptions ) { @@ -93,7 +93,7 @@ async function asyncSearch( } async function rollupSearch( - caller: APICaller, + caller: LegacyAPICaller, request: IEnhancedEsSearchRequest, options?: ISearchOptions ) { 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 459a2cc65671e6..feec1ee9ba0088 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 @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ClusterClient, Logger } from '../../../../../src/core/server'; +import { LegacyClusterClient, Logger } from '../../../../../src/core/server'; import { elasticsearchServiceMock, loggingSystemMock } from '../../../../../src/core/server/mocks'; import { ClusterClientAdapter, IClusterClientAdapter } from './cluster_client_adapter'; import moment from 'moment'; import { findOptionsSchema } from '../event_log_client'; -type EsClusterClient = Pick, 'callAsInternalUser' | 'asScoped'>; +type EsClusterClient = Pick, 'callAsInternalUser' | 'asScoped'>; let logger: Logger; let clusterClient: EsClusterClient; 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 a036bfb74e4081..3478358f88a545 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 @@ -6,11 +6,11 @@ import { reject, isUndefined } from 'lodash'; import { SearchResponse, Client } from 'elasticsearch'; -import { Logger, ClusterClient } from '../../../../../src/core/server'; +import { Logger, LegacyClusterClient } from '../../../../../src/core/server'; import { IEvent, SAVED_OBJECT_REL_PRIMARY } from '../types'; import { FindOptionsType } from '../event_log_client'; -export type EsClusterClient = Pick; +export type EsClusterClient = Pick; export type IClusterClientAdapter = PublicMethodsOf; export interface ConstructorOpts { diff --git a/x-pack/plugins/event_log/server/es/context.test.ts b/x-pack/plugins/event_log/server/es/context.test.ts index 8bd0009dcd218a..d2758cac2bf6e6 100644 --- a/x-pack/plugins/event_log/server/es/context.test.ts +++ b/x-pack/plugins/event_log/server/es/context.test.ts @@ -5,12 +5,12 @@ */ import { createEsContext } from './context'; -import { ClusterClient, Logger } from '../../../../../src/core/server'; +import { LegacyClusterClient, Logger } from '../../../../../src/core/server'; import { elasticsearchServiceMock, loggingSystemMock } from '../../../../../src/core/server/mocks'; jest.mock('../lib/../../../../package.json', () => ({ version: '1.2.3', })); -export type EsClusterClient = Pick; +export type EsClusterClient = Pick; let logger: Logger; let clusterClient: EsClusterClient; diff --git a/x-pack/plugins/event_log/server/es/context.ts b/x-pack/plugins/event_log/server/es/context.ts index 0b3f22c6eecc06..16a460be1793b2 100644 --- a/x-pack/plugins/event_log/server/es/context.ts +++ b/x-pack/plugins/event_log/server/es/context.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, ClusterClient } from 'src/core/server'; +import { Logger, LegacyClusterClient } from 'src/core/server'; import { EsNames, getEsNames } from './names'; import { initializeEs } from './init'; import { ClusterClientAdapter, IClusterClientAdapter } from './cluster_client_adapter'; import { createReadySignal, ReadySignal } from '../lib/ready_signal'; -export type EsClusterClient = Pick; +export type EsClusterClient = Pick; export interface EsContext { logger: Logger; diff --git a/x-pack/plugins/event_log/server/event_log_client.ts b/x-pack/plugins/event_log/server/event_log_client.ts index 8ef245e60aadc4..e7ba598de2ac68 100644 --- a/x-pack/plugins/event_log/server/event_log_client.ts +++ b/x-pack/plugins/event_log/server/event_log_client.ts @@ -5,13 +5,13 @@ */ import { Observable } from 'rxjs'; -import { ClusterClient, SavedObjectsClientContract } from 'src/core/server'; +import { LegacyClusterClient, SavedObjectsClientContract } from 'src/core/server'; import { schema, TypeOf } from '@kbn/config-schema'; import { EsContext } from './es'; import { IEventLogClient } from './types'; import { QueryEventsBySavedObjectResult } from './es/cluster_client_adapter'; -export type PluginClusterClient = Pick; +export type PluginClusterClient = Pick; export type AdminClusterClient$ = Observable; interface EventLogServiceCtorParams { diff --git a/x-pack/plugins/event_log/server/event_log_service.ts b/x-pack/plugins/event_log/server/event_log_service.ts index fc72de6e473568..6cfb16d1264272 100644 --- a/x-pack/plugins/event_log/server/event_log_service.ts +++ b/x-pack/plugins/event_log/server/event_log_service.ts @@ -6,13 +6,13 @@ import _ from 'lodash'; import { Observable } from 'rxjs'; -import { ClusterClient } from 'src/core/server'; +import { LegacyClusterClient } from 'src/core/server'; import { Plugin } from './plugin'; import { EsContext } from './es'; import { IEvent, IEventLogger, IEventLogService, IEventLogConfig } from './types'; import { EventLogger } from './event_logger'; -export type PluginClusterClient = Pick; +export type PluginClusterClient = Pick; export type AdminClusterClient$ = Observable; type SystemLogger = Plugin['systemLogger']; diff --git a/x-pack/plugins/event_log/server/event_log_start_service.ts b/x-pack/plugins/event_log/server/event_log_start_service.ts index 5938f7a2e614ec..36a6bc0a926afb 100644 --- a/x-pack/plugins/event_log/server/event_log_start_service.ts +++ b/x-pack/plugins/event_log/server/event_log_start_service.ts @@ -7,7 +7,7 @@ import _ from 'lodash'; import { Observable } from 'rxjs'; import { - ClusterClient, + LegacyClusterClient, KibanaRequest, SavedObjectsServiceStart, SavedObjectsClientContract, @@ -16,7 +16,7 @@ import { import { EsContext } from './es'; import { IEventLogClientService } from './types'; import { EventLogClient } from './event_log_client'; -export type PluginClusterClient = Pick; +export type PluginClusterClient = Pick; export type AdminClusterClient$ = Observable; interface EventLogServiceCtorParams { diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index dd83b2cfb03b8e..ed530607aabbaa 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -12,7 +12,7 @@ import { Logger, Plugin as CorePlugin, PluginInitializerContext, - ClusterClient, + LegacyClusterClient, SharedGlobalConfig, IContextProvider, RequestHandler, @@ -30,7 +30,7 @@ import { EventLogService } from './event_log_service'; import { createEsContext, EsContext } from './es'; import { EventLogClientService } from './event_log_start_service'; -export type PluginClusterClient = Pick; +export type PluginClusterClient = Pick; const PROVIDER = 'eventLog'; diff --git a/x-pack/plugins/global_search/server/types.ts b/x-pack/plugins/global_search/server/types.ts index eca4aff366883d..7d3f5ebc5d0792 100644 --- a/x-pack/plugins/global_search/server/types.ts +++ b/x-pack/plugins/global_search/server/types.ts @@ -7,7 +7,7 @@ import { Observable } from 'rxjs'; import { ISavedObjectTypeRegistry, - IScopedClusterClient, + ILegacyScopedClusterClient, IUiSettingsClient, SavedObjectsClientContract, } from 'src/core/server'; @@ -46,7 +46,7 @@ export interface GlobalSearchProviderContext { }; elasticsearch: { legacy: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; }; }; uiSettings: { diff --git a/x-pack/plugins/index_lifecycle_management/server/plugin.ts b/x-pack/plugins/index_lifecycle_management/server/plugin.ts index 79a9849e634b5f..ed179255226100 100644 --- a/x-pack/plugins/index_lifecycle_management/server/plugin.ts +++ b/x-pack/plugins/index_lifecycle_management/server/plugin.ts @@ -7,7 +7,13 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { i18n } from '@kbn/i18n'; -import { CoreSetup, Plugin, Logger, PluginInitializerContext, APICaller } from 'src/core/server'; +import { + CoreSetup, + Plugin, + Logger, + PluginInitializerContext, + LegacyAPICaller, +} from 'src/core/server'; import { PLUGIN } from '../common/constants'; import { Dependencies } from './types'; @@ -16,7 +22,7 @@ import { License } from './services'; import { IndexLifecycleManagementConfig } from './config'; import { isEsError } from './shared_imports'; -const indexLifecycleDataEnricher = async (indicesList: any, callAsCurrentUser: APICaller) => { +const indexLifecycleDataEnricher = async (indicesList: any, callAsCurrentUser: LegacyAPICaller) => { if (!indicesList || !indicesList.length) { return; } diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts index b8870a83ac5ac8..853e3e7662d09b 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts @@ -5,13 +5,13 @@ */ import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; async function addLifecyclePolicy( - callAsCurrentUser: APICaller, + callAsCurrentUser: LegacyAPICaller, indexName: string, policyName: string, alias: string diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts index b1bc2264fc5290..2601775f5d76e6 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts @@ -5,12 +5,12 @@ */ import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; -async function removeLifecycle(callAsCurrentUser: APICaller, indexNames: string[]) { +async function removeLifecycle(callAsCurrentUser: LegacyAPICaller, indexNames: string[]) { const responses = []; for (let i = 0; i < indexNames.length; i++) { const indexName = indexNames[i]; diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts index 0a5ca1730d170e..09fd1d6068285f 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts @@ -5,12 +5,12 @@ */ import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; -async function retryLifecycle(callAsCurrentUser: APICaller, indexNames: string[]) { +async function retryLifecycle(callAsCurrentUser: LegacyAPICaller, indexNames: string[]) { const responses = []; for (let i = 0; i < indexNames.length; i++) { const indexName = indexNames[i]; diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts index db0352ec83ee0e..f8d4a9681b3d83 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; @@ -26,7 +26,7 @@ function findMatchingNodes(stats: any, nodeAttrs: string): any { }, []); } -async function fetchNodeStats(callAsCurrentUser: APICaller): Promise { +async function fetchNodeStats(callAsCurrentUser: LegacyAPICaller): Promise { const params = { format: 'json', }; diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts index 91b542284a0417..b30a59c997e874 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; @@ -24,7 +24,7 @@ function convertStatsIntoList(stats: any, disallowedNodeAttributes: string[]): a }, {}); } -async function fetchNodeStats(callAsCurrentUser: APICaller): Promise { +async function fetchNodeStats(callAsCurrentUser: LegacyAPICaller): Promise { const params = { format: 'json', }; 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 7bf3f96e2b2ef0..c09e56d236f7f5 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 @@ -5,12 +5,16 @@ */ import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; -async function createPolicy(callAsCurrentUser: APICaller, name: string, phases: any): Promise { +async function createPolicy( + callAsCurrentUser: LegacyAPICaller, + name: string, + phases: any +): Promise { const body = { policy: { phases, 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 241668780ea251..992a0fab452ec7 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 @@ -5,12 +5,15 @@ */ import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; -async function deletePolicies(callAsCurrentUser: APICaller, policyNames: string): Promise { +async function deletePolicies( + callAsCurrentUser: LegacyAPICaller, + policyNames: string +): Promise { const params = { method: 'DELETE', path: `/_ilm/policy/${encodeURIComponent(policyNames)}`, 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 d581cc15f3053f..2dc1ed1006adb8 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 @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; @@ -25,7 +25,7 @@ function formatPolicies(policiesMap: any): any { }, []); } -async function fetchPolicies(callAsCurrentUser: APICaller): Promise { +async function fetchPolicies(callAsCurrentUser: LegacyAPICaller): Promise { const params = { method: 'GET', path: '/_ilm/policy', @@ -36,7 +36,7 @@ async function fetchPolicies(callAsCurrentUser: APICaller): Promise { return await callAsCurrentUser('transport.request', params); } -async function addLinkedIndices(callAsCurrentUser: APICaller, policiesMap: any) { +async function addLinkedIndices(callAsCurrentUser: LegacyAPICaller, policiesMap: any) { if (policiesMap.status === 404) { return policiesMap; } diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts index ed05cc270e4c1e..21a389b9a0e358 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts @@ -6,18 +6,21 @@ import { merge } from 'lodash'; import { schema } from '@kbn/config-schema'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; -async function getIndexTemplate(callAsCurrentUser: APICaller, templateName: string): Promise { +async function getIndexTemplate( + callAsCurrentUser: LegacyAPICaller, + templateName: string +): Promise { const response = await callAsCurrentUser('indices.getTemplate', { name: templateName }); return response[templateName]; } async function updateIndexTemplate( - callAsCurrentUser: APICaller, + callAsCurrentUser: LegacyAPICaller, templateName: string, policyName: string, aliasName?: string diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts index 546d9674b0956d..942eec347341f1 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../../../services'; @@ -49,7 +49,7 @@ function filterAndFormatTemplates(templates: any): any { return formattedTemplates; } -async function fetchTemplates(callAsCurrentUser: APICaller): Promise { +async function fetchTemplates(callAsCurrentUser: LegacyAPICaller): Promise { const params = { method: 'GET', path: '/_template', diff --git a/x-pack/plugins/index_management/server/plugin.ts b/x-pack/plugins/index_management/server/plugin.ts index 94af8415bfd559..0cd180a980a84c 100644 --- a/x-pack/plugins/index_management/server/plugin.ts +++ b/x-pack/plugins/index_management/server/plugin.ts @@ -16,8 +16,8 @@ import { Plugin, Logger, PluginInitializerContext, - IScopedClusterClient, - ICustomClusterClient, + ILegacyScopedClusterClient, + ILegacyCustomClusterClient, } from 'src/core/server'; import { PLUGIN } from '../common'; @@ -28,7 +28,7 @@ import { isEsError } from './shared_imports'; import { elasticsearchJsPlugin } from './client/elasticsearch'; export interface DataManagementContext { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; } export interface IndexManagementPluginSetup { @@ -48,7 +48,7 @@ export class IndexMgmtServerPlugin implements Plugin) => { + return new IndexPatternsFetcher((...rest: Parameters) => { rest[1] = rest[1] || {}; rest[1].allowNoIndices = true; return requestContext.core.elasticsearch.legacy.client.callAsCurrentUser(...rest); diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts index 6e8c624e61c49a..ba43303bccf0ba 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/preview_inventory_metric_threshold_alert.ts @@ -6,7 +6,7 @@ import { Unit } from '@elastic/datemath'; import { first } from 'lodash'; import { InventoryMetricConditions } from './types'; -import { IScopedClusterClient } from '../../../../../../../src/core/server'; +import { ILegacyScopedClusterClient } from '../../../../../../../src/core/server'; import { InfraSource } from '../../../../common/http_api/source_api'; import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds'; import { InventoryItemType } from '../../../../common/inventory_models/types'; @@ -20,7 +20,7 @@ interface InventoryMetricThresholdParams { } interface PreviewInventoryMetricThresholdAlertParams { - callCluster: IScopedClusterClient['callAsCurrentUser']; + callCluster: ILegacyScopedClusterClient['callAsCurrentUser']; params: InventoryMetricThresholdParams; config: InfraSource['configuration']; lookback: Unit; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts index 52637d52175a42..e58667bfdf3e11 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/preview_metric_threshold_alert.ts @@ -10,7 +10,7 @@ import { TOO_MANY_BUCKETS_PREVIEW_EXCEPTION, isTooManyBucketsPreviewException, } from '../../../../common/alerting/metrics'; -import { IScopedClusterClient } from '../../../../../../../src/core/server'; +import { ILegacyScopedClusterClient } from '../../../../../../../src/core/server'; import { InfraSource } from '../../../../common/http_api/source_api'; import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds'; import { MetricExpressionParams } from './types'; @@ -19,7 +19,7 @@ import { evaluateAlert } from './lib/evaluate_alert'; const MAX_ITERATIONS = 50; interface PreviewMetricThresholdAlertParams { - callCluster: IScopedClusterClient['callAsCurrentUser']; + callCluster: ILegacyScopedClusterClient['callAsCurrentUser']; params: { criteria: MetricExpressionParams[]; groupBy: string | undefined | string[]; 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 4298ccb61bbedd..c95df6ce93b494 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import type { IScopedClusterClient } from 'src/core/server'; +import type { ILegacyScopedClusterClient } from 'src/core/server'; import { compareDatasetsByMaximumAnomalyScore, getJobId, @@ -186,7 +186,7 @@ export async function getLogEntryCategoryDatasets( export async function getLogEntryCategoryExamples( context: { - core: { elasticsearch: { legacy: { client: IScopedClusterClient } } }; + core: { elasticsearch: { legacy: { client: ILegacyScopedClusterClient } } }; infra: { mlAnomalyDetectors: MlAnomalyDetectors; mlSystem: MlSystem; @@ -472,7 +472,7 @@ async function fetchMlJob( } async function fetchLogEntryCategoryExamples( - requestContext: { core: { elasticsearch: { legacy: { client: IScopedClusterClient } } } }, + requestContext: { core: { elasticsearch: { legacy: { client: ILegacyScopedClusterClient } } } }, indices: string, timestampField: string, startTime: number, diff --git a/x-pack/plugins/ingest_manager/server/types/index.tsx b/x-pack/plugins/ingest_manager/server/types/index.tsx index 2b543490ca8dab..d8214e95aa2a05 100644 --- a/x-pack/plugins/ingest_manager/server/types/index.tsx +++ b/x-pack/plugins/ingest_manager/server/types/index.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ScopedClusterClient } from 'src/core/server'; +import { LegacyScopedClusterClient } from 'src/core/server'; export { // Object types @@ -59,7 +59,7 @@ export { SettingsSOAttributes, } from '../../common'; -export type CallESAsCurrentUser = ScopedClusterClient['callAsCurrentUser']; +export type CallESAsCurrentUser = LegacyScopedClusterClient['callAsCurrentUser']; export type AgentConfigUpdateHandler = ( action: 'created' | 'updated' | 'deleted', diff --git a/x-pack/plugins/lens/server/routes/existing_fields.ts b/x-pack/plugins/lens/server/routes/existing_fields.ts index 698680d32ea1b2..7ab3cdceb21457 100644 --- a/x-pack/plugins/lens/server/routes/existing_fields.ts +++ b/x-pack/plugins/lens/server/routes/existing_fields.ts @@ -6,7 +6,7 @@ import Boom from 'boom'; import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient, SavedObject, RequestHandlerContext } from 'src/core/server'; +import { ILegacyScopedClusterClient, SavedObject, RequestHandlerContext } from 'src/core/server'; import { CoreSetup } from 'src/core/server'; import { BASE_API_URL } from '../../common'; import { @@ -218,7 +218,7 @@ async function fetchIndexPatternStats({ toDate, fields, }: { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; index: string; dslQuery: object; timeFieldName?: string; diff --git a/x-pack/plugins/lens/server/usage/task.ts b/x-pack/plugins/lens/server/usage/task.ts index cde6e7eb6c090b..edc5a778749af1 100644 --- a/x-pack/plugins/lens/server/usage/task.ts +++ b/x-pack/plugins/lens/server/usage/task.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, CoreSetup, Logger } from 'kibana/server'; +import { LegacyAPICaller, CoreSetup, Logger } from 'kibana/server'; import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import moment from 'moment'; @@ -70,7 +70,7 @@ async function scheduleTasks(logger: Logger, taskManager: TaskManagerStartContra export async function getDailyEvents( kibanaIndex: string, - callCluster: APICaller + callCluster: LegacyAPICaller ): Promise<{ byDate: Record>; suggestionsByDate: Record>; @@ -185,7 +185,7 @@ export function telemetryTaskRunner( ) { return ({ taskInstance }: RunContext) => { const { state } = taskInstance; - const callCluster = async (...args: Parameters) => { + const callCluster = async (...args: Parameters) => { const [coreStart] = await core.getStartServices(); return coreStart.elasticsearch.legacy.client.callAsInternalUser(...args); }; diff --git a/x-pack/plugins/lens/server/usage/visualization_counts.ts b/x-pack/plugins/lens/server/usage/visualization_counts.ts index 00b84fe100224e..c3c6b2b7e4cbdd 100644 --- a/x-pack/plugins/lens/server/usage/visualization_counts.ts +++ b/x-pack/plugins/lens/server/usage/visualization_counts.ts @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { LensVisualizationUsage } from './types'; export async function getVisualizationCounts( - callCluster: APICaller, + callCluster: LegacyAPICaller, kibanaIndex: string ): Promise { const scriptedMetric = { diff --git a/x-pack/plugins/license_management/server/types.ts b/x-pack/plugins/license_management/server/types.ts index 11b1ed696874bc..5b432b7ff05798 100644 --- a/x-pack/plugins/license_management/server/types.ts +++ b/x-pack/plugins/license_management/server/types.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ScopedClusterClient, IRouter } from 'kibana/server'; +import { LegacyScopedClusterClient, IRouter } from 'kibana/server'; import { LicensingPluginSetup } from '../../licensing/server'; import { SecurityPluginSetup } from '../../security/server'; @@ -27,6 +27,6 @@ export interface RouteDependencies { }; } -export type CallAsCurrentUser = ScopedClusterClient['callAsCurrentUser']; +export type CallAsCurrentUser = LegacyScopedClusterClient['callAsCurrentUser']; -export type CallAsInternalUser = ScopedClusterClient['callAsInternalUser']; +export type CallAsInternalUser = LegacyScopedClusterClient['callAsInternalUser']; diff --git a/x-pack/plugins/licensing/server/plugin.test.ts b/x-pack/plugins/licensing/server/plugin.test.ts index 9d76472b51cd26..bf549c18da303f 100644 --- a/x-pack/plugins/licensing/server/plugin.test.ts +++ b/x-pack/plugins/licensing/server/plugin.test.ts @@ -14,7 +14,7 @@ import { elasticsearchServiceMock, loggingSystemMock, } from '../../../../src/core/server/mocks'; -import { IClusterClient } from '../../../../src/core/server/'; +import { ILegacyClusterClient } from '../../../../src/core/server/'; function buildRawLicense(options: Partial = {}): RawLicense { const defaultRawLicense: RawLicense = { @@ -29,7 +29,7 @@ function buildRawLicense(options: Partial = {}): RawLicense { const flushPromises = (ms = 50) => new Promise((res) => setTimeout(res, ms)); -function createCoreSetupWith(esClient: IClusterClient) { +function createCoreSetupWith(esClient: ILegacyClusterClient) { const coreSetup = coreMock.createSetup(); coreSetup.getStartServices.mockResolvedValue([ diff --git a/x-pack/plugins/licensing/server/plugin.ts b/x-pack/plugins/licensing/server/plugin.ts index 0a6964b1b829d1..6cdba0ac466446 100644 --- a/x-pack/plugins/licensing/server/plugin.ts +++ b/x-pack/plugins/licensing/server/plugin.ts @@ -15,8 +15,8 @@ import { Logger, Plugin, PluginInitializerContext, - IClusterClient, - IScopedClusterClient, + ILegacyClusterClient, + ILegacyScopedClusterClient, ScopeableRequest, } from 'src/core/server'; @@ -100,20 +100,20 @@ export class LicensingPlugin implements Plugin - ): ReturnType { + ...args: Parameters + ): ReturnType { const [coreStart] = await core.getStartServices(); const client = coreStart.elasticsearch.legacy.client; return await client.callAsInternalUser(...args); } - const client: IClusterClient = { + const client: ILegacyClusterClient = { callAsInternalUser, - asScoped(request?: ScopeableRequest): IScopedClusterClient { + asScoped(request?: ScopeableRequest): ILegacyScopedClusterClient { return { async callAsCurrentUser( - ...args: Parameters - ): ReturnType { + ...args: Parameters + ): ReturnType { const [coreStart] = await core.getStartServices(); const _client = coreStart.elasticsearch.legacy.client; return await _client.asScoped(request).callAsCurrentUser(...args); @@ -147,7 +147,7 @@ export class LicensingPlugin implements Plugin => { + private fetchLicense = async (clusterClient: ILegacyClusterClient): Promise => { try { const response = await clusterClient.callAsInternalUser('transport.request', { method: 'GET', diff --git a/x-pack/plugins/licensing/server/types.ts b/x-pack/plugins/licensing/server/types.ts index 53d9a8ddfcb873..dd1277429eabda 100644 --- a/x-pack/plugins/licensing/server/types.ts +++ b/x-pack/plugins/licensing/server/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { Observable } from 'rxjs'; -import { IClusterClient } from 'src/core/server'; +import { ILegacyClusterClient } from 'src/core/server'; import { ILicense, LicenseStatus, LicenseType } from '../common/types'; import { FeatureUsageServiceSetup, FeatureUsageServiceStart } from './services'; @@ -74,7 +74,7 @@ export interface LicensingPluginSetup { * @deprecated in favour of the counterpart provided from start contract */ createLicensePoller: ( - clusterClient: IClusterClient, + clusterClient: ILegacyClusterClient, pollingFrequency: number ) => { license$: Observable; refresh(): Promise }; /** @@ -99,7 +99,7 @@ export interface LicensingPluginStart { * given polling frequency. */ createLicensePoller: ( - clusterClient: IClusterClient, + clusterClient: ILegacyClusterClient, pollingFrequency: number ) => { license$: Observable; refresh(): Promise }; /** diff --git a/x-pack/plugins/lists/common/get_call_cluster.mock.ts b/x-pack/plugins/lists/common/get_call_cluster.mock.ts index f036605a6a1742..be6f1b3a58629a 100644 --- a/x-pack/plugins/lists/common/get_call_cluster.mock.ts +++ b/x-pack/plugins/lists/common/get_call_cluster.mock.ts @@ -5,7 +5,7 @@ */ import { CreateDocumentResponse } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { LIST_INDEX } from './constants.mock'; import { getShardMock } from './get_shard.mock'; @@ -22,4 +22,4 @@ export const getEmptyCreateDocumentResponseMock = (): CreateDocumentResponse => export const getCallClusterMock = ( callCluster: unknown = getEmptyCreateDocumentResponseMock() -): APICaller => jest.fn().mockResolvedValue(callCluster); +): LegacyAPICaller => jest.fn().mockResolvedValue(callCluster); diff --git a/x-pack/plugins/lists/server/services/items/create_list_item.ts b/x-pack/plugins/lists/server/services/items/create_list_item.ts index d46b9b4703fcbc..7c2f8ade6521e5 100644 --- a/x-pack/plugins/lists/server/services/items/create_list_item.ts +++ b/x-pack/plugins/lists/server/services/items/create_list_item.ts @@ -6,7 +6,7 @@ import uuid from 'uuid'; import { CreateDocumentResponse } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { IdOrUndefined, @@ -22,7 +22,7 @@ export interface CreateListItemOptions { listId: string; type: Type; value: string; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; user: string; meta: MetaOrUndefined; diff --git a/x-pack/plugins/lists/server/services/items/create_list_items_bulk.ts b/x-pack/plugins/lists/server/services/items/create_list_items_bulk.ts index eac294c5f244a2..ced1a6344f9b7f 100644 --- a/x-pack/plugins/lists/server/services/items/create_list_items_bulk.ts +++ b/x-pack/plugins/lists/server/services/items/create_list_items_bulk.ts @@ -5,7 +5,7 @@ */ import uuid from 'uuid'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { transformListItemToElasticQuery } from '../utils'; import { @@ -19,7 +19,7 @@ export interface CreateListItemsBulkOptions { listId: string; type: Type; value: string[]; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; user: string; meta: MetaOrUndefined; diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item.ts b/x-pack/plugins/lists/server/services/items/delete_list_item.ts index 9992f43387c89f..b006aed6f6dde3 100644 --- a/x-pack/plugins/lists/server/services/items/delete_list_item.ts +++ b/x-pack/plugins/lists/server/services/items/delete_list_item.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Id, ListItemSchema } from '../../../common/schemas'; @@ -12,7 +12,7 @@ import { getListItem } from '.'; export interface DeleteListItemOptions { id: Id; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; } diff --git a/x-pack/plugins/lists/server/services/items/delete_list_item_by_value.ts b/x-pack/plugins/lists/server/services/items/delete_list_item_by_value.ts index 57aced5f3701cf..3551cb75dc5bcb 100644 --- a/x-pack/plugins/lists/server/services/items/delete_list_item_by_value.ts +++ b/x-pack/plugins/lists/server/services/items/delete_list_item_by_value.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ListItemArraySchema, Type } from '../../../common/schemas'; import { getQueryFilterFromTypeValue } from '../utils'; @@ -15,7 +15,7 @@ export interface DeleteListItemByValueOptions { listId: string; type: Type; value: string; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; } diff --git a/x-pack/plugins/lists/server/services/items/find_list_item.ts b/x-pack/plugins/lists/server/services/items/find_list_item.ts index d10e6466d03d0c..0f120f73d195e1 100644 --- a/x-pack/plugins/lists/server/services/items/find_list_item.ts +++ b/x-pack/plugins/lists/server/services/items/find_list_item.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Filter, @@ -35,7 +35,7 @@ interface FindListItemOptions { page: Page; sortField: SortFieldOrUndefined; sortOrder: SortOrderOrUndefined; - callCluster: APICaller; + callCluster: LegacyAPICaller; listIndex: string; listItemIndex: string; } diff --git a/x-pack/plugins/lists/server/services/items/get_list_item.ts b/x-pack/plugins/lists/server/services/items/get_list_item.ts index 296d1e4e821849..0c84ba50525cf8 100644 --- a/x-pack/plugins/lists/server/services/items/get_list_item.ts +++ b/x-pack/plugins/lists/server/services/items/get_list_item.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Id, ListItemSchema, SearchEsListItemSchema } from '../../../common/schemas'; import { deriveTypeFromItem, transformElasticToListItem } from '../utils'; interface GetListItemOptions { id: Id; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; } diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_value.ts b/x-pack/plugins/lists/server/services/items/get_list_item_by_value.ts index 49bcf12043d7c9..6b75a171a26d6a 100644 --- a/x-pack/plugins/lists/server/services/items/get_list_item_by_value.ts +++ b/x-pack/plugins/lists/server/services/items/get_list_item_by_value.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ListItemArraySchema, Type } from '../../../common/schemas'; @@ -12,7 +12,7 @@ import { getListItemByValues } from '.'; export interface GetListItemByValueOptions { listId: string; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; type: Type; value: string; diff --git a/x-pack/plugins/lists/server/services/items/get_list_item_by_values.ts b/x-pack/plugins/lists/server/services/items/get_list_item_by_values.ts index cf0ccf3f10aa6e..5e232443625dd3 100644 --- a/x-pack/plugins/lists/server/services/items/get_list_item_by_values.ts +++ b/x-pack/plugins/lists/server/services/items/get_list_item_by_values.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ListItemArraySchema, SearchEsListItemSchema, Type } from '../../../common/schemas'; import { getQueryFilterFromTypeValue, transformElasticToListItem } from '../utils'; export interface GetListItemByValuesOptions { listId: string; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; type: Type; value: string[]; diff --git a/x-pack/plugins/lists/server/services/items/update_list_item.ts b/x-pack/plugins/lists/server/services/items/update_list_item.ts index 6a428b4be854d3..4ddb6e4c4c7423 100644 --- a/x-pack/plugins/lists/server/services/items/update_list_item.ts +++ b/x-pack/plugins/lists/server/services/items/update_list_item.ts @@ -5,7 +5,7 @@ */ import { CreateDocumentResponse } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Id, @@ -20,7 +20,7 @@ import { getListItem } from './get_list_item'; export interface UpdateListItemOptions { id: Id; value: string | null | undefined; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; user: string; meta: MetaOrUndefined; diff --git a/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts b/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts index b3097799628896..de983158ac7072 100644 --- a/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts +++ b/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.ts @@ -6,7 +6,7 @@ import { Readable } from 'stream'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { MetaOrUndefined, Type } from '../../../common/schemas'; @@ -17,7 +17,7 @@ import { createListItemsBulk } from './create_list_items_bulk'; export interface ImportListItemsToStreamOptions { listId: string; stream: Readable; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; type: Type; user: string; @@ -55,7 +55,7 @@ export const importListItemsToStream = ({ export interface WriteBufferToItemsOptions { listId: string; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; buffer: string[]; type: Type; 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 f485f557433c6e..91f4644d359e36 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 { SearchResponse } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { SearchEsListItemSchema } from '../../../common/schemas'; import { ErrorWithStatusCode } from '../../error_with_status_code'; @@ -20,7 +20,7 @@ export const SIZE = 100; export interface ExportListItemsToStreamOptions { listId: string; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; stream: PassThrough; stringToAppend: string | null | undefined; @@ -60,7 +60,7 @@ export const exportListItemsToStream = ({ export interface WriteNextResponseOptions { listId: string; - callCluster: APICaller; + callCluster: LegacyAPICaller; listItemIndex: string; stream: PassThrough; searchAfter: string[] | undefined; @@ -100,7 +100,7 @@ export const getSearchAfterFromResponse = ({ : undefined; export interface GetResponseOptions { - callCluster: APICaller; + callCluster: LegacyAPICaller; listId: string; searchAfter: undefined | string[]; listItemIndex: string; diff --git a/x-pack/plugins/lists/server/services/lists/create_list.ts b/x-pack/plugins/lists/server/services/lists/create_list.ts index 0d2ee606a066df..29ac5ebd967107 100644 --- a/x-pack/plugins/lists/server/services/lists/create_list.ts +++ b/x-pack/plugins/lists/server/services/lists/create_list.ts @@ -6,7 +6,7 @@ import uuid from 'uuid'; import { CreateDocumentResponse } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Description, @@ -23,7 +23,7 @@ export interface CreateListOptions { type: Type; name: Name; description: Description; - callCluster: APICaller; + callCluster: LegacyAPICaller; listIndex: string; user: string; meta: MetaOrUndefined; diff --git a/x-pack/plugins/lists/server/services/lists/delete_list.ts b/x-pack/plugins/lists/server/services/lists/delete_list.ts index bc66c88b082a31..64359b72732744 100644 --- a/x-pack/plugins/lists/server/services/lists/delete_list.ts +++ b/x-pack/plugins/lists/server/services/lists/delete_list.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Id, ListSchema } from '../../../common/schemas'; @@ -12,7 +12,7 @@ import { getList } from './get_list'; export interface DeleteListOptions { id: Id; - callCluster: APICaller; + callCluster: LegacyAPICaller; listIndex: string; listItemIndex: string; } diff --git a/x-pack/plugins/lists/server/services/lists/find_list.ts b/x-pack/plugins/lists/server/services/lists/find_list.ts index 41dcdfcd0f8dbe..86cead9e868d6e 100644 --- a/x-pack/plugins/lists/server/services/lists/find_list.ts +++ b/x-pack/plugins/lists/server/services/lists/find_list.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Filter, @@ -32,7 +32,7 @@ interface FindListOptions { page: Page; sortField: SortFieldOrUndefined; sortOrder: SortOrderOrUndefined; - callCluster: APICaller; + callCluster: LegacyAPICaller; listIndex: string; } diff --git a/x-pack/plugins/lists/server/services/lists/get_list.ts b/x-pack/plugins/lists/server/services/lists/get_list.ts index 386232bfeee1f3..13550eb7d30dd0 100644 --- a/x-pack/plugins/lists/server/services/lists/get_list.ts +++ b/x-pack/plugins/lists/server/services/lists/get_list.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Id, ListSchema, SearchEsListSchema } from '../../../common/schemas'; import { transformElasticToList } from '../utils/transform_elastic_to_list'; interface GetListOptions { id: Id; - callCluster: APICaller; + callCluster: LegacyAPICaller; listIndex: string; } diff --git a/x-pack/plugins/lists/server/services/lists/list_client.ts b/x-pack/plugins/lists/server/services/lists/list_client.ts index 5a7d20c7d64d53..662d082a08e4ba 100644 --- a/x-pack/plugins/lists/server/services/lists/list_client.ts +++ b/x-pack/plugins/lists/server/services/lists/list_client.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { FoundListItemSchema, @@ -75,7 +75,7 @@ export class ListClient { private readonly spaceId: string; private readonly user: string; private readonly config: ConfigType; - private readonly callCluster: APICaller; + private readonly callCluster: LegacyAPICaller; constructor({ spaceId, user, config, callCluster }: ConstructorOptions) { this.spaceId = spaceId; diff --git a/x-pack/plugins/lists/server/services/lists/list_client_types.ts b/x-pack/plugins/lists/server/services/lists/list_client_types.ts index 4171b6ee9f1655..0c7a6a6e99a8e2 100644 --- a/x-pack/plugins/lists/server/services/lists/list_client_types.ts +++ b/x-pack/plugins/lists/server/services/lists/list_client_types.ts @@ -6,7 +6,7 @@ import { PassThrough, Readable } from 'stream'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Description, @@ -27,7 +27,7 @@ import { import { ConfigType } from '../../config'; export interface ConstructorOptions { - callCluster: APICaller; + callCluster: LegacyAPICaller; config: ConfigType; spaceId: string; user: string; diff --git a/x-pack/plugins/lists/server/services/lists/update_list.ts b/x-pack/plugins/lists/server/services/lists/update_list.ts index 28be50e9d6ac86..7d763013fb10e4 100644 --- a/x-pack/plugins/lists/server/services/lists/update_list.ts +++ b/x-pack/plugins/lists/server/services/lists/update_list.ts @@ -5,7 +5,7 @@ */ import { CreateDocumentResponse } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { DescriptionOrUndefined, @@ -20,7 +20,7 @@ import { getList } from '.'; export interface UpdateListOptions { id: Id; - callCluster: APICaller; + callCluster: LegacyAPICaller; listIndex: string; user: string; name: NameOrUndefined; diff --git a/x-pack/plugins/lists/server/services/utils/get_search_after_scroll.ts b/x-pack/plugins/lists/server/services/utils/get_search_after_scroll.ts index 2af501106d6598..dd1ac74d40acd1 100644 --- a/x-pack/plugins/lists/server/services/utils/get_search_after_scroll.ts +++ b/x-pack/plugins/lists/server/services/utils/get_search_after_scroll.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Filter, SortFieldOrUndefined, SortOrderOrUndefined } from '../../../common/schemas'; import { Scroll } from '../lists/types'; @@ -15,7 +15,7 @@ import { getSourceWithTieBreaker } from './get_source_with_tie_breaker'; import { TieBreaker, getSearchAfterWithTieBreaker } from './get_search_after_with_tie_breaker'; interface GetSearchAfterOptions { - callCluster: APICaller; + callCluster: LegacyAPICaller; filter: Filter; hops: number; hopSize: number; diff --git a/x-pack/plugins/lists/server/services/utils/scroll_to_start_page.ts b/x-pack/plugins/lists/server/services/utils/scroll_to_start_page.ts index 6b898a54bb9fef..0b04cdc196eb6f 100644 --- a/x-pack/plugins/lists/server/services/utils/scroll_to_start_page.ts +++ b/x-pack/plugins/lists/server/services/utils/scroll_to_start_page.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Filter, SortFieldOrUndefined, SortOrderOrUndefined } from '../../../common/schemas'; import { Scroll } from '../lists/types'; @@ -13,7 +13,7 @@ import { calculateScrollMath } from './calculate_scroll_math'; import { getSearchAfterScroll } from './get_search_after_scroll'; interface ScrollToStartPageOptions { - callCluster: APICaller; + callCluster: LegacyAPICaller; filter: Filter; sortField: SortFieldOrUndefined; sortOrder: SortOrderOrUndefined; diff --git a/x-pack/plugins/lists/server/types.ts b/x-pack/plugins/lists/server/types.ts index 6808aaa04ab7a0..9ea7e7a2bc0018 100644 --- a/x-pack/plugins/lists/server/types.ts +++ b/x-pack/plugins/lists/server/types.ts @@ -5,8 +5,8 @@ */ import { - APICaller, IContextProvider, + LegacyAPICaller, RequestHandler, SavedObjectsClientContract, } from 'kibana/server'; @@ -25,7 +25,7 @@ export interface PluginsSetup { } export type GetListClientType = ( - dataClient: APICaller, + dataClient: LegacyAPICaller, spaceId: string, user: string ) => ListClient; diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts index 060cf188a4c60e..f7cfc4d4fa12a9 100755 --- a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { SearchResponse } from 'elasticsearch'; import { ES_SCROLL_SETTINGS } from '../../../common/constants'; @@ -11,7 +11,7 @@ import { Hits } from '../../types'; export async function fetchAllFromScroll( response: SearchResponse, - callWithRequest: APICaller, + callWithRequest: LegacyAPICaller, hits: Hits = [] ): Promise { const newHits = response.hits?.hits || []; diff --git a/x-pack/plugins/logstash/server/plugin.ts b/x-pack/plugins/logstash/server/plugin.ts index c048dd13bfb0cf..eb79e1d2a8d8bc 100644 --- a/x-pack/plugins/logstash/server/plugin.ts +++ b/x-pack/plugins/logstash/server/plugin.ts @@ -6,7 +6,7 @@ import { CoreSetup, CoreStart, - ICustomClusterClient, + ILegacyCustomClusterClient, Logger, Plugin, PluginInitializerContext, @@ -23,7 +23,7 @@ interface SetupDeps { export class LogstashPlugin implements Plugin { private readonly logger: Logger; - private esClient?: ICustomClusterClient; + private esClient?: ILegacyCustomClusterClient; private coreSetup?: CoreSetup; constructor(context: PluginInitializerContext) { this.logger = context.logger.get(); diff --git a/x-pack/plugins/logstash/server/routes/pipelines/delete.ts b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts index e29d0128353b56..4b2471c89fe07c 100644 --- a/x-pack/plugins/logstash/server/routes/pipelines/delete.ts +++ b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -import { APICaller, IRouter } from 'src/core/server'; +import { LegacyAPICaller, IRouter } from 'src/core/server'; import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { INDEX_NAMES } from '../../../common/constants'; import { checkLicense } from '../../lib/check_license'; -async function deletePipelines(callWithRequest: APICaller, pipelineIds: string[]) { +async function deletePipelines(callWithRequest: LegacyAPICaller, pipelineIds: string[]) { const deletePromises = pipelineIds.map((pipelineId) => { return callWithRequest('delete', { index: INDEX_NAMES.PIPELINES, diff --git a/x-pack/plugins/logstash/server/routes/pipelines/list.ts b/x-pack/plugins/logstash/server/routes/pipelines/list.ts index 594e2b8ed8b3c2..de2266b89e3d03 100644 --- a/x-pack/plugins/logstash/server/routes/pipelines/list.ts +++ b/x-pack/plugins/logstash/server/routes/pipelines/list.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; import { SearchResponse } from 'elasticsearch'; -import { APICaller, IRouter } from 'src/core/server'; +import { LegacyAPICaller, IRouter } from 'src/core/server'; import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../common/constants'; @@ -13,7 +13,7 @@ import { PipelineListItem } from '../../models/pipeline_list_item'; import { fetchAllFromScroll } from '../../lib/fetch_all_from_scroll'; import { checkLicense } from '../../lib/check_license'; -async function fetchPipelines(callWithRequest: APICaller) { +async function fetchPipelines(callWithRequest: LegacyAPICaller) { const params = { index: INDEX_NAMES.PIPELINES, scroll: ES_SCROLL_SETTINGS.KEEPALIVE, diff --git a/x-pack/plugins/logstash/server/types.ts b/x-pack/plugins/logstash/server/types.ts index 2b266b2f277089..29198407013abe 100644 --- a/x-pack/plugins/logstash/server/types.ts +++ b/x-pack/plugins/logstash/server/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { SearchResponse } from 'elasticsearch'; -import { IScopedClusterClient } from 'src/core/server'; +import { ILegacyScopedClusterClient } from 'src/core/server'; type UnwrapArray = T extends Array ? U : never; @@ -21,7 +21,7 @@ export interface PipelineListItemOptions { declare module 'src/core/server' { interface RequestHandlerContext { logstash?: { - esClient: IScopedClusterClient; + esClient: ILegacyScopedClusterClient; }; } } diff --git a/x-pack/plugins/ml/server/lib/capabilities/check_capabilities.ts b/x-pack/plugins/ml/server/lib/capabilities/check_capabilities.ts index ce775a425fa730..d4218d8e55c3e5 100644 --- a/x-pack/plugins/ml/server/lib/capabilities/check_capabilities.ts +++ b/x-pack/plugins/ml/server/lib/capabilities/check_capabilities.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { MlCapabilities, adminMlCapabilities, @@ -14,7 +14,7 @@ import { upgradeCheckProvider } from './upgrade'; import { MlLicense } from '../../../common/license'; export function capabilitiesProvider( - callAsCurrentUser: IScopedClusterClient['callAsCurrentUser'], + callAsCurrentUser: ILegacyScopedClusterClient['callAsCurrentUser'], capabilities: MlCapabilities, mlLicense: MlLicense, isMlEnabledInSpace: () => Promise diff --git a/x-pack/plugins/ml/server/lib/capabilities/upgrade.ts b/x-pack/plugins/ml/server/lib/capabilities/upgrade.ts index a1d66f00f26e19..259606ba8c7ea9 100644 --- a/x-pack/plugins/ml/server/lib/capabilities/upgrade.ts +++ b/x-pack/plugins/ml/server/lib/capabilities/upgrade.ts @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { mlLog } from '../../client/log'; -export function upgradeCheckProvider(callAsCurrentUser: IScopedClusterClient['callAsCurrentUser']) { +export function upgradeCheckProvider( + callAsCurrentUser: ILegacyScopedClusterClient['callAsCurrentUser'] +) { async function isUpgradeInProgress(): Promise { let upgradeInProgress = false; try { diff --git a/x-pack/plugins/ml/server/lib/check_annotations/index.ts b/x-pack/plugins/ml/server/lib/check_annotations/index.ts index 980a48df480d79..2c46be394cbb22 100644 --- a/x-pack/plugins/ml/server/lib/check_annotations/index.ts +++ b/x-pack/plugins/ml/server/lib/check_annotations/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { mlLog } from '../../client/log'; import { @@ -17,7 +17,7 @@ import { // - ML_ANNOTATIONS_INDEX_PATTERN index is present // - ML_ANNOTATIONS_INDEX_ALIAS_READ alias is present // - ML_ANNOTATIONS_INDEX_ALIAS_WRITE alias is present -export async function isAnnotationsFeatureAvailable(callAsCurrentUser: APICaller) { +export async function isAnnotationsFeatureAvailable(callAsCurrentUser: LegacyAPICaller) { try { const indexParams = { index: ML_ANNOTATIONS_INDEX_PATTERN }; diff --git a/x-pack/plugins/ml/server/models/annotation_service/annotation.test.ts b/x-pack/plugins/ml/server/models/annotation_service/annotation.test.ts index 0d88fd0cd1bb02..19db8b7b56aa6a 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/annotation.test.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.test.ts @@ -6,7 +6,7 @@ import getAnnotationsRequestMock from './__mocks__/get_annotations_request.json'; import getAnnotationsResponseMock from './__mocks__/get_annotations_response.json'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ANNOTATION_TYPE } from '../../../common/constants/annotations'; import { ML_ANNOTATIONS_INDEX_ALIAS_WRITE } from '../../../common/constants/index_patterns'; @@ -31,7 +31,7 @@ describe('annotation_service', () => { case 'search': return Promise.resolve(getAnnotationsResponseMock); } - }) as unknown) as APICaller; + }) as unknown) as LegacyAPICaller; }); describe('deleteAnnotation()', () => { @@ -86,7 +86,7 @@ describe('annotation_service', () => { const callWithRequestSpyError = (jest.fn(() => { return Promise.resolve(mockEsError); - }) as unknown) as APICaller; + }) as unknown) as LegacyAPICaller; const { getAnnotations } = annotationServiceProvider(callWithRequestSpyError); 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 6c33de94c94b33..2808b06103a757 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts @@ -6,7 +6,7 @@ import Boom from 'boom'; import _ from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ANNOTATION_TYPE } from '../../../common/constants/annotations'; import { @@ -68,7 +68,7 @@ export type callWithRequestType = ( params: annotationProviderParams ) => Promise; -export function annotationProvider(callAsCurrentUser: APICaller) { +export function annotationProvider(callAsCurrentUser: LegacyAPICaller) { async function indexAnnotation(annotation: Annotation, username: string) { if (isAnnotation(annotation) === false) { // No need to translate, this will not be exposed in the UI. diff --git a/x-pack/plugins/ml/server/models/annotation_service/index.ts b/x-pack/plugins/ml/server/models/annotation_service/index.ts index 995f800b0a498e..efc42c693c24b6 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/index.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/index.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { annotationProvider } from './annotation'; -export function annotationServiceProvider(callAsCurrentUser: APICaller) { +export function annotationServiceProvider(callAsCurrentUser: LegacyAPICaller) { return { ...annotationProvider(callAsCurrentUser), }; diff --git a/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts index bdf1cbd5b34dca..3e80e79705a5c2 100644 --- a/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts +++ b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.d.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ES_AGGREGATION } from '../../../common/constants/aggregation_types'; export interface BucketSpanEstimatorData { @@ -21,7 +21,7 @@ export interface BucketSpanEstimatorData { } export function estimateBucketSpanFactory( - callAsCurrentUser: APICaller, - callAsInternalUser: APICaller, + callAsCurrentUser: LegacyAPICaller, + callAsInternalUser: LegacyAPICaller, isSecurityDisabled: boolean ): (config: BucketSpanEstimatorData) => Promise; diff --git a/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.test.ts b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.test.ts index 8e8301db2a3a37..8da1fb69eec34f 100644 --- a/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.test.ts +++ b/x-pack/plugins/ml/server/models/bucket_span_estimator/bucket_span_estimator.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ES_AGGREGATION } from '../../../common/constants/aggregation_types'; @@ -17,7 +17,7 @@ import { estimateBucketSpanFactory, BucketSpanEstimatorData } from './bucket_spa // sufficient permissions should be returned, the second time insufficient // permissions. const permissions = [false, true]; -const callWithRequest: APICaller = (method: string) => { +const callWithRequest: LegacyAPICaller = (method: string) => { return new Promise((resolve) => { if (method === 'ml.privilegeCheck') { resolve({ @@ -34,7 +34,7 @@ const callWithRequest: APICaller = (method: string) => { }) as Promise; }; -const callWithInternalUser: APICaller = () => { +const callWithInternalUser: LegacyAPICaller = () => { return new Promise((resolve) => { resolve({}); }) as Promise; 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 9533fbc89c76cb..61299aa3ae26df 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 @@ -5,7 +5,7 @@ */ import numeral from '@elastic/numeral'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { MLCATEGORY } from '../../../common/constants/field_types'; import { AnalysisConfig } from '../../../common/types/anomaly_detection_jobs'; import { fieldsServiceProvider } from '../fields_service'; @@ -36,7 +36,7 @@ export interface ModelMemoryEstimate { /** * Retrieves overall and max bucket cardinalities. */ -const cardinalityCheckProvider = (callAsCurrentUser: APICaller) => { +const cardinalityCheckProvider = (callAsCurrentUser: LegacyAPICaller) => { const fieldsService = fieldsServiceProvider(callAsCurrentUser); return async ( @@ -123,7 +123,7 @@ const cardinalityCheckProvider = (callAsCurrentUser: APICaller) => { }; }; -export function calculateModelMemoryLimitProvider(callAsCurrentUser: APICaller) { +export function calculateModelMemoryLimitProvider(callAsCurrentUser: LegacyAPICaller) { const getCardinalities = cardinalityCheckProvider(callAsCurrentUser); /** 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 2eec704f1e784c..5df9c037b3f837 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 @@ */ import { difference } from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { EventManager, CalendarEvent } from './event_manager'; interface BasicCalendar { @@ -23,10 +23,10 @@ export interface FormCalendar extends BasicCalendar { } export class CalendarManager { - private _callAsCurrentUser: APICaller; + private _callAsCurrentUser: LegacyAPICaller; private _eventManager: EventManager; - constructor(callAsCurrentUser: APICaller) { + constructor(callAsCurrentUser: LegacyAPICaller) { this._callAsCurrentUser = callAsCurrentUser; this._eventManager = new EventManager(callAsCurrentUser); } 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 02da0718d83ae6..57034ab772710f 100644 --- a/x-pack/plugins/ml/server/models/calendar/event_manager.ts +++ b/x-pack/plugins/ml/server/models/calendar/event_manager.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { GLOBAL_CALENDAR } from '../../../common/constants/calendars'; export interface CalendarEvent { @@ -16,7 +16,7 @@ export interface CalendarEvent { } export class EventManager { - constructor(private _callAsCurrentUser: APICaller) {} + constructor(private _callAsCurrentUser: LegacyAPICaller) {} async getCalendarEvents(calendarId: string) { const resp = await this._callAsCurrentUser('ml.events', { calendarId }); diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts index bcdc58e61ad7cb..ee8598ad338e32 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.test.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, SavedObjectsClientContract } from 'kibana/server'; +import { LegacyAPICaller, SavedObjectsClientContract } from 'kibana/server'; import { Module } from '../../../common/types/modules'; import { DataRecognizer } from '../data_recognizer'; describe('ML - data recognizer', () => { const dr = new DataRecognizer( - jest.fn() as APICaller, + jest.fn() as LegacyAPICaller, ({ find: jest.fn(), bulkCreate: jest.fn(), diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts index 82a272b068bb39..1ed9df8da65dde 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts @@ -7,7 +7,7 @@ import fs from 'fs'; import Boom from 'boom'; import numeral from '@elastic/numeral'; -import { APICaller, SavedObjectsClientContract } from 'kibana/server'; +import { LegacyAPICaller, SavedObjectsClientContract } from 'kibana/server'; import moment from 'moment'; import { IndexPatternAttributes } from 'src/plugins/data/server'; import { merge } from 'lodash'; @@ -113,7 +113,7 @@ export class DataRecognizer { jobsForModelMemoryEstimation: Array<{ job: ModuleJob; query: any }> = []; constructor( - private callAsCurrentUser: APICaller, + private callAsCurrentUser: LegacyAPICaller, private savedObjectsClient: SavedObjectsClientContract ) {} diff --git a/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts index 43581ad75fb17a..dc1eef8edd0be8 100644 --- a/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts +++ b/x-pack/plugins/ml/server/models/data_visualizer/data_visualizer.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CallAPIOptions, IScopedClusterClient } from 'kibana/server'; +import { LegacyCallAPIOptions, ILegacyScopedClusterClient } from 'kibana/server'; import _ from 'lodash'; import { ML_JOB_FIELD_TYPES } from '../../../common/constants/field_types'; import { getSafeAggregationName } from '../../../common/util/job_utils'; @@ -110,10 +110,10 @@ export class DataVisualizer { callAsCurrentUser: ( endpoint: string, clientParams: Record, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => Promise; - constructor(callAsCurrentUser: IScopedClusterClient['callAsCurrentUser']) { + constructor(callAsCurrentUser: ILegacyScopedClusterClient['callAsCurrentUser']) { this.callAsCurrentUser = callAsCurrentUser; } diff --git a/x-pack/plugins/ml/server/models/fields_service/fields_service.ts b/x-pack/plugins/ml/server/models/fields_service/fields_service.ts index d9d765028b123a..661ea6c6fec24b 100644 --- a/x-pack/plugins/ml/server/models/fields_service/fields_service.ts +++ b/x-pack/plugins/ml/server/models/fields_service/fields_service.ts @@ -5,7 +5,7 @@ */ import Boom from 'boom'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { duration } from 'moment'; import { parseInterval } from '../../../common/util/parse_interval'; import { initCardinalityFieldsCache } from './fields_aggs_cache'; @@ -14,7 +14,7 @@ import { initCardinalityFieldsCache } from './fields_aggs_cache'; * Service for carrying out queries to obtain data * specific to fields in Elasticsearch indices. */ -export function fieldsServiceProvider(callAsCurrentUser: APICaller) { +export function fieldsServiceProvider(callAsCurrentUser: LegacyAPICaller) { const fieldsAggsCache = initCardinalityFieldsCache(); /** diff --git a/x-pack/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts b/x-pack/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts index d53378b886a995..978355d098b13a 100644 --- a/x-pack/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts +++ b/x-pack/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { AnalysisResult, FormattedOverrides, @@ -13,7 +13,7 @@ import { export type InputData = any[]; -export function fileDataVisualizerProvider(callAsCurrentUser: APICaller) { +export function fileDataVisualizerProvider(callAsCurrentUser: LegacyAPICaller) { async function analyzeFile(data: any, overrides: any): Promise { const results = await callAsCurrentUser('ml.fileStructure', { body: data, diff --git a/x-pack/plugins/ml/server/models/file_data_visualizer/import_data.ts b/x-pack/plugins/ml/server/models/file_data_visualizer/import_data.ts index afe699cc7fecf7..e082a7462241a5 100644 --- a/x-pack/plugins/ml/server/models/file_data_visualizer/import_data.ts +++ b/x-pack/plugins/ml/server/models/file_data_visualizer/import_data.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { INDEX_META_DATA_CREATED_BY } from '../../../common/constants/file_datavisualizer'; import { ImportResponse, @@ -15,7 +15,7 @@ import { } from '../../../common/types/file_datavisualizer'; import { InputData } from './file_data_visualizer'; -export function importDataProvider(callAsCurrentUser: APICaller) { +export function importDataProvider(callAsCurrentUser: LegacyAPICaller) { async function importData( id: string, index: string, 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 11208b4d941f38..22d3df3cc8a63f 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 @@ */ import Boom from 'boom'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { DetectorRule, DetectorRuleScope } from '../../../common/types/detector_rules'; @@ -58,9 +58,9 @@ interface PartialJob { } export class FilterManager { - private _client: IScopedClusterClient['callAsCurrentUser']; + private _client: ILegacyScopedClusterClient['callAsCurrentUser']; - constructor(client: IScopedClusterClient['callAsCurrentUser']) { + constructor(client: ILegacyScopedClusterClient['callAsCurrentUser']) { this._client = client; } diff --git a/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts index 00538f498d61b1..f11771a88c5c63 100644 --- a/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts +++ b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.d.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; export function jobAuditMessagesProvider( - callAsCurrentUser: APICaller + callAsCurrentUser: LegacyAPICaller ): { getJobAuditMessages: (jobId?: string, from?: string) => any; getAuditMessagesSummary: (jobIds?: string[]) => any; 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 f0168980759185..0f64f5e0e7b4f2 100644 --- a/x-pack/plugins/ml/server/models/job_service/datafeeds.ts +++ b/x-pack/plugins/ml/server/models/job_service/datafeeds.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { i18n } from '@kbn/i18n'; import { JOB_STATE, DATAFEED_STATE } from '../../../common/constants/states'; import { fillResultsWithTimeouts, isRequestTimeout } from './error_utils'; @@ -26,7 +26,7 @@ interface Results { }; } -export function datafeedsProvider(callAsCurrentUser: APICaller) { +export function datafeedsProvider(callAsCurrentUser: LegacyAPICaller) { async function forceStartDatafeeds(datafeedIds: string[], start?: number, end?: number) { const jobIds = await getJobIdsByDatafeedId(); const doStartsCalled = datafeedIds.reduce((acc, cur) => { diff --git a/x-pack/plugins/ml/server/models/job_service/groups.ts b/x-pack/plugins/ml/server/models/job_service/groups.ts index 56757e4cc3ff7c..ab5707ab29e65c 100644 --- a/x-pack/plugins/ml/server/models/job_service/groups.ts +++ b/x-pack/plugins/ml/server/models/job_service/groups.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { CalendarManager } from '../calendar'; import { GLOBAL_CALENDAR } from '../../../common/constants/calendars'; import { Job } from '../../../common/types/anomaly_detection_jobs'; @@ -23,7 +23,7 @@ interface Results { }; } -export function groupsProvider(callAsCurrentUser: APICaller) { +export function groupsProvider(callAsCurrentUser: LegacyAPICaller) { const calMngr = new CalendarManager(callAsCurrentUser); async function getAllGroups() { diff --git a/x-pack/plugins/ml/server/models/job_service/index.ts b/x-pack/plugins/ml/server/models/job_service/index.ts index b6e87b98735ee7..5d053c1be73e42 100644 --- a/x-pack/plugins/ml/server/models/job_service/index.ts +++ b/x-pack/plugins/ml/server/models/job_service/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { datafeedsProvider } from './datafeeds'; import { jobsProvider } from './jobs'; import { groupsProvider } from './groups'; @@ -12,7 +12,7 @@ import { newJobCapsProvider } from './new_job_caps'; import { newJobChartsProvider, topCategoriesProvider } from './new_job'; import { modelSnapshotProvider } from './model_snapshots'; -export function jobServiceProvider(callAsCurrentUser: APICaller) { +export function jobServiceProvider(callAsCurrentUser: LegacyAPICaller) { return { ...datafeedsProvider(callAsCurrentUser), ...jobsProvider(callAsCurrentUser), diff --git a/x-pack/plugins/ml/server/models/job_service/jobs.ts b/x-pack/plugins/ml/server/models/job_service/jobs.ts index 852264b3d03374..2d26b2150edf33 100644 --- a/x-pack/plugins/ml/server/models/job_service/jobs.ts +++ b/x-pack/plugins/ml/server/models/job_service/jobs.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { uniq } from 'lodash'; import Boom from 'boom'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { JOB_STATE, DATAFEED_STATE } from '../../../common/constants/states'; import { MlSummaryJob, @@ -46,7 +46,7 @@ interface Results { }; } -export function jobsProvider(callAsCurrentUser: APICaller) { +export function jobsProvider(callAsCurrentUser: LegacyAPICaller) { const { forceDeleteDatafeed, getDatafeedIdsByJobId } = datafeedsProvider(callAsCurrentUser); const { getAuditMessagesSummary } = jobAuditMessagesProvider(callAsCurrentUser); const { getLatestBucketTimestampByJob } = resultsServiceProvider(callAsCurrentUser); diff --git a/x-pack/plugins/ml/server/models/job_service/model_snapshots.ts b/x-pack/plugins/ml/server/models/job_service/model_snapshots.ts index 4ffae17fc1c069..136d4f47c7facc 100644 --- a/x-pack/plugins/ml/server/models/job_service/model_snapshots.ts +++ b/x-pack/plugins/ml/server/models/job_service/model_snapshots.ts @@ -6,7 +6,7 @@ import Boom from 'boom'; import { i18n } from '@kbn/i18n'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ModelSnapshot } from '../../../common/types/anomaly_detection_jobs'; import { datafeedsProvider, MlDatafeedsResponse } from './datafeeds'; import { MlJobsResponse } from './jobs'; @@ -20,7 +20,7 @@ export interface RevertModelSnapshotResponse { model: ModelSnapshot; } -export function modelSnapshotProvider(callAsCurrentUser: APICaller) { +export function modelSnapshotProvider(callAsCurrentUser: LegacyAPICaller) { const { forceStartDatafeeds, getDatafeedIdsByJobId } = datafeedsProvider(callAsCurrentUser); async function revertModelSnapshot( diff --git a/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts b/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts index 11f979bc127497..664f1dd1ae8328 100644 --- a/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts +++ b/x-pack/plugins/ml/server/models/job_validation/job_validation.test.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { validateJob, ValidateJobPayload } from './job_validation'; import { JobValidationMessage } from '../../../common/constants/messages'; // mock callWithRequest -const callWithRequest: APICaller = (method: string) => { +const callWithRequest: LegacyAPICaller = (method: string) => { return new Promise((resolve) => { if (method === 'fieldCaps') { resolve({ fields: [] }); diff --git a/x-pack/plugins/ml/server/models/job_validation/job_validation.ts b/x-pack/plugins/ml/server/models/job_validation/job_validation.ts index 9d7154bbbb304d..6e65e5e64f3b75 100644 --- a/x-pack/plugins/ml/server/models/job_validation/job_validation.ts +++ b/x-pack/plugins/ml/server/models/job_validation/job_validation.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import Boom from 'boom'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { TypeOf } from '@kbn/config-schema'; import { fieldsServiceProvider } from '../fields_service'; @@ -35,10 +35,10 @@ export type ValidateJobPayload = TypeOf; * @kbn/config-schema has checked the payload {@link validateJobSchema}. */ export async function validateJob( - callWithRequest: APICaller, + callWithRequest: LegacyAPICaller, payload: ValidateJobPayload, kbnVersion = 'current', - callAsInternalUser?: APICaller, + callAsInternalUser?: LegacyAPICaller, isSecurityDisabled?: boolean ) { const messages = getMessages(); diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.test.ts b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.test.ts index 13e5495aac4c41..bcfe4a48a0de00 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.test.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.test.ts @@ -6,7 +6,7 @@ import _ from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; @@ -21,7 +21,7 @@ const mockResponses = { }; // mock callWithRequestFactory -const callWithRequestFactory = (responses: Record, fail = false): APICaller => { +const callWithRequestFactory = (responses: Record, fail = false): LegacyAPICaller => { return (requestName: string) => { return new Promise((resolve, reject) => { const response = responses[requestName]; diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.ts b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.ts index 62f272f26bb3f1..d5bc6aa20e32aa 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { DataVisualizer } from '../data_visualizer'; import { validateJobObject } from './validate_job_object'; @@ -43,7 +43,7 @@ type Validator = (obj: { messages: Messages; }>; -const validateFactory = (callWithRequest: APICaller, job: CombinedJob): Validator => { +const validateFactory = (callWithRequest: LegacyAPICaller, job: CombinedJob): Validator => { const dv = new DataVisualizer(callWithRequest); const modelPlotConfigTerms = job?.model_plot_config?.terms ?? ''; @@ -150,7 +150,7 @@ const validateFactory = (callWithRequest: APICaller, job: CombinedJob): Validato }; export async function validateCardinality( - callWithRequest: APICaller, + callWithRequest: LegacyAPICaller, job?: CombinedJob ): Promise | never { const messages: Messages = []; diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_influencers.test.ts b/x-pack/plugins/ml/server/models/job_validation/validate_influencers.test.ts index 89c265d0b6f602..594b51a773adae 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_influencers.test.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_influencers.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; @@ -13,7 +13,7 @@ import { validateInfluencers } from './validate_influencers'; describe('ML - validateInfluencers', () => { it('called without arguments throws an error', (done) => { validateInfluencers( - (undefined as unknown) as APICaller, + (undefined as unknown) as LegacyAPICaller, (undefined as unknown) as CombinedJob ).then( () => done(new Error('Promise should not resolve for this test without job argument.')), @@ -22,7 +22,10 @@ describe('ML - validateInfluencers', () => { }); it('called with non-valid job argument #1, missing analysis_config', (done) => { - validateInfluencers((undefined as unknown) as APICaller, ({} as unknown) as CombinedJob).then( + validateInfluencers( + (undefined as unknown) as LegacyAPICaller, + ({} as unknown) as CombinedJob + ).then( () => done(new Error('Promise should not resolve for this test without valid job argument.')), () => done() ); @@ -34,7 +37,10 @@ describe('ML - validateInfluencers', () => { datafeed_config: { indices: [] }, data_description: { time_field: '@timestamp' }, }; - validateInfluencers((undefined as unknown) as APICaller, (job as unknown) as CombinedJob).then( + validateInfluencers( + (undefined as unknown) as LegacyAPICaller, + (job as unknown) as CombinedJob + ).then( () => done(new Error('Promise should not resolve for this test without valid job argument.')), () => done() ); @@ -46,7 +52,10 @@ describe('ML - validateInfluencers', () => { datafeed_config: { indices: [] }, data_description: { time_field: '@timestamp' }, }; - validateInfluencers((undefined as unknown) as APICaller, (job as unknown) as CombinedJob).then( + validateInfluencers( + (undefined as unknown) as LegacyAPICaller, + (job as unknown) as CombinedJob + ).then( () => done(new Error('Promise should not resolve for this test without valid job argument.')), () => done() ); @@ -66,7 +75,7 @@ describe('ML - validateInfluencers', () => { it('success_influencer', () => { const job = getJobConfig(['airline']); - return validateInfluencers((undefined as unknown) as APICaller, job).then((messages) => { + return validateInfluencers((undefined as unknown) as LegacyAPICaller, job).then((messages) => { const ids = messages.map((m) => m.id); expect(ids).toStrictEqual(['success_influencers']); }); @@ -84,7 +93,7 @@ describe('ML - validateInfluencers', () => { ] ); - return validateInfluencers((undefined as unknown) as APICaller, job).then((messages) => { + return validateInfluencers((undefined as unknown) as LegacyAPICaller, job).then((messages) => { const ids = messages.map((m) => m.id); expect(ids).toStrictEqual([]); }); @@ -92,7 +101,7 @@ describe('ML - validateInfluencers', () => { it('influencer_low', () => { const job = getJobConfig(); - return validateInfluencers((undefined as unknown) as APICaller, job).then((messages) => { + return validateInfluencers((undefined as unknown) as LegacyAPICaller, job).then((messages) => { const ids = messages.map((m) => m.id); expect(ids).toStrictEqual(['influencer_low']); }); @@ -100,7 +109,7 @@ describe('ML - validateInfluencers', () => { it('influencer_high', () => { const job = getJobConfig(['i1', 'i2', 'i3', 'i4']); - return validateInfluencers((undefined as unknown) as APICaller, job).then((messages) => { + return validateInfluencers((undefined as unknown) as LegacyAPICaller, job).then((messages) => { const ids = messages.map((m) => m.id); expect(ids).toStrictEqual(['influencer_high']); }); @@ -118,7 +127,7 @@ describe('ML - validateInfluencers', () => { }, ] ); - return validateInfluencers((undefined as unknown) as APICaller, job).then((messages) => { + return validateInfluencers((undefined as unknown) as LegacyAPICaller, job).then((messages) => { const ids = messages.map((m) => m.id); expect(ids).toStrictEqual(['influencer_low_suggestion']); }); @@ -148,7 +157,7 @@ describe('ML - validateInfluencers', () => { }, ] ); - return validateInfluencers((undefined as unknown) as APICaller, job).then((messages) => { + return validateInfluencers((undefined as unknown) as LegacyAPICaller, job).then((messages) => { expect(messages).toStrictEqual([ { id: 'influencer_low_suggestions', 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 531d4dfdba0c55..1a77bfaf608115 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; @@ -14,7 +14,7 @@ const INFLUENCER_LOW_THRESHOLD = 0; const INFLUENCER_HIGH_THRESHOLD = 4; const DETECTOR_FIELD_NAMES_THRESHOLD = 1; -export async function validateInfluencers(callWithRequest: APICaller, job: CombinedJob) { +export async function validateInfluencers(callWithRequest: LegacyAPICaller, job: CombinedJob) { validateJobObject(job); const messages = []; diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.test.ts b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.test.ts index 581153036fed7c..d9be8e282e9235 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.test.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { CombinedJob, Detector } from '../../../common/types/anomaly_detection_jobs'; import { ModelMemoryEstimate } from '../calculate_model_memory_limit/calculate_model_memory_limit'; import { validateModelMemoryLimit } from './validate_model_memory_limit'; @@ -97,7 +97,7 @@ describe('ML - validateModelMemoryLimit', () => { response = estimateModelMemory || modelMemoryEstimateResponse; } return Promise.resolve(response); - }) as APICaller; + }) as LegacyAPICaller; function getJobConfig(influencers: string[] = [], detectors: Detector[] = []) { return ({ diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.ts b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.ts index 5c3250af6ef468..2c7d1cc23bbaad 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_model_memory_limit.ts @@ -5,7 +5,7 @@ */ import numeral from '@elastic/numeral'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; import { validateJobObject } from './validate_job_object'; import { calculateModelMemoryLimitProvider } from '../calculate_model_memory_limit'; @@ -16,7 +16,7 @@ import { MlInfoResponse } from '../../../common/types/ml_server_info'; const MODEL_MEMORY_LIMIT_MINIMUM_BYTES = 1048576; export async function validateModelMemoryLimit( - callWithRequest: APICaller, + callWithRequest: LegacyAPICaller, job: CombinedJob, duration?: { start?: number; end?: number } ) { diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_time_range.test.ts b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.test.ts index 3ba8701b4bbd2b..d4e1f0cc379fb9 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_time_range.test.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.test.ts @@ -6,7 +6,7 @@ import _ from 'lodash'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; @@ -21,7 +21,7 @@ const mockSearchResponse = { search: mockTimeRange, }; -const callWithRequestFactory = (resp: any): APICaller => { +const callWithRequestFactory = (resp: any): LegacyAPICaller => { return (path: string) => { return new Promise((resolve) => { resolve(resp[path]); diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts index f60ca66b092f91..f47938e059ec04 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/server'; import { parseInterval } from '../../../common/util/parse_interval'; import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; @@ -27,7 +27,7 @@ const BUCKET_SPAN_COMPARE_FACTOR = 25; const MIN_TIME_SPAN_MS = 7200000; const MIN_TIME_SPAN_READABLE = '2 hours'; -export async function isValidTimeField(callAsCurrentUser: APICaller, job: CombinedJob) { +export async function isValidTimeField(callAsCurrentUser: LegacyAPICaller, job: CombinedJob) { const index = job.datafeed_config.indices.join(','); const timeField = job.data_description.time_field; @@ -45,7 +45,7 @@ export async function isValidTimeField(callAsCurrentUser: APICaller, job: Combin } export async function validateTimeRange( - callAsCurrentUser: APICaller, + callAsCurrentUser: LegacyAPICaller, job: CombinedJob, timeRange?: Partial ) { diff --git a/x-pack/plugins/ml/server/models/results_service/results_service.ts b/x-pack/plugins/ml/server/models/results_service/results_service.ts index a985ef7b8f3f58..8255395000f47d 100644 --- a/x-pack/plugins/ml/server/models/results_service/results_service.ts +++ b/x-pack/plugins/ml/server/models/results_service/results_service.ts @@ -7,7 +7,7 @@ import _ from 'lodash'; import moment from 'moment'; import { SearchResponse } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { buildAnomalyTableItems } from './build_anomaly_table_items'; import { ML_RESULTS_INDEX_PATTERN } from '../../../common/constants/index_patterns'; import { ANOMALIES_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search'; @@ -30,7 +30,7 @@ interface Influencer { fieldValue: any; } -export function resultsServiceProvider(callAsCurrentUser: APICaller) { +export function resultsServiceProvider(callAsCurrentUser: LegacyAPICaller) { // Obtains data for the anomalies table, aggregating anomalies by day or hour as requested. // Return an Object with properties 'anomalies' and 'interval' (interval used to aggregate anomalies, // one of day, hour or second. Note 'auto' can be provided as the aggregationInterval in the request, diff --git a/x-pack/plugins/ml/server/plugin.ts b/x-pack/plugins/ml/server/plugin.ts index b167214cc33cfd..3e753627ead937 100644 --- a/x-pack/plugins/ml/server/plugin.ts +++ b/x-pack/plugins/ml/server/plugin.ts @@ -9,11 +9,11 @@ import { CoreSetup, CoreStart, Plugin, - IScopedClusterClient, + ILegacyScopedClusterClient, KibanaRequest, Logger, PluginInitializerContext, - ICustomClusterClient, + ILegacyCustomClusterClient, CapabilitiesStart, } from 'kibana/server'; import { PluginsSetup, RouteInitialization } from './types'; @@ -52,13 +52,13 @@ import { registerKibanaSettings } from './lib/register_settings'; declare module 'kibana/server' { interface RequestHandlerContext { ml?: { - mlClient: IScopedClusterClient; + mlClient: ILegacyScopedClusterClient; }; } } export interface MlPluginSetup extends SharedServices { - mlClient: ICustomClusterClient; + mlClient: ILegacyCustomClusterClient; } export type MlPluginStart = void; diff --git a/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts b/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts index 880aebfde409c3..a2e3ce6569e604 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { LicenseCheck } from '../license_checks'; import { Job } from '../../../common/types/anomaly_detection_jobs'; export interface AnomalyDetectorsProvider { anomalyDetectorsProvider( - callAsCurrentUser: APICaller + callAsCurrentUser: LegacyAPICaller ): { jobs(jobId?: string): Promise<{ count: number; jobs: Job[] }>; }; @@ -18,7 +18,7 @@ export interface AnomalyDetectorsProvider { export function getAnomalyDetectorsProvider(isFullLicense: LicenseCheck): AnomalyDetectorsProvider { return { - anomalyDetectorsProvider(callAsCurrentUser: APICaller) { + anomalyDetectorsProvider(callAsCurrentUser: LegacyAPICaller) { return { jobs(jobId?: string) { isFullLicense(); diff --git a/x-pack/plugins/ml/server/shared_services/providers/job_service.ts b/x-pack/plugins/ml/server/shared_services/providers/job_service.ts index 8dd3f1ca145823..5deb7c3cb75654 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/job_service.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/job_service.ts @@ -4,17 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { LicenseCheck } from '../license_checks'; import { jobServiceProvider } from '../../models/job_service'; export interface JobServiceProvider { - jobServiceProvider(callAsCurrentUser: APICaller): ReturnType; + jobServiceProvider(callAsCurrentUser: LegacyAPICaller): ReturnType; } export function getJobServiceProvider(isFullLicense: LicenseCheck): JobServiceProvider { return { - jobServiceProvider(callAsCurrentUser: APICaller) { + jobServiceProvider(callAsCurrentUser: LegacyAPICaller) { isFullLicense(); return jobServiceProvider(callAsCurrentUser); }, diff --git a/x-pack/plugins/ml/server/shared_services/providers/modules.ts b/x-pack/plugins/ml/server/shared_services/providers/modules.ts index ec876273c2c33e..e5359a0b0f804b 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/modules.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/modules.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, SavedObjectsClientContract } from 'kibana/server'; +import { LegacyAPICaller, SavedObjectsClientContract } from 'kibana/server'; import { LicenseCheck } from '../license_checks'; import { DataRecognizer, RecognizeResult } from '../../models/data_recognizer'; import { @@ -16,7 +16,7 @@ import { export interface ModulesProvider { modulesProvider( - callAsCurrentUser: APICaller, + callAsCurrentUser: LegacyAPICaller, savedObjectsClient: SavedObjectsClientContract ): { recognize(indexPatternTitle: string): Promise; @@ -40,7 +40,10 @@ export interface ModulesProvider { export function getModulesProvider(isFullLicense: LicenseCheck): ModulesProvider { return { - modulesProvider(callAsCurrentUser: APICaller, savedObjectsClient: SavedObjectsClientContract) { + modulesProvider( + callAsCurrentUser: LegacyAPICaller, + savedObjectsClient: SavedObjectsClientContract + ) { isFullLicense(); return { recognize(indexPatternTitle: string) { @@ -91,7 +94,7 @@ export function getModulesProvider(isFullLicense: LicenseCheck): ModulesProvider } function dataRecognizerFactory( - callAsCurrentUser: APICaller, + callAsCurrentUser: LegacyAPICaller, savedObjectsClient: SavedObjectsClientContract ) { return new DataRecognizer(callAsCurrentUser, savedObjectsClient); diff --git a/x-pack/plugins/ml/server/shared_services/providers/results_service.ts b/x-pack/plugins/ml/server/shared_services/providers/results_service.ts index e321713e27d81f..8da25a02278ef5 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/results_service.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/results_service.ts @@ -4,17 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { LicenseCheck } from '../license_checks'; import { resultsServiceProvider } from '../../models/results_service'; export interface ResultsServiceProvider { - resultsServiceProvider(callAsCurrentUser: APICaller): ReturnType; + resultsServiceProvider( + callAsCurrentUser: LegacyAPICaller + ): ReturnType; } export function getResultsServiceProvider(isFullLicense: LicenseCheck): ResultsServiceProvider { return { - resultsServiceProvider(callAsCurrentUser: APICaller) { + resultsServiceProvider(callAsCurrentUser: LegacyAPICaller) { isFullLicense(); return resultsServiceProvider(callAsCurrentUser); }, 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 33a4d854dd3e98..8f1cfbc5c1b631 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/system.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/system.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, KibanaRequest } from 'kibana/server'; +import { LegacyAPICaller, KibanaRequest } from 'kibana/server'; import { SearchResponse, SearchParams } from 'elasticsearch'; import { MlServerLicense } from '../../lib/license'; import { CloudSetup } from '../../../../cloud/server'; @@ -18,7 +18,7 @@ import { MlCapabilitiesResponse, ResolveMlCapabilities } from '../../../common/t export interface MlSystemProvider { mlSystemProvider( - callAsCurrentUser: APICaller, + callAsCurrentUser: LegacyAPICaller, request: KibanaRequest ): { mlCapabilities(): Promise; @@ -36,7 +36,7 @@ export function getMlSystemProvider( resolveMlCapabilities: ResolveMlCapabilities ): MlSystemProvider { return { - mlSystemProvider(callAsCurrentUser: APICaller, request: KibanaRequest) { + mlSystemProvider(callAsCurrentUser: LegacyAPICaller, request: KibanaRequest) { return { async mlCapabilities() { isMinimumLicense(); diff --git a/x-pack/plugins/monitoring/server/alerts/cluster_state.ts b/x-pack/plugins/monitoring/server/alerts/cluster_state.ts index 5b6521179002a0..c357a5878b93a5 100644 --- a/x-pack/plugins/monitoring/server/alerts/cluster_state.ts +++ b/x-pack/plugins/monitoring/server/alerts/cluster_state.ts @@ -6,7 +6,7 @@ import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; -import { Logger, ICustomClusterClient, UiSettingsServiceStart } from 'src/core/server'; +import { Logger, ILegacyCustomClusterClient, UiSettingsServiceStart } from 'src/core/server'; import { ALERT_TYPE_CLUSTER_STATE } from '../../common/constants'; import { AlertType } from '../../../alerts/server'; import { executeActions, getUiMessage } from '../lib/alerts/cluster_state.lib'; @@ -22,7 +22,7 @@ import { fetchClusterState } from '../lib/alerts/fetch_cluster_state'; export const getClusterState = ( getUiSettingsService: () => Promise, - monitoringCluster: ICustomClusterClient, + monitoringCluster: ILegacyCustomClusterClient, getLogger: (...scopes: string[]) => Logger, ccsEnabled: boolean ): AlertType => { diff --git a/x-pack/plugins/monitoring/server/alerts/license_expiration.ts b/x-pack/plugins/monitoring/server/alerts/license_expiration.ts index d57f1a7655b187..277e108e8f0c0a 100644 --- a/x-pack/plugins/monitoring/server/alerts/license_expiration.ts +++ b/x-pack/plugins/monitoring/server/alerts/license_expiration.ts @@ -5,7 +5,7 @@ */ import moment from 'moment-timezone'; -import { Logger, ICustomClusterClient, UiSettingsServiceStart } from 'src/core/server'; +import { Logger, ILegacyCustomClusterClient, UiSettingsServiceStart } from 'src/core/server'; import { i18n } from '@kbn/i18n'; import { ALERT_TYPE_LICENSE_EXPIRATION } from '../../common/constants'; import { AlertType } from '../../../alerts/server'; @@ -24,7 +24,7 @@ const EXPIRES_DAYS = [60, 30, 14, 7]; export const getLicenseExpiration = ( getUiSettingsService: () => Promise, - monitoringCluster: ICustomClusterClient, + monitoringCluster: ILegacyCustomClusterClient, getLogger: (...scopes: string[]) => Logger, ccsEnabled: boolean ): AlertType => { diff --git a/x-pack/plugins/monitoring/server/es_client/instantiate_client.ts b/x-pack/plugins/monitoring/server/es_client/instantiate_client.ts index 5b097220352cfe..d9746853846340 100644 --- a/x-pack/plugins/monitoring/server/es_client/instantiate_client.ts +++ b/x-pack/plugins/monitoring/server/es_client/instantiate_client.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { ConfigOptions } from 'elasticsearch'; -import { Logger, ICustomClusterClient } from 'kibana/server'; +import { Logger, ILegacyCustomClusterClient } from 'kibana/server'; // @ts-ignore import { monitoringBulk } from '../kibana_monitoring/lib/monitoring_bulk'; import { MonitoringElasticsearchConfig } from '../config'; @@ -20,7 +20,10 @@ type ESClusterConfig = MonitoringElasticsearchConfig & Pick) => ICustomClusterClient + createClient: ( + type: string, + clientConfig?: Partial + ) => ILegacyCustomClusterClient ) { const isMonitoringCluster = hasMonitoringCluster(elasticsearchConfig); const cluster = createClient('monitoring', { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts b/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts index cfaaeb36535a01..1d307bc018a7bf 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/get_prepared_alert.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, ICustomClusterClient, UiSettingsServiceStart } from 'kibana/server'; +import { Logger, ILegacyCustomClusterClient, UiSettingsServiceStart } from 'kibana/server'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; import { AlertServices } from '../../../../alerts/server'; import { AlertCommonCluster } from '../../alerts/types'; @@ -23,7 +23,7 @@ export interface PreparedAlert { } async function getCallCluster( - monitoringCluster: ICustomClusterClient, + monitoringCluster: ILegacyCustomClusterClient, services: Pick ): Promise { if (!monitoringCluster) { @@ -36,7 +36,7 @@ async function getCallCluster( export async function getPreparedAlert( alertType: string, getUiSettingsService: () => Promise, - monitoringCluster: ICustomClusterClient, + monitoringCluster: ILegacyCustomClusterClient, logger: Logger, ccsEnabled: boolean, services: Pick, diff --git a/x-pack/plugins/monitoring/server/license_service.ts b/x-pack/plugins/monitoring/server/license_service.ts index 396e8cd566e1fd..7dcdf8897f6a18 100644 --- a/x-pack/plugins/monitoring/server/license_service.ts +++ b/x-pack/plugins/monitoring/server/license_service.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { Subscription } from 'rxjs'; -import { ICustomClusterClient } from 'kibana/server'; +import { ILegacyCustomClusterClient } from 'kibana/server'; import { ILicense, LicenseFeature } from '../../licensing/common/types'; import { LicensingPluginSetup } from '../../licensing/server'; import { MonitoringConfig } from './config'; @@ -13,7 +13,7 @@ import { MonitoringLicenseService } from './types'; interface SetupDeps { licensing: LicensingPluginSetup; - monitoringClient: ICustomClusterClient; + monitoringClient: ILegacyCustomClusterClient; config: MonitoringConfig; log: Logger; } diff --git a/x-pack/plugins/monitoring/server/plugin.ts b/x-pack/plugins/monitoring/server/plugin.ts index 881d0080ab7892..ad2a5b7bb1ce2f 100644 --- a/x-pack/plugins/monitoring/server/plugin.ts +++ b/x-pack/plugins/monitoring/server/plugin.ts @@ -18,10 +18,10 @@ import { KibanaRequest, KibanaResponseFactory, CoreSetup, - ICustomClusterClient, + ILegacyCustomClusterClient, CoreStart, IRouter, - IClusterClient, + ILegacyClusterClient, CustomHttpResponseOptions, ResponseError, } from 'kibana/server'; @@ -83,7 +83,7 @@ interface MonitoringCore { interface LegacyShimDependencies { router: IRouter; instanceUuid: string; - esDataClient: IClusterClient; + esDataClient: ILegacyClusterClient; kibanaStatsCollector: any; } @@ -109,7 +109,7 @@ export class Plugin { private readonly initializerContext: PluginInitializerContext; private readonly log: Logger; private readonly getLogger: (...scopes: string[]) => Logger; - private cluster = {} as ICustomClusterClient; + private cluster = {} as ILegacyCustomClusterClient; private licenseService = {} as MonitoringLicenseService; private monitoringCore = {} as MonitoringCore; private legacyShimDependencies = {} as LegacyShimDependencies; @@ -322,7 +322,7 @@ export class Plugin { legacyConfig: any, getCoreServices: () => Promise<[CoreStart, PluginsStart, {}]>, licenseService: MonitoringLicenseService, - cluster: ICustomClusterClient + cluster: ILegacyCustomClusterClient ): MonitoringCore { const router = this.legacyShimDependencies.router; const legacyConfigWrapper = () => ({ diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts b/x-pack/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts index d81f549de75229..1e5549fe4d8003 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ICustomClusterClient } from 'kibana/server'; +import { ILegacyCustomClusterClient } from 'kibana/server'; import { TelemetryCollectionManagerPluginSetup } from 'src/plugins/telemetry_collection_manager/server'; import { getAllStats, CustomContext } from './get_all_stats'; import { getClusterUuids } from './get_cluster_uuids'; @@ -12,7 +12,7 @@ import { getLicenses } from './get_licenses'; export function registerMonitoringCollection( telemetryCollectionManager: TelemetryCollectionManagerPluginSetup, - esCluster: ICustomClusterClient, + esCluster: ILegacyCustomClusterClient, customContext: CustomContext ) { telemetryCollectionManager.setCollection({ diff --git a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts index 71b1a42b2000d9..1fb5211a71bcdf 100644 --- a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts +++ b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, Logger } from 'kibana/server'; +import { LegacyAPICaller, Logger } from 'kibana/server'; import * as t from 'io-ts'; import { Client } from 'elasticsearch'; import Boom from 'boom'; @@ -40,7 +40,7 @@ interface IndexDocumentResponse { export function createAnnotationsClient(params: { index: string; - apiCaller: APICaller; + apiCaller: LegacyAPICaller; logger: Logger; license?: ILicense; }) { 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 aa12b2227b7d23..1898331451262c 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 @@ * you may not use this file except in compliance with the Elastic License. */ import pRetry from 'p-retry'; -import { Logger, APICaller } from 'src/core/server'; +import { Logger, LegacyAPICaller } from 'src/core/server'; export interface MappingsObject { type: string; @@ -29,7 +29,7 @@ export async function createOrUpdateIndex({ }: { index: string; mappings: MappingsDefinition; - apiCaller: APICaller; + apiCaller: LegacyAPICaller; logger: Logger; }) { try { @@ -79,7 +79,7 @@ function createNewIndex({ mappings, }: { index: string; - apiCaller: APICaller; + apiCaller: LegacyAPICaller; mappings: MappingsDefinition; }) { return apiCaller('indices.create', { @@ -98,7 +98,7 @@ function updateExistingIndex({ mappings, }: { index: string; - apiCaller: APICaller; + apiCaller: LegacyAPICaller; mappings: MappingsDefinition; }) { return apiCaller('indices.putMapping', { diff --git a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts index 5f7f70ee5d62a6..d7a708173d3adc 100644 --- a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts +++ b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.ts @@ -8,7 +8,7 @@ import { Observable } from 'rxjs'; import _, { countBy, groupBy, mapValues } from 'lodash'; import { first } from 'rxjs/operators'; -import { APICaller, IClusterClient } from 'src/core/server'; +import { LegacyAPICaller, ILegacyClusterClient } from 'src/core/server'; import { getNextMidnight } from '../../get_next_midnight'; import { getPastDays } from '../../get_past_days'; import { TaskInstance } from '../../../../../task_manager/server'; @@ -23,7 +23,7 @@ interface VisSummary { /* * Parse the response data into telemetry payload */ -async function getStats(callCluster: APICaller, index: string) { +async function getStats(callCluster: LegacyAPICaller, index: string) { const searchParams = { size: 10000, // elasticsearch index.max_result_window default value index, @@ -85,7 +85,7 @@ async function getStats(callCluster: APICaller, index: string) { export function visualizationsTaskRunner( taskInstance: TaskInstance, config: Observable<{ kibana: { index: string } }>, - esClientPromise: Promise + esClientPromise: Promise ) { return async () => { let stats; diff --git a/x-pack/plugins/oss_telemetry/server/test_utils/index.ts b/x-pack/plugins/oss_telemetry/server/test_utils/index.ts index 5dd7338d278807..4f92c4ab66f9ca 100644 --- a/x-pack/plugins/oss_telemetry/server/test_utils/index.ts +++ b/x-pack/plugins/oss_telemetry/server/test_utils/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { of } from 'rxjs'; import moment from 'moment'; import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; @@ -45,16 +45,20 @@ const defaultMockSavedObjects = [ const defaultMockTaskDocs = [getMockTaskInstance()]; -export const getMockEs = async (mockCallWithInternal: APICaller = getMockCallWithInternal()) => { +export const getMockEs = async ( + mockCallWithInternal: LegacyAPICaller = getMockCallWithInternal() +) => { const client = elasticsearchServiceMock.createClusterClient(); (client.callAsInternalUser as any) = mockCallWithInternal; return client; }; -export const getMockCallWithInternal = (hits: unknown[] = defaultMockSavedObjects): APICaller => { +export const getMockCallWithInternal = ( + hits: unknown[] = defaultMockSavedObjects +): LegacyAPICaller => { return ((() => { return Promise.resolve({ hits: { hits } }); - }) as unknown) as APICaller; + }) as unknown) as LegacyAPICaller; }; export const getMockTaskFetch = ( diff --git a/x-pack/plugins/rollup/server/plugin.ts b/x-pack/plugins/rollup/server/plugin.ts index 0d795ab7dbfe1d..713852b4d73984 100644 --- a/x-pack/plugins/rollup/server/plugin.ts +++ b/x-pack/plugins/rollup/server/plugin.ts @@ -14,13 +14,13 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { CoreSetup, - ICustomClusterClient, + ILegacyCustomClusterClient, Plugin, Logger, KibanaRequest, PluginInitializerContext, - IScopedClusterClient, - APICaller, + ILegacyScopedClusterClient, + LegacyAPICaller, SharedGlobalConfig, } from 'src/core/server'; import { i18n } from '@kbn/i18n'; @@ -41,7 +41,7 @@ import { getCapabilitiesForRollupIndices } from './lib/map_capabilities'; import { mergeCapabilitiesWithFields } from './lib/merge_capabilities_with_fields'; interface RollupContext { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; } async function getCustomEsClient(getStartServices: CoreSetup['getStartServices']) { const [core] = await getStartServices(); @@ -54,7 +54,7 @@ export class RollupPlugin implements Plugin { private readonly logger: Logger; private readonly globalConfig$: Observable; private readonly license: License; - private rollupEsClient?: ICustomClusterClient; + private rollupEsClient?: ILegacyCustomClusterClient; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); @@ -122,8 +122,8 @@ export class RollupPlugin implements Plugin { const callWithRequestFactoryShim = ( elasticsearchServiceShim: CallWithRequestFactoryShim, request: KibanaRequest - ): APICaller => { - return async (...args: Parameters) => { + ): LegacyAPICaller => { + return async (...args: Parameters) => { this.rollupEsClient = this.rollupEsClient ?? (await getCustomEsClient(getStartServices)); return await this.rollupEsClient.asScoped(request).callAsCurrentUser(...args); }; diff --git a/x-pack/plugins/rollup/server/types.ts b/x-pack/plugins/rollup/server/types.ts index 6659ac2b023579..2a7644de764b2f 100644 --- a/x-pack/plugins/rollup/server/types.ts +++ b/x-pack/plugins/rollup/server/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IRouter, APICaller, KibanaRequest } from 'src/core/server'; +import { IRouter, LegacyAPICaller, KibanaRequest } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { VisTypeTimeseriesSetup } from 'src/plugins/vis_type_timeseries/server'; @@ -42,4 +42,4 @@ export interface RouteDependencies { export type CallWithRequestFactoryShim = ( elasticsearchServiceShim: CallWithRequestFactoryShim, request: KibanaRequest -) => APICaller; +) => LegacyAPICaller; diff --git a/x-pack/plugins/security/server/authentication/api_keys.test.ts b/x-pack/plugins/security/server/authentication/api_keys.test.ts index ad55f15545bd9f..0cdd452d459d1f 100644 --- a/x-pack/plugins/security/server/authentication/api_keys.test.ts +++ b/x-pack/plugins/security/server/authentication/api_keys.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, IScopedClusterClient } from '../../../../../src/core/server'; +import { ILegacyClusterClient, ILegacyScopedClusterClient } from '../../../../../src/core/server'; import { SecurityLicense } from '../../common/licensing'; import { APIKeys } from './api_keys'; @@ -19,15 +19,15 @@ const encodeToBase64 = (str: string) => Buffer.from(str).toString('base64'); describe('API Keys', () => { let apiKeys: APIKeys; - let mockClusterClient: jest.Mocked; - let mockScopedClusterClient: jest.Mocked; + let mockClusterClient: jest.Mocked; + let mockScopedClusterClient: jest.Mocked; let mockLicense: jest.Mocked; beforeEach(() => { mockClusterClient = elasticsearchServiceMock.createClusterClient(); mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockClusterClient.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked + (mockScopedClusterClient as unknown) as jest.Mocked ); mockLicense = licenseMock.create(); diff --git a/x-pack/plugins/security/server/authentication/api_keys.ts b/x-pack/plugins/security/server/authentication/api_keys.ts index 29ff7e1f69f955..3b6aee72651e29 100644 --- a/x-pack/plugins/security/server/authentication/api_keys.ts +++ b/x-pack/plugins/security/server/authentication/api_keys.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, KibanaRequest, Logger } from '../../../../../src/core/server'; +import { ILegacyClusterClient, KibanaRequest, Logger } from '../../../../../src/core/server'; import { SecurityLicense } from '../../common/licensing'; import { HTTPAuthorizationHeader } from './http_authentication'; import { BasicHTTPAuthorizationHeaderCredentials } from './http_authentication'; @@ -15,7 +15,7 @@ import { BasicHTTPAuthorizationHeaderCredentials } from './http_authentication'; */ export interface ConstructorOptions { logger: Logger; - clusterClient: IClusterClient; + clusterClient: ILegacyClusterClient; license: SecurityLicense; } @@ -116,7 +116,7 @@ export interface InvalidateAPIKeyResult { */ export class APIKeys { private readonly logger: Logger; - private readonly clusterClient: IClusterClient; + private readonly clusterClient: ILegacyClusterClient; private readonly license: SecurityLicense; constructor({ logger, clusterClient, license }: ConstructorOptions) { diff --git a/x-pack/plugins/security/server/authentication/authenticator.ts b/x-pack/plugins/security/server/authentication/authenticator.ts index e9754daaac646d..c4d44cb2012365 100644 --- a/x-pack/plugins/security/server/authentication/authenticator.ts +++ b/x-pack/plugins/security/server/authentication/authenticator.ts @@ -12,7 +12,7 @@ import { LoggerFactory, Logger, HttpServiceSetup, - IClusterClient, + ILegacyClusterClient, } from '../../../../../src/core/server'; import { SecurityLicense } from '../../common/licensing'; import { AuthenticatedUser } from '../../common/model'; @@ -101,7 +101,7 @@ export interface AuthenticatorOptions { basePath: HttpServiceSetup['basePath']; license: SecurityLicense; loggers: LoggerFactory; - clusterClient: IClusterClient; + clusterClient: ILegacyClusterClient; sessionStorageFactory: SessionStorageFactory; getServerBaseURL: () => string; } diff --git a/x-pack/plugins/security/server/authentication/index.test.ts b/x-pack/plugins/security/server/authentication/index.test.ts index 725659f99c260d..492a781bf4908b 100644 --- a/x-pack/plugins/security/server/authentication/index.test.ts +++ b/x-pack/plugins/security/server/authentication/index.test.ts @@ -24,11 +24,11 @@ import { securityAuditLoggerMock } from '../audit/index.mock'; import { AuthenticationHandler, AuthToolkit, - IClusterClient, + ILegacyClusterClient, CoreSetup, KibanaRequest, LoggerFactory, - ScopedClusterClient, + LegacyScopedClusterClient, } from '../../../../../src/core/server'; import { AuthenticatedUser } from '../../common/model'; import { ConfigSchema, ConfigType, createConfig } from '../config'; @@ -51,11 +51,11 @@ describe('setupAuthentication()', () => { config: ConfigType; loggers: LoggerFactory; http: jest.Mocked; - clusterClient: jest.Mocked; + clusterClient: jest.Mocked; license: jest.Mocked; getFeatureUsageService: () => jest.Mocked; }; - let mockScopedClusterClient: jest.Mocked>; + let mockScopedClusterClient: jest.Mocked>; beforeEach(() => { mockSetupAuthenticationParams = { auditLogger: securityAuditLoggerMock.create(), @@ -79,7 +79,7 @@ describe('setupAuthentication()', () => { mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockSetupAuthenticationParams.clusterClient.asScoped.mockReturnValue( - (mockScopedClusterClient as unknown) as jest.Mocked + (mockScopedClusterClient as unknown) as jest.Mocked ); }); diff --git a/x-pack/plugins/security/server/authentication/index.ts b/x-pack/plugins/security/server/authentication/index.ts index c2321b0d3c8744..02d8a6621e6bc8 100644 --- a/x-pack/plugins/security/server/authentication/index.ts +++ b/x-pack/plugins/security/server/authentication/index.ts @@ -5,7 +5,7 @@ */ import { UnwrapPromise } from '@kbn/utility-types'; import { - IClusterClient, + ILegacyClusterClient, CoreSetup, KibanaRequest, LoggerFactory, @@ -40,7 +40,7 @@ interface SetupAuthenticationParams { auditLogger: SecurityAuditLogger; getFeatureUsageService: () => SecurityFeatureUsageServiceStart; http: CoreSetup['http']; - clusterClient: IClusterClient; + clusterClient: ILegacyClusterClient; config: ConfigType; license: SecurityLicense; loggers: LoggerFactory; diff --git a/x-pack/plugins/security/server/authentication/providers/base.ts b/x-pack/plugins/security/server/authentication/providers/base.ts index de9f0e891bd393..1370b0f0ed5292 100644 --- a/x-pack/plugins/security/server/authentication/providers/base.ts +++ b/x-pack/plugins/security/server/authentication/providers/base.ts @@ -8,7 +8,7 @@ import { KibanaRequest, Logger, HttpServiceSetup, - IClusterClient, + ILegacyClusterClient, Headers, } from '../../../../../../src/core/server'; import { deepFreeze } from '../../../../../../src/core/server'; @@ -24,7 +24,7 @@ export interface AuthenticationProviderOptions { name: string; getServerBaseURL: () => string; basePath: HttpServiceSetup['basePath']; - client: IClusterClient; + client: ILegacyClusterClient; logger: Logger; tokens: PublicMethodsOf; urls: { diff --git a/x-pack/plugins/security/server/authentication/providers/basic.test.ts b/x-pack/plugins/security/server/authentication/providers/basic.test.ts index ee6a12e36df05f..95de8ca9d00e71 100644 --- a/x-pack/plugins/security/server/authentication/providers/basic.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/basic.test.ts @@ -8,7 +8,7 @@ import { elasticsearchServiceMock, httpServerMock } from '../../../../../../src/ import { mockAuthenticatedUser } from '../../../common/model/authenticated_user.mock'; import { mockAuthenticationProviderOptions } from './base.mock'; -import { IClusterClient, ScopeableRequest } from '../../../../../../src/core/server'; +import { ILegacyClusterClient, ScopeableRequest } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; import { BasicAuthenticationProvider } from './basic'; @@ -18,7 +18,7 @@ function generateAuthorizationHeader(username: string, password: string) { } function expectAuthenticateCall( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, scopeableRequest: ScopeableRequest ) { expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security/server/authentication/providers/http.test.ts b/x-pack/plugins/security/server/authentication/providers/http.test.ts index 47715670e4697a..e6949269e3fc75 100644 --- a/x-pack/plugins/security/server/authentication/providers/http.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/http.test.ts @@ -9,8 +9,8 @@ import { mockAuthenticatedUser } from '../../../common/model/authenticated_user. import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; import { - ElasticsearchErrorHelpers, - IClusterClient, + LegacyElasticsearchErrorHelpers, + ILegacyClusterClient, ScopeableRequest, } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; @@ -18,7 +18,7 @@ import { DeauthenticationResult } from '../deauthentication_result'; import { HTTPAuthenticationProvider } from './http'; function expectAuthenticateCall( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, scopeableRequest: ScopeableRequest ) { expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); @@ -146,7 +146,7 @@ describe('HTTPAuthenticationProvider', () => { }); it('fails if authentication via `authorization` header with supported scheme fails.', async () => { - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); for (const { schemes, header } of [ { schemes: ['basic'], header: 'Basic xxx' }, { schemes: ['bearer'], header: 'Bearer xxx' }, diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts index ebf1341127e5f0..c00374efd59b47 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.test.ts @@ -12,8 +12,8 @@ import { mockAuthenticatedUser } from '../../../common/model/authenticated_user. import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; import { - ElasticsearchErrorHelpers, - IClusterClient, + LegacyElasticsearchErrorHelpers, + ILegacyClusterClient, KibanaRequest, ScopeableRequest, } from '../../../../../../src/core/server'; @@ -22,7 +22,7 @@ import { DeauthenticationResult } from '../deauthentication_result'; import { KerberosAuthenticationProvider } from './kerberos'; function expectAuthenticateCall( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, scopeableRequest: ScopeableRequest ) { expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); @@ -63,7 +63,7 @@ describe('KerberosAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -77,7 +77,7 @@ describe('KerberosAuthenticationProvider', () => { it('fails with `Negotiate` challenge if backend supports Kerberos.', async () => { const request = httpServerMock.createKibanaRequest({ headers: {} }); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new (errors.AuthenticationException as any)('Unauthorized', { body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, }) @@ -189,7 +189,7 @@ describe('KerberosAuthenticationProvider', () => { headers: { authorization: 'negotiate spnego' }, }); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new (errors.AuthenticationException as any)('Unauthorized', { body: { error: { header: { 'WWW-Authenticate': 'Negotiate response-token' } } }, }) @@ -214,7 +214,7 @@ describe('KerberosAuthenticationProvider', () => { headers: { authorization: 'negotiate spnego' }, }); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new (errors.AuthenticationException as any)('Unauthorized', { body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, }) @@ -239,7 +239,7 @@ describe('KerberosAuthenticationProvider', () => { headers: { authorization: 'negotiate spnego' }, }); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); await expect(operation(request)).resolves.toEqual(AuthenticationResult.failed(failureReason)); @@ -256,7 +256,7 @@ describe('KerberosAuthenticationProvider', () => { headers: { authorization: 'negotiate spnego' }, }); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -322,7 +322,7 @@ describe('KerberosAuthenticationProvider', () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'token', refreshToken: 'refresh-token' }; - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -380,7 +380,7 @@ describe('KerberosAuthenticationProvider', () => { if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); return mockScopedClusterClient; } @@ -445,7 +445,7 @@ describe('KerberosAuthenticationProvider', () => { const request = httpServerMock.createKibanaRequest(); const tokenPair = { accessToken: 'expired-token', refreshToken: 'some-valid-refresh-token' }; - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new (errors.AuthenticationException as any)('Unauthorized', { body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, }) @@ -470,7 +470,7 @@ describe('KerberosAuthenticationProvider', () => { const request = httpServerMock.createKibanaRequest({ routeAuthRequired: false }); const tokenPair = { accessToken: 'expired-token', refreshToken: 'some-valid-refresh-token' }; - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError( + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError( new (errors.AuthenticationException as any)('Unauthorized', { body: { error: { header: { 'WWW-Authenticate': 'Negotiate' } } }, }) diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.ts index 66a0ce22d3d19f..44919fae9ced8f 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.ts @@ -6,8 +6,8 @@ import Boom from 'boom'; import { - ElasticsearchError, - ElasticsearchErrorHelpers, + LegacyElasticsearchError, + LegacyElasticsearchErrorHelpers, KibanaRequest, } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; @@ -149,7 +149,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { this.logger.debug(`Failed to exchange SPNEGO token for an access token: ${err.message}`); // Check if SPNEGO context wasn't established and we have a response token to return to the client. - const challenge = ElasticsearchErrorHelpers.isNotAuthorizedError(err) + const challenge = LegacyElasticsearchErrorHelpers.isNotAuthorizedError(err) ? this.getNegotiateChallenge(err) : undefined; if (!challenge) { @@ -294,7 +294,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { this.logger.debug('Trying to authenticate request via SPNEGO.'); // Try to authenticate current request with Elasticsearch to see whether it supports SPNEGO. - let elasticsearchError: ElasticsearchError; + let elasticsearchError: LegacyElasticsearchError; try { await this.getUser(request, { // We should send a fake SPNEGO token to Elasticsearch to make sure Kerberos realm is included @@ -308,7 +308,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { } catch (err) { // Fail immediately if we get unexpected error (e.g. ES isn't available). We should not touch // session cookie in this case. - if (!ElasticsearchErrorHelpers.isNotAuthorizedError(err)) { + if (!LegacyElasticsearchErrorHelpers.isNotAuthorizedError(err)) { return AuthenticationResult.failed(err); } @@ -334,7 +334,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { * Extracts `Negotiate` challenge from the list of challenges returned with Elasticsearch error if any. * @param error Error to extract challenges from. */ - private getNegotiateChallenge(error: ElasticsearchError) { + private getNegotiateChallenge(error: LegacyElasticsearchError) { const challenges = ([] as string[]).concat(error.output.headers[WWWAuthenticateHeaderName]); const negotiateChallenge = challenges.find((challenge) => diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts index 74344e8ae3edad..d787e76628d6db 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.test.ts @@ -11,8 +11,8 @@ import { mockAuthenticatedUser } from '../../../common/model/authenticated_user. import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; import { - ElasticsearchErrorHelpers, - IClusterClient, + LegacyElasticsearchErrorHelpers, + ILegacyClusterClient, KibanaRequest, ScopeableRequest, } from '../../../../../../src/core/server'; @@ -21,7 +21,7 @@ import { DeauthenticationResult } from '../deauthentication_result'; import { OIDCAuthenticationProvider, OIDCLogin, ProviderLoginAttempt } from './oidc'; function expectAuthenticateCall( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, scopeableRequest: ScopeableRequest ) { expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); @@ -468,7 +468,7 @@ describe('OIDCAuthenticationProvider', () => { if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); return mockScopedClusterClient; } @@ -516,7 +516,7 @@ describe('OIDCAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -556,7 +556,7 @@ describe('OIDCAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -604,7 +604,7 @@ describe('OIDCAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -633,7 +633,7 @@ describe('OIDCAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); diff --git a/x-pack/plugins/security/server/authentication/providers/pki.test.ts b/x-pack/plugins/security/server/authentication/providers/pki.test.ts index a1279c9b9ca7f8..fd014e1a7cb814 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.test.ts @@ -17,8 +17,8 @@ import { mockAuthenticatedUser } from '../../../common/model/authenticated_user. import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; import { - ElasticsearchErrorHelpers, - IClusterClient, + LegacyElasticsearchErrorHelpers, + ILegacyClusterClient, KibanaRequest, ScopeableRequest, } from '../../../../../../src/core/server'; @@ -64,7 +64,7 @@ function getMockSocket({ } function expectAuthenticateCall( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, scopeableRequest: ScopeableRequest ) { expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); @@ -197,7 +197,7 @@ describe('PKIAuthenticationProvider', () => { }), }); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); mockOptions.client.callAsInternalUser.mockRejectedValue(failureReason); await expect(operation(request)).resolves.toEqual(AuthenticationResult.failed(failureReason)); @@ -219,7 +219,7 @@ describe('PKIAuthenticationProvider', () => { }), }); - const failureReason = ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); + const failureReason = LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()); const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue(failureReason); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -395,7 +395,9 @@ describe('PKIAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser // In response to call with an expired token. - .mockRejectedValueOnce(ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error())) + .mockRejectedValueOnce( + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + ) // In response to a call with a new token. .mockResolvedValueOnce(user); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -436,7 +438,7 @@ describe('PKIAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValueOnce( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -454,7 +456,7 @@ describe('PKIAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); diff --git a/x-pack/plugins/security/server/authentication/providers/saml.test.ts b/x-pack/plugins/security/server/authentication/providers/saml.test.ts index 364564326af964..50770c93134e47 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.test.ts @@ -12,8 +12,8 @@ import { mockAuthenticatedUser } from '../../../common/model/authenticated_user. import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; import { - ElasticsearchErrorHelpers, - IClusterClient, + LegacyElasticsearchErrorHelpers, + ILegacyClusterClient, ScopeableRequest, } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; @@ -21,7 +21,7 @@ import { DeauthenticationResult } from '../deauthentication_result'; import { SAMLAuthenticationProvider, SAMLLogin } from './saml'; function expectAuthenticateCall( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, scopeableRequest: ScopeableRequest ) { expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); @@ -615,7 +615,7 @@ describe('SAMLAuthenticationProvider', () => { ], [ 'session is is expired', - Promise.reject(ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error())), + Promise.reject(LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error())), ], ] as Array<[string, Promise]>) { it(`redirects to the home page if new SAML Response is for the same user if ${description}.`, async () => { @@ -1342,7 +1342,7 @@ describe('SAMLAuthenticationProvider', () => { if (scopeableRequest?.headers.authorization === `Bearer ${state.accessToken}`) { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); return mockScopedClusterClient; } @@ -1394,7 +1394,7 @@ describe('SAMLAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -1428,7 +1428,7 @@ describe('SAMLAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -1460,7 +1460,7 @@ describe('SAMLAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -1492,7 +1492,7 @@ describe('SAMLAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -1534,7 +1534,7 @@ describe('SAMLAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); diff --git a/x-pack/plugins/security/server/authentication/providers/token.test.ts b/x-pack/plugins/security/server/authentication/providers/token.test.ts index 84ff7d1f5a1ef7..ba0f23a3393ae6 100644 --- a/x-pack/plugins/security/server/authentication/providers/token.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/token.test.ts @@ -12,8 +12,8 @@ import { mockAuthenticatedUser } from '../../../common/model/authenticated_user. import { MockAuthenticationProviderOptions, mockAuthenticationProviderOptions } from './base.mock'; import { - ElasticsearchErrorHelpers, - IClusterClient, + LegacyElasticsearchErrorHelpers, + ILegacyClusterClient, ScopeableRequest, } from '../../../../../../src/core/server'; import { AuthenticationResult } from '../authentication_result'; @@ -21,7 +21,7 @@ import { DeauthenticationResult } from '../deauthentication_result'; import { TokenAuthenticationProvider } from './token'; function expectAuthenticateCall( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, scopeableRequest: ScopeableRequest ) { expect(mockClusterClient.asScoped).toHaveBeenCalledTimes(1); @@ -215,7 +215,7 @@ describe('TokenAuthenticationProvider', () => { if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); return mockScopedClusterClient; } @@ -276,7 +276,7 @@ describe('TokenAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -302,7 +302,7 @@ describe('TokenAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -333,7 +333,7 @@ describe('TokenAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -364,7 +364,7 @@ describe('TokenAuthenticationProvider', () => { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); mockOptions.client.asScoped.mockReturnValue(mockScopedClusterClient); @@ -391,7 +391,7 @@ describe('TokenAuthenticationProvider', () => { if (scopeableRequest?.headers.authorization === `Bearer ${tokenPair.accessToken}`) { const mockScopedClusterClient = elasticsearchServiceMock.createScopedClusterClient(); mockScopedClusterClient.callAsCurrentUser.mockRejectedValue( - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()) ); return mockScopedClusterClient; } diff --git a/x-pack/plugins/security/server/authentication/tokens.test.ts b/x-pack/plugins/security/server/authentication/tokens.test.ts index b42018b93e73fd..8ad04672fdfade 100644 --- a/x-pack/plugins/security/server/authentication/tokens.test.ts +++ b/x-pack/plugins/security/server/authentication/tokens.test.ts @@ -8,12 +8,15 @@ import { errors } from 'elasticsearch'; import { elasticsearchServiceMock, loggingSystemMock } from '../../../../../src/core/server/mocks'; -import { IClusterClient, ElasticsearchErrorHelpers } from '../../../../../src/core/server'; +import { + ILegacyClusterClient, + LegacyElasticsearchErrorHelpers, +} from '../../../../../src/core/server'; import { Tokens } from './tokens'; describe('Tokens', () => { let tokens: Tokens; - let mockClusterClient: jest.Mocked; + let mockClusterClient: jest.Mocked; beforeEach(() => { mockClusterClient = elasticsearchServiceMock.createClusterClient(); @@ -39,7 +42,7 @@ describe('Tokens', () => { const expirationErrors = [ { statusCode: 401 }, - ElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()), + LegacyElasticsearchErrorHelpers.decorateNotAuthorizedError(new Error()), new errors.AuthenticationException(), ]; for (const error of expirationErrors) { diff --git a/x-pack/plugins/security/server/authentication/tokens.ts b/x-pack/plugins/security/server/authentication/tokens.ts index 9117c9a679a4a2..3918b0b190a154 100644 --- a/x-pack/plugins/security/server/authentication/tokens.ts +++ b/x-pack/plugins/security/server/authentication/tokens.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, Logger } from '../../../../../src/core/server'; +import { ILegacyClusterClient, Logger } from '../../../../../src/core/server'; import { getErrorStatusCode } from '../errors'; /** @@ -34,7 +34,9 @@ export class Tokens { */ private readonly logger: Logger; - constructor(private readonly options: Readonly<{ client: IClusterClient; logger: Logger }>) { + constructor( + private readonly options: Readonly<{ client: ILegacyClusterClient; logger: Logger }> + ) { this.logger = options.logger; } diff --git a/x-pack/plugins/security/server/authorization/authorization_service.ts b/x-pack/plugins/security/server/authorization/authorization_service.ts index 989784a1436d26..cae273ecac3383 100644 --- a/x-pack/plugins/security/server/authorization/authorization_service.ts +++ b/x-pack/plugins/security/server/authorization/authorization_service.ts @@ -10,7 +10,7 @@ import { UICapabilities } from 'ui/capabilities'; import { LoggerFactory, KibanaRequest, - IClusterClient, + ILegacyClusterClient, ServiceStatusLevels, Logger, StatusServiceSetup, @@ -54,7 +54,7 @@ interface AuthorizationServiceSetupParams { http: HttpServiceSetup; status: StatusServiceSetup; capabilities: CapabilitiesSetup; - clusterClient: IClusterClient; + clusterClient: ILegacyClusterClient; license: SecurityLicense; loggers: LoggerFactory; features: FeaturesPluginSetup; @@ -64,7 +64,7 @@ interface AuthorizationServiceSetupParams { interface AuthorizationServiceStartParams { features: FeaturesPluginStart; - clusterClient: IClusterClient; + clusterClient: ILegacyClusterClient; } export interface AuthorizationServiceSetup { @@ -173,7 +173,7 @@ export class AuthorizationService { } } - private registerPrivileges(clusterClient: IClusterClient) { + private registerPrivileges(clusterClient: ILegacyClusterClient) { const RETRY_SCALE_DURATION = 100; const RETRY_TIMEOUT_MAX = 10000; const retries$ = new BehaviorSubject(0); diff --git a/x-pack/plugins/security/server/authorization/check_privileges.ts b/x-pack/plugins/security/server/authorization/check_privileges.ts index 44e9438bd07f5c..3129777a7881f6 100644 --- a/x-pack/plugins/security/server/authorization/check_privileges.ts +++ b/x-pack/plugins/security/server/authorization/check_privileges.ts @@ -5,7 +5,7 @@ */ import { pick, transform, uniq } from 'lodash'; -import { IClusterClient, KibanaRequest } from '../../../../../src/core/server'; +import { ILegacyClusterClient, KibanaRequest } from '../../../../../src/core/server'; import { GLOBAL_RESOURCE } from '../../common/constants'; import { ResourceSerializer } from './resource_serializer'; import { HasPrivilegesResponse, HasPrivilegesResponseApplication } from './types'; @@ -45,7 +45,7 @@ export interface CheckPrivileges { export function checkPrivilegesWithRequestFactory( actions: CheckPrivilegesActions, - clusterClient: IClusterClient, + clusterClient: ILegacyClusterClient, applicationName: string ) { const hasIncompatibleVersion = ( diff --git a/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.test.ts b/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.test.ts index 8604e02b632766..0ce7eae932feae 100644 --- a/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.test.ts +++ b/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, Logger } from 'kibana/server'; +import { ILegacyClusterClient, Logger } from 'kibana/server'; import { RawKibanaPrivileges } from '../../common/model'; import { registerPrivilegesWithCluster } from './register_privileges_with_cluster'; @@ -32,7 +32,7 @@ const registerPrivilegesWithClusterTest = ( } ) => { const createExpectUpdatedPrivileges = ( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, mockLogger: jest.Mocked, error: Error ) => { @@ -67,7 +67,7 @@ const registerPrivilegesWithClusterTest = ( }; const createExpectDidntUpdatePrivileges = ( - mockClusterClient: jest.Mocked, + mockClusterClient: jest.Mocked, mockLogger: Logger, error: Error ) => { diff --git a/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.ts b/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.ts index 8e54794494a908..448b7b7e7ef484 100644 --- a/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.ts +++ b/x-pack/plugins/security/server/authorization/register_privileges_with_cluster.ts @@ -5,7 +5,7 @@ */ import { isEqual, difference } from 'lodash'; -import { IClusterClient, Logger } from '../../../../../src/core/server'; +import { ILegacyClusterClient, Logger } from '../../../../../src/core/server'; import { serializePrivileges } from './privileges_serializer'; import { PrivilegesService } from './privileges'; @@ -14,7 +14,7 @@ export async function registerPrivilegesWithCluster( logger: Logger, privileges: PrivilegesService, application: string, - clusterClient: IClusterClient + clusterClient: ILegacyClusterClient ) { const arePrivilegesEqual = ( existingPrivileges: Record, diff --git a/x-pack/plugins/security/server/plugin.test.ts b/x-pack/plugins/security/server/plugin.test.ts index 627d1408673be5..64af6fc857273d 100644 --- a/x-pack/plugins/security/server/plugin.test.ts +++ b/x-pack/plugins/security/server/plugin.test.ts @@ -6,7 +6,7 @@ import { of } from 'rxjs'; import { ByteSizeValue } from '@kbn/config-schema'; -import { ICustomClusterClient } from '../../../../src/core/server'; +import { ILegacyCustomClusterClient } from '../../../../src/core/server'; import { elasticsearchClientPlugin } from './elasticsearch_client_plugin'; import { Plugin, PluginSetupDependencies } from './plugin'; @@ -15,7 +15,7 @@ import { coreMock, elasticsearchServiceMock } from '../../../../src/core/server/ describe('Security Plugin', () => { let plugin: Plugin; let mockCoreSetup: ReturnType; - let mockClusterClient: jest.Mocked; + let mockClusterClient: jest.Mocked; let mockDependencies: PluginSetupDependencies; beforeEach(() => { plugin = new Plugin( diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index a14617c8489ccb..c4b16c9eec8729 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -9,7 +9,7 @@ import { first, map } from 'rxjs/operators'; import { TypeOf } from '@kbn/config-schema'; import { deepFreeze, - ICustomClusterClient, + ILegacyCustomClusterClient, CoreSetup, CoreStart, Logger, @@ -81,7 +81,7 @@ export interface PluginStartDependencies { */ export class Plugin { private readonly logger: Logger; - private clusterClient?: ICustomClusterClient; + private clusterClient?: ILegacyCustomClusterClient; private spacesService?: SpacesService | symbol = Symbol('not accessed'); private securityLicenseService?: SecurityLicenseService; diff --git a/x-pack/plugins/security/server/routes/index.ts b/x-pack/plugins/security/server/routes/index.ts index 5721a2699d15ce..82c0186898d383 100644 --- a/x-pack/plugins/security/server/routes/index.ts +++ b/x-pack/plugins/security/server/routes/index.ts @@ -8,7 +8,7 @@ import { Feature } from '../../../features/server'; import { CoreSetup, HttpResources, - IClusterClient, + ILegacyClusterClient, IRouter, Logger, } from '../../../../../src/core/server'; @@ -34,7 +34,7 @@ export interface RouteDefinitionParams { basePath: CoreSetup['http']['basePath']; httpResources: HttpResources; logger: Logger; - clusterClient: IClusterClient; + clusterClient: ILegacyClusterClient; config: ConfigType; authc: Authentication; authz: AuthorizationServiceSetup; diff --git a/x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts b/x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts index 4fde93d0ad8596..8070b3371fcb38 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts +++ b/x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts @@ -9,7 +9,7 @@ import { elasticsearchServiceMock, httpServerMock } from 'src/core/server/mocks' import { kibanaResponseFactory, RequestHandlerContext, - IClusterClient, + ILegacyClusterClient, } from '../../../../../../src/core/server'; import { LicenseCheck } from '../../../../licensing/server'; import { defineRoleMappingFeatureCheckRoute } from './feature_check'; @@ -19,7 +19,7 @@ interface TestOptions { canManageRoleMappings?: boolean; nodeSettingsResponse?: Record; xpackUsageResponse?: Record; - internalUserClusterClientImpl?: IClusterClient['callAsInternalUser']; + internalUserClusterClientImpl?: ILegacyClusterClient['callAsInternalUser']; asserts: { statusCode: number; result?: Record }; } diff --git a/x-pack/plugins/security/server/routes/role_mapping/feature_check.ts b/x-pack/plugins/security/server/routes/role_mapping/feature_check.ts index b056d9e358737d..88c7f193cea34b 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/feature_check.ts +++ b/x-pack/plugins/security/server/routes/role_mapping/feature_check.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Logger, IClusterClient } from 'src/core/server'; +import { Logger, ILegacyClusterClient } from 'src/core/server'; import { createLicensedRouteHandler } from '../licensed_route_handler'; import { RouteDefinitionParams } from '..'; @@ -73,7 +73,7 @@ export function defineRoleMappingFeatureCheckRoute({ ); } -async function getEnabledRoleMappingsFeatures(clusterClient: IClusterClient, logger: Logger) { +async function getEnabledRoleMappingsFeatures(clusterClient: ILegacyClusterClient, logger: Logger) { logger.debug(`Retrieving role mappings features`); const nodeScriptSettingsPromise: Promise = clusterClient diff --git a/x-pack/plugins/security/server/routes/users/change_password.test.ts b/x-pack/plugins/security/server/routes/users/change_password.test.ts index c163ff4e256cd2..721c020c7431b5 100644 --- a/x-pack/plugins/security/server/routes/users/change_password.test.ts +++ b/x-pack/plugins/security/server/routes/users/change_password.test.ts @@ -7,9 +7,9 @@ import { errors } from 'elasticsearch'; import { ObjectType } from '@kbn/config-schema'; import { - IClusterClient, + ILegacyClusterClient, IRouter, - IScopedClusterClient, + ILegacyScopedClusterClient, kibanaResponseFactory, RequestHandler, RequestHandlerContext, @@ -26,8 +26,8 @@ import { routeDefinitionParamsMock } from '../index.mock'; describe('Change password', () => { let router: jest.Mocked; let authc: jest.Mocked; - let mockClusterClient: jest.Mocked; - let mockScopedClusterClient: jest.Mocked; + let mockClusterClient: jest.Mocked; + let mockScopedClusterClient: jest.Mocked; let routeHandler: RequestHandler; let routeConfig: RouteConfig; let mockContext: RequestHandlerContext; diff --git a/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/alerts.test.ts b/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/alerts.test.ts index 6c0ff9fcdc66f7..24af9917186ba7 100644 --- a/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/alerts.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/alerts.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, IRouter, IScopedClusterClient } from 'kibana/server'; +import { ILegacyClusterClient, IRouter, ILegacyScopedClusterClient } from 'kibana/server'; import { elasticsearchServiceMock, httpServiceMock, @@ -17,8 +17,8 @@ import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__ describe('test alerts route', () => { let routerMock: jest.Mocked; - let mockClusterClient: jest.Mocked; - let mockScopedClient: jest.Mocked; + let mockClusterClient: jest.Mocked; + let mockScopedClient: jest.Mocked; let endpointAppContextService: EndpointAppContextService; beforeEach(() => { diff --git a/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts b/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts index e398e70f1d7b7b..e5bcc9bcfdc061 100644 --- a/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { SearchResponse } from 'elasticsearch'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { AlertEvent } from '../../../../../common/endpoint/types'; import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; import { esQuery } from '../../../../../../../../src/plugins/data/server'; @@ -145,7 +145,7 @@ const buildAlertSearchQuery = async ( * Makes a request to Elasticsearch, given an `AlertSearchRequestWrapper`. **/ export const searchESForAlerts = async ( - dataClient: IScopedClusterClient, + dataClient: ILegacyScopedClusterClient, query: AlertSearchQuery, indexPattern: string ): Promise> => { diff --git a/x-pack/plugins/security_solution/server/endpoint/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/mocks.ts index aca8a4e0ce78f6..84f3d1a5631bfc 100644 --- a/x-pack/plugins/security_solution/server/endpoint/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/mocks.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient, SavedObjectsClientContract } from 'kibana/server'; +import { ILegacyScopedClusterClient, SavedObjectsClientContract } from 'kibana/server'; import { xpackMocks } from '../../../../mocks'; import { AgentService, @@ -62,7 +62,7 @@ export const createMockIngestManagerStartContract = ( }; export function createRouteHandlerContext( - dataClient: jest.Mocked, + dataClient: jest.Mocked, savedObjectsClient: jest.Mocked ) { const context = xpackMocks.createRequestHandlerContext(); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts index 1ca205f669fa37..f6ae2c584a3466 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ import { - IClusterClient, + ILegacyClusterClient, IRouter, - IScopedClusterClient, + ILegacyScopedClusterClient, KibanaResponseFactory, RequestHandler, RouteConfig, @@ -40,8 +40,8 @@ import { HostId } from './support/unenroll'; describe('test endpoint route', () => { let routerMock: jest.Mocked; let mockResponse: jest.Mocked; - let mockClusterClient: jest.Mocked; - let mockScopedClient: jest.Mocked; + let mockClusterClient: jest.Mocked; + let mockScopedClient: jest.Mocked; let mockSavedObjectClient: jest.Mocked; // eslint-disable-next-line @typescript-eslint/no-explicit-any let routeHandler: RequestHandler; @@ -60,7 +60,7 @@ describe('test endpoint route', () => { beforeEach(() => { mockClusterClient = elasticsearchServiceMock.createClusterClient() as jest.Mocked< - IClusterClient + ILegacyClusterClient >; mockScopedClient = elasticsearchServiceMock.createScopedClusterClient(); mockSavedObjectClient = savedObjectsClientMock.create(); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts index 2e6bb2c976fef1..545095a6a0c16f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { findAllUnenrolledHostIds, fetchAllUnenrolledHostIdsWithScroll, @@ -24,7 +24,7 @@ const noUnenrolledEndpoint = () => } as unknown) as SearchResponse); describe('test find all unenrolled HostId', () => { - let mockScopedClient: jest.Mocked; + let mockScopedClient: jest.Mocked; it('can find all hits with scroll', async () => { const firstHostId = '1fdca33f-799f-49f4-939c-ea4383c77671'; @@ -82,7 +82,7 @@ describe('test find all unenrolled HostId', () => { }); describe('test find unenrolled endpoint host id by hostId', () => { - let mockScopedClient: jest.Mocked; + let mockScopedClient: jest.Mocked; it('can find unenrolled endpoint by the host id when unenrolled', async () => { const firstEndpointHostId = '1fdca33f-799f-49f4-939c-ea4383c77671'; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts index ef6898fad2807d..332f969ddf7e59 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/unenroll.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, IScopedClusterClient } from 'kibana/server'; +import { LegacyAPICaller, ILegacyScopedClusterClient } from 'kibana/server'; import { SearchResponse } from 'elasticsearch'; import { metadataMirrorIndexPattern } from '../../../../../common/endpoint/constants'; import { EndpointStatus } from '../../../../../common/endpoint/types'; @@ -23,7 +23,7 @@ interface HitSource { } export async function findUnenrolledHostByHostId( - client: IScopedClusterClient, + client: ILegacyScopedClusterClient, hostId: string ): Promise { const queryParams = { @@ -63,7 +63,9 @@ export async function findUnenrolledHostByHostId( } } -export async function findAllUnenrolledHostIds(client: IScopedClusterClient): Promise { +export async function findAllUnenrolledHostIds( + client: ILegacyScopedClusterClient +): Promise { const queryParams = { index: metadataMirrorIndexPattern, scroll: KEEPALIVE, @@ -90,7 +92,7 @@ export async function findAllUnenrolledHostIds(client: IScopedClusterClient): Pr export async function fetchAllUnenrolledHostIdsWithScroll( response: SearchResponse, - client: APICaller, + client: LegacyAPICaller, hits: HostId[] = [] ): Promise { let newHits = response.hits?.hits || []; 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 16af3a95bc72da..0578f795f4a4e5 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 @@ -10,7 +10,7 @@ import { } from '../../mocks'; import { getHostPolicyResponseHandler } from './handlers'; import { - IScopedClusterClient, + ILegacyScopedClusterClient, KibanaResponseFactory, SavedObjectsClientContract, } from 'kibana/server'; @@ -27,7 +27,7 @@ import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__ describe('test policy response handler', () => { let endpointAppContextService: EndpointAppContextService; - let mockScopedClient: jest.Mocked; + let mockScopedClient: jest.Mocked; let mockSavedObjectClient: jest.Mocked; let mockResponse: jest.Mocked; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts index 5e3c3537ec591c..703c46b05f7660 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts @@ -5,7 +5,7 @@ */ import { SearchResponse } from 'elasticsearch'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { GetHostPolicyResponse, HostPolicyResponse } from '../../../../common/endpoint/types'; export function getESQueryPolicyResponseByHostID(hostID: string, index: string) { @@ -32,7 +32,7 @@ export function getESQueryPolicyResponseByHostID(hostID: string, index: string) export async function getPolicyResponseByHostId( index: string, hostId: string, - dataClient: IScopedClusterClient + dataClient: ILegacyScopedClusterClient ): Promise { const query = getESQueryPolicyResponseByHostID(hostId, index); const response = (await dataClient.callAsCurrentUser('search', query)) as SearchResponse< diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts index 025d3a9420634c..35f8cad01e6720 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts @@ -5,7 +5,7 @@ */ import { SearchResponse } from 'elasticsearch'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { ResolverEvent } from '../../../../../common/endpoint/types'; import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; import { legacyEventIndexPattern } from './legacy_event_index_pattern'; @@ -73,7 +73,7 @@ export abstract class ResolverQuery implements MSearchQuery { * @param client a client for searching ES * @param ids a single more multiple unique node ids (e.g. entity_id or unique_pid) */ - async search(client: IScopedClusterClient, ids: string | string[]): Promise { + async search(client: ILegacyScopedClusterClient, ids: string | string[]): Promise { const res: SearchResponse = await client.callAsCurrentUser( 'search', this.buildSearch(ids) diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts index 4c0e1a5126e7c6..f873ab3019f64c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { MSearchResponse } from 'elasticsearch'; import { ResolverEvent } from '../../../../../common/endpoint/types'; import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; @@ -44,7 +44,7 @@ export interface QueryInfo { * https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/msearch_examples.html */ export class MultiSearcher { - constructor(private readonly client: IScopedClusterClient) {} + constructor(private readonly client: ILegacyScopedClusterClient) {} /** * Perform the multi search on the passed in queries diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/fetch.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/fetch.ts index 0af2fca7106bef..1a532c54c7d5d1 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/fetch.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/fetch.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { ResolverChildren, ResolverRelatedEvents, @@ -33,7 +33,7 @@ import { AlertsQuery } from '../queries/alerts'; */ export class Fetcher { constructor( - private readonly client: IScopedClusterClient, + private readonly client: ILegacyScopedClusterClient, /** * The anchoring origin for the tree. */ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_ml_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_ml_signals.ts index e95b713105fc67..258201f2a940bf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_ml_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_ml_signals.ts @@ -6,7 +6,7 @@ import dateMath from '@elastic/datemath'; -import { APICaller, KibanaRequest } from '../../../../../../../src/core/server'; +import { LegacyAPICaller, KibanaRequest } from '../../../../../../../src/core/server'; import { MlPluginSetup } from '../../../../../ml/server'; import { getAnomalies } from '../../machine_learning'; @@ -20,7 +20,7 @@ export const findMlSignals = async ({ to, }: { ml: MlPluginSetup; - callCluster: APICaller; + callCluster: LegacyAPICaller; request: KibanaRequest; jobId: string; anomalyThreshold: number; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts index 90484a46dc6d3e..0fb743c9c3ed67 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts @@ -29,7 +29,7 @@ import { MetaOrUndefined, RuleId, } from '../../../common/detection_engine/schemas/common/schemas'; -import { CallAPIOptions } from '../../../../../../src/core/server'; +import { LegacyCallAPIOptions } from '../../../../../../src/core/server'; import { Filter } from '../../../../../../src/plugins/data/server'; import { RuleType } from '../../../common/detection_engine/types'; import { ListArrayOrUndefined } from '../../../common/detection_engine/schemas/types'; @@ -69,7 +69,7 @@ export interface RuleTypeParams { export type CallWithRequest, V> = ( endpoint: string, params: T, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => Promise; export type RefreshTypes = false | 'wait_for'; diff --git a/x-pack/plugins/snapshot_restore/server/plugin.ts b/x-pack/plugins/snapshot_restore/server/plugin.ts index 10d259e28ee43b..cf7504363b823c 100644 --- a/x-pack/plugins/snapshot_restore/server/plugin.ts +++ b/x-pack/plugins/snapshot_restore/server/plugin.ts @@ -13,11 +13,11 @@ import { first } from 'rxjs/operators'; import { i18n } from '@kbn/i18n'; import { CoreSetup, - ICustomClusterClient, + ILegacyCustomClusterClient, Plugin, Logger, PluginInitializerContext, - IScopedClusterClient, + ILegacyScopedClusterClient, } from 'kibana/server'; import { PLUGIN } from '../common'; @@ -30,7 +30,7 @@ import { Dependencies } from './types'; import { SnapshotRestoreConfig } from './config'; export interface SnapshotRestoreContext { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; } async function getCustomEsClient(getStartServices: CoreSetup['getStartServices']) { @@ -43,7 +43,7 @@ export class SnapshotRestoreServerPlugin implements Plugin private readonly logger: Logger; private readonly apiRoutes: ApiRoutes; private readonly license: License; - private snapshotRestoreESClient?: ICustomClusterClient; + private snapshotRestoreESClient?: ILegacyCustomClusterClient; constructor(private context: PluginInitializerContext) { const { logger } = this.context; diff --git a/x-pack/plugins/snapshot_restore/server/types.ts b/x-pack/plugins/snapshot_restore/server/types.ts index 9710f812abf234..7794156eb1b888 100644 --- a/x-pack/plugins/snapshot_restore/server/types.ts +++ b/x-pack/plugins/snapshot_restore/server/types.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ScopedClusterClient, IRouter } from 'src/core/server'; +import { LegacyScopedClusterClient, IRouter } from 'src/core/server'; import { LicensingPluginSetup } from '../../licensing/server'; import { SecurityPluginSetup } from '../../security/server'; import { CloudSetup } from '../../cloud/server'; @@ -31,4 +31,4 @@ export interface RouteDependencies { }; } -export type CallAsCurrentUser = ScopedClusterClient['callAsCurrentUser']; +export type CallAsCurrentUser = LegacyScopedClusterClient['callAsCurrentUser']; diff --git a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts index 9f980df8da1b97..4ab309cc6015cc 100644 --- a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts +++ b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CallAPIOptions } from 'src/core/server'; +import { LegacyCallAPIOptions } from 'src/core/server'; import { take } from 'rxjs/operators'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { Observable } from 'rxjs'; @@ -14,7 +14,7 @@ import { PluginsSetup } from '../plugin'; type CallCluster = ( endpoint: string, clientParams: Record, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => Promise; interface SpacesAggregationResponse { diff --git a/x-pack/plugins/task_manager/server/task_manager.ts b/x-pack/plugins/task_manager/server/task_manager.ts index cb0d1ff3554d58..23cb33cfac6c23 100644 --- a/x-pack/plugins/task_manager/server/task_manager.ts +++ b/x-pack/plugins/task_manager/server/task_manager.ts @@ -12,7 +12,7 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { Option, some, map as mapOptional } from 'fp-ts/lib/Option'; import { SavedObjectsSerializer, - IScopedClusterClient, + ILegacyScopedClusterClient, ISavedObjectsRepository, } from '../../../../src/core/server'; import { Result, asErr, either, map, mapErr, promiseResult } from './lib/result_type'; @@ -63,7 +63,7 @@ const VERSION_CONFLICT_STATUS = 409; export interface TaskManagerOpts { logger: Logger; config: TaskManagerConfig; - callAsInternalUser: IScopedClusterClient['callAsInternalUser']; + callAsInternalUser: ILegacyScopedClusterClient['callAsInternalUser']; savedObjectsRepository: ISavedObjectsRepository; serializer: SavedObjectsSerializer; taskManagerId: string; diff --git a/x-pack/plugins/transform/server/plugin.ts b/x-pack/plugins/transform/server/plugin.ts index c8057a3e2fae11..79e9be239c798f 100644 --- a/x-pack/plugins/transform/server/plugin.ts +++ b/x-pack/plugins/transform/server/plugin.ts @@ -6,9 +6,9 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, - ICustomClusterClient, + ILegacyCustomClusterClient, Plugin, - IScopedClusterClient, + ILegacyScopedClusterClient, Logger, PluginInitializerContext, } from 'src/core/server'; @@ -23,7 +23,7 @@ import { License } from './services'; declare module 'kibana/server' { interface RequestHandlerContext { transform?: { - dataClient: IScopedClusterClient; + dataClient: ILegacyScopedClusterClient; }; } } @@ -50,7 +50,7 @@ export class TransformServerPlugin implements Plugin<{}, void, any, any> { private readonly apiRoutes: ApiRoutes; private readonly license: License; private readonly logger: Logger; - private transformESClient?: ICustomClusterClient; + private transformESClient?: ILegacyCustomClusterClient; constructor(initContext: PluginInitializerContext) { this.logger = initContext.logger.get(); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/apm/index.ts b/x-pack/plugins/upgrade_assistant/server/lib/apm/index.ts index 3ede2ce394eda0..0703d55aa8050c 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/apm/index.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/apm/index.ts @@ -7,13 +7,13 @@ import { get } from 'lodash'; import minimatch from 'minimatch'; import { SemVer, valid } from 'semver'; -import { IScopedClusterClient } from 'src/core/server'; +import { ILegacyScopedClusterClient } from 'src/core/server'; import { EnrichedDeprecationInfo } from '../../../common/types'; import { FlatSettings } from '../reindexing/types'; export async function getDeprecatedApmIndices( - clusterClient: IScopedClusterClient, + clusterClient: ILegacyScopedClusterClient, indexPatterns: string[] = [] ): Promise { const indices = await clusterClient.callAsCurrentUser('indices.getMapping', { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts index 8f25533c0afb1e..348eebb97e384b 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; -import { IScopedClusterClient } from 'src/core/server'; +import { ILegacyScopedClusterClient } from 'src/core/server'; interface DeprecationLoggingStatus { isEnabled: boolean; } export async function getDeprecationLoggingStatus( - dataClient: IScopedClusterClient + dataClient: ILegacyScopedClusterClient ): Promise { const response = await dataClient.callAsCurrentUser('cluster.getSettings', { includeDefaults: true, @@ -23,7 +23,7 @@ export async function getDeprecationLoggingStatus( } export async function setDeprecationLogging( - dataClient: IScopedClusterClient, + dataClient: ILegacyScopedClusterClient, isEnabled: boolean ): Promise { const response = await dataClient.callAsCurrentUser('cluster.putSettings', { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts index 7b84c00a1eb848..cec89bbe2745e7 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { getIndexStateFromClusterState } from '../../common/get_index_state_from_cluster_state'; import { ClusterStateAPIResponse } from '../../common/types'; type StatusCheckResult = Record; export const esIndicesStateCheck = async ( - callAsUser: APICaller, + callAsUser: LegacyAPICaller, indices: string[] ): Promise => { // According to https://www.elastic.co/guide/en/elasticsearch/reference/7.6/cluster-state.html diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts index fd14d299bff13a..7a01d0d954ffe2 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts @@ -3,7 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'src/core/server'; + +import { ILegacyScopedClusterClient } from 'src/core/server'; import { DeprecationAPIResponse } from 'src/legacy/core_plugins/elasticsearch'; import { EnrichedDeprecationInfo, UpgradeAssistantStatus } from '../../common/types'; import { getDeprecatedApmIndices } from './apm'; @@ -12,7 +13,7 @@ import { isSystemIndex } from './reindexing'; import { esIndicesStateCheck } from './es_indices_state_check'; export async function getUpgradeAssistantStatus( - dataClient: IScopedClusterClient, + dataClient: ILegacyScopedClusterClient, isCloudEnabled: boolean, apmIndices: string[] ): Promise { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts index 8cb296719c19e6..78f159ed988674 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts @@ -5,7 +5,7 @@ */ import { SemVer } from 'semver'; -import { IScopedClusterClient, kibanaResponseFactory } from 'src/core/server'; +import { ILegacyScopedClusterClient, kibanaResponseFactory } from 'src/core/server'; import { xpackMocks } from '../../../../mocks'; import { CURRENT_VERSION } from '../../common/version'; import { @@ -24,7 +24,7 @@ describe('getAllNodeVersions', () => { node3: { version: '6.0.0' }, }, }), - } as unknown) as IScopedClusterClient; + } as unknown) as ILegacyScopedClusterClient; await expect(getAllNodeVersions(adminClient)).resolves.toEqual([ new SemVer('6.0.0'), diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts index e12f501ba02be5..2b49d4c286f610 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts @@ -7,7 +7,7 @@ import { uniq } from 'lodash'; import { SemVer } from 'semver'; import { - IScopedClusterClient, + ILegacyScopedClusterClient, KibanaRequest, KibanaResponseFactory, RequestHandler, @@ -18,7 +18,7 @@ import { CURRENT_VERSION } from '../../common/version'; /** * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster. */ -export const getAllNodeVersions = async (adminClient: IScopedClusterClient) => { +export const getAllNodeVersions = async (adminClient: ILegacyScopedClusterClient) => { // Get the version information for all nodes in the cluster. const { nodes } = (await adminClient.callAsInternalUser('nodes.info', { filterPath: 'nodes.*.version', diff --git a/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.test.ts index 51c605f56e11c8..9956894e274fea 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'src/core/server'; +import { ILegacyScopedClusterClient } from 'src/core/server'; import { elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; import { MappingProperties } from './reindexing/types'; @@ -42,7 +42,7 @@ describe('getDefaultFieldList', () => { }); describe('fixMetricbeatIndex', () => { - let dataClient: IScopedClusterClient; + let dataClient: ILegacyScopedClusterClient; const mockMappings = { 'metricbeat-1': { mappings: { properties: { field1: { type: 'text' }, field2: { type: 'float' } } }, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.ts b/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.ts index a930fbed45a51e..9bd9475207e8a0 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/query_default_field.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import Boom from 'boom'; import { get } from 'lodash'; @@ -20,7 +20,7 @@ import { MappingProperties } from './reindexing/types'; * @param otherFields - Other fields that should be included in the generated default_field that do not match `fieldTypes` */ export const addDefaultField = async ( - clusterClient: IScopedClusterClient, + clusterClient: ILegacyScopedClusterClient, indexName: string, fieldTypes: ReadonlySet, otherFields: ReadonlySet = new Set() diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts index d94e48fea36e86..851e947cca10ec 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts @@ -6,7 +6,11 @@ import moment from 'moment'; -import { SavedObjectsFindResponse, SavedObjectsClientContract, APICaller } from 'src/core/server'; +import { + SavedObjectsFindResponse, + SavedObjectsClientContract, + LegacyAPICaller, +} from 'src/core/server'; import { IndexGroup, REINDEX_OP_TYPE, @@ -118,7 +122,7 @@ export interface ReindexActions { export const reindexActionsFactory = ( client: SavedObjectsClientContract, - callAsUser: APICaller + callAsUser: LegacyAPICaller ): ReindexActions => { // ----- Internal functions const isLocked = (reindexOp: ReindexSavedObject) => { 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 2746b5bdef070e..aa4bbdeb6314e9 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 @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, Logger } from 'src/core/server'; +import { LegacyAPICaller, Logger } from 'src/core/server'; import { first } from 'rxjs/operators'; import { LicensingPluginSetup } from '../../../../licensing/server'; @@ -130,7 +130,7 @@ export interface ReindexService { } export const reindexServiceFactory = ( - callAsUser: APICaller, + callAsUser: LegacyAPICaller, actions: ReindexActions, log: Logger, licensing: LicensingPluginSetup, diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts index 6787b6d328f455..45177d2fa2dc75 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts @@ -3,7 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { IClusterClient, Logger, SavedObjectsClientContract, FakeRequest } from 'src/core/server'; +import { + ILegacyClusterClient, + Logger, + SavedObjectsClientContract, + FakeRequest, +} from 'src/core/server'; import moment from 'moment'; import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; import { Credential, CredentialStore } from './credential_store'; @@ -48,7 +53,7 @@ export class ReindexWorker { constructor( private client: SavedObjectsClientContract, private credentialStore: CredentialStore, - private clusterClient: IClusterClient, + private clusterClient: ILegacyClusterClient, log: Logger, private licensing: LicensingPluginSetup, private apmIndexPatterns: string[] diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts index 24347b7799871f..7188241e10f9a2 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts @@ -5,7 +5,7 @@ */ import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { registerUpgradeAssistantUsageCollector } from './usage_collector'; -import { IClusterClient } from 'src/core/server'; +import { ILegacyClusterClient } from 'src/core/server'; /** * Since these route callbacks are so thin, these serve simply as integration tests @@ -18,7 +18,7 @@ describe('Upgrade Assistant Usage Collector', () => { let dependencies: any; let callClusterStub: any; let usageCollection: any; - let clusterClient: IClusterClient; + let clusterClient: ILegacyClusterClient; beforeEach(() => { clusterClient = elasticsearchServiceMock.createClusterClient(); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index 4616f5f553077c..0e152121af8b2f 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -6,7 +6,7 @@ import { get } from 'lodash'; import { - APICaller, + LegacyAPICaller, ElasticsearchServiceStart, ISavedObjectsRepository, SavedObjectsServiceStart, @@ -38,7 +38,9 @@ async function getSavedObjectAttributesFromRepo( } } -async function getDeprecationLoggingStatusValue(callAsCurrentUser: APICaller): Promise { +async function getDeprecationLoggingStatusValue( + callAsCurrentUser: LegacyAPICaller +): Promise { try { const loggerDeprecationCallResult = await callAsCurrentUser('cluster.getSettings', { includeDefaults: true, diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts index 74c349d8948392..fffde339c59e57 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { IScopedClusterClient, Logger, SavedObjectsClientContract } from 'kibana/server'; +import { ILegacyScopedClusterClient, Logger, SavedObjectsClientContract } from 'kibana/server'; import { LicensingPluginSetup } from '../../../../licensing/server'; @@ -17,7 +17,7 @@ import { error } from '../../lib/reindexing/error'; interface ReindexHandlerArgs { savedObjects: SavedObjectsClientContract; - dataClient: IScopedClusterClient; + dataClient: ILegacyScopedClusterClient; indexName: string; log: Logger; licensing: LicensingPluginSetup; diff --git a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index 8d26838811262e..2e732f59e4f307 100644 --- a/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -7,7 +7,7 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { IRouter, - CallAPIOptions, + LegacyCallAPIOptions, SavedObjectsClientContract, ISavedObjectsRepository, } from 'src/core/server'; @@ -18,7 +18,7 @@ import { DynamicSettings } from '../../../../common/runtime_types'; export type APICaller = ( endpoint: string, clientParams: Record, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => Promise; export type UMElasticsearchQueryFn = ( diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts index 656571ee7c8297..e063ecddcd0c4b 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_status.test.ts @@ -6,7 +6,7 @@ import { elasticsearchServiceMock } from '../../../../../../../src/core/server/mocks'; import { getMonitorStatus } from '../get_monitor_status'; -import { ScopedClusterClient } from 'src/core/server'; +import { LegacyScopedClusterClient } from 'src/core/server'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../common/constants'; interface BucketItemCriteria { @@ -50,7 +50,7 @@ type MockCallES = (method: any, params: any) => Promise; const setupMock = ( criteria: MultiPageCriteria[] -): [MockCallES, jest.Mocked>] => { +): [MockCallES, jest.Mocked>] => { const esMock = elasticsearchServiceMock.createScopedClusterClient(); criteria.forEach(({ after_key, bucketCriteria }) => { diff --git a/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts b/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts index 7b08752f122497..345d02b990eb78 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APICaller, CallAPIOptions } from 'src/core/server'; +import { LegacyAPICaller, LegacyCallAPIOptions } from 'src/core/server'; import { UMElasticsearchQueryFn } from '../adapters'; import { IndexPatternsFetcher, IIndexPattern } from '../../../../../../src/plugins/data/server'; @@ -12,10 +12,10 @@ export const getUptimeIndexPattern: UMElasticsearchQueryFn<{}, IIndexPattern | u callES, dynamicSettings, }) => { - const callAsCurrentUser: APICaller = async ( + const callAsCurrentUser: LegacyAPICaller = async ( endpoint: string, clientParams: Record = {}, - options?: CallAPIOptions + options?: LegacyCallAPIOptions ) => callES(endpoint, clientParams, options); const indexPatternsFetcher = new IndexPatternsFetcher(callAsCurrentUser); diff --git a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts index 6d62ae7ba2b29f..b2fb9ce68c1326 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts @@ -5,12 +5,12 @@ */ import moment from 'moment'; -import { APICaller } from 'src/core/server'; +import { LegacyAPICaller } from 'src/core/server'; import { CursorPagination } from './types'; import { parseRelativeDate } from '../../helper'; export class QueryContext { - callES: APICaller; + callES: LegacyAPICaller; heartbeatIndices: string; dateRangeStart: string; dateRangeEnd: string; diff --git a/x-pack/plugins/uptime/server/rest_api/types.ts b/x-pack/plugins/uptime/server/rest_api/types.ts index 8720b9dc60b12a..589cb82d550f67 100644 --- a/x-pack/plugins/uptime/server/rest_api/types.ts +++ b/x-pack/plugins/uptime/server/rest_api/types.ts @@ -9,7 +9,7 @@ import { RequestHandler, RouteConfig, RouteMethod, - CallAPIOptions, + LegacyCallAPIOptions, SavedObjectsClientContract, RequestHandlerContext, KibanaRequest, @@ -66,7 +66,7 @@ export interface UMRouteParams { callES: ( endpoint: string, clientParams?: Record, - options?: CallAPIOptions | undefined + options?: LegacyCallAPIOptions | undefined ) => Promise; dynamicSettings: DynamicSettings; savedObjectsClient: SavedObjectsClientContract; 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 8e8ca369dd02b4..2ee8b04b82eb8e 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 @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { ES_SCROLL_SETTINGS } from '../../../common/constants'; export function fetchAllFromScroll( searchResuls: any, - dataClient: IScopedClusterClient, + dataClient: ILegacyScopedClusterClient, hits: any[] = [] ): Promise { const newHits = get(searchResuls, 'hits.hits', []); diff --git a/x-pack/plugins/watcher/server/plugin.ts b/x-pack/plugins/watcher/server/plugin.ts index 67bf9a92abde69..70c4f980580e8b 100644 --- a/x-pack/plugins/watcher/server/plugin.ts +++ b/x-pack/plugins/watcher/server/plugin.ts @@ -12,8 +12,8 @@ declare module 'kibana/server' { import { CoreSetup, - ICustomClusterClient, - IScopedClusterClient, + ILegacyCustomClusterClient, + ILegacyScopedClusterClient, Logger, Plugin, PluginInitializerContext, @@ -31,7 +31,7 @@ import { registerLoadHistoryRoute } from './routes/api/register_load_history_rou import { elasticsearchJsPlugin } from './lib/elasticsearch_js_plugin'; export interface WatcherContext { - client: IScopedClusterClient; + client: ILegacyScopedClusterClient; } async function getCustomEsClient(getStartServices: CoreSetup['getStartServices']) { @@ -42,7 +42,7 @@ async function getCustomEsClient(getStartServices: CoreSetup['getStartServices'] export class WatcherServerPlugin implements Plugin { private readonly log: Logger; - private watcherESClient?: ICustomClusterClient; + private watcherESClient?: ILegacyCustomClusterClient; private licenseStatus: LicenseStatus = { hasRequired: false, 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 6d5b359b53d396..97018a55234895 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 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { reduce, size } from 'lodash'; import { isEsError } from '../../../shared_imports'; import { RouteDependencies } from '../../../types'; @@ -27,7 +27,7 @@ function getIndexNamesFromAliasesResponse(json: Record) { ); } -function getIndices(dataClient: IScopedClusterClient, pattern: string, limit = 10) { +function getIndices(dataClient: ILegacyScopedClusterClient, pattern: string, limit = 10) { return dataClient .callAsCurrentUser('indices.getAlias', { index: pattern, diff --git a/x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts b/x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts index e3c82ef3965f45..f4e8c8e33b04cc 100644 --- a/x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/register_list_fields_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { isEsError } from '../../shared_imports'; // @ts-ignore import { Fields } from '../../models/fields/index'; @@ -16,7 +16,7 @@ const bodySchema = schema.object({ indexes: schema.arrayOf(schema.string()), }); -function fetchFields(dataClient: IScopedClusterClient, indexes: string[]) { +function fetchFields(dataClient: ILegacyScopedClusterClient, indexes: string[]) { const params = { index: indexes, fields: ['*'], diff --git a/x-pack/plugins/watcher/server/routes/api/register_load_history_route.ts b/x-pack/plugins/watcher/server/routes/api/register_load_history_route.ts index c61953db555d3e..c44a574df6f6e0 100644 --- a/x-pack/plugins/watcher/server/routes/api/register_load_history_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/register_load_history_route.ts @@ -6,7 +6,7 @@ import { schema } from '@kbn/config-schema'; import { get } from 'lodash'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { isEsError } from '../../shared_imports'; import { INDEX_NAMES } from '../../../common/constants'; import { RouteDependencies } from '../../types'; @@ -18,7 +18,7 @@ const paramsSchema = schema.object({ id: schema.string(), }); -function fetchHistoryItem(dataClient: IScopedClusterClient, watchHistoryItemId: string) { +function fetchHistoryItem(dataClient: ILegacyScopedClusterClient, watchHistoryItemId: string) { return dataClient.callAsCurrentUser('search', { index: INDEX_NAMES.WATCHER_HISTORY, body: { diff --git a/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.ts b/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.ts index 9f501b56d47030..ca01ddf64dcc74 100644 --- a/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/settings/register_load_route.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { isEsError } from '../../../shared_imports'; // @ts-ignore import { Settings } from '../../../models/settings/index'; import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -function fetchClusterSettings(client: IScopedClusterClient) { +function fetchClusterSettings(client: ILegacyScopedClusterClient) { return client.callAsInternalUser('cluster.getSettings', { includeDefaults: true, filterPath: '**.xpack.notification', diff --git a/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.ts index 923714739065ee..74bf8e99b6b182 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/action/register_acknowledge_route.ts @@ -6,7 +6,7 @@ import { schema } from '@kbn/config-schema'; import { get } from 'lodash'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { isEsError } from '../../../../shared_imports'; // @ts-ignore import { WatchStatus } from '../../../../models/watch_status/index'; @@ -18,7 +18,11 @@ const paramsSchema = schema.object({ actionId: schema.string(), }); -function acknowledgeAction(dataClient: IScopedClusterClient, watchId: string, actionId: string) { +function acknowledgeAction( + dataClient: ILegacyScopedClusterClient, + watchId: string, + actionId: string +) { return dataClient.callAsCurrentUser('watcher.ackWatch', { id: watchId, action: actionId, diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.ts index e7e3f5e3d9ba3a..468db5aa13fac6 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_activate_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { isEsError } from '../../../shared_imports'; import { RouteDependencies } from '../../../types'; @@ -13,7 +13,7 @@ import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_facto // @ts-ignore import { WatchStatus } from '../../../models/watch_status/index'; -function activateWatch(dataClient: IScopedClusterClient, watchId: string) { +function activateWatch(dataClient: ILegacyScopedClusterClient, watchId: string) { return dataClient.callAsCurrentUser('watcher.activateWatch', { id: watchId, }); diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.ts index de4b1dbb4b44db..3fda7e1a270343 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_deactivate_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { isEsError } from '../../../shared_imports'; import { RouteDependencies } from '../../../types'; @@ -17,7 +17,7 @@ const paramsSchema = schema.object({ watchId: schema.string(), }); -function deactivateWatch(dataClient: IScopedClusterClient, watchId: string) { +function deactivateWatch(dataClient: ILegacyScopedClusterClient, watchId: string) { return dataClient.callAsCurrentUser('watcher.deactivateWatch', { id: watchId, }); diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.ts index 9f43d311a182fc..f70c24f6e12653 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_delete_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { isEsError } from '../../../shared_imports'; import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; @@ -14,7 +14,7 @@ const paramsSchema = schema.object({ watchId: schema.string(), }); -function deleteWatch(dataClient: IScopedClusterClient, watchId: string) { +function deleteWatch(dataClient: ILegacyScopedClusterClient, watchId: string) { return dataClient.callAsCurrentUser('watcher.deleteWatch', { id: watchId, }); diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.ts index 9f27f3ca35bf6d..75e42023660951 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_execute_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { isEsError } from '../../../shared_imports'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; @@ -23,7 +23,7 @@ const bodySchema = schema.object({ watch: schema.object({}, { unknowns: 'allow' }), }); -function executeWatch(dataClient: IScopedClusterClient, executeDetails: any, watchJson: any) { +function executeWatch(dataClient: ILegacyScopedClusterClient, executeDetails: any, watchJson: any) { const body = executeDetails; body.watch = watchJson; diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.ts index faa860b3ce6dd9..b311e81ff5ec12 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_history_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { fetchAllFromScroll } from '../../../lib/fetch_all_from_scroll'; import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../common/constants'; @@ -23,7 +23,7 @@ const querySchema = schema.object({ startTime: schema.string(), }); -function fetchHistoryItems(dataClient: IScopedClusterClient, watchId: any, startTime: any) { +function fetchHistoryItems(dataClient: ILegacyScopedClusterClient, watchId: any, startTime: any) { const params: any = { index: INDEX_NAMES.WATCHER_HISTORY, scroll: ES_SCROLL_SETTINGS.KEEPALIVE, diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.ts index d8905bcebeef33..2ecb94d2fe0d49 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_load_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { isEsError } from '../../../shared_imports'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; @@ -17,7 +17,7 @@ const paramsSchema = schema.object({ id: schema.string(), }); -function fetchWatch(dataClient: IScopedClusterClient, watchId: string) { +function fetchWatch(dataClient: ILegacyScopedClusterClient, watchId: string) { return dataClient.callAsCurrentUser('watcher.getWatch', { id: watchId, }); diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts index 2eb6d270e808a3..5f81a25074a199 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_visualize_route.ts @@ -5,7 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { isEsError } from '../../../shared_imports'; import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; @@ -20,7 +20,7 @@ const bodySchema = schema.object({ options: schema.object({}, { unknowns: 'allow' }), }); -function fetchVisualizeData(dataClient: IScopedClusterClient, index: any, body: any) { +function fetchVisualizeData(dataClient: ILegacyScopedClusterClient, index: any, body: any) { const params = { index, body, 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 41bf363978ab8b..c0494360feb43d 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 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { RouteDependencies } from '../../../types'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; @@ -13,7 +13,7 @@ const bodySchema = schema.object({ watchIds: schema.arrayOf(schema.string()), }); -function deleteWatches(dataClient: IScopedClusterClient, watchIds: string[]) { +function deleteWatches(dataClient: ILegacyScopedClusterClient, watchIds: string[]) { const deletePromises = watchIds.map((watchId) => { return dataClient .callAsCurrentUser('watcher.deleteWatch', { diff --git a/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.ts b/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.ts index ca93221bf1de77..47eb76de31e6b6 100644 --- a/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watches/register_list_route.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IScopedClusterClient } from 'kibana/server'; +import { ILegacyScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { fetchAllFromScroll } from '../../../lib/fetch_all_from_scroll'; import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../common/constants'; @@ -14,7 +14,7 @@ import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_facto // @ts-ignore import { Watch } from '../../../models/watch/index'; -function fetchWatches(dataClient: IScopedClusterClient) { +function fetchWatches(dataClient: ILegacyScopedClusterClient) { const params = { index: INDEX_NAMES.WATCHES, scroll: ES_SCROLL_SETTINGS.KEEPALIVE, diff --git a/x-pack/test/api_integration/apis/lens/telemetry.ts b/x-pack/test/api_integration/apis/lens/telemetry.ts index a2a3db288e37a1..24ae7d4ab89766 100644 --- a/x-pack/test/api_integration/apis/lens/telemetry.ts +++ b/x-pack/test/api_integration/apis/lens/telemetry.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import expect from '@kbn/expect'; import { Client, SearchParams } from 'elasticsearch'; -import { APICaller } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { FtrProviderContext } from '../../ftr_provider_context'; @@ -22,9 +22,9 @@ const COMMON_HEADERS = { export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const es: Client = getService('legacyEs'); - const callCluster: APICaller = (((path: 'search', searchParams: SearchParams) => { + const callCluster: LegacyAPICaller = (((path: 'search', searchParams: SearchParams) => { return es[path].call(es, searchParams); - }) as unknown) as APICaller; + }) as unknown) as LegacyAPICaller; async function assertExpectedSavedObjects(num: number) { // Make sure that new/deleted docs are available to search From 1f7d38be099a1287e4c9eeb6094dc5ea8514e685 Mon Sep 17 00:00:00 2001 From: Spencer Date: Mon, 29 Jun 2020 14:48:06 -0700 Subject: [PATCH 18/91] [7.x] [ui-shared-deps] include styled-components (#69322) (#70252) * [ui-shared-deps] include styled-components * update snapshots caused by react-is upgrade * fix jest snapshots * declare react-is dep in x-pack too so it uses the right version Co-authored-by: spalger Co-authored-by: Elastic Machine Co-authored-by: spalger Co-authored-by: Elastic Machine --- packages/kbn-ui-shared-deps/entry.js | 1 + packages/kbn-ui-shared-deps/index.js | 1 + packages/kbn-ui-shared-deps/package.json | 6 +++-- x-pack/package.json | 1 + yarn.lock | 28 ++++-------------------- 5 files changed, 11 insertions(+), 26 deletions(-) diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js index 88e84fc87ae533..aaa46ab74714f1 100644 --- a/packages/kbn-ui-shared-deps/entry.js +++ b/packages/kbn-ui-shared-deps/entry.js @@ -38,6 +38,7 @@ export const ReactDomServer = require('react-dom/server'); export const ReactIntl = require('react-intl'); export const ReactRouter = require('react-router'); // eslint-disable-line export const ReactRouterDom = require('react-router-dom'); +export const StyledComponents = require('styled-components'); Moment.tz.load(require('moment-timezone/data/packed/latest.json')); diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js index 301d1765558479..596c31820e80d0 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/index.js @@ -42,6 +42,7 @@ exports.externals = { 'react-intl': '__kbnSharedDeps__.ReactIntl', 'react-router': '__kbnSharedDeps__.ReactRouter', 'react-router-dom': '__kbnSharedDeps__.ReactRouterDom', + 'styled-components': '__kbnSharedDeps__.StyledComponents', '@kbn/monaco': '__kbnSharedDeps__.KbnMonaco', // this is how plugins/consumers from npm load monaco 'monaco-editor/esm/vs/editor/editor.api': '__kbnSharedDeps__.MonacoBarePluginApi', diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index e070e35ababdde..e1e4b75d5dc388 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -26,20 +26,22 @@ "react": "^16.12.0", "react-dom": "^16.12.0", "react-intl": "^2.8.0", + "react-is": "^16.8.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", "regenerator-runtime": "^0.13.3", "rxjs": "^6.5.5", + "styled-components": "^5.1.0", "symbol-observable": "^1.2.0", "whatwg-fetch": "^3.0.0" }, "devDependencies": { "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", - "loader-utils": "^1.2.3", - "val-loader": "^1.1.1", "css-loader": "^3.4.2", "del": "^5.1.0", + "loader-utils": "^1.2.3", + "val-loader": "^1.1.1", "webpack": "^4.41.5" } } diff --git a/x-pack/package.json b/x-pack/package.json index e297440ab0437a..cfe74f49cfced9 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -172,6 +172,7 @@ "pixelmatch": "^5.1.0", "proxyquire": "1.8.0", "react-docgen-typescript-loader": "^3.1.1", + "react-is": "^16.8.0", "react-test-renderer": "^16.12.0", "rxjs-marbles": "^5.0.6", "sass-loader": "^8.0.2", diff --git a/yarn.lock b/yarn.lock index 538110d42e0031..955cb6f0bd9bbc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25751,30 +25751,10 @@ react-intl@^2.8.0: intl-relativeformat "^2.1.0" invariant "^2.1.1" -react-is@^16.12.0: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" - integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== - -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6: - version "16.8.6" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" - integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== - -react-is@^16.8.3: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb" - integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw== - -react-is@^16.8.4: - version "16.8.5" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8" - integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ== - -react-is@^16.9.0: - version "16.11.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa" - integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw== +react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.3, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-is@~16.3.0: version "16.3.2" From 52b5e35ed9062112690271e8651e3b586702bb4c Mon Sep 17 00:00:00 2001 From: nnamdifrankie <56440728+nnamdifrankie@users.noreply.github.com> Date: Mon, 29 Jun 2020 18:28:07 -0400 Subject: [PATCH 19/91] SECURITY-ENDPOINT: add host properties (#70238) (#70254) SECURITY-ENDPOINT: add host properties (#70238) (#70254) --- .../common/endpoint/generate_data.ts | 17 +++++++++++++---- .../security_solution/common/endpoint/types.ts | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 5af34b6a694e83..563e2e4ccc9f2b 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -48,6 +48,8 @@ const Windows: OSFields[] = [ name: 'windows 10.0', full: 'Windows 10', version: '10.0', + platform: 'Windows', + family: 'Windows', Ext: { variant: 'Windows Pro', }, @@ -56,6 +58,8 @@ const Windows: OSFields[] = [ name: 'windows 10.0', full: 'Windows Server 2016', version: '10.0', + platform: 'Windows', + family: 'Windows', Ext: { variant: 'Windows Server', }, @@ -64,6 +68,8 @@ const Windows: OSFields[] = [ name: 'windows 6.2', full: 'Windows Server 2012', version: '6.2', + platform: 'Windows', + family: 'Windows', Ext: { variant: 'Windows Server', }, @@ -72,6 +78,8 @@ const Windows: OSFields[] = [ name: 'windows 6.3', full: 'Windows Server 2012R2', version: '6.3', + platform: 'Windows', + family: 'Windows', Ext: { variant: 'Windows Server Release 2', }, @@ -316,6 +324,7 @@ export class EndpointDocGenerator { } private createHostData(): HostInfo { + const hostName = this.randomHostname(); return { agent: { version: this.randomVersion(), @@ -329,7 +338,9 @@ export class EndpointDocGenerator { }, host: { id: this.seededUUIDv4(), - hostname: this.randomHostname(), + hostname: hostName, + name: hostName, + architecture: this.randomString(10), ip: this.randomArray(3, () => this.randomIP()), mac: this.randomArray(3, () => this.randomMac()), os: this.randomChoice(OS), @@ -1016,9 +1027,7 @@ export class EndpointDocGenerator { ecs: { version: '1.4.0', }, - host: { - id: this.commonInfo.host.id, - }, + host: this.commonInfo.host, Endpoint: { policy: { applied: { diff --git a/x-pack/plugins/security_solution/common/endpoint/types.ts b/x-pack/plugins/security_solution/common/endpoint/types.ts index f71af34722dcf3..72839a8370495a 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types.ts @@ -179,6 +179,8 @@ export interface OSFields { full: string; name: string; version: string; + platform: string; + family: string; Ext: OSFieldsExt; } @@ -195,8 +197,10 @@ export interface OSFieldsExt { export interface Host { id: string; hostname: string; + name: string; ip: string[]; mac: string[]; + architecture: string; os: OSFields; } From 96a88d25c2e5462cca618be2eeb5a028102eb0d0 Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Mon, 29 Jun 2020 16:07:03 -0700 Subject: [PATCH 20/91] docs: update alerting (#69839) (#70233) --- docs/apm/apm-alerts.asciidoc | 23 +++++++++++++++++++++-- docs/apm/images/add-variable.png | Bin 0 -> 4043 bytes 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 docs/apm/images/add-variable.png diff --git a/docs/apm/apm-alerts.asciidoc b/docs/apm/apm-alerts.asciidoc index 75ce5f56c96c65..bc5e1ccc1dd55e 100644 --- a/docs/apm/apm-alerts.asciidoc +++ b/docs/apm/apm-alerts.asciidoc @@ -15,15 +15,20 @@ and enables central management of all alerts from <>. + +The APM app supports two different types of threshold alerts: transaction duration, and error rate. Below, we'll create one of each. [float] [[apm-create-transaction-alert]] === Create a transaction duration alert -This guide creates an alert for the `opbeans-java` service based on the following criteria: +Transaction duration alerts trigger when the duration of a specific transaction type in a service exceeds a defined threshold. +This guide will create an alert for the `opbeans-java` service based on the following criteria: +* Environment: Production * Transaction type: `transaction.type:request` * Average request is above `1500ms` for the last 5 minutes * Check every 10 minutes, and repeat the alert every 30 minutes @@ -52,14 +57,22 @@ Enter a name for the connector, and paste the webhook URL. See Slack's webhook documentation if you need to create one. +Add a message body in markdown format. +You can use the https://mustache.github.io/[Mustache] template syntax, i.e., `{{variable}}` +to pass alert values at the time a condition is detected to an action. +A list of available variables can be accessed by selecting the +**add variable** button image:apm/images/add-variable.png[add variable button]. + Select **Save**. The alert has been created and is now active! [float] [[apm-create-error-alert]] === Create an error rate alert +Error rate alerts trigger when the number of errors in a service exceeds a defined threshold. This guide creates an alert for the `opbeans-python` service based on the following criteria: +* Environment: Production * Error rate is above 25 for the last minute * Check every 1 minute, and repeat the alert every 10 minutes * Send the alert via email to the `opbeans-python` team @@ -81,6 +94,12 @@ Based on the alert criteria, define the following alert details: Select the **Email** action type and click **Create a connector**. Fill out the required details: sender, host, port, etc., and click **save**. +Add a message body in markdown format. +You can use the https://mustache.github.io/[Mustache] template syntax, i.e., `{{variable}}` +to pass alert values at the time a condition is detected to an action. +A list of available variables can be accessed by selecting the +**add variable** button image:apm/images/add-variable.png[add variable button]. + Select **Save**. The alert has been created and is now active! [float] diff --git a/docs/apm/images/add-variable.png b/docs/apm/images/add-variable.png new file mode 100644 index 0000000000000000000000000000000000000000..860ab66f22f4e28bee273f3d638b1fc1ad3f863a GIT binary patch literal 4043 zcmZ`*by$>L)4%C%St)^~LttGRVOcsPmQa^wDFK0{WGRvEMnbw32??nOK?FgiL`rF- zaS0JA5qKB%d!Fa|-s?Tr^*b|XW_~kg=01PiF$g^kDsmQb005}8G*u08lIsGb#JF8f zgQ5!n$Ui%&s35ddR5%fyXa^@3djQakNzWufq)mc?cg`P25#o~-X_B>*jgWEjhJ)Zr za?#qF_+-41myBJWT&-C!MbN#fFOK6P&nSzgsp#)U$BLnrAQ8>X|4c;iCjJnYM$?y z=GC(J)W}tRt>eY{j{2D%Cx~Z5w;5Om)jzQT@-hAC4glO!bu(Vxl9)c~QbcV@mKZ&^ zd2p?m{@WGq_+_F|FHcb7E^XID^h-hjN`-QmDzI_*$s3d{1k21RT8!!FCE^fB)v9m3 zarVCCcs@0)I%@zGb2Syg!jj-& zV%{hn;Paa2aa^eEQyEXaO&$t6rE6(dEtsnN(nakX_#O%8^;N!&HJXgTPZSF3fJmWI z_f&Tq_)Rhx8DJ~jwP^=`CF|jb`ni2pTr`N4R6C7|pG1>jp|-1H>W#M(&4()54W5b*EJv#8LZbn2Fy10u zDw#lVA=H`^--a`p0@VK|8zuJeYDz3L+>@BX&jX)WW56qG$lb?V-EHpENnQ*6&ic|0 zeX&(eeRTz1=US;@g}kIaMH^9PoiPwiWh9050}wy(T0FBKC$H*$8n#trf)la?6Mqk; zgAhz~vda))7N~wI(UKCRaDsS3j)O_UIY}x4>5#;?Lbwq4QX#H|_?vhqol5S6Y$Uo1 z5;8QRVb}#w3kiFe+c1e`2_mCwv5vnv``Pdo zLP(Hb@KBID+gO)>P;-!Na6dar;+ZqG9A93F?SgR3^ zZ1tQ~g#_tp->F@vBuZ-nvoOc7GU5|TH>P+d7UoDMZAuK2C4>!H%zDgf&*Ca6cUQtu zNAf@t#Eh1N-T9eXG-!RTo_QrcE*`}|kcME0cxRbLon~MpJSsCfUcO(hKN#(x)8O4u z?cnOrz1q9lFp&A^W42;FClVqO4w@F35`iI2P56*CjV|?UwIhv-$Q843Q-wM{vlEjw z)7vKVjjyI4uJtZHlQZ=ZuCp!?P3cY2Th`Yx*HdOi+lDr>Hu6V%Mk~wboB1ajHupB~ zZUwNdQ`1pbUdd*&d=Du|k+;?bJC9Q>*%m?d5~Y%t7+BcQlia;D<{sHC-<1(%LCGKSCj54|Vp45FvikFZ z&^r->Q&8+Xm$=ErN!=9AREAdGZ%z+y8oP~E$bOPF@Df^k5$zLe37TbBNid=H5?HQY)|n#L;e;H*@$ zSdU1VK-t~=@fSUNHA5c@3KY%<@Dqq;i1-b!RghIg8NPJqZoN5^BB3`m^c=;W)0}r0 zyYqg&kK@u2sW#E+25h5jgMb;vYz8Hc2- zg0yTe!z$h(dMk6s=kB{*dNFyWnj?AG^fnO;l0~#SL#f`c-a(d%`JtOY72~|1|F^(B zp*@&rtd+M--Kx#*BI^y8%qp{y0*>7CQN!HGQW0{myU3%PP;2X|?5L!?m@AwTErVJI--qaiwa9AN`-r?kW5T_;7dy zYd*1sJgm;L3aoxzS6a2)??3nBuAX(+&k9zkVJD3x#?O}UnMjhHJjPI({pxox}|vS!PAO~XQCBn{_w!U z6YKA<;w0H6C8H>*U8^GQGB$=q8Bx#6(fgLR4t2Pp71}$N1!SJe{P>3aQdhI|`OUN* zM1SnmWp{6g*jdGcd#t6@qebh}*lh0Dj30E<&MXddqgyb_h(s?Zw?@9?zQdBq;$&At zpV#r4x+!n9%9{AlVUvhsKp=RxYc|eH)W@9srT2>G*ADac>~J!2)lAn)!E@%=i{-zs)usb!f!&3LM^$8p`t?B&@p=6oJa$xnUQ zp3-5^VR5dvGaI64e(uN`!{T=UTRUBkT1@iipb4@Gaz4-f+WNrz!{wRGZ_lKx%sL_- z1QZV#2=ST=VgfJ0!4!J>Bnw-3b}&8s;Mf7$*R2eD`z>&WdBP>aGY0*Eg{4Jm_?6;b zb#5PFKqJN81PG2)1Z-^$suY7Q%#E>DTsJTt`O#|1ZhozhX}HYn3^&s5vuQ zasRxr_DC%UU0py3r;`GNcq{-BPQ$|ihR6E1u8t=F5d5;^13;7$K=>y{4<|2HG7cA< z-;y9T5+K2y=yC8Z#Q!^*tB~Ly9p?j-j8wF=aMH-u)85|A%MtCpQCc33GmyD!ns@;K zi1z|`T82DdarwubjFH|*T^%`Fw5uq}4sByE>g(!$kq40XmBXp7_TDH?Uso45FF9WY zu3r&yIQ_yb#>M$7#QUxS7g86&se<;j=adwc5QT8T$T>MV$I3)!xh2)5+c2 z3GK#tkr!oyzUQsL#dT5W@Adnh_P$R4RC4qB(-y8lu?vsbHBpGz-??#A`3tKY!pYa( z1*z)fiklg(225N+{#W>aIsPg5n|Ra9-ctqbisO01{+an7^1q$`pZKey$^WYOFUKFE zyx2wG|C+<^A^)=CrVJyO7yJ8*!N|u>UtBycHYZhmW1Pf2v0sZ0w+rBKAulk(%hoZ9 zllfYzO2$Yso1Zj?<)JkBg9EX;}$S0&C<8Ma7V zq=L#oXo_=gKvah%lTp&K83s{>ge1u-9?^xYz*31>cpOcfO%{xaqdb3IBGe6trxA~) zrD|X*r|FH_;GP0Qs2+}RkAfegU!r6J) z?|q}jja>uxfLka_1I89S-xg|Bh4Gz)D#xbc56+wC7s*Z}yW8|I@{ZAF(&K}6(^Wyc zW3{w7%$yoJn%u=B-Q|yxnVv8YH?ER*_omV83K6Mkm_$>13<59s=#mL}7aE%9p}BvZ xW`FKYOR^p>{4%F=^WiJx&8%0Kkg3H4fU#e=kto4e9^7yNEj2yW8fELy{{U?O1{44Q literal 0 HcmV?d00001 From f0002f4a32a14263053693f350ec3da23b64cfbb Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Mon, 29 Jun 2020 16:07:13 -0700 Subject: [PATCH 21/91] [APM] docs: unique transaction troubleshooting (#69831) (#70269) * docs: draft * docs: finishing touches --- docs/apm/troubleshooting.asciidoc | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/docs/apm/troubleshooting.asciidoc b/docs/apm/troubleshooting.asciidoc index cb16082c290a3b..7da8f73bed1c62 100644 --- a/docs/apm/troubleshooting.asciidoc +++ b/docs/apm/troubleshooting.asciidoc @@ -10,6 +10,11 @@ your proposed changes in the https://github.com/elastic/kibana[Kibana repository Also, check out the https://discuss.elastic.co/c/apm[APM discussion forum]. +* <> +* <> +* <> +* <> + [float] [[no-apm-data-found]] === No APM data found @@ -58,6 +63,66 @@ Navigate to *APM* > *Settings* > *Indices*, and change all `apm_oss.*Pattern` va include the new index pattern. For example: `customIndexName-*`. [float] +[[troubleshooting-too-many-transactions]] +=== Too many unique transaction names + +Transaction names are defined in each APM Agent; when an Agent supports a framework, +it includes logic for naming the transactions that the framework creates. +In some cases though, like when using an Agent's API to create custom transactions, +it is up to the user to define a pattern for transaction naming. +When transactions are named incorrectly, each unique URL can be associated with a unique transaction group—causing +an explosion in the number of transaction groups per service, and leading to inaccuracies in the APM app. + +To fix a large number of unique transaction names, +you need to change how you are using the Agent API to name your transactions. +To do this, ensure you are **not** naming based on parameters that can change. +For example, user ids, product ids, order numbers, query parameters, etc., +should be stripped away, and commonality should be found between your unique URLs. + +Let's look at an example from the RUM Agent documentation. Here are a few URLs you might find on Elastic.co: + +[source,yml] +---- +// Blog Posts +https://www.elastic.co/blog/reflections-on-three-years-in-the-elastic-public-sector +https://www.elastic.co/blog/say-heya-to-the-elastic-search-awards +https://www.elastic.co/blog/and-the-winner-of-the-elasticon-2018-training-subscription-drawing-is + +// Documentation +https://www.elastic.co/guide/en/elastic-stack/current/index.html +https://www.elastic.co/guide/en/apm/get-started/current/index.html +https://www.elastic.co/guide/en/infrastructure/guide/current/index.html +---- + +These URLs, like most, include unique names. +If we named transactions based on each unique URL, we'd end up with the problem described above—a +very large number of different transaction names. +Instead, we should strip away the unique information and group our transactions based on common information. +In this case, that means naming all blog transactions, `/blog`, and all documentation transactions, `/guide`. + +If you feel like you'd be losing valuable information by following this naming convention, don't fret! +You can always add additional metadata to your transactions using {apm-overview-ref-v}/metadata.html#labels-fields[labels] (indexed) or +{apm-overview-ref-v}/metadata.html#custom-fields[custom context] (non-indexed). + +After ensuring you've correctly named your transactions, +you might still see an error in the APM app related to too many transaction names. +If this is the case, you can increase the default number of transaction groups displayed in the APM app by configuring +<>. + +**More information** + +While this can happen with any APM Agent, it typically occurs with the RUM Agent. +For more information on how to correctly set `transaction.name` in the RUM Agent, +see {apm-rum-ref}/custom-transaction-name.html[custom initial page load transaction names]. + +The RUM Agent can also set the `transaction.name` when observing for transaction events. +See {apm-rum-ref}/agent-api.html#observe[`apm.observe()`] for more information. + +If your problem is occurring in a different Agent, the tips above still apply. +See the relevant {apm-agents-ref}[Agent API documentation] to adjust how you're naming your transactions. + +[float] +[[troubleshooting-unknown-route]] === Unknown route The {apm-app-ref}/transactions.html[transaction overview] will only display helpful information @@ -78,6 +143,7 @@ Specifically, view the Agent's supported technologies page. You can also use the Agent's public API to manually set a name for the transaction. [float] +[[troubleshooting-fields-unsearchable]] === Fields are not searchable In Elasticsearch, index templates are used to define settings and mappings that determine how fields should be analyzed. From 2e07eb4476889761dc6ee2647ebe604ca5a91710 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Mon, 29 Jun 2020 16:07:26 -0700 Subject: [PATCH 22/91] [Ingest Manager] Support updated package output structure (#69864) (#70263) * Update EPM package registry typings to reflect registry changes * Change `dataset.id` references to `dataset.name` * Fix RegistryStream * Fix packageToConfigDatasourceInputs service * Fix assignPackageStream service * Fix validateDatasource service * Fix configure data source components * Fix variable * Fix stream template installation * Add support for `input[].dataset.type` and change `stream.dataset` mapping to be object containing `name` with instead of just a string * Nest package information under `meta` in agent config yaml * Move `dataset.type` to stream level instead of input level * Make single call to fetch registry package information instead of doing it per stream * Fix type issues * Update endpoint test assertion Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../common/services/config_to_yaml.ts | 2 +- .../datasources_to_agent_inputs.test.ts | 30 +++- .../services/datasources_to_agent_inputs.ts | 14 +- .../common/services/package_to_config.test.ts | 150 +++++++++++------- .../common/services/package_to_config.ts | 62 ++++++-- .../common/types/models/agent_config.ts | 5 +- .../common/types/models/datasource.ts | 5 +- .../ingest_manager/common/types/models/epm.ts | 19 +-- .../components/datasource_input_panel.tsx | 19 ++- .../datasource_input_stream_config.tsx | 2 +- .../services/validate_datasource.test.ts | 134 +++++++++------- .../services/validate_datasource.ts | 24 ++- .../step_configure_datasource.tsx | 36 ++++- .../ingest_manager/types/index.ts | 2 +- .../server/saved_objects/index.ts | 7 +- .../migrations/datasources_v790.ts | 19 ++- .../server/services/datasource.test.ts | 75 +++++---- .../server/services/datasource.ts | 66 +++++--- .../services/epm/elasticsearch/index.test.ts | 2 +- .../services/epm/elasticsearch/index.ts | 2 +- .../ingest_pipeline/ingest_pipelines.test.ts | 8 +- .../elasticsearch/ingest_pipeline/install.ts | 2 +- .../server/services/epm/packages/assets.ts | 10 -- .../ingest_manager/server/types/index.tsx | 2 + .../server/types/models/datasource.ts | 3 +- .../server/types/models/output.ts | 1 - .../apps/endpoint/policy_details.ts | 8 +- 27 files changed, 461 insertions(+), 248 deletions(-) diff --git a/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts b/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts index a3bef72e8db5a3..c2043a40369e28 100644 --- a/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts +++ b/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts @@ -16,7 +16,7 @@ const CONFIG_KEYS_ORDER = [ 'inputs', 'enabled', 'use_output', - 'package', + 'meta', 'input', ]; diff --git a/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.test.ts b/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.test.ts index df94168ec88d02..538951ff103992 100644 --- a/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.test.ts +++ b/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.test.ts @@ -39,7 +39,7 @@ describe('Ingest Manager - storedDatasourcesToAgentInputs', () => { { id: 'test-logs-foo', enabled: true, - dataset: 'foo', + dataset: { name: 'foo', type: 'logs' }, vars: { fooVar: { value: 'foo-value' }, fooVar2: { value: [1, 2] }, @@ -52,7 +52,7 @@ describe('Ingest Manager - storedDatasourcesToAgentInputs', () => { { id: 'test-logs-bar', enabled: true, - dataset: 'bar', + dataset: { name: 'bar', type: 'logs' }, vars: { barVar: { value: 'bar-value' }, barVar2: { value: [1, 2] }, @@ -101,23 +101,41 @@ describe('Ingest Manager - storedDatasourcesToAgentInputs', () => { }); it('returns agent inputs', () => { - expect(storedDatasourcesToAgentInputs([{ ...mockDatasource, inputs: [mockInput] }])).toEqual([ + expect( + storedDatasourcesToAgentInputs([ + { + ...mockDatasource, + package: { + name: 'mock-package', + title: 'Mock package', + version: '0.0.0', + }, + inputs: [mockInput], + }, + ]) + ).toEqual([ { id: 'some-uuid', name: 'mock-datasource', type: 'test-logs', dataset: { namespace: 'default' }, use_output: 'default', + meta: { + package: { + name: 'mock-package', + version: '0.0.0', + }, + }, streams: [ { id: 'test-logs-foo', - dataset: { name: 'foo' }, + dataset: { name: 'foo', type: 'logs' }, fooKey: 'fooValue1', fooKey2: ['fooValue2'], }, { id: 'test-logs-bar', - dataset: { name: 'bar' }, + dataset: { name: 'bar', type: 'logs' }, }, ], }, @@ -147,7 +165,7 @@ describe('Ingest Manager - storedDatasourcesToAgentInputs', () => { streams: [ { id: 'test-logs-foo', - dataset: { name: 'foo' }, + dataset: { name: 'foo', type: 'logs' }, fooKey: 'fooValue1', fooKey2: ['fooValue2'], }, diff --git a/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.ts b/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.ts index d5a752e817b4f2..c6c5d784396db3 100644 --- a/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.ts +++ b/x-pack/plugins/ingest_manager/common/services/datasources_to_agent_inputs.ts @@ -24,7 +24,9 @@ export const storedDatasourcesToAgentInputs = ( id: datasource.id || datasource.name, name: datasource.name, type: input.type, - dataset: { namespace: datasource.namespace || 'default' }, + dataset: { + namespace: datasource.namespace || 'default', + }, use_output: DEFAULT_OUTPUT.name, ...Object.entries(input.config || {}).reduce((acc, [key, { value }]) => { acc[key] = value; @@ -35,7 +37,7 @@ export const storedDatasourcesToAgentInputs = ( .map((stream) => { const fullStream: FullAgentConfigInputStream = { id: stream.id, - dataset: { name: stream.dataset }, + dataset: stream.dataset, ...stream.agent_stream, ...Object.entries(stream.config || {}).reduce((acc, [key, { value }]) => { acc[key] = value; @@ -50,9 +52,11 @@ export const storedDatasourcesToAgentInputs = ( }; if (datasource.package) { - fullInput.package = { - name: datasource.package.name, - version: datasource.package.version, + fullInput.meta = { + package: { + name: datasource.package.name, + version: datasource.package.version, + }, }; } diff --git a/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts b/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts index a977a1a66e059a..7739fdc3a3b611 100644 --- a/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts +++ b/x-pack/plugins/ingest_manager/common/services/package_to_config.test.ts @@ -34,14 +34,14 @@ describe('Ingest Manager - packageToConfig', () => { describe('packageToConfigDatasourceInputs', () => { it('returns empty array for packages with no datasources', () => { expect(packageToConfigDatasourceInputs(mockPackage)).toEqual([]); - expect(packageToConfigDatasourceInputs({ ...mockPackage, datasources: [] })).toEqual([]); + expect(packageToConfigDatasourceInputs({ ...mockPackage, config_templates: [] })).toEqual([]); }); it('returns empty array for packages a datasource but no inputs', () => { expect( packageToConfigDatasourceInputs(({ ...mockPackage, - datasources: [{ inputs: [] }], + config_templates: [{ inputs: [] }], } as unknown) as PackageInfo) ).toEqual([]); }); @@ -50,13 +50,13 @@ describe('Ingest Manager - packageToConfig', () => { expect( packageToConfigDatasourceInputs(({ ...mockPackage, - datasources: [{ inputs: [{ type: 'foo' }] }], + config_templates: [{ inputs: [{ type: 'foo' }] }], } as unknown) as PackageInfo) ).toEqual([{ type: 'foo', enabled: true, streams: [] }]); expect( packageToConfigDatasourceInputs(({ ...mockPackage, - datasources: [{ inputs: [{ type: 'foo' }, { type: 'bar' }] }], + config_templates: [{ inputs: [{ type: 'foo' }, { type: 'bar' }] }], } as unknown) as PackageInfo) ).toEqual([ { type: 'foo', enabled: true, streams: [] }, @@ -68,12 +68,14 @@ describe('Ingest Manager - packageToConfig', () => { expect( packageToConfigDatasourceInputs(({ ...mockPackage, - datasources: [ + datasets: [ + { type: 'logs', name: 'foo', streams: [{ input: 'foo' }] }, + { type: 'logs', name: 'bar', streams: [{ input: 'bar' }] }, + { type: 'logs', name: 'bar2', streams: [{ input: 'bar' }] }, + ], + config_templates: [ { - inputs: [ - { type: 'foo', streams: [{ dataset: 'foo' }] }, - { type: 'bar', streams: [{ dataset: 'bar' }, { dataset: 'bar2' }] }, - ], + inputs: [{ type: 'foo' }, { type: 'bar' }], }, ], } as unknown) as PackageInfo) @@ -81,14 +83,14 @@ describe('Ingest Manager - packageToConfig', () => { { type: 'foo', enabled: true, - streams: [{ id: 'foo-foo', enabled: true, dataset: 'foo' }], + streams: [{ id: 'foo-foo', enabled: true, dataset: { name: 'foo', type: 'logs' } }], }, { type: 'bar', enabled: true, streams: [ - { id: 'bar-bar', enabled: true, dataset: 'bar' }, - { id: 'bar-bar2', enabled: true, dataset: 'bar2' }, + { id: 'bar-bar', enabled: true, dataset: { name: 'bar', type: 'logs' } }, + { id: 'bar-bar2', enabled: true, dataset: { name: 'bar2', type: 'logs' } }, ], }, ]); @@ -98,31 +100,38 @@ describe('Ingest Manager - packageToConfig', () => { expect( packageToConfigDatasourceInputs(({ ...mockPackage, - datasources: [ + datasets: [ { - inputs: [ + type: 'logs', + name: 'foo', + streams: [{ input: 'foo', vars: [{ default: 'foo-var-value', name: 'var-name' }] }], + }, + { + type: 'logs', + name: 'bar', + streams: [ { - type: 'foo', - streams: [ - { dataset: 'foo', vars: [{ default: 'foo-var-value', name: 'var-name' }] }, - ], + input: 'bar', + vars: [{ default: 'bar-var-value', name: 'var-name', type: 'text' }], }, + ], + }, + { + type: 'logs', + name: 'bar2', + streams: [ { - type: 'bar', - streams: [ - { - dataset: 'bar', - vars: [{ default: 'bar-var-value', name: 'var-name', type: 'text' }], - }, - { - dataset: 'bar2', - vars: [{ default: 'bar2-var-value', name: 'var-name', type: 'yaml' }], - }, - ], + input: 'bar', + vars: [{ default: 'bar2-var-value', name: 'var-name', type: 'yaml' }], }, ], }, ], + config_templates: [ + { + inputs: [{ type: 'foo' }, { type: 'bar' }], + }, + ], } as unknown) as PackageInfo) ).toEqual([ { @@ -132,7 +141,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'foo-foo', enabled: true, - dataset: 'foo', + dataset: { name: 'foo', type: 'logs' }, vars: { 'var-name': { value: 'foo-var-value' } }, }, ], @@ -144,13 +153,13 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'bar-bar', enabled: true, - dataset: 'bar', + dataset: { name: 'bar', type: 'logs' }, vars: { 'var-name': { type: 'text', value: 'bar-var-value' } }, }, { id: 'bar-bar2', enabled: true, - dataset: 'bar2', + dataset: { name: 'bar2', type: 'logs' }, vars: { 'var-name': { type: 'yaml', value: 'bar2-var-value' } }, }, ], @@ -162,7 +171,55 @@ describe('Ingest Manager - packageToConfig', () => { expect( packageToConfigDatasourceInputs(({ ...mockPackage, - datasources: [ + datasets: [ + { + type: 'logs', + name: 'foo', + streams: [{ input: 'foo', vars: [{ default: 'foo-var-value', name: 'var-name' }] }], + }, + { + type: 'logs', + name: 'bar', + streams: [ + { + input: 'bar', + vars: [{ default: 'bar-var-value', name: 'var-name' }], + }, + ], + }, + { + type: 'logs', + name: 'bar2', + streams: [ + { + input: 'bar', + vars: [{ default: 'bar2-var-value', name: 'var-name' }], + }, + ], + }, + { + type: 'logs', + name: 'disabled', + streams: [ + { + input: 'with-disabled-streams', + enabled: false, + vars: [{ multi: true, name: 'var-name' }], + }, + ], + }, + { + type: 'logs', + name: 'disabled2', + streams: [ + { + input: 'with-disabled-streams', + enabled: false, + }, + ], + }, + ], + config_templates: [ { inputs: [ { @@ -172,9 +229,6 @@ describe('Ingest Manager - packageToConfig', () => { { default: 'foo-input2-var-value', name: 'foo-input2-var-name' }, { name: 'foo-input3-var-name' }, ], - streams: [ - { dataset: 'foo', vars: [{ default: 'foo-var-value', name: 'var-name' }] }, - ], }, { type: 'bar', @@ -182,21 +236,9 @@ describe('Ingest Manager - packageToConfig', () => { { default: ['value1', 'value2'], name: 'bar-input-var-name' }, { default: 123456, name: 'bar-input2-var-name' }, ], - streams: [ - { dataset: 'bar', vars: [{ default: 'bar-var-value', name: 'var-name' }] }, - { dataset: 'bar2', vars: [{ default: 'bar2-var-value', name: 'var-name' }] }, - ], }, { type: 'with-disabled-streams', - streams: [ - { - dataset: 'disabled', - enabled: false, - vars: [{ multi: true, name: 'var-name' }], - }, - { dataset: 'disabled2', enabled: false }, - ], }, ], }, @@ -215,7 +257,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'foo-foo', enabled: true, - dataset: 'foo', + dataset: { name: 'foo', type: 'logs' }, vars: { 'var-name': { value: 'foo-var-value' }, }, @@ -233,7 +275,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'bar-bar', enabled: true, - dataset: 'bar', + dataset: { name: 'bar', type: 'logs' }, vars: { 'var-name': { value: 'bar-var-value' }, }, @@ -241,7 +283,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'bar-bar2', enabled: true, - dataset: 'bar2', + dataset: { name: 'bar2', type: 'logs' }, vars: { 'var-name': { value: 'bar2-var-value' }, }, @@ -255,7 +297,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'with-disabled-streams-disabled', enabled: false, - dataset: 'disabled', + dataset: { name: 'disabled', type: 'logs' }, vars: { 'var-name': { value: [] }, }, @@ -263,7 +305,7 @@ describe('Ingest Manager - packageToConfig', () => { { id: 'with-disabled-streams-disabled2', enabled: false, - dataset: 'disabled2', + dataset: { name: 'disabled2', type: 'logs' }, }, ], }, @@ -328,7 +370,7 @@ describe('Ingest Manager - packageToConfig', () => { it('returns datasource with inputs', () => { const mockPackageWithDatasources = ({ ...mockPackage, - datasources: [{ inputs: [{ type: 'foo' }] }], + config_templates: [{ inputs: [{ type: 'foo' }] }], } as unknown) as PackageInfo; expect(packageToConfigDatasource(mockPackageWithDatasources, '1', '2', 'ds-1')).toEqual({ diff --git a/x-pack/plugins/ingest_manager/common/services/package_to_config.ts b/x-pack/plugins/ingest_manager/common/services/package_to_config.ts index dc0f73b47c599a..1817077e97f9c1 100644 --- a/x-pack/plugins/ingest_manager/common/services/package_to_config.ts +++ b/x-pack/plugins/ingest_manager/common/services/package_to_config.ts @@ -5,8 +5,9 @@ */ import { PackageInfo, - RegistryDatasource, + RegistryConfigTemplate, RegistryVarsEntry, + RegistryStream, Datasource, DatasourceConfigRecord, DatasourceConfigRecordEntry, @@ -15,6 +16,29 @@ import { NewDatasource, } from '../types'; +const getStreamsForInputType = ( + inputType: string, + packageInfo: PackageInfo +): Array => { + const streams: Array = []; + + (packageInfo.datasets || []).forEach((dataset) => { + (dataset.streams || []).forEach((stream) => { + if (stream.input === inputType) { + streams.push({ + ...stream, + dataset: { + type: dataset.type, + name: dataset.name, + }, + }); + } + }); + }); + + return streams; +}; + /* * This service creates a datasource inputs definition from defaults provided in package info */ @@ -22,8 +46,10 @@ export const packageToConfigDatasourceInputs = (packageInfo: PackageInfo): Datas const inputs: Datasource['inputs'] = []; // Assume package will only ever ship one datasource for now - const packageDatasource: RegistryDatasource | null = - packageInfo.datasources && packageInfo.datasources[0] ? packageInfo.datasources[0] : null; + const packageDatasource: RegistryConfigTemplate | null = + packageInfo.config_templates && packageInfo.config_templates[0] + ? packageInfo.config_templates[0] + : null; // Create datasource input property if (packageDatasource?.inputs?.length) { @@ -45,19 +71,23 @@ export const packageToConfigDatasourceInputs = (packageInfo: PackageInfo): Datas }; // Map each package input stream into datasource input stream - const streams: DatasourceInputStream[] = packageInput.streams - ? packageInput.streams.map((packageStream) => { - const stream: DatasourceInputStream = { - id: `${packageInput.type}-${packageStream.dataset}`, - enabled: packageStream.enabled === false ? false : true, - dataset: packageStream.dataset, - }; - if (packageStream.vars && packageStream.vars.length) { - stream.vars = packageStream.vars.reduce(varsReducer, {}); - } - return stream; - }) - : []; + const streams: DatasourceInputStream[] = getStreamsForInputType( + packageInput.type, + packageInfo + ).map((packageStream) => { + const stream: DatasourceInputStream = { + id: `${packageInput.type}-${packageStream.dataset.name}`, + enabled: packageStream.enabled === false ? false : true, + dataset: { + name: packageStream.dataset.name, + type: packageStream.dataset.type, + }, + }; + if (packageStream.vars && packageStream.vars.length) { + stream.vars = packageStream.vars.reduce(varsReducer, {}); + } + return stream; + }); const input: DatasourceInput = { type: packageInput.type, diff --git a/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts b/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts index 36b3176ffa4151..0d7dc13af7a30b 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/agent_config.ts @@ -41,7 +41,10 @@ export interface FullAgentConfigInput { type: string; dataset: { namespace: string }; use_output: string; - package?: Pick; + meta?: { + package?: Pick; + [key: string]: unknown; + }; streams: FullAgentConfigInputStream[]; [key: string]: any; } diff --git a/x-pack/plugins/ingest_manager/common/types/models/datasource.ts b/x-pack/plugins/ingest_manager/common/types/models/datasource.ts index aa92b90a6caec2..aae65bb0039959 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/datasource.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/datasource.ts @@ -20,7 +20,10 @@ export type DatasourceConfigRecord = Record export interface NewDatasourceInputStream { id: string; enabled: boolean; - dataset: string; + dataset: { + name: string; + type: string; + }; processors?: string[]; config?: DatasourceConfigRecord; vars?: DatasourceConfigRecord; diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index 599165d2bfd981..3ae0628fa695d2 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -60,7 +60,7 @@ export interface RegistryPackage { internal?: boolean; format_version: string; datasets?: Dataset[]; - datasources?: RegistryDatasource[]; + config_templates?: RegistryConfigTemplate[]; download: string; path: string; } @@ -74,7 +74,7 @@ interface RegistryImage { size?: string; type?: string; } -export interface RegistryDatasource { +export interface RegistryConfigTemplate { name: string; title: string; description: string; @@ -86,17 +86,15 @@ export interface RegistryInput { title: string; description?: string; vars?: RegistryVarsEntry[]; - streams: RegistryStream[]; } export interface RegistryStream { input: string; - dataset: string; title: string; description?: string; enabled?: boolean; vars?: RegistryVarsEntry[]; - template?: string; + template_path: string; } export type RequirementVersion = string; @@ -122,7 +120,7 @@ export type RegistrySearchResult = Pick< | 'download' | 'path' | 'datasets' - | 'datasources' + | 'config_templates' >; export type ScreenshotItem = RegistryImage; @@ -169,15 +167,14 @@ export type ElasticsearchAssetTypeToParts = Record< >; export interface Dataset { + type: string; + name: string; title: string; - path: string; - id: string; release: string; - ingest_pipeline: string; - vars?: RegistryVarsEntry[]; - type: string; streams?: RegistryStream[]; package: string; + path: string; + ingest_pipeline: string; } // EPR types this as `[]map[string]interface{}` diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_panel.tsx index db704d8b1d0f3c..6f6fa5aaa7f3e8 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_panel.tsx @@ -19,7 +19,12 @@ import { EuiSpacer, EuiIconTip, } from '@elastic/eui'; -import { DatasourceInput, DatasourceInputStream, RegistryInput } from '../../../../types'; +import { + DatasourceInput, + DatasourceInputStream, + RegistryInput, + RegistryStream, +} from '../../../../types'; import { DatasourceInputValidationResults, validationHasErrors } from '../services'; import { DatasourceInputConfig } from './datasource_input_config'; import { DatasourceInputStreamConfig } from './datasource_input_stream_config'; @@ -32,12 +37,14 @@ const FlushHorizontalRule = styled(EuiHorizontalRule)` export const DatasourceInputPanel: React.FunctionComponent<{ packageInput: RegistryInput; + packageInputStreams: Array; datasourceInput: DatasourceInput; updateDatasourceInput: (updatedInput: Partial) => void; inputValidationResults: DatasourceInputValidationResults; forceShowErrors?: boolean; }> = ({ packageInput, + packageInputStreams, datasourceInput, updateDatasourceInput, inputValidationResults, @@ -111,7 +118,7 @@ export const DatasourceInputPanel: React.FunctionComponent<{ ), - total: packageInput.streams.length, + total: packageInputStreams.length, }} /> @@ -168,18 +175,18 @@ export const DatasourceInputPanel: React.FunctionComponent<{ {/* Per-stream configuration */} {isShowingStreams ? ( - {packageInput.streams.map((packageInputStream) => { + {packageInputStreams.map((packageInputStream) => { const datasourceInputStream = datasourceInput.streams.find( - (stream) => stream.dataset === packageInputStream.dataset + (stream) => stream.dataset.name === packageInputStream.dataset.name ); return datasourceInputStream ? ( - + ) => { const indexOfUpdatedStream = datasourceInput.streams.findIndex( - (stream) => stream.dataset === packageInputStream.dataset + (stream) => stream.dataset.name === packageInputStream.dataset.name ); const newStreams = [...datasourceInput.streams]; newStreams[indexOfUpdatedStream] = { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_stream_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_stream_config.tsx index 978ad83cd5c3c9..f697ef736ef705 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_stream_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/datasource_input_stream_config.tsx @@ -60,7 +60,7 @@ export const DatasourceInputStreamConfig: React.FunctionComponent<{ - {packageInputStream.title || packageInputStream.dataset} + {packageInputStream.title} {hasErrors ? ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.test.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.test.ts index 67cde2dec3a56e..64facf01d474a7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.test.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.test.ts @@ -7,7 +7,7 @@ import { PackageInfo, InstallationStatus, NewDatasource, - RegistryDatasource, + RegistryConfigTemplate, } from '../../../../types'; import { validateDatasource, validationHasErrors } from './validate_datasource'; @@ -32,7 +32,65 @@ describe('Ingest Manager - validateDatasource()', () => { }, }, status: InstallationStatus.notInstalled, - datasources: [ + datasets: [ + { + name: 'foo', + streams: [ + { + input: 'foo', + title: 'Foo', + vars: [{ name: 'var-name', type: 'yaml' }], + }, + ], + }, + { + name: 'bar', + streams: [ + { + input: 'bar', + title: 'Bar', + vars: [{ name: 'var-name', type: 'yaml', required: true }], + }, + { + input: 'with-no-stream-vars', + title: 'Bar stream no vars', + enabled: true, + }, + ], + }, + { + name: 'bar2', + streams: [ + { + input: 'bar', + title: 'Bar 2', + vars: [{ default: 'bar2-var-value', name: 'var-name', type: 'text' }], + }, + ], + }, + { + name: 'disabled', + streams: [ + { + input: 'with-disabled-streams', + title: 'Disabled', + enabled: false, + vars: [{ multi: true, required: true, name: 'var-name', type: 'text' }], + }, + ], + }, + { + name: 'disabled2', + streams: [ + { + input: 'with-disabled-streams', + title: 'Disabled 2', + enabled: false, + }, + ], + }, + ], + config_templates: [ { name: 'datasource1', title: 'Datasource 1', @@ -51,14 +109,6 @@ describe('Ingest Manager - validateDatasource()', () => { }, { name: 'foo-input3-var-name', type: 'text', required: true, multi: true }, ], - streams: [ - { - dataset: 'foo', - input: 'foo', - title: 'Foo', - vars: [{ name: 'var-name', type: 'yaml' }], - }, - ], }, { type: 'bar', @@ -72,51 +122,19 @@ describe('Ingest Manager - validateDatasource()', () => { }, { name: 'bar-input2-var-name', required: true, type: 'text' }, ], - streams: [ - { - dataset: 'bar', - input: 'bar', - title: 'Bar', - vars: [{ name: 'var-name', type: 'yaml', required: true }], - }, - { - dataset: 'bar2', - input: 'bar2', - title: 'Bar 2', - vars: [{ default: 'bar2-var-value', name: 'var-name', type: 'text' }], - }, - ], }, { type: 'with-no-config-or-streams', title: 'With no config or streams', - streams: [], }, { type: 'with-disabled-streams', title: 'With disabled streams', - streams: [ - { - dataset: 'disabled', - input: 'disabled', - title: 'Disabled', - enabled: false, - vars: [{ multi: true, required: true, name: 'var-name', type: 'text' }], - }, - { dataset: 'disabled2', input: 'disabled2', title: 'Disabled 2', enabled: false }, - ], }, { type: 'with-no-stream-vars', enabled: true, vars: [{ required: true, name: 'var-name', type: 'text' }], - streams: [ - { - id: 'with-no-stream-vars-bar', - dataset: 'bar', - enabled: true, - }, - ], }, ], }, @@ -140,7 +158,7 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'foo-foo', - dataset: 'foo', + dataset: { name: 'foo', type: 'logs' }, enabled: true, vars: { 'var-name': { value: 'test_yaml: value', type: 'yaml' } }, }, @@ -156,13 +174,13 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'bar-bar', - dataset: 'bar', + dataset: { name: 'bar', type: 'logs' }, enabled: true, vars: { 'var-name': { value: 'test_yaml: value', type: 'yaml' } }, }, { id: 'bar-bar2', - dataset: 'bar2', + dataset: { name: 'bar2', type: 'logs' }, enabled: true, vars: { 'var-name': { value: undefined, type: 'text' } }, }, @@ -179,13 +197,13 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'with-disabled-streams-disabled', - dataset: 'disabled', + dataset: { name: 'disabled', type: 'logs' }, enabled: false, vars: { 'var-name': { value: undefined, type: 'text' } }, }, { id: 'with-disabled-streams-disabled-without-vars', - dataset: 'disabled2', + dataset: { name: 'disabled2', type: 'logs' }, enabled: false, }, ], @@ -199,7 +217,7 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'with-no-stream-vars-bar', - dataset: 'bar', + dataset: { name: 'bar', type: 'logs' }, enabled: true, }, ], @@ -222,7 +240,7 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'foo-foo', - dataset: 'foo', + dataset: { name: 'foo', type: 'logs' }, enabled: true, vars: { 'var-name': { value: 'invalidyaml: test\n foo bar:', type: 'yaml' } }, }, @@ -238,13 +256,13 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'bar-bar', - dataset: 'bar', + dataset: { name: 'bar', type: 'logs' }, enabled: true, vars: { 'var-name': { value: ' \n\n', type: 'yaml' } }, }, { id: 'bar-bar2', - dataset: 'bar2', + dataset: { name: 'bar2', type: 'logs' }, enabled: true, vars: { 'var-name': { value: undefined, type: 'text' } }, }, @@ -261,7 +279,7 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'with-disabled-streams-disabled', - dataset: 'disabled', + dataset: { name: 'disabled', type: 'logs' }, enabled: false, vars: { 'var-name': { @@ -272,7 +290,7 @@ describe('Ingest Manager - validateDatasource()', () => { }, { id: 'with-disabled-streams-disabled-without-vars', - dataset: 'disabled2', + dataset: { name: 'disabled2', type: 'logs' }, enabled: false, }, ], @@ -286,7 +304,7 @@ describe('Ingest Manager - validateDatasource()', () => { streams: [ { id: 'with-no-stream-vars-bar', - dataset: 'bar', + dataset: { name: 'bar', type: 'logs' }, enabled: true, }, ], @@ -435,7 +453,7 @@ describe('Ingest Manager - validateDatasource()', () => { expect( validateDatasource(validDatasource, { ...mockPackage, - datasources: undefined, + config_templates: undefined, }) ).toEqual({ name: null, @@ -445,7 +463,7 @@ describe('Ingest Manager - validateDatasource()', () => { expect( validateDatasource(validDatasource, { ...mockPackage, - datasources: [], + config_templates: [], }) ).toEqual({ name: null, @@ -458,7 +476,7 @@ describe('Ingest Manager - validateDatasource()', () => { expect( validateDatasource(validDatasource, { ...mockPackage, - datasources: [{} as RegistryDatasource], + config_templates: [{} as RegistryConfigTemplate], }) ).toEqual({ name: null, @@ -468,7 +486,7 @@ describe('Ingest Manager - validateDatasource()', () => { expect( validateDatasource(validDatasource, { ...mockPackage, - datasources: [({ inputs: [] } as unknown) as RegistryDatasource], + config_templates: [({ inputs: [] } as unknown) as RegistryConfigTemplate], }) ).toEqual({ name: null, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.ts index 5b4cfe170a4786..30dca4a5fbf816 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/services/validate_datasource.ts @@ -13,6 +13,7 @@ import { DatasourceConfigRecordEntry, PackageInfo, RegistryInput, + RegistryStream, RegistryVarsEntry, } from '../../../../types'; @@ -57,11 +58,11 @@ export const validateDatasource = ( } if ( - !packageInfo.datasources || - packageInfo.datasources.length === 0 || - !packageInfo.datasources[0] || - !packageInfo.datasources[0].inputs || - packageInfo.datasources[0].inputs.length === 0 + !packageInfo.config_templates || + packageInfo.config_templates.length === 0 || + !packageInfo.config_templates[0] || + !packageInfo.config_templates[0].inputs || + packageInfo.config_templates[0].inputs.length === 0 ) { validationResults.inputs = null; return validationResults; @@ -70,11 +71,18 @@ export const validateDatasource = ( const registryInputsByType: Record< string, RegistryInput - > = packageInfo.datasources[0].inputs.reduce((inputs, registryInput) => { + > = packageInfo.config_templates[0].inputs.reduce((inputs, registryInput) => { inputs[registryInput.type] = registryInput; return inputs; }, {} as Record); + const registryStreamsByDataset: Record = ( + packageInfo.datasets || [] + ).reduce((datasets, registryDataset) => { + datasets[registryDataset.name] = registryDataset.streams || []; + return datasets; + }, {} as Record); + // Validate each datasource input with either its own config fields or streams datasource.inputs.forEach((input) => { if (!input.vars && !input.streams) { @@ -116,8 +124,8 @@ export const validateDatasource = ( if (stream.vars) { const streamVarsByName = ( ( - registryInputsByType[input.type].streams.find( - (registryStream) => registryStream.dataset === stream.dataset + registryStreamsByDataset[stream.dataset.name].find( + (registryStream) => registryStream.input === input.type ) || {} ).vars || [] ).reduce((vars, registryVar) => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx index 5499ac287ff051..c319dbc08b2c6b 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx @@ -7,12 +7,34 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { PackageInfo, NewDatasource, DatasourceInput } from '../../../types'; +import { PackageInfo, RegistryStream, NewDatasource, DatasourceInput } from '../../../types'; import { Loading } from '../../../components'; import { DatasourceValidationResults, validationHasErrors } from './services'; import { DatasourceInputPanel, CustomConfigureDatasource } from './components'; import { CreateDatasourceFrom } from './types'; +const findStreamsForInputType = ( + inputType: string, + packageInfo: PackageInfo +): Array => { + const streams: Array = []; + + (packageInfo.datasets || []).forEach((dataset) => { + (dataset.streams || []).forEach((stream) => { + if (stream.input === inputType) { + streams.push({ + ...stream, + dataset: { + name: dataset.name, + }, + }); + } + }); + }); + + return streams; +}; + export const StepConfigureDatasource: React.FunctionComponent<{ from?: CreateDatasourceFrom; packageInfo: PackageInfo; @@ -35,19 +57,21 @@ export const StepConfigureDatasource: React.FunctionComponent<{ // Configure inputs (and their streams) // Assume packages only export one datasource for now const renderConfigureInputs = () => - packageInfo.datasources && - packageInfo.datasources[0] && - packageInfo.datasources[0].inputs && - packageInfo.datasources[0].inputs.length ? ( + packageInfo.config_templates && + packageInfo.config_templates[0] && + packageInfo.config_templates[0].inputs && + packageInfo.config_templates[0].inputs.length ? ( - {packageInfo.datasources[0].inputs.map((packageInput) => { + {packageInfo.config_templates[0].inputs.map((packageInput) => { const datasourceInput = datasource.inputs.find( (input) => input.type === packageInput.type ); + const packageInputStreams = findStreamsForInputType(packageInput.type, packageInfo); return datasourceInput ? ( ) => { const indexOfUpdatedInput = datasource.inputs.findIndex( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts index 1a4c6a8a86f6ed..90315f38fd476b 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts @@ -81,7 +81,7 @@ export { RegistryVarsEntry, RegistryInput, RegistryStream, - RegistryDatasource, + RegistryConfigTemplate, PackageList, PackageListItem, PackagesGroupedByStatus, diff --git a/x-pack/plugins/ingest_manager/server/saved_objects/index.ts b/x-pack/plugins/ingest_manager/server/saved_objects/index.ts index 9afc06c193a3b1..d00e403849a768 100644 --- a/x-pack/plugins/ingest_manager/server/saved_objects/index.ts +++ b/x-pack/plugins/ingest_manager/server/saved_objects/index.ts @@ -212,7 +212,12 @@ const savedObjectTypes: { [key: string]: SavedObjectsType } = { properties: { id: { type: 'keyword' }, enabled: { type: 'boolean' }, - dataset: { type: 'keyword' }, + dataset: { + properties: { + name: { type: 'keyword' }, + type: { type: 'keyword' }, + }, + }, processors: { type: 'keyword' }, config: { type: 'flattened' }, agent_stream: { type: 'flattened' }, diff --git a/x-pack/plugins/ingest_manager/server/saved_objects/migrations/datasources_v790.ts b/x-pack/plugins/ingest_manager/server/saved_objects/migrations/datasources_v790.ts index 0d1fb6f21a1ae7..d1e4b29daefc60 100644 --- a/x-pack/plugins/ingest_manager/server/saved_objects/migrations/datasources_v790.ts +++ b/x-pack/plugins/ingest_manager/server/saved_objects/migrations/datasources_v790.ts @@ -6,12 +6,22 @@ import { SavedObjectMigrationFn } from 'kibana/server'; import { cloneDeep } from 'lodash'; -import { Datasource } from '../../types/models'; +import { Datasource, DatasourceInput, DatasourceInputStream } from '../../types'; type Pre790Datasource = Exclude< Datasource, 'created_at' | 'created_by' | 'updated_at' | 'updated_by' ->; +> & { + inputs: Array< + Exclude & { + streams: Array< + Exclude & { + dataset: string; + } + >; + } + >; +}; export const migrateDatasourcesToV790: SavedObjectMigrationFn = ( doc @@ -23,6 +33,11 @@ export const migrateDatasourcesToV790: SavedObjectMigrationFn { + input.streams.forEach((stream) => { + stream.dataset = { name: (stream.dataset as unknown) as string, type: '' }; + }); + }); return updatedDatasource; }; diff --git a/x-pack/plugins/ingest_manager/server/services/datasource.test.ts b/x-pack/plugins/ingest_manager/server/services/datasource.test.ts index 3682ae6d1167b9..8d98e41c8ae690 100644 --- a/x-pack/plugins/ingest_manager/server/services/datasource.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/datasource.test.ts @@ -7,33 +7,51 @@ import { datasourceService } from './datasource'; import { PackageInfo } from '../types'; -const TEMPLATE = ` +async function mockedGetAssetsData(_a: any, _b: any, dataset: string) { + if (dataset === 'dataset1') { + return [ + { + buffer: Buffer.from(` type: log metricset: ["dataset1"] paths: {{#each paths}} - {{this}} {{/each}} -`; +`), + }, + ]; + } + return []; +} + +jest.mock('./epm/packages/assets', () => { + return { + getAssetsData: mockedGetAssetsData, + }; +}); + +jest.mock('./epm/registry', () => { + return { + fetchInfo: () => ({}), + }; +}); describe('Datasource service', () => { describe('assignPackageStream', () => { it('should work with config variables from the stream', async () => { const inputs = await datasourceService.assignPackageStream( ({ - datasources: [ + datasets: [ { - inputs: [ - { - type: 'log', - streams: [ - { - dataset: 'package.dataset1', - template: TEMPLATE, - }, - ], - }, - ], + type: 'logs', + name: 'package.dataset1', + streams: [{ input: 'log', template_path: 'some_template_path.yml' }], + }, + ], + config_templates: [ + { + inputs: [{ type: 'log' }], }, ], } as unknown) as PackageInfo, @@ -44,7 +62,7 @@ describe('Datasource service', () => { streams: [ { id: 'dataset01', - dataset: 'package.dataset1', + dataset: { name: 'package.dataset1', type: 'logs' }, enabled: true, vars: { paths: { @@ -64,7 +82,7 @@ describe('Datasource service', () => { streams: [ { id: 'dataset01', - dataset: 'package.dataset1', + dataset: { name: 'package.dataset1', type: 'logs' }, enabled: true, vars: { paths: { @@ -85,19 +103,16 @@ describe('Datasource service', () => { it('should work with config variables at the input level', async () => { const inputs = await datasourceService.assignPackageStream( ({ - datasources: [ + datasets: [ { - inputs: [ - { - type: 'log', - streams: [ - { - dataset: 'package.dataset1', - template: TEMPLATE, - }, - ], - }, - ], + name: 'package.dataset1', + type: 'logs', + streams: [{ input: 'log', template_path: 'some_template_path.yml' }], + }, + ], + config_templates: [ + { + inputs: [{ type: 'log' }], }, ], } as unknown) as PackageInfo, @@ -113,7 +128,7 @@ describe('Datasource service', () => { streams: [ { id: 'dataset01', - dataset: 'package.dataset1', + dataset: { name: 'package.dataset1', type: 'logs' }, enabled: true, }, ], @@ -133,7 +148,7 @@ describe('Datasource service', () => { streams: [ { id: 'dataset01', - dataset: 'package.dataset1', + dataset: { name: 'package.dataset1', type: 'logs' }, enabled: true, agent_stream: { metricset: ['dataset1'], diff --git a/x-pack/plugins/ingest_manager/server/services/datasource.ts b/x-pack/plugins/ingest_manager/server/services/datasource.ts index f3f460d2a74206..fecec0c463459c 100644 --- a/x-pack/plugins/ingest_manager/server/services/datasource.ts +++ b/x-pack/plugins/ingest_manager/server/services/datasource.ts @@ -13,10 +13,18 @@ import { PackageInfo, } from '../../common'; import { DATASOURCE_SAVED_OBJECT_TYPE } from '../constants'; -import { NewDatasource, Datasource, ListWithKuery, DatasourceSOAttributes } from '../types'; +import { + NewDatasource, + Datasource, + ListWithKuery, + DatasourceSOAttributes, + RegistryPackage, +} from '../types'; import { agentConfigService } from './agent_config'; -import { getPackageInfo, getInstallation } from './epm/packages'; import { outputService } from './output'; +import * as Registry from './epm/registry'; +import { getPackageInfo, getInstallation } from './epm/packages'; +import { getAssetsData } from './epm/packages/assets'; import { createStream } from './epm/agent/agent'; const SAVED_OBJECT_TYPE = DATASOURCE_SAVED_OBJECT_TYPE; @@ -251,15 +259,22 @@ class DatasourceService { pkgInfo: PackageInfo, inputs: DatasourceInput[] ): Promise { - const inputsPromises = inputs.map((input) => _assignPackageStreamToInput(pkgInfo, input)); + const registryPkgInfo = await Registry.fetchInfo(pkgInfo.name, pkgInfo.version); + const inputsPromises = inputs.map((input) => + _assignPackageStreamToInput(registryPkgInfo, pkgInfo, input) + ); return Promise.all(inputsPromises); } } -async function _assignPackageStreamToInput(pkgInfo: PackageInfo, input: DatasourceInput) { +async function _assignPackageStreamToInput( + registryPkgInfo: RegistryPackage, + pkgInfo: PackageInfo, + input: DatasourceInput +) { const streamsPromises = input.streams.map((stream) => - _assignPackageStreamToStream(pkgInfo, input, stream) + _assignPackageStreamToStream(registryPkgInfo, pkgInfo, input, stream) ); const streams = await Promise.all(streamsPromises); @@ -267,6 +282,7 @@ async function _assignPackageStreamToInput(pkgInfo: PackageInfo, input: Datasour } async function _assignPackageStreamToStream( + registryPkgInfo: RegistryPackage, pkgInfo: PackageInfo, input: DatasourceInput, stream: DatasourceInputStream @@ -274,32 +290,46 @@ async function _assignPackageStreamToStream( if (!stream.enabled) { return { ...stream, agent_stream: undefined }; } - const dataset = getDataset(stream.dataset); - const datasource = pkgInfo.datasources?.[0]; - if (!datasource) { - throw new Error('Stream template not found, no datasource'); + const datasetPath = getDataset(stream.dataset.name); + const packageDatasets = pkgInfo.datasets; + if (!packageDatasets) { + throw new Error('Stream template not found, no datasets'); } - const inputFromPkg = datasource.inputs.find((pkgInput) => pkgInput.type === input.type); - if (!inputFromPkg) { - throw new Error(`Stream template not found, unable to found input ${input.type}`); + const packageDataset = packageDatasets.find( + (pkgDataset) => pkgDataset.name === stream.dataset.name + ); + if (!packageDataset) { + throw new Error(`Stream template not found, unable to find dataset ${datasetPath}`); } - const streamFromPkg = inputFromPkg.streams.find( - (pkgStream) => pkgStream.dataset === stream.dataset + const streamFromPkg = (packageDataset.streams || []).find( + (pkgStream) => pkgStream.input === input.type ); if (!streamFromPkg) { - throw new Error(`Stream template not found, unable to found stream ${stream.dataset}`); + throw new Error(`Stream template not found, unable to find stream for input ${input.type}`); + } + + if (!streamFromPkg.template_path) { + throw new Error(`Stream template path not found for dataset ${datasetPath}`); } - if (!streamFromPkg.template) { - throw new Error(`Stream template not found for dataset ${dataset}`); + const [pkgStream] = await getAssetsData( + registryPkgInfo, + (path: string) => path.endsWith(streamFromPkg.template_path), + datasetPath + ); + + if (!pkgStream || !pkgStream.buffer) { + throw new Error( + `Unable to load stream template ${streamFromPkg.template_path} for dataset ${datasetPath}` + ); } const yaml = createStream( // Populate template variables from input vars and stream vars Object.assign({}, input.vars, stream.vars), - streamFromPkg.template + pkgStream.buffer.toString() ); stream.agent_stream = yaml; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.test.ts index 851a3bc2dd7206..bdd8883ea29c24 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.test.ts @@ -9,7 +9,7 @@ import { getDatasetAssetBaseName } from './index'; test('getBaseName', () => { const dataset: Dataset = { - id: 'nginx.access', + name: 'nginx.access', title: 'Nginx Acess Logs', release: 'beta', type: 'logs', diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.ts index e00b9db71db10b..0cb09ba054bf10 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/index.ts @@ -11,5 +11,5 @@ import { Dataset } from '../../../types'; * {type}-{id} */ export function getDatasetAssetBaseName(dataset: Dataset): string { - return `${dataset.type}-${dataset.id}`; + return `${dataset.type}-${dataset.name}`; } diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts index c3b135993105e5..36a19c512a8b48 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/ingest_pipelines.test.ts @@ -107,7 +107,7 @@ test('a yml-format pipeline with no pipeline references stays unchanged', () => test('getPipelineNameForInstallation gets correct name', () => { const dataset: Dataset = { - id: 'coredns.log', + name: 'coredns.log', title: 'CoreDNS logs', release: 'ga', type: 'logs', @@ -127,8 +127,10 @@ test('getPipelineNameForInstallation gets correct name', () => { dataset, packageVersion, }); - expect(pipelineEntryNameForInstallation).toBe(`${dataset.type}-${dataset.id}-${packageVersion}`); + expect(pipelineEntryNameForInstallation).toBe( + `${dataset.type}-${dataset.name}-${packageVersion}` + ); expect(pipelineRefNameForInstallation).toBe( - `${dataset.type}-${dataset.id}-${packageVersion}-${pipelineRefName}` + `${dataset.type}-${dataset.name}-${packageVersion}-${pipelineRefName}` ); }); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts index 11543fe73886f2..0865ee5d59e57a 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts @@ -192,5 +192,5 @@ export const getPipelineNameForInstallation = ({ const isPipelineEntry = pipelineName === dataset.ingest_pipeline; const suffix = isPipelineEntry ? '' : `-${pipelineName}`; // if this is the pipeline entry, don't add a suffix - return `${dataset.type}-${dataset.id}-${packageVersion}${suffix}`; + return `${dataset.type}-${dataset.name}-${packageVersion}${suffix}`; }; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts index 37fcf0db671310..19a023eb2ad4c5 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts @@ -71,13 +71,3 @@ export async function getAssetsData( return entries; } - -export async function getAssetsDataForPackageKey( - { pkgName, pkgVersion }: { pkgName: string; pkgVersion: string }, - filter = (path: string): boolean => true, - datasetName?: string -): Promise { - const registryPkgInfo = await Registry.fetchInfo(pkgName, pkgVersion); - - return getAssetsData(registryPkgInfo, filter, datasetName); -} diff --git a/x-pack/plugins/ingest_manager/server/types/index.tsx b/x-pack/plugins/ingest_manager/server/types/index.tsx index d8214e95aa2a05..eedb5d86abda32 100644 --- a/x-pack/plugins/ingest_manager/server/types/index.tsx +++ b/x-pack/plugins/ingest_manager/server/types/index.tsx @@ -18,6 +18,8 @@ export { AgentAction, AgentActionSOAttributes, Datasource, + DatasourceInput, + DatasourceInputStream, NewDatasource, DatasourceSOAttributes, FullAgentConfigInput, diff --git a/x-pack/plugins/ingest_manager/server/types/models/datasource.ts b/x-pack/plugins/ingest_manager/server/types/models/datasource.ts index 3bca6d20d96a20..114986c4a486e5 100644 --- a/x-pack/plugins/ingest_manager/server/types/models/datasource.ts +++ b/x-pack/plugins/ingest_manager/server/types/models/datasource.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -export { Datasource, NewDatasource } from '../../../common'; const ConfigRecordSchema = schema.recordOf( schema.string(), @@ -47,7 +46,7 @@ const DatasourceBaseSchema = { schema.object({ id: schema.string(), enabled: schema.boolean(), - dataset: schema.string(), + dataset: schema.object({ name: schema.string(), type: schema.string() }), processors: schema.maybe(schema.arrayOf(schema.string())), vars: schema.maybe(ConfigRecordSchema), config: schema.maybe( diff --git a/x-pack/plugins/ingest_manager/server/types/models/output.ts b/x-pack/plugins/ingest_manager/server/types/models/output.ts index 36b945db2cbcef..22a101ecd94b8e 100644 --- a/x-pack/plugins/ingest_manager/server/types/models/output.ts +++ b/x-pack/plugins/ingest_manager/server/types/models/output.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -export { Output, NewOutput } from '../../../common'; export enum OutputType { Elasticsearch = 'elasticsearch', diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts index b0c161ca1d0c24..f0e47c68866010 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts @@ -110,9 +110,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { id: policyInfo.datasource.id, dataset: { namespace: 'default' }, name: 'Protect East Coast', - package: { - name: 'endpoint', - version: policyInfo.packageInfo.version, + meta: { + package: { + name: 'endpoint', + version: policyInfo.packageInfo.version, + }, }, policy: { linux: { From 02fb42f0cdd5c0eda97033ee625fb68c23c8d883 Mon Sep 17 00:00:00 2001 From: Rashmi Kulkarni Date: Mon, 29 Jun 2020 16:48:28 -0700 Subject: [PATCH 23/91] Cross cluster search functional test with minimun privileges assigned to the test_user (#70007) (#70268) * using test_user with limited read permission to search profiler test * gitcheck * search profiler test using test_user * using limited roles and privileges for CCR * changed the global ccr role kibana section to be consistent with other roles with no feature controls * removed canvas role * changes to include pagination for 100 rows Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../apps/cross_cluster_replication/home_page.ts | 8 +++++++- x-pack/test/functional/config.js | 14 ++++++++++++++ .../test/functional/page_objects/security_page.ts | 4 ++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/cross_cluster_replication/home_page.ts b/x-pack/test/functional/apps/cross_cluster_replication/home_page.ts index 883d3ed3388399..24ddac8ba22e7b 100644 --- a/x-pack/test/functional/apps/cross_cluster_replication/home_page.ts +++ b/x-pack/test/functional/apps/cross_cluster_replication/home_page.ts @@ -10,14 +10,20 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['common', 'crossClusterReplication']); const log = getService('log'); + const security = getService('security'); describe('Home page', function () { before(async () => { + await security.testUser.setRoles(['global_ccr_role']); await pageObjects.common.navigateToApp('crossClusterReplication'); }); + after(async () => { + await security.testUser.restoreDefaults(); + }); + it('Loads the app', async () => { - await log.debug(`Checking for app title to be Cross-Cluster Replication`); + log.debug(`Checking for app title to be Cross-Cluster Replication`); const appTitleText = await pageObjects.crossClusterReplication.appTitleText(); expect(appTitleText).to.be('Cross-Cluster Replication'); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index aaddc460f89cfa..6feb534ebc6b65 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -242,6 +242,20 @@ export default async function ({ readConfigFile }) { ], }, + global_ccr_role: { + elasticsearch: { + cluster: ['manage', 'manage_ccr'], + }, + kibana: [ + { + feature: { + discover: ['read'], + }, + spaces: ['*'], + }, + ], + }, + //Kibana feature privilege isn't specific to advancedSetting. It can be anything. https://github.com/elastic/kibana/issues/35965 test_api_keys: { elasticsearch: { diff --git a/x-pack/test/functional/page_objects/security_page.ts b/x-pack/test/functional/page_objects/security_page.ts index 395e41a91f53a4..e3efc8731e6b3d 100644 --- a/x-pack/test/functional/page_objects/security_page.ts +++ b/x-pack/test/functional/page_objects/security_page.ts @@ -315,6 +315,8 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider async getElasticsearchUsers() { const users = []; + await testSubjects.click('tablePaginationPopoverButton'); + await testSubjects.click('tablePagination-100-rows'); for (const user of await testSubjects.findAll('userRow')) { const fullnameElement = await user.findByTestSubject('userRowFullName'); const usernameElement = await user.findByTestSubject('userRowUserName'); @@ -339,6 +341,8 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider async getElasticsearchRoles() { const roles = []; + await testSubjects.click('tablePaginationPopoverButton'); + await testSubjects.click('tablePagination-100-rows'); for (const role of await testSubjects.findAll('roleRow')) { const [rolename, reserved, deprecated] = await Promise.all([ role.findByTestSubject('roleRowName').then((el) => el.getVisibleText()), From 6f688eb6bf012cf956abfa941348064b004c4fdf Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 29 Jun 2020 21:12:21 -0400 Subject: [PATCH 24/91] [IngestManager] Allow to filter agent by packages (#69731) (#70273) --- .../common/types/models/agent.ts | 2 + .../server/saved_objects/index.ts | 1 + .../server/services/agents/acks.test.ts | 269 ++++++++++++++++++ .../server/services/agents/acks.ts | 27 +- .../server/services/agents/saved_objects.ts | 1 + 5 files changed, 292 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/ingest_manager/common/types/models/agent.ts b/x-pack/plugins/ingest_manager/common/types/models/agent.ts index 7644e2ca57f268..d2a2a3f5705ae3 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/agent.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/agent.ts @@ -90,8 +90,10 @@ export interface Agent extends AgentBase { current_error_events: AgentEvent[]; access_api_key?: string; status?: string; + packages: string[]; } export interface AgentSOAttributes extends AgentBase { current_error_events?: string; + packages?: string[]; } diff --git a/x-pack/plugins/ingest_manager/server/saved_objects/index.ts b/x-pack/plugins/ingest_manager/server/saved_objects/index.ts index d00e403849a768..af0e19107e298c 100644 --- a/x-pack/plugins/ingest_manager/server/saved_objects/index.ts +++ b/x-pack/plugins/ingest_manager/server/saved_objects/index.ts @@ -68,6 +68,7 @@ const savedObjectTypes: { [key: string]: SavedObjectsType } = { default_api_key: { type: 'keyword' }, updated_at: { type: 'date' }, current_error_events: { type: 'text' }, + packages: { type: 'keyword' }, }, }, }, diff --git a/x-pack/plugins/ingest_manager/server/services/agents/acks.test.ts b/x-pack/plugins/ingest_manager/server/services/agents/acks.test.ts index efdcbdb5c36bb9..abc4518e70573b 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/acks.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/acks.test.ts @@ -93,6 +93,275 @@ describe('test agent acks services', () => { ]); }); + it('should update config field on the agent if a config change is acknowledged', async () => { + const mockSavedObjectsClient = savedObjectsClientMock.create(); + const mockStartEncryptedSOPlugin = encryptedSavedObjectsMock.createStart(); + appContextService.start(({ + encryptedSavedObjectsStart: mockStartEncryptedSOPlugin, + } as unknown) as IngestManagerAppContext); + + const [ + { value: mockStartEncryptedSOClient }, + ] = mockStartEncryptedSOPlugin.getClient.mock.results; + + mockStartEncryptedSOClient.getDecryptedAsInternalUser.mockReturnValue( + Promise.resolve({ + id: 'action1', + references: [], + type: AGENT_ACTION_SAVED_OBJECT_TYPE, + attributes: { + type: 'CONFIG_CHANGE', + agent_id: 'id', + sent_at: '2020-03-14T19:45:02.620Z', + timestamp: '2019-01-04T14:32:03.36764-05:00', + created_at: '2020-03-14T19:45:02.620Z', + data: JSON.stringify({ + config: { + id: 'config1', + revision: 4, + settings: { + monitoring: { + enabled: true, + use_output: 'default', + logs: true, + metrics: true, + }, + }, + outputs: { + default: { + type: 'elasticsearch', + hosts: ['http://localhost:9200'], + }, + }, + inputs: [ + { + id: 'f2293360-b57c-11ea-8bd3-7bd51e425399', + name: 'system-1', + type: 'logs', + use_output: 'default', + package: { + name: 'system', + version: '0.3.0', + }, + dataset: { + namespace: 'default', + }, + streams: [ + { + id: 'logs-system.syslog', + dataset: { + name: 'system.syslog', + }, + paths: ['/var/log/messages*', '/var/log/syslog*'], + exclude_files: ['.gz$'], + multiline: { + pattern: '^\\s', + match: 'after', + }, + processors: [ + { + add_locale: null, + }, + { + add_fields: { + target: '', + fields: { + 'ecs.version': '1.5.0', + }, + }, + }, + ], + }, + ], + }, + ], + }, + }), + }, + }) + ); + + mockSavedObjectsClient.bulkGet.mockReturnValue( + Promise.resolve({ + saved_objects: [ + { + id: 'action1', + references: [], + type: AGENT_ACTION_SAVED_OBJECT_TYPE, + attributes: { + type: 'CONFIG_CHANGE', + agent_id: 'id', + sent_at: '2020-03-14T19:45:02.620Z', + timestamp: '2019-01-04T14:32:03.36764-05:00', + created_at: '2020-03-14T19:45:02.620Z', + }, + }, + ], + } as SavedObjectsBulkResponse) + ); + + await acknowledgeAgentActions( + mockSavedObjectsClient, + ({ + id: 'id', + type: AGENT_TYPE_PERMANENT, + config_id: 'config1', + } as unknown) as Agent, + [ + { + type: 'ACTION_RESULT', + subtype: 'CONFIG', + timestamp: '2019-01-04T14:32:03.36764-05:00', + action_id: 'action1', + agent_id: 'id', + } as AgentEvent, + ] + ); + expect(mockSavedObjectsClient.bulkUpdate).toBeCalled(); + expect(mockSavedObjectsClient.bulkUpdate.mock.calls[0][0]).toHaveLength(2); + expect(mockSavedObjectsClient.bulkUpdate.mock.calls[0][0][0]).toMatchInlineSnapshot(` + Object { + "attributes": Object { + "config_revision": 4, + "packages": Array [ + "system", + ], + }, + "id": "id", + "type": "fleet-agents", + } + `); + }); + + it('should not update config field on the agent if a config change for an old revision is acknowledged', async () => { + const mockSavedObjectsClient = savedObjectsClientMock.create(); + const mockStartEncryptedSOPlugin = encryptedSavedObjectsMock.createStart(); + appContextService.start(({ + encryptedSavedObjectsStart: mockStartEncryptedSOPlugin, + } as unknown) as IngestManagerAppContext); + + const [ + { value: mockStartEncryptedSOClient }, + ] = mockStartEncryptedSOPlugin.getClient.mock.results; + + mockStartEncryptedSOClient.getDecryptedAsInternalUser.mockReturnValue( + Promise.resolve({ + id: 'action1', + references: [], + type: AGENT_ACTION_SAVED_OBJECT_TYPE, + attributes: { + type: 'CONFIG_CHANGE', + agent_id: 'id', + sent_at: '2020-03-14T19:45:02.620Z', + timestamp: '2019-01-04T14:32:03.36764-05:00', + created_at: '2020-03-14T19:45:02.620Z', + data: JSON.stringify({ + config: { + id: 'config1', + revision: 4, + settings: { + monitoring: { + enabled: true, + use_output: 'default', + logs: true, + metrics: true, + }, + }, + outputs: { + default: { + type: 'elasticsearch', + hosts: ['http://localhost:9200'], + }, + }, + inputs: [ + { + id: 'f2293360-b57c-11ea-8bd3-7bd51e425399', + name: 'system-1', + type: 'logs', + use_output: 'default', + package: { + name: 'system', + version: '0.3.0', + }, + dataset: { + namespace: 'default', + }, + streams: [ + { + id: 'logs-system.syslog', + dataset: { + name: 'system.syslog', + }, + paths: ['/var/log/messages*', '/var/log/syslog*'], + exclude_files: ['.gz$'], + multiline: { + pattern: '^\\s', + match: 'after', + }, + processors: [ + { + add_locale: null, + }, + { + add_fields: { + target: '', + fields: { + 'ecs.version': '1.5.0', + }, + }, + }, + ], + }, + ], + }, + ], + }, + }), + }, + }) + ); + + mockSavedObjectsClient.bulkGet.mockReturnValue( + Promise.resolve({ + saved_objects: [ + { + id: 'action1', + references: [], + type: AGENT_ACTION_SAVED_OBJECT_TYPE, + attributes: { + type: 'CONFIG_CHANGE', + agent_id: 'id', + sent_at: '2020-03-14T19:45:02.620Z', + timestamp: '2019-01-04T14:32:03.36764-05:00', + created_at: '2020-03-14T19:45:02.620Z', + }, + }, + ], + } as SavedObjectsBulkResponse) + ); + + await acknowledgeAgentActions( + mockSavedObjectsClient, + ({ + id: 'id', + type: AGENT_TYPE_PERMANENT, + config_id: 'config1', + config_revision: 100, + } as unknown) as Agent, + [ + { + type: 'ACTION_RESULT', + subtype: 'CONFIG', + timestamp: '2019-01-04T14:32:03.36764-05:00', + action_id: 'action1', + agent_id: 'id', + } as AgentEvent, + ] + ); + expect(mockSavedObjectsClient.bulkUpdate).toBeCalled(); + expect(mockSavedObjectsClient.bulkUpdate.mock.calls[0][0]).toHaveLength(1); + }); + it('should fail for actions that cannot be found on agent actions list', async () => { const mockSavedObjectsClient = savedObjectsClientMock.create(); mockSavedObjectsClient.bulkGet.mockReturnValue( diff --git a/x-pack/plugins/ingest_manager/server/services/agents/acks.ts b/x-pack/plugins/ingest_manager/server/services/agents/acks.ts index a1b48a879bb890..e391e81ebd0a62 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/acks.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/acks.ts @@ -18,6 +18,7 @@ import { AgentEventSOAttributes, AgentSOAttributes, AgentActionSOAttributes, + FullAgentConfig, } from '../../types'; import { AGENT_EVENT_SAVED_OBJECT_TYPE, @@ -62,18 +63,18 @@ export async function acknowledgeAgentActions( if (actions.length === 0) { return []; } - const configRevision = getLatestConfigRevison(agent, actions); + const config = getLatestConfigIfUpdated(agent, actions); await soClient.bulkUpdate([ - buildUpdateAgentConfigRevision(agent.id, configRevision), + ...(config ? [buildUpdateAgentConfig(agent.id, config)] : []), ...buildUpdateAgentActionSentAt(actionIds), ]); return actions; } -function getLatestConfigRevison(agent: Agent, actions: AgentAction[]) { - return actions.reduce((acc, action) => { +function getLatestConfigIfUpdated(agent: Agent, actions: AgentAction[]) { + return actions.reduce((acc, action) => { if (action.type !== 'CONFIG_CHANGE') { return acc; } @@ -83,16 +84,26 @@ function getLatestConfigRevison(agent: Agent, actions: AgentAction[]) { return acc; } - return data?.config?.revision > acc ? data?.config?.revision : acc; - }, agent.config_revision || 0); + const currentRevision = (acc && acc.revision) || agent.config_revision || 0; + + return data?.config?.revision > currentRevision ? data?.config : acc; + }, null); } -function buildUpdateAgentConfigRevision(agentId: string, configRevision: number) { +function buildUpdateAgentConfig(agentId: string, config: FullAgentConfig) { + const packages = config.inputs.reduce((acc, input) => { + if (input.package && input.package.name && acc.indexOf(input.package.name) < 0) { + return [input.package.name, ...acc]; + } + return acc; + }, []); + return { type: AGENT_SAVED_OBJECT_TYPE, id: agentId, attributes: { - config_revision: configRevision, + config_revision: config.revision, + packages, }, }; } diff --git a/x-pack/plugins/ingest_manager/server/services/agents/saved_objects.ts b/x-pack/plugins/ingest_manager/server/services/agents/saved_objects.ts index 11beba1cd7e43e..2ab5cc8139f69f 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/saved_objects.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/saved_objects.ts @@ -23,6 +23,7 @@ export function savedObjectToAgent(so: SavedObject): Agent { user_provided_metadata: so.attributes.user_provided_metadata, access_api_key: undefined, status: undefined, + packages: so.attributes.packages ?? [], }; } From 8bf0e89439d13f41503a1f7ec567dfb4b3234240 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 29 Jun 2020 19:12:40 -0600 Subject: [PATCH 25/91] [Maps] choropleth layer wizard (#69699) (#70264) * [Maps] choropleth layer wizard * add boundaries radio group * geo_index_pattern_select * consolidate more logic into geo_index_pattern_select * small clean-up * left geo field and join field * move EuiPanel into render wizard * cleanup * right panel * createEmsChoroplethLayerDescriptor * createEsChoroplethLayerDescriptor * i18n cleanup * tslint * snapshot update * review feedback * review feedback * update snapshot * make EMS default source * tslint Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../layer_template.test.tsx.snap | 107 ++++ .../choropleth_layer_wizard.tsx | 25 + .../create_choropleth_layer_descriptor.ts | 144 ++++++ .../layers/choropleth_layer_wizard/index.ts | 7 + .../layer_template.test.tsx | 43 ++ .../layer_template.tsx | 459 ++++++++++++++++++ .../classes/layers/load_layer_wizards.ts | 2 + .../observability_layer_template.tsx | 7 +- .../security/security_layer_template.tsx | 7 +- .../create_client_file_source_editor.tsx | 21 +- .../ems_file_source/create_source_editor.tsx | 80 +-- .../ems_tms_source/tile_service_select.js | 40 +- .../create_source_editor.js | 131 +---- .../es_pew_pew_source/create_source_editor.js | 6 +- .../__snapshots__/scaling_form.test.tsx.snap | 2 + .../es_search_source/create_source_editor.js | 143 ++---- .../es_documents_layer_wizard.tsx | 2 +- .../es_search_source/scaling_form.test.tsx | 1 + .../sources/es_search_source/scaling_form.tsx | 6 +- .../create_source_editor.js | 30 +- .../create_source_editor.js | 34 +- .../mvt_single_layer_vector_source_editor.tsx | 8 +- .../wms_source/wms_create_source_editor.js | 6 +- .../sources/xyz_tms_source/xyz_tms_editor.tsx | 8 +- .../geo_index_pattern_select.test.tsx.snap | 104 ++++ .../public/components/ems_file_select.tsx | 105 ++++ .../ems_unavailable_message.tsx} | 2 +- .../geo_index_pattern_select.test.tsx | 42 ++ .../components/geo_index_pattern_select.tsx | 139 ++++++ .../components/no_index_pattern_callout.js | 52 -- .../public/components/single_field_select.tsx | 2 +- .../flyout_body/flyout_body.tsx | 4 +- .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - 34 files changed, 1337 insertions(+), 440 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap create mode 100644 x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/choropleth_layer_wizard.tsx create mode 100644 x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts create mode 100644 x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/index.ts create mode 100644 x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.test.tsx create mode 100644 x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.tsx create mode 100644 x-pack/plugins/maps/public/components/__snapshots__/geo_index_pattern_select.test.tsx.snap create mode 100644 x-pack/plugins/maps/public/components/ems_file_select.tsx rename x-pack/plugins/maps/public/{classes/sources/ems_unavailable_message.ts => components/ems_unavailable_message.tsx} (93%) create mode 100644 x-pack/plugins/maps/public/components/geo_index_pattern_select.test.tsx create mode 100644 x-pack/plugins/maps/public/components/geo_index_pattern_select.tsx delete mode 100644 x-pack/plugins/maps/public/components/no_index_pattern_callout.js diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap new file mode 100644 index 00000000000000..3a301a951ed571 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap @@ -0,0 +1,107 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render EMS UI when left source is BOUNDARIES_SOURCE.EMS 1`] = ` + + + +
+ +
+
+ + + + + +
+ +
+`; + +exports[`should render elasticsearch UI when left source is BOUNDARIES_SOURCE.ELASTICSEARCH 1`] = ` + + + +
+ +
+
+ + + + + +
+ +
+`; diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/choropleth_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/choropleth_layer_wizard.tsx new file mode 100644 index 00000000000000..6e806f4530df25 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/choropleth_layer_wizard.tsx @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; +import { LayerWizard, RenderWizardArguments } from '../layer_wizard_registry'; +import { LayerTemplate } from './layer_template'; + +export const choroplethLayerWizardConfig: LayerWizard = { + categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], + description: i18n.translate('xpack.maps.choropleth.desc', { + defaultMessage: 'Shaded areas to compare statistics across boundaries', + }), + icon: 'logoElasticsearch', + renderWizard: (renderWizardArguments: RenderWizardArguments) => { + return ; + }, + title: i18n.translate('xpack.maps.choropleth.title', { + defaultMessage: 'Choropleth', + }), +}; diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts new file mode 100644 index 00000000000000..61fb6ef54c2073 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import uuid from 'uuid/v4'; +import { + AGG_TYPE, + COLOR_MAP_TYPE, + FIELD_ORIGIN, + SCALING_TYPES, + SOURCE_TYPES, + STYLE_TYPE, + VECTOR_STYLES, +} from '../../../../common/constants'; +import { getJoinAggKey } from '../../../../common/get_agg_key'; +import { + AggDescriptor, + ColorDynamicOptions, + EMSFileSourceDescriptor, + ESSearchSourceDescriptor, +} from '../../../../common/descriptor_types'; +import { VectorStyle } from '../../styles/vector/vector_style'; +import { VectorLayer } from '../vector_layer/vector_layer'; +import { EMSFileSource } from '../../sources/ems_file_source'; +// @ts-ignore +import { ESSearchSource } from '../../sources/es_search_source'; +import { getDefaultDynamicProperties } from '../../styles/vector/vector_style_defaults'; + +const defaultDynamicProperties = getDefaultDynamicProperties(); + +function createChoroplethLayerDescriptor({ + sourceDescriptor, + leftField, + rightIndexPatternId, + rightIndexPatternTitle, + rightTermField, +}: { + sourceDescriptor: EMSFileSourceDescriptor | ESSearchSourceDescriptor; + leftField: string; + rightIndexPatternId: string; + rightIndexPatternTitle: string; + rightTermField: string; +}) { + const metricsDescriptor: AggDescriptor = { type: AGG_TYPE.COUNT }; + const joinId = uuid(); + const joinKey = getJoinAggKey({ + aggType: metricsDescriptor.type, + aggFieldName: metricsDescriptor.field ? metricsDescriptor.field : '', + rightSourceId: joinId, + }); + return VectorLayer.createDescriptor({ + joins: [ + { + leftField, + right: { + type: SOURCE_TYPES.ES_TERM_SOURCE, + id: joinId, + indexPatternId: rightIndexPatternId, + indexPatternTitle: rightIndexPatternTitle, + term: rightTermField, + metrics: [metricsDescriptor], + }, + }, + ], + sourceDescriptor, + style: VectorStyle.createDescriptor({ + [VECTOR_STYLES.FILL_COLOR]: { + type: STYLE_TYPE.DYNAMIC, + options: { + ...(defaultDynamicProperties[VECTOR_STYLES.FILL_COLOR]!.options as ColorDynamicOptions), + field: { + name: joinKey, + origin: FIELD_ORIGIN.JOIN, + }, + color: 'Yellow to Red', + type: COLOR_MAP_TYPE.ORDINAL, + }, + }, + [VECTOR_STYLES.LINE_COLOR]: { + type: STYLE_TYPE.STATIC, + options: { + color: '#3d3d3d', + }, + }, + }), + }); +} + +export function createEmsChoroplethLayerDescriptor({ + leftEmsFileId, + leftEmsField, + rightIndexPatternId, + rightIndexPatternTitle, + rightTermField, +}: { + leftEmsFileId: string; + leftEmsField: string; + rightIndexPatternId: string; + rightIndexPatternTitle: string; + rightTermField: string; +}) { + return createChoroplethLayerDescriptor({ + sourceDescriptor: EMSFileSource.createDescriptor({ + id: leftEmsFileId, + tooltipProperties: [leftEmsField], + }), + leftField: leftEmsField, + rightIndexPatternId, + rightIndexPatternTitle, + rightTermField, + }); +} + +export function createEsChoroplethLayerDescriptor({ + leftIndexPatternId, + leftGeoField, + leftJoinField, + rightIndexPatternId, + rightIndexPatternTitle, + rightTermField, +}: { + leftIndexPatternId: string; + leftGeoField: string; + leftJoinField: string; + rightIndexPatternId: string; + rightIndexPatternTitle: string; + rightTermField: string; +}) { + return createChoroplethLayerDescriptor({ + sourceDescriptor: ESSearchSource.createDescriptor({ + indexPatternId: leftIndexPatternId, + geoField: leftGeoField, + scalingType: SCALING_TYPES.LIMIT, + tooltipProperties: [leftJoinField], + applyGlobalQuery: false, + }), + leftField: leftJoinField, + rightIndexPatternId, + rightIndexPatternTitle, + rightTermField, + }); +} diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/index.ts b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/index.ts new file mode 100644 index 00000000000000..afabfea0c8d46a --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { choroplethLayerWizardConfig } from './choropleth_layer_wizard'; diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.test.tsx b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.test.tsx new file mode 100644 index 00000000000000..ecb86756e1ca73 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.test.tsx @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('../../../kibana_services', () => { + const MockIndexPatternSelect = (props: unknown) => { + return
; + }; + return { + getIndexPatternSelectComponent: () => { + return MockIndexPatternSelect; + }, + }; +}); + +import React from 'react'; +import { shallow } from 'enzyme'; +import { BOUNDARIES_SOURCE, LayerTemplate } from './layer_template'; + +const renderWizardArguments = { + previewLayers: () => {}, + mapColors: [], + currentStepId: null, + enableNextBtn: () => {}, + disableNextBtn: () => {}, + startStepLoading: () => {}, + stopStepLoading: () => {}, + advanceToNextStep: () => {}, +}; + +test('should render elasticsearch UI when left source is BOUNDARIES_SOURCE.ELASTICSEARCH', async () => { + const component = shallow(); + component.setState({ leftSource: BOUNDARIES_SOURCE.ELASTICSEARCH }); + expect(component).toMatchSnapshot(); +}); + +test('should render EMS UI when left source is BOUNDARIES_SOURCE.EMS', async () => { + const component = shallow(); + component.setState({ leftSource: BOUNDARIES_SOURCE.EMS }); + expect(component).toMatchSnapshot(); +}); diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.tsx b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.tsx new file mode 100644 index 00000000000000..72618781902d2a --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.tsx @@ -0,0 +1,459 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { FileLayer } from '@elastic/ems-client'; +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFormRow, + EuiPanel, + EuiRadioGroup, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { IFieldType, IndexPattern } from 'src/plugins/data/public'; +import { RenderWizardArguments } from '../layer_wizard_registry'; +import { EMSFileSelect } from '../../../components/ems_file_select'; +import { GeoIndexPatternSelect } from '../../../components/geo_index_pattern_select'; +import { SingleFieldSelect } from '../../../components/single_field_select'; +import { getGeoFields, getSourceFields, getTermsFields } from '../../../index_pattern_util'; +import { getEmsFileLayers } from '../../../meta'; +import { getIndexPatternSelectComponent, getIndexPatternService } from '../../../kibana_services'; +import { + createEmsChoroplethLayerDescriptor, + createEsChoroplethLayerDescriptor, +} from './create_choropleth_layer_descriptor'; + +export enum BOUNDARIES_SOURCE { + ELASTICSEARCH = 'ELASTICSEARCH', + EMS = 'EMS', +} + +const BOUNDARIES_OPTIONS = [ + { + id: BOUNDARIES_SOURCE.EMS, + label: i18n.translate('xpack.maps.choropleth.boundaries.ems', { + defaultMessage: 'Administrative boundaries from Elastic Maps Service', + }), + }, + { + id: BOUNDARIES_SOURCE.ELASTICSEARCH, + label: i18n.translate('xpack.maps.choropleth.boundaries.elasticsearch', { + defaultMessage: 'Points, lines, and polygons from Elasticsearch', + }), + }, +]; + +interface State { + leftSource: BOUNDARIES_SOURCE; + leftEmsFileId: string | null; + leftEmsFields: Array>; + leftIndexPattern: IndexPattern | null; + leftGeoFields: IFieldType[]; + leftJoinFields: IFieldType[]; + leftGeoField: string | null; + leftEmsJoinField: string | null; + leftElasticsearchJoinField: string | null; + rightIndexPatternId: string | null; + rightIndexPatternTitle: string | null; + rightTermsFields: IFieldType[]; + rightJoinField: string | null; +} + +export class LayerTemplate extends Component { + private _isMounted: boolean = false; + + state = { + leftSource: BOUNDARIES_SOURCE.EMS, + leftEmsFileId: null, + leftEmsFields: [], + leftIndexPattern: null, + leftGeoFields: [], + leftJoinFields: [], + leftGeoField: null, + leftEmsJoinField: null, + leftElasticsearchJoinField: null, + rightIndexPatternId: null, + rightIndexPatternTitle: null, + rightTermsFields: [], + rightJoinField: null, + }; + + componentWillUnmount() { + this._isMounted = false; + } + + componentDidMount() { + this._isMounted = true; + } + + _loadRightFields = async (indexPatternId: string) => { + this.setState({ rightTermsFields: [], rightIndexPatternTitle: null }); + + let indexPattern; + try { + indexPattern = await getIndexPatternService().get(indexPatternId); + } catch (err) { + return; + } + + // method may be called again before 'get' returns + // ignore response when fetched index pattern does not match active index pattern + if (!this._isMounted || indexPatternId !== this.state.rightIndexPatternId) { + return; + } + + this.setState({ + rightTermsFields: getTermsFields(indexPattern.fields), + rightIndexPatternTitle: indexPattern.title, + }); + }; + + _loadEmsFileFields = async () => { + const emsFileLayers = await getEmsFileLayers(); + const emsFileLayer = emsFileLayers.find((fileLayer: FileLayer) => { + return fileLayer.getId() === this.state.leftEmsFileId; + }); + + if (!this._isMounted || !emsFileLayer) { + return; + } + + const leftEmsFields = emsFileLayer + .getFieldsInLanguage() + .filter((field) => { + return field.type === 'id'; + }) + .map((field) => { + return { + value: field.name, + label: field.description, + }; + }); + this.setState( + { + leftEmsFields, + leftEmsJoinField: leftEmsFields.length ? leftEmsFields[0].value : null, + }, + this._previewLayer + ); + }; + + _onLeftSourceChange = (optionId: string) => { + this.setState( + { leftSource: optionId as BOUNDARIES_SOURCE, rightJoinField: null }, + this._previewLayer + ); + }; + + _onLeftIndexPatternChange = (indexPattern: IndexPattern) => { + this.setState( + { + leftIndexPattern: indexPattern, + leftGeoFields: getGeoFields(indexPattern.fields), + leftJoinFields: getSourceFields(indexPattern.fields), + leftGeoField: null, + leftElasticsearchJoinField: null, + rightJoinField: null, + }, + () => { + // make default geo field selection + if (this.state.leftGeoFields.length) { + // @ts-expect-error - avoid wrong "Property 'name' does not exist on type 'never'." compile error + this._onLeftGeoFieldSelect(this.state.leftGeoFields[0].name); + } + } + ); + }; + + _onLeftGeoFieldSelect = (geoField?: string) => { + if (!geoField) { + return; + } + this.setState({ leftGeoField: geoField }, this._previewLayer); + }; + + _onLeftJoinFieldSelect = (joinField?: string) => { + if (!joinField) { + return; + } + this.setState({ leftElasticsearchJoinField: joinField }, this._previewLayer); + }; + + _onLeftEmsFileChange = (emFileId: string) => { + this.setState({ leftEmsFileId: emFileId, leftEmsJoinField: null, rightJoinField: null }, () => { + this._previewLayer(); + this._loadEmsFileFields(); + }); + }; + + _onLeftEmsFieldChange = (selectedOptions: Array>) => { + if (selectedOptions.length === 0) { + return; + } + + this.setState({ leftEmsJoinField: selectedOptions[0].value! }, this._previewLayer); + }; + + _onRightIndexPatternChange = (indexPatternId: string) => { + if (!indexPatternId) { + return; + } + + this.setState( + { + rightIndexPatternId: indexPatternId, + rightJoinField: null, + }, + () => { + this._previewLayer(); + this._loadRightFields(indexPatternId); + } + ); + }; + + _onRightJoinFieldSelect = (joinField?: string) => { + if (!joinField) { + return; + } + this.setState({ rightJoinField: joinField }, this._previewLayer); + }; + + _isLeftConfigComplete() { + if (this.state.leftSource === BOUNDARIES_SOURCE.ELASTICSEARCH) { + return ( + !!this.state.leftIndexPattern && + !!this.state.leftGeoField && + !!this.state.leftElasticsearchJoinField + ); + } else { + return !!this.state.leftEmsFileId && !!this.state.leftEmsJoinField; + } + } + + _isRightConfigComplete() { + return !!this.state.rightIndexPatternId && !!this.state.rightJoinField; + } + + _previewLayer() { + if (!this._isLeftConfigComplete() || !this._isRightConfigComplete()) { + this.props.previewLayers([]); + return; + } + + const layerDescriptor = + this.state.leftSource === BOUNDARIES_SOURCE.ELASTICSEARCH + ? createEsChoroplethLayerDescriptor({ + // @ts-expect-error - avoid wrong "Property 'id' does not exist on type 'never'." compile error + leftIndexPatternId: this.state.leftIndexPattern!.id, + leftGeoField: this.state.leftGeoField!, + leftJoinField: this.state.leftElasticsearchJoinField!, + rightIndexPatternId: this.state.rightIndexPatternId!, + rightIndexPatternTitle: this.state.rightIndexPatternTitle!, + rightTermField: this.state.rightJoinField!, + }) + : createEmsChoroplethLayerDescriptor({ + leftEmsFileId: this.state.leftEmsFileId!, + leftEmsField: this.state.leftEmsJoinField!, + rightIndexPatternId: this.state.rightIndexPatternId!, + rightIndexPatternTitle: this.state.rightIndexPatternTitle!, + rightTermField: this.state.rightJoinField!, + }); + + this.props.previewLayers([layerDescriptor]); + } + + _renderLeftSourceForm() { + if (this.state.leftSource === BOUNDARIES_SOURCE.ELASTICSEARCH) { + let geoFieldSelect; + if (this.state.leftGeoFields.length) { + geoFieldSelect = ( + + + + ); + } + let joinFieldSelect; + if (this.state.leftJoinFields.length) { + joinFieldSelect = ( + + + + ); + } + return ( + <> + + {geoFieldSelect} + {joinFieldSelect} + + ); + } else { + let emsFieldSelect; + if (this.state.leftEmsFields.length) { + let selectedOption; + if (this.state.leftEmsJoinField) { + selectedOption = this.state.leftEmsFields.find( + (option: EuiComboBoxOptionOption) => { + return this.state.leftEmsJoinField === option.value; + } + ); + } + emsFieldSelect = ( + + + + ); + } + return ( + <> + + {emsFieldSelect} + + ); + } + } + + _renderLeftPanel() { + return ( + + +
+ +
+
+ + + + + + + + {this._renderLeftSourceForm()} +
+ ); + } + + _renderRightPanel() { + if (!this._isLeftConfigComplete()) { + return null; + } + const IndexPatternSelect = getIndexPatternSelectComponent(); + + let joinFieldSelect; + if (this.state.rightTermsFields.length) { + joinFieldSelect = ( + + + + ); + } + + return ( + + +
+ +
+
+ + + + + + + + {joinFieldSelect} +
+ ); + } + + render() { + return ( + <> + {this._renderLeftPanel()} + + + + {this._renderRightPanel()} + + ); + } +} diff --git a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts index 8357971a3778f3..37bcb3b23c0728 100644 --- a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts +++ b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts @@ -26,6 +26,7 @@ import { wmsLayerWizardConfig } from '../sources/wms_source'; import { mvtVectorSourceWizardConfig } from '../sources/mvt_single_layer_vector_source'; import { ObservabilityLayerWizardConfig } from './solution_layers/observability'; import { SecurityLayerWizardConfig } from './solution_layers/security'; +import { choroplethLayerWizardConfig } from './choropleth_layer_wizard'; import { getEnableVectorTiles } from '../../kibana_services'; let registered = false; @@ -41,6 +42,7 @@ export function registerLayerWizards() { // @ts-ignore registerLayerWizard(esDocumentsLayerWizardConfig); // @ts-ignore + registerLayerWizard(choroplethLayerWizardConfig); registerLayerWizard(clustersLayerWizardConfig); // @ts-ignore registerLayerWizard(heatmapLayerWizardConfig); diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_template.tsx b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_template.tsx index 3f3c556dcae1e5..3fe640a135aa61 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_template.tsx +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_template.tsx @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; +import { EuiPanel } from '@elastic/eui'; import { RenderWizardArguments } from '../../layer_wizard_registry'; import { LayerSelect, OBSERVABILITY_LAYER_TYPE } from './layer_select'; import { getMetricOptionsForLayer, MetricSelect, OBSERVABILITY_METRIC_TYPE } from './metric_select'; @@ -63,7 +64,7 @@ export class ObservabilityLayerTemplate extends Component + - + ); } } diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_template.tsx b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_template.tsx index eda489c88fda22..b20f57f4c276d7 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_template.tsx +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_template.tsx @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; +import { EuiPanel } from '@elastic/eui'; import { RenderWizardArguments } from '../../layer_wizard_registry'; import { IndexPatternSelect } from './index_pattern_select'; import { createSecurityLayerDescriptors } from './create_layer_descriptors'; @@ -44,12 +45,12 @@ export class SecurityLayerTemplate extends Component + - + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/client_file_source/create_client_file_source_editor.tsx b/x-pack/plugins/maps/public/classes/sources/client_file_source/create_client_file_source_editor.tsx index 344bdc92489e03..cf2692393192d7 100644 --- a/x-pack/plugins/maps/public/classes/sources/client_file_source/create_client_file_source_editor.tsx +++ b/x-pack/plugins/maps/public/classes/sources/client_file_source/create_client_file_source_editor.tsx @@ -5,6 +5,7 @@ */ import React, { Component } from 'react'; +import { EuiPanel } from '@elastic/eui'; import { IFieldType } from 'src/plugins/data/public'; import { ES_GEO_FIELD_TYPE, @@ -146,15 +147,17 @@ export class ClientFileCreateSourceEditor extends Component + + + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx index a78a49032503b8..ef15a8d7866076 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx @@ -5,95 +5,33 @@ */ import React, { Component } from 'react'; -import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; -import { FileLayer } from '@elastic/ems-client'; -import { getEmsFileLayers } from '../../../meta'; -import { getEmsUnavailableMessage } from '../ems_unavailable_message'; +import { EuiPanel } from '@elastic/eui'; import { EMSFileSourceDescriptor } from '../../../../common/descriptor_types'; +import { EMSFileSelect } from '../../../components/ems_file_select'; interface Props { onSourceConfigChange: (sourceConfig: Partial) => void; } interface State { - hasLoadedOptions: boolean; - emsFileOptions: Array>; - selectedOption: EuiComboBoxOptionOption | null; + emsFileId: string | null; } export class EMSFileCreateSourceEditor extends Component { - private _isMounted: boolean = false; - state = { - hasLoadedOptions: false, - emsFileOptions: [], - selectedOption: null, - }; - - _loadFileOptions = async () => { - const fileLayers: FileLayer[] = await getEmsFileLayers(); - const options = fileLayers.map((fileLayer) => { - return { - value: fileLayer.getId(), - label: fileLayer.getDisplayName(), - }; - }); - if (this._isMounted) { - this.setState({ - hasLoadedOptions: true, - emsFileOptions: options, - }); - } + emsFileId: null, }; - componentWillUnmount() { - this._isMounted = false; - } - - componentDidMount() { - this._isMounted = true; - this._loadFileOptions(); - } - - _onChange = (selectedOptions: Array>) => { - if (selectedOptions.length === 0) { - return; - } - - this.setState({ selectedOption: selectedOptions[0] }); - - const emsFileId = selectedOptions[0].value; + _onChange = (emsFileId: string) => { + this.setState({ emsFileId }); this.props.onSourceConfigChange({ id: emsFileId }); }; render() { - if (!this.state.hasLoadedOptions) { - // TODO display loading message - return null; - } - return ( - - - + + + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js index 3931e441ff2548..2b54e00cae7394 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js +++ b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js @@ -5,10 +5,10 @@ */ import React from 'react'; -import { EuiSelect, EuiFormRow } from '@elastic/eui'; +import { EuiSelect, EuiFormRow, EuiPanel } from '@elastic/eui'; import { getEmsTmsServices } from '../../../meta'; -import { getEmsUnavailableMessage } from '../ems_unavailable_message'; +import { getEmsUnavailableMessage } from '../../../components/ems_unavailable_message'; import { i18n } from '@kbn/i18n'; export const AUTO_SELECT = 'auto_select'; @@ -71,23 +71,25 @@ export class TileServiceSelect extends React.Component { } return ( - - - + + + + + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js index 24edf0251c1535..ebe312d73eccea 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/create_source_editor.js @@ -4,17 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; -import React, { Fragment, Component } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { ES_GEO_FIELD_TYPES } from '../../../../common/constants'; import { SingleFieldSelect } from '../../../components/single_field_select'; -import { getIndexPatternService, getIndexPatternSelectComponent } from '../../../kibana_services'; -import { NoIndexPatternCallout } from '../../../components/no_index_pattern_callout'; +import { GeoIndexPatternSelect } from '../../../components/geo_index_pattern_select'; import { i18n } from '@kbn/i18n'; -import { EuiFormRow, EuiSpacer } from '@elastic/eui'; +import { EuiFormRow, EuiPanel } from '@elastic/eui'; import { getFieldsWithGeoTileAgg, getGeoFields, @@ -33,76 +30,26 @@ export class CreateSourceEditor extends Component { }; state = { - isLoadingIndexPattern: false, - indexPatternId: '', + indexPattern: null, geoField: '', requestType: this.props.requestType, - noGeoIndexPatternsExist: false, }; - componentWillUnmount() { - this._isMounted = false; - } - - componentDidMount() { - this._isMounted = true; - } - - onIndexPatternSelect = (indexPatternId) => { + onIndexPatternSelect = (indexPattern) => { this.setState( { - indexPatternId, + indexPattern, }, - this.loadIndexPattern.bind(null, indexPatternId) + () => { + //make default selection + const geoFieldsWithGeoTileAgg = getFieldsWithGeoTileAgg(indexPattern.fields); + if (geoFieldsWithGeoTileAgg[0]) { + this._onGeoFieldSelect(geoFieldsWithGeoTileAgg[0].name); + } + } ); }; - loadIndexPattern = (indexPatternId) => { - this.setState( - { - isLoadingIndexPattern: true, - indexPattern: undefined, - geoField: undefined, - }, - this.debouncedLoad.bind(null, indexPatternId) - ); - }; - - debouncedLoad = _.debounce(async (indexPatternId) => { - if (!indexPatternId || indexPatternId.length === 0) { - return; - } - - let indexPattern; - try { - indexPattern = await getIndexPatternService().get(indexPatternId); - } catch (err) { - // index pattern no longer exists - return; - } - - if (!this._isMounted) { - return; - } - - // props.indexPatternId may be updated before getIndexPattern returns - // ignore response when fetched index pattern does not match active index pattern - if (indexPattern.id !== indexPatternId) { - return; - } - - this.setState({ - isLoadingIndexPattern: false, - indexPattern: indexPattern, - }); - - //make default selection - const geoFieldsWithGeoTileAgg = getFieldsWithGeoTileAgg(indexPattern.fields); - if (geoFieldsWithGeoTileAgg[0]) { - this._onGeoFieldSelect(geoFieldsWithGeoTileAgg[0].name); - } - }, 300); - _onGeoFieldSelect = (geoField) => { this.setState( { @@ -122,17 +69,13 @@ export class CreateSourceEditor extends Component { }; previewLayer = () => { - const { indexPatternId, geoField, requestType } = this.state; + const { indexPattern, geoField, requestType } = this.state; const sourceConfig = - indexPatternId && geoField ? { indexPatternId, geoField, requestType } : null; + indexPattern && geoField ? { indexPatternId: indexPattern.id, geoField, requestType } : null; this.props.onSourceConfigChange(sourceConfig); }; - _onNoIndexPatterns = () => { - this.setState({ noGeoIndexPatternsExist: true }); - }; - _renderGeoSelect() { if (!this.state.indexPattern) { return null; @@ -170,50 +113,16 @@ export class CreateSourceEditor extends Component { ); } - _renderIndexPatternSelect() { - const IndexPatternSelect = getIndexPatternSelectComponent(); - + render() { return ( - - + - - ); - } - - _renderNoIndexPatternWarning() { - if (!this.state.noGeoIndexPatternsExist) { - return null; - } - - return ( - - - - - ); - } - - render() { - return ( - - {this._renderNoIndexPatternWarning()} - {this._renderIndexPatternSelect()} {this._renderGeoSelect()} {this._renderRenderAsSelect()} - + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js index 38a5850537200b..3fe3d536ff8098 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/create_source_editor.js @@ -13,7 +13,7 @@ import { getIndexPatternService, getIndexPatternSelectComponent } from '../../.. import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiFormRow, EuiCallOut } from '@elastic/eui'; +import { EuiFormRow, EuiCallOut, EuiPanel } from '@elastic/eui'; import { getFieldsWithGeoTileAgg } from '../../../index_pattern_util'; import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; @@ -200,11 +200,11 @@ export class CreateSourceEditor extends Component { } return ( - + {callout} {this._renderIndexPatternSelect()} {this._renderGeoSelects()} - + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/__snapshots__/scaling_form.test.tsx.snap b/x-pack/plugins/maps/public/classes/sources/es_search_source/__snapshots__/scaling_form.test.tsx.snap index 2b04da92517561..8ebb389472f74c 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/__snapshots__/scaling_form.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/__snapshots__/scaling_form.test.tsx.snap @@ -210,8 +210,10 @@ exports[`should render top hits form when scaling type is TOP_HITS 1`] = ` diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_search_source/create_source_editor.js index 73abfd87e47975..0423d70b3f4276 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/create_source_editor.js @@ -4,16 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; import React, { Fragment, Component } from 'react'; import PropTypes from 'prop-types'; -import { EuiFormRow, EuiSpacer } from '@elastic/eui'; +import { EuiFormRow, EuiPanel, EuiSpacer } from '@elastic/eui'; import { SingleFieldSelect } from '../../../components/single_field_select'; -import { getIndexPatternService, getIndexPatternSelectComponent } from '../../../kibana_services'; -import { NoIndexPatternCallout } from '../../../components/no_index_pattern_callout'; +import { GeoIndexPatternSelect } from '../../../components/geo_index_pattern_select'; import { i18n } from '@kbn/i18n'; -import { ES_GEO_FIELD_TYPES, SCALING_TYPES } from '../../../../common/constants'; +import { SCALING_TYPES } from '../../../../common/constants'; import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; import { ScalingForm } from './scaling_form'; import { @@ -45,80 +43,33 @@ export class CreateSourceEditor extends Component { }; state = { - isLoadingIndexPattern: false, - noGeoIndexPatternsExist: false, ...RESET_INDEX_PATTERN_STATE, }; - componentWillUnmount() { - this._isMounted = false; - } - - componentDidMount() { - this._isMounted = true; - } - - _onIndexPatternSelect = (indexPatternId) => { - this.setState( - { - indexPatternId, - }, - this._loadIndexPattern(indexPatternId) - ); - }; + _onIndexPatternSelect = (indexPattern) => { + const geoFields = getGeoFields(indexPattern.fields); - _loadIndexPattern = (indexPatternId) => { this.setState( { - isLoadingIndexPattern: true, ...RESET_INDEX_PATTERN_STATE, + indexPattern, + geoFields, }, - this._debouncedLoad.bind(null, indexPatternId) + () => { + if (geoFields.length) { + // make default selection, prefer aggregatable field over the first available + const firstAggregatableGeoField = geoFields.find((geoField) => { + return geoField.aggregatable; + }); + const defaultGeoFieldName = firstAggregatableGeoField + ? firstAggregatableGeoField + : geoFields[0]; + this._onGeoFieldSelect(defaultGeoFieldName.name); + } + } ); }; - _debouncedLoad = _.debounce(async (indexPatternId) => { - if (!indexPatternId || indexPatternId.length === 0) { - return; - } - - let indexPattern; - try { - indexPattern = await getIndexPatternService().get(indexPatternId); - } catch (err) { - // index pattern no longer exists - return; - } - - if (!this._isMounted) { - return; - } - - // props.indexPatternId may be updated before getIndexPattern returns - // ignore response when fetched index pattern does not match active index pattern - if (indexPattern.id !== indexPatternId) { - return; - } - - const geoFields = getGeoFields(indexPattern.fields); - this.setState({ - isLoadingIndexPattern: false, - indexPattern: indexPattern, - geoFields, - }); - - if (geoFields.length) { - // make default selection, prefer aggregatable field over the first available - const firstAggregatableGeoField = geoFields.find((geoField) => { - return geoField.aggregatable; - }); - const defaultGeoFieldName = firstAggregatableGeoField - ? firstAggregatableGeoField - : geoFields[0]; - this._onGeoFieldSelect(defaultGeoFieldName.name); - } - }, 300); - _onGeoFieldSelect = (geoFieldName) => { // Respect previous scaling type selection unless newly selected geo field does not support clustering. const scalingType = @@ -146,7 +97,7 @@ export class CreateSourceEditor extends Component { _previewLayer = () => { const { - indexPatternId, + indexPattern, geoFieldName, filterByMapBounds, scalingType, @@ -155,9 +106,9 @@ export class CreateSourceEditor extends Component { } = this.state; const sourceConfig = - indexPatternId && geoFieldName + indexPattern && geoFieldName ? { - indexPatternId, + indexPatternId: indexPattern.id, geoField: geoFieldName, filterByMapBounds, scalingType, @@ -168,10 +119,6 @@ export class CreateSourceEditor extends Component { this.props.onSourceConfigChange(sourceConfig); }; - _onNoIndexPatterns = () => { - this.setState({ noGeoIndexPatternsExist: true }); - }; - _renderGeoSelect() { if (!this.state.indexPattern) { return; @@ -205,7 +152,7 @@ export class CreateSourceEditor extends Component { - - - - ); - } - render() { - const IndexPatternSelect = getIndexPatternSelectComponent(); - return ( - - {this._renderNoIndexPatternWarning()} - - - - + + {this._renderGeoSelect()} {this._renderScalingPanel()} - + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx index 4598b1467229d4..1ec6d2a1ff6716 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx @@ -26,7 +26,7 @@ export function createDefaultLayerDescriptor(sourceConfig: unknown, mapColors: s export const esDocumentsLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], description: i18n.translate('xpack.maps.source.esSearchDescription', { - defaultMessage: 'Vector data from a Kibana index pattern', + defaultMessage: 'Points, lines, and polygons from Elasticsearch', }), icon: 'logoElasticsearch', renderWizard: ({ previewLayers, mapColors }: RenderWizardArguments) => { diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.test.tsx index 3ec746223c7cf3..6e56c179b4ead2 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.test.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.test.tsx @@ -25,6 +25,7 @@ const defaultProps = { scalingType: SCALING_TYPES.LIMIT, supportsClustering: true, termFields: [], + topHitsSplitField: null, topHitsSize: 1, }; diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.tsx index a998fe3569835c..816db6a98d593b 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/scaling_form.tsx @@ -40,7 +40,7 @@ interface Props { supportsClustering: boolean; clusteringDisabledReason?: string | null; termFields: IFieldType[]; - topHitsSplitField?: string; + topHitsSplitField: string | null; topHitsSize: number; } @@ -90,6 +90,9 @@ export class ScalingForm extends Component { }; _onTopHitsSplitFieldChange = (topHitsSplitField?: string) => { + if (!topHitsSplitField) { + return; + } this.props.onChange({ propName: 'topHitsSplitField', value: topHitsSplitField }); }; @@ -141,6 +144,7 @@ export class ScalingForm extends Component { value={this.props.topHitsSplitField} onChange={this._onTopHitsSplitFieldChange} fields={this.props.termFields} + isClearable={false} compressed /> diff --git a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/create_source_editor.js index 5e28916e79f3f8..82f80e7fe484b5 100644 --- a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/create_source_editor.js @@ -6,7 +6,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { EuiSelect, EuiFormRow } from '@elastic/eui'; +import { EuiSelect, EuiFormRow, EuiPanel } from '@elastic/eui'; import { getKibanaRegionList } from '../../../meta'; import { i18n } from '@kbn/i18n'; @@ -31,19 +31,21 @@ export function CreateSourceEditor({ onSourceConfigChange }) { : null; return ( - - - + + + + + ); } diff --git a/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/create_source_editor.js index a0a507ff9d32d7..1cbf4c1a87de31 100644 --- a/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/create_source_editor.js @@ -6,7 +6,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { EuiFieldText, EuiFormRow } from '@elastic/eui'; +import { EuiFieldText, EuiFormRow, EuiPanel } from '@elastic/eui'; import { getKibanaTileMap } from '../../../meta'; import { i18n } from '@kbn/i18n'; @@ -19,21 +19,23 @@ export function CreateSourceEditor({ onSourceConfigChange }) { } return ( - - - + + + + + ); } diff --git a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source_editor.tsx b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source_editor.tsx index 7a4b8d43811da8..760b8c676cb37e 100644 --- a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source_editor.tsx +++ b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/mvt_single_layer_vector_source_editor.tsx @@ -5,9 +5,9 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import React, { Fragment, Component, ChangeEvent } from 'react'; +import React, { Component, ChangeEvent } from 'react'; import _ from 'lodash'; -import { EuiFieldText, EuiFormRow } from '@elastic/eui'; +import { EuiFieldText, EuiFormRow, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { MAX_ZOOM, MIN_ZOOM } from '../../../../common/constants'; import { ValidatedDualRange, Value } from '../../../../../../../src/plugins/kibana_react/public'; @@ -85,7 +85,7 @@ export class MVTSingleLayerVectorSourceEditor extends Component { render() { return ( - + { } )} /> - + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/wms_source/wms_create_source_editor.js b/x-pack/plugins/maps/public/classes/sources/wms_source/wms_create_source_editor.js index df00faf43daa38..ce9af42117683c 100644 --- a/x-pack/plugins/maps/public/classes/sources/wms_source/wms_create_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/wms_source/wms_create_source_editor.js @@ -13,7 +13,7 @@ import { EuiComboBox, EuiFieldText, EuiFormRow, - EuiForm, + EuiPanel, EuiSpacer, } from '@elastic/eui'; import { WmsClient } from './wms_client'; @@ -289,7 +289,7 @@ export class WMSCreateSourceEditor extends Component { render() { return ( - + + ); } } diff --git a/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/xyz_tms_editor.tsx b/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/xyz_tms_editor.tsx index 715ff0e4c2fdd4..bf5f2c3dfe04d5 100644 --- a/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/xyz_tms_editor.tsx +++ b/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/xyz_tms_editor.tsx @@ -5,9 +5,9 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import React, { Fragment, Component, ChangeEvent } from 'react'; +import React, { Component, ChangeEvent } from 'react'; import _ from 'lodash'; -import { EuiFormRow, EuiFieldText } from '@elastic/eui'; +import { EuiFormRow, EuiFieldText, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { AttributionDescriptor } from '../../../../common/descriptor_types'; @@ -77,7 +77,7 @@ export class XYZTMSEditor extends Component { render() { const { attributionText, attributionUrl } = this.state; return ( - + { } /> - + ); } } diff --git a/x-pack/plugins/maps/public/components/__snapshots__/geo_index_pattern_select.test.tsx.snap b/x-pack/plugins/maps/public/components/__snapshots__/geo_index_pattern_select.test.tsx.snap new file mode 100644 index 00000000000000..809fe618625130 --- /dev/null +++ b/x-pack/plugins/maps/public/components/__snapshots__/geo_index_pattern_select.test.tsx.snap @@ -0,0 +1,104 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render 1`] = ` + + + + + +`; + +exports[`should render no index pattern warning when there are no matching index patterns 1`] = ` + + +

+ + + + + +

+

+ + + + +

+
+ + + + +
+`; diff --git a/x-pack/plugins/maps/public/components/ems_file_select.tsx b/x-pack/plugins/maps/public/components/ems_file_select.tsx new file mode 100644 index 00000000000000..f66e813608ce19 --- /dev/null +++ b/x-pack/plugins/maps/public/components/ems_file_select.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component } from 'react'; +import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow, EuiSelect } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; +import { FileLayer } from '@elastic/ems-client'; +import { getEmsFileLayers } from '../meta'; +import { getEmsUnavailableMessage } from './ems_unavailable_message'; + +interface Props { + onChange: (emsFileId: string) => void; + value: string | null; +} + +interface State { + hasLoadedOptions: boolean; + emsFileOptions: Array>; +} + +export class EMSFileSelect extends Component { + private _isMounted: boolean = false; + + state = { + hasLoadedOptions: false, + emsFileOptions: [], + }; + + _loadFileOptions = async () => { + const fileLayers: FileLayer[] = await getEmsFileLayers(); + const options = fileLayers.map((fileLayer) => { + return { + value: fileLayer.getId(), + label: fileLayer.getDisplayName(), + }; + }); + if (this._isMounted) { + this.setState({ + hasLoadedOptions: true, + emsFileOptions: options, + }); + } + }; + + componentWillUnmount() { + this._isMounted = false; + } + + componentDidMount() { + this._isMounted = true; + this._loadFileOptions(); + } + + _onChange = (selectedOptions: Array>) => { + if (selectedOptions.length === 0) { + return; + } + + this.props.onChange(selectedOptions[0].value!); + }; + + _renderSelect() { + if (!this.state.hasLoadedOptions) { + return ; + } + + const selectedOption = this.state.emsFileOptions.find( + (option: EuiComboBoxOptionOption) => { + return option.value === this.props.value; + } + ); + + return ( + + ); + } + + render() { + return ( + + {this._renderSelect()} + + ); + } +} diff --git a/x-pack/plugins/maps/public/classes/sources/ems_unavailable_message.ts b/x-pack/plugins/maps/public/components/ems_unavailable_message.tsx similarity index 93% rename from x-pack/plugins/maps/public/classes/sources/ems_unavailable_message.ts rename to x-pack/plugins/maps/public/components/ems_unavailable_message.tsx index 748016cf889e25..dea161fafd609e 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_unavailable_message.ts +++ b/x-pack/plugins/maps/public/components/ems_unavailable_message.tsx @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; // @ts-ignore -import { getIsEmsEnabled } from '../../kibana_services'; +import { getIsEmsEnabled } from '../kibana_services'; export function getEmsUnavailableMessage(): string { const isEmsEnabled = getIsEmsEnabled(); diff --git a/x-pack/plugins/maps/public/components/geo_index_pattern_select.test.tsx b/x-pack/plugins/maps/public/components/geo_index_pattern_select.test.tsx new file mode 100644 index 00000000000000..74d29e7d7e59a8 --- /dev/null +++ b/x-pack/plugins/maps/public/components/geo_index_pattern_select.test.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('../kibana_services', () => { + const MockIndexPatternSelect = (props: unknown) => { + return
; + }; + const MockHttp = { + basePath: { + prepend: (path: string) => { + return `abc/${path}`; + }, + }, + }; + return { + getIndexPatternSelectComponent: () => { + return MockIndexPatternSelect; + }, + getHttp: () => { + return MockHttp; + }, + }; +}); + +import React from 'react'; +import { shallow } from 'enzyme'; +import { GeoIndexPatternSelect } from './geo_index_pattern_select'; + +test('should render', async () => { + const component = shallow( {}} value={'indexPatternId'} />); + + expect(component).toMatchSnapshot(); +}); + +test('should render no index pattern warning when there are no matching index patterns', async () => { + const component = shallow( {}} value={'indexPatternId'} />); + component.setState({ noGeoIndexPatternsExist: true }); + expect(component).toMatchSnapshot(); +}); diff --git a/x-pack/plugins/maps/public/components/geo_index_pattern_select.tsx b/x-pack/plugins/maps/public/components/geo_index_pattern_select.tsx new file mode 100644 index 00000000000000..ae23d9d97de86e --- /dev/null +++ b/x-pack/plugins/maps/public/components/geo_index_pattern_select.tsx @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component } from 'react'; +import { EuiCallOut, EuiFormRow, EuiLink, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { IndexPattern } from 'src/plugins/data/public'; +import { + getIndexPatternSelectComponent, + getIndexPatternService, + getHttp, +} from '../kibana_services'; +import { ES_GEO_FIELD_TYPES } from '../../common/constants'; + +interface Props { + onChange: (indexPattern: IndexPattern) => void; + value: string | null; +} + +interface State { + noGeoIndexPatternsExist: boolean; +} + +export class GeoIndexPatternSelect extends Component { + private _isMounted: boolean = false; + + state = { + noGeoIndexPatternsExist: false, + }; + + componentWillUnmount() { + this._isMounted = false; + } + + componentDidMount() { + this._isMounted = true; + } + + _onIndexPatternSelect = async (indexPatternId: string) => { + if (!indexPatternId || indexPatternId.length === 0) { + return; + } + + let indexPattern; + try { + indexPattern = await getIndexPatternService().get(indexPatternId); + } catch (err) { + return; + } + + // method may be called again before 'get' returns + // ignore response when fetched index pattern does not match active index pattern + if (this._isMounted && indexPattern.id === indexPatternId) { + this.props.onChange(indexPattern); + } + }; + + _onNoIndexPatterns = () => { + this.setState({ noGeoIndexPatternsExist: true }); + }; + + _renderNoIndexPatternWarning() { + if (!this.state.noGeoIndexPatternsExist) { + return null; + } + + return ( + <> + +

+ + + + + +

+

+ + + + +

+
+ + + ); + } + + render() { + const IndexPatternSelect = getIndexPatternSelectComponent(); + return ( + <> + {this._renderNoIndexPatternWarning()} + + + + + + ); + } +} diff --git a/x-pack/plugins/maps/public/components/no_index_pattern_callout.js b/x-pack/plugins/maps/public/components/no_index_pattern_callout.js deleted file mode 100644 index 2daab8c6322dd3..00000000000000 --- a/x-pack/plugins/maps/public/components/no_index_pattern_callout.js +++ /dev/null @@ -1,52 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { getHttp } from '../kibana_services'; -import React from 'react'; -import { EuiCallOut, EuiLink } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export function NoIndexPatternCallout() { - const http = getHttp(); - return ( - -

- - - - - -

-

- - - - -

-
- ); -} diff --git a/x-pack/plugins/maps/public/components/single_field_select.tsx b/x-pack/plugins/maps/public/components/single_field_select.tsx index eb3a28be0efc01..2895479c4fd0e7 100644 --- a/x-pack/plugins/maps/public/components/single_field_select.tsx +++ b/x-pack/plugins/maps/public/components/single_field_select.tsx @@ -49,7 +49,7 @@ type Props = Omit< > & { fields?: IFieldType[]; onChange: (fieldName?: string) => void; - value?: string; // index pattern field name + value: string | null; // index pattern field name isFieldDisabled?: (field: IFieldType) => boolean; getFieldDisabledReason?: (field: IFieldType) => string | null; }; diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx index 38474b84114fab..3f493ef7d43555 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx @@ -5,7 +5,7 @@ */ import React, { Fragment } from 'react'; -import { EuiButtonEmpty, EuiPanel, EuiSpacer } from '@elastic/eui'; +import { EuiButtonEmpty, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { LayerWizardSelect } from './layer_wizard_select'; import { LayerWizard, RenderWizardArguments } from '../../../classes/layers/layer_wizard_registry'; @@ -50,7 +50,7 @@ export const FlyoutBody = (props: Props) => { return ( {backButton} - {props.layerWizard.renderWizard(renderWizardArgs)} + {props.layerWizard.renderWizard(renderWizardArgs)} ); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 29ea4426ac5f64..cb2d3e60be9ac9 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9155,7 +9155,6 @@ "xpack.maps.source.ems.disabledDescription": "Elastic Maps Service へのアクセスが無効になっています。システム管理者に問い合わせるか、kibana.yml で「map.includeElasticMapsService」を設定してください。", "xpack.maps.source.ems.noAccessDescription": "Kibana が Elastic Maps Service にアクセスできません。システム管理者にお問い合わせください", "xpack.maps.source.emsFile.layerLabel": "レイヤー", - "xpack.maps.source.emsFile.selectPlaceholder": "EMS ベクターシェイプを選択", "xpack.maps.source.emsFile.unableToFindIdErrorMessage": "ID {id} の EMS ベクターシェイプが見つかりません", "xpack.maps.source.emsFileDescription": "Elastic Maps Service の行政区画のベクターシェイプ", "xpack.maps.source.emsFileTitle": "ベクターシェイプ", @@ -9171,8 +9170,6 @@ "xpack.maps.source.esGeoGrid.geofieldLabel": "地理空間フィールド", "xpack.maps.source.esGeoGrid.geofieldPlaceholder": "ジオフィールドを選択", "xpack.maps.source.esGeoGrid.gridRectangleDropdownOption": "グリッド", - "xpack.maps.source.esGeoGrid.indexPatternLabel": "インデックスパターン", - "xpack.maps.source.esGeoGrid.indexPatternPlaceholder": "インデックスパターンを選択", "xpack.maps.source.esGeoGrid.pointsDropdownOption": "クラスター", "xpack.maps.source.esGeoGrid.showAsLabel": "表示形式", "xpack.maps.source.esGrid.coarseDropdownOption": "粗い", @@ -9206,7 +9203,6 @@ "xpack.maps.source.esSearch.limitScalingLabel": "結果を {maxResultWindow} に限定。", "xpack.maps.source.esSearch.loadErrorMessage": "インデックスパターン {id} が見つかりません", "xpack.maps.source.esSearch.loadTooltipPropertiesErrorMsg": "ドキュメントが見つかりません。_id: {docId}", - "xpack.maps.source.esSearch.selectIndexPatternPlaceholder": "インデックスパターンを選択", "xpack.maps.source.esSearch.selectLabel": "ジオフィールドを選択", "xpack.maps.source.esSearch.sortFieldLabel": "フィールド", "xpack.maps.source.esSearch.sortFieldSelectPlaceholder": "ソートフィールドを選択", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 84a4fb41cdd761..b63212b11b1d62 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9159,7 +9159,6 @@ "xpack.maps.source.ems.disabledDescription": "已禁用对 Elastic 地图服务的访问。让您的系统管理员在 kibana.yml 中设置“map.includeElasticMapsService”。", "xpack.maps.source.ems.noAccessDescription": "Kibana 无法访问 Elastic 地图服务。请联系您的系统管理员", "xpack.maps.source.emsFile.layerLabel": "图层", - "xpack.maps.source.emsFile.selectPlaceholder": "选择 EMS 矢量形状", "xpack.maps.source.emsFile.unableToFindIdErrorMessage": "找不到 ID {id} 的 EMS 矢量形状", "xpack.maps.source.emsFileDescription": "来自 Elastic 地图服务的管理边界的矢量形状", "xpack.maps.source.emsFileTitle": "矢量形状", @@ -9175,8 +9174,6 @@ "xpack.maps.source.esGeoGrid.geofieldLabel": "地理空间字段", "xpack.maps.source.esGeoGrid.geofieldPlaceholder": "选择地理字段", "xpack.maps.source.esGeoGrid.gridRectangleDropdownOption": "网格", - "xpack.maps.source.esGeoGrid.indexPatternLabel": "索引模式", - "xpack.maps.source.esGeoGrid.indexPatternPlaceholder": "选择索引模式", "xpack.maps.source.esGeoGrid.pointsDropdownOption": "集群", "xpack.maps.source.esGeoGrid.showAsLabel": "显示为", "xpack.maps.source.esGrid.coarseDropdownOption": "粗糙", @@ -9210,7 +9207,6 @@ "xpack.maps.source.esSearch.limitScalingLabel": "将结果数限制到 {maxResultWindow}。", "xpack.maps.source.esSearch.loadErrorMessage": "找不到索引模式 {id}", "xpack.maps.source.esSearch.loadTooltipPropertiesErrorMsg": "找不到文档,_id:{docId}", - "xpack.maps.source.esSearch.selectIndexPatternPlaceholder": "选择索引模式", "xpack.maps.source.esSearch.selectLabel": "选择地理字段", "xpack.maps.source.esSearch.sortFieldLabel": "字段", "xpack.maps.source.esSearch.sortFieldSelectPlaceholder": "选择排序字段", From fd47408c4bec5a4bb52c2b36fc29e34a3492c8f6 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Mon, 29 Jun 2020 20:23:44 -0600 Subject: [PATCH 26/91] [Platform][Security] Updates cluster_manager ignorePaths to include security scripts (#70139) (#70276) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Updates the cluster_manager `ignorePaths` to include security related script directories so that the server doesn't restart when modifying scripts like below... 🙂

--- src/cli/cluster/cluster_manager.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index 09f9bb2333dbe9..6db6199b391e14 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -266,6 +266,11 @@ export class ClusterManager { fromRoot('x-pack/plugins/apm/e2e'), fromRoot('x-pack/plugins/apm/scripts'), fromRoot('x-pack/plugins/canvas/canvas_plugin_src'), // prevents server from restarting twice for Canvas plugin changes, + fromRoot('x-pack/plugins/case/server/scripts'), + fromRoot('x-pack/plugins/lists/scripts'), + fromRoot('x-pack/plugins/lists/server/scripts'), + fromRoot('x-pack/plugins/security_solution/scripts'), + fromRoot('x-pack/plugins/security_solution/server/lib/detection_engine/scripts'), 'plugins/java_languageserver', ]; From 91bf50b5d40e011de9dfe858a6391dd2b624db89 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 30 Jun 2020 09:33:43 +0200 Subject: [PATCH 27/91] Implement recursive plugin discovery (#68811) (#70286) * implements recursive scanning in plugin discovery system * update optimizer to find plugins in sub-directories * update renovate * update optimizer IT snapshot * refactor processPluginSearchPaths$ and add test for inaccessible manifest * add symlink test * add maxDepth to the optimizer * adapt mockFs definitions * remove `flat` usage # Conflicts: # renovate.json5 --- package.json | 2 + .../plugins/{ => nested}/baz/kibana.json | 0 .../plugins/{ => nested}/baz/server/index.ts | 0 .../plugins/{ => nested}/baz/server/lib.ts | 0 .../basic_optimization.test.ts.snap | 12 +- .../optimizer/kibana_platform_plugins.test.ts | 12 +- .../src/optimizer/kibana_platform_plugins.ts | 13 +- .../discovery/plugins_discovery.test.mocks.ts | 9 - .../discovery/plugins_discovery.test.ts | 571 +++++++++++------- .../plugins/discovery/plugins_discovery.ts | 107 +++- yarn.lock | 12 + 11 files changed, 478 insertions(+), 260 deletions(-) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/{ => nested}/baz/kibana.json (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/{ => nested}/baz/server/index.ts (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/{ => nested}/baz/server/lib.ts (100%) diff --git a/package.json b/package.json index 69c414e6905882..58c9bee381e465 100644 --- a/package.json +++ b/package.json @@ -356,6 +356,7 @@ "@types/markdown-it": "^0.0.7", "@types/minimatch": "^2.0.29", "@types/mocha": "^7.0.2", + "@types/mock-fs": "^4.10.0", "@types/moment-timezone": "^0.5.12", "@types/mustache": "^0.8.31", "@types/node": ">=10.17.17 <10.20.0", @@ -468,6 +469,7 @@ "listr": "^0.14.1", "load-grunt-config": "^3.0.1", "mocha": "^7.1.1", + "mock-fs": "^4.12.0", "mock-http-server": "1.3.0", "ms-chromium-edge-driver": "^0.2.3", "multistream": "^2.1.1", diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/baz/kibana.json b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz/kibana.json similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/baz/kibana.json rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz/kibana.json diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/baz/server/index.ts b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz/server/index.ts similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/baz/server/index.ts rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz/server/index.ts diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/baz/server/lib.ts b/packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz/server/lib.ts similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/baz/server/lib.ts rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz/server/lib.ts diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index fb1c9edef080f9..0528cef0788892 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -43,18 +43,18 @@ OptimizerConfig { "id": "bar", "isUiPlugin": true, }, - Object { - "directory": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/baz, - "extraPublicDirs": Array [], - "id": "baz", - "isUiPlugin": false, - }, Object { "directory": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/foo, "extraPublicDirs": Array [], "id": "foo", "isUiPlugin": true, }, + Object { + "directory": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/nested/baz, + "extraPublicDirs": Array [], + "id": "baz", + "isUiPlugin": false, + }, ], "profileWebpack": false, "repoRoot": /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo, diff --git a/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.test.ts b/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.test.ts index 0961881df461c5..f7b457ca42c6dc 100644 --- a/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.test.ts +++ b/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.test.ts @@ -41,18 +41,18 @@ it('parses kibana.json files of plugins found in pluginDirs', () => { "id": "bar", "isUiPlugin": true, }, - Object { - "directory": /packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/baz, - "extraPublicDirs": Array [], - "id": "baz", - "isUiPlugin": false, - }, Object { "directory": /packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/foo, "extraPublicDirs": Array [], "id": "foo", "isUiPlugin": true, }, + Object { + "directory": /packages/kbn-optimizer/src/__fixtures__/mock_repo/plugins/nested/baz, + "extraPublicDirs": Array [], + "id": "baz", + "isUiPlugin": false, + }, Object { "directory": /packages/kbn-optimizer/src/__fixtures__/mock_repo/test_plugins/test_baz, "extraPublicDirs": Array [], diff --git a/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts b/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts index bfc60a29efa27d..83637691004f40 100644 --- a/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts +++ b/packages/kbn-optimizer/src/optimizer/kibana_platform_plugins.ts @@ -37,7 +37,7 @@ export function findKibanaPlatformPlugins(scanDirs: string[], paths: string[]) { .sync( Array.from( new Set([ - ...scanDirs.map((dir) => `${dir}/*/kibana.json`), + ...scanDirs.map(nestedScanDirPaths).reduce((dirs, current) => [...dirs, ...current], []), ...paths.map((path) => `${path}/kibana.json`), ]) ), @@ -51,6 +51,17 @@ export function findKibanaPlatformPlugins(scanDirs: string[], paths: string[]) { ); } +function nestedScanDirPaths(dir: string): string[] { + // down to 5 level max + return [ + `${dir}/*/kibana.json`, + `${dir}/*/*/kibana.json`, + `${dir}/*/*/*/kibana.json`, + `${dir}/*/*/*/*/kibana.json`, + `${dir}/*/*/*/*/*/kibana.json`, + ]; +} + function readKibanaPlatformPlugin(manifestPath: string): KibanaPlatformPlugin { if (!Path.isAbsolute(manifestPath)) { throw new TypeError('expected new platform manifest path to be absolute'); diff --git a/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts b/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts index d92465e4dd4971..83accc06cb9956 100644 --- a/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts +++ b/src/core/server/plugins/discovery/plugins_discovery.test.mocks.ts @@ -17,14 +17,5 @@ * under the License. */ -export const mockReaddir = jest.fn(); -export const mockReadFile = jest.fn(); -export const mockStat = jest.fn(); -jest.mock('fs', () => ({ - readdir: mockReaddir, - readFile: mockReadFile, - stat: mockStat, -})); - export const mockPackage = new Proxy({ raw: {} as any }, { get: (obj, prop) => obj.raw[prop] }); jest.mock('../../../../../package.json', () => mockPackage); diff --git a/src/core/server/plugins/discovery/plugins_discovery.test.ts b/src/core/server/plugins/discovery/plugins_discovery.test.ts index 1c42f5dcfc7a70..70413757de9da2 100644 --- a/src/core/server/plugins/discovery/plugins_discovery.test.ts +++ b/src/core/server/plugins/discovery/plugins_discovery.test.ts @@ -17,251 +17,384 @@ * under the License. */ -import { mockPackage, mockReaddir, mockReadFile, mockStat } from './plugins_discovery.test.mocks'; -import { rawConfigServiceMock } from '../../config/raw_config_service.mock'; +import { mockPackage } from './plugins_discovery.test.mocks'; +import mockFs from 'mock-fs'; import { loggingSystemMock } from '../../logging/logging_system.mock'; -import { resolve } from 'path'; import { first, map, toArray } from 'rxjs/operators'; - +import { resolve } from 'path'; import { ConfigService, Env } from '../../config'; import { getEnvOptions } from '../../config/__mocks__/env'; -import { PluginWrapper } from '../plugin'; import { PluginsConfig, PluginsConfigType, config } from '../plugins_config'; import { discover } from './plugins_discovery'; +import { rawConfigServiceMock } from '../../config/raw_config_service.mock'; +import { CoreContext } from '../../core_context'; -const TEST_PLUGIN_SEARCH_PATHS = { - nonEmptySrcPlugins: resolve(process.cwd(), 'src', 'plugins'), - emptyPlugins: resolve(process.cwd(), 'plugins'), - nonExistentKibanaExtra: resolve(process.cwd(), '..', 'kibana-extra'), +const KIBANA_ROOT = process.cwd(); + +const Plugins = { + invalid: () => ({ + 'kibana.json': 'not-json', + }), + incomplete: () => ({ + 'kibana.json': JSON.stringify({ version: '1' }), + }), + incompatible: () => ({ + 'kibana.json': JSON.stringify({ id: 'plugin', version: '1' }), + }), + missingManifest: () => ({}), + inaccessibleManifest: () => ({ + 'kibana.json': mockFs.file({ + mode: 0, // 0000, + content: JSON.stringify({ id: 'plugin', version: '1' }), + }), + }), + valid: (id: string) => ({ + 'kibana.json': JSON.stringify({ + id, + configPath: ['plugins', id], + version: '1', + kibanaVersion: '1.2.3', + requiredPlugins: [], + optionalPlugins: [], + server: true, + }), + }), +}; + +const packageMock = { + branch: 'master', + version: '1.2.3', + build: { + distributable: true, + number: 1, + sha: '', + }, }; -const TEST_EXTRA_PLUGIN_PATH = resolve(process.cwd(), 'my-extra-plugin'); - -const logger = loggingSystemMock.create(); - -beforeEach(() => { - mockReaddir.mockImplementation((path, cb) => { - if (path === TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins) { - cb(null, [ - '1', - '2-no-manifest', - '3', - '4-incomplete-manifest', - '5-invalid-manifest', - '6', - '7-non-dir', - '8-incompatible-manifest', - '9-inaccessible-dir', - ]); - } else if (path === TEST_PLUGIN_SEARCH_PATHS.nonExistentKibanaExtra) { - cb(new Error('ENOENT')); - } else { - cb(null, []); - } + +const manifestPath = (...pluginPath: string[]) => + resolve(KIBANA_ROOT, 'src', 'plugins', ...pluginPath, 'kibana.json'); + +describe('plugins discovery system', () => { + let logger: ReturnType; + let env: Env; + let configService: ConfigService; + let pluginConfig: PluginsConfigType; + let coreContext: CoreContext; + + beforeEach(async () => { + logger = loggingSystemMock.create(); + + mockPackage.raw = packageMock; + + env = Env.createDefault( + getEnvOptions({ + cliArgs: { envName: 'development' }, + }) + ); + + configService = new ConfigService( + rawConfigServiceMock.create({ rawConfig: { plugins: { paths: [] } } }), + env, + logger + ); + await configService.setSchema(config.path, config.schema); + + coreContext = { + coreId: Symbol(), + configService, + env, + logger, + }; + + pluginConfig = await configService + .atPath('plugins') + .pipe(first()) + .toPromise(); + + // jest relies on the filesystem to get sourcemaps when using console.log + // which breaks with the mocked FS, see https://github.com/tschaub/mock-fs/issues/234 + // hijacking logging to process.stdout as a workaround for this suite. + jest.spyOn(console, 'log').mockImplementation((...args) => { + process.stdout.write(args + '\n'); + }); }); - mockStat.mockImplementation((path, cb) => { - if (path.includes('9-inaccessible-dir')) { - cb(new Error(`ENOENT (disappeared between "readdir" and "stat").`)); - } else { - cb(null, { isDirectory: () => !path.includes('non-dir') }); - } + afterEach(() => { + mockFs.restore(); + // restore the console.log behavior + jest.restoreAllMocks(); }); - mockReadFile.mockImplementation((path, cb) => { - if (path.includes('no-manifest')) { - cb(new Error('ENOENT')); - } else if (path.includes('invalid-manifest')) { - cb(null, Buffer.from('not-json')); - } else if (path.includes('incomplete-manifest')) { - cb(null, Buffer.from(JSON.stringify({ version: '1' }))); - } else if (path.includes('incompatible-manifest')) { - cb(null, Buffer.from(JSON.stringify({ id: 'plugin', version: '1' }))); - } else { - cb( - null, - Buffer.from( - JSON.stringify({ - id: 'plugin', - configPath: ['core', 'config'], - version: '1', - kibanaVersion: '1.2.3', - requiredPlugins: ['a', 'b'], - optionalPlugins: ['c', 'd'], - server: true, - }) - ) - ); - } + it('discovers plugins in the search locations', async () => { + const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + mockFs( + { + [`${KIBANA_ROOT}/src/plugins/plugin_a`]: Plugins.valid('pluginA'), + [`${KIBANA_ROOT}/plugins/plugin_b`]: Plugins.valid('pluginB'), + [`${KIBANA_ROOT}/x-pack/plugins/plugin_c`]: Plugins.valid('pluginC'), + }, + { createCwd: false } + ); + + const plugins = await plugin$.pipe(toArray()).toPromise(); + const pluginNames = plugins.map((plugin) => plugin.name); + + expect(pluginNames).toHaveLength(3); + expect(pluginNames).toEqual(expect.arrayContaining(['pluginA', 'pluginB', 'pluginC'])); }); -}); -afterEach(() => { - jest.clearAllMocks(); -}); + it('return errors when the manifest is invalid or incompatible', async () => { + const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + mockFs( + { + [`${KIBANA_ROOT}/src/plugins/plugin_a`]: Plugins.invalid(), + [`${KIBANA_ROOT}/src/plugins/plugin_b`]: Plugins.incomplete(), + [`${KIBANA_ROOT}/src/plugins/plugin_c`]: Plugins.incompatible(), + [`${KIBANA_ROOT}/src/plugins/plugin_ad`]: Plugins.missingManifest(), + }, + { createCwd: false } + ); + + const plugins = await plugin$.pipe(toArray()).toPromise(); + expect(plugins).toHaveLength(0); + + const errors = await error$ + .pipe( + map((error) => error.toString()), + toArray() + ) + .toPromise(); -test('properly iterates through plugin search locations', async () => { - mockPackage.raw = { - branch: 'master', - version: '1.2.3', - build: { - distributable: true, - number: 1, - sha: '', - }, - }; - - const env = Env.createDefault( - getEnvOptions({ - cliArgs: { envName: 'development' }, - }) - ); - const configService = new ConfigService( - rawConfigServiceMock.create({ rawConfig: { plugins: { paths: [TEST_EXTRA_PLUGIN_PATH] } } }), - env, - logger - ); - await configService.setSchema(config.path, config.schema); - - const rawConfig = await configService - .atPath('plugins') - .pipe(first()) - .toPromise(); - const { plugin$, error$ } = discover(new PluginsConfig(rawConfig, env), { - coreId: Symbol(), - configService, - env, - logger, + expect(errors).toEqual( + expect.arrayContaining([ + `Error: Unexpected token o in JSON at position 1 (invalid-manifest, ${manifestPath( + 'plugin_a' + )})`, + `Error: Plugin manifest must contain an "id" property. (invalid-manifest, ${manifestPath( + 'plugin_b' + )})`, + `Error: Plugin "plugin" is only compatible with Kibana version "1", but used Kibana version is "1.2.3". (incompatible-version, ${manifestPath( + 'plugin_c' + )})`, + ]) + ); }); - const plugins = await plugin$.pipe(toArray()).toPromise(); - expect(plugins).toHaveLength(4); - - for (const path of [ - resolve(TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, '1'), - resolve(TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, '3'), - resolve(TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, '6'), - TEST_EXTRA_PLUGIN_PATH, - ]) { - const discoveredPlugin = plugins.find((plugin) => plugin.path === path)!; - expect(discoveredPlugin).toBeInstanceOf(PluginWrapper); - expect(discoveredPlugin.configPath).toEqual(['core', 'config']); - expect(discoveredPlugin.requiredPlugins).toEqual(['a', 'b']); - expect(discoveredPlugin.optionalPlugins).toEqual(['c', 'd']); - } - - await expect( - error$ + it('return errors when the plugin search path is not accessible', async () => { + const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + mockFs( + { + [`${KIBANA_ROOT}/src/plugins`]: mockFs.directory({ + mode: 0, // 0000 + items: { + plugin_a: Plugins.valid('pluginA'), + }, + }), + }, + { createCwd: false } + ); + + const plugins = await plugin$.pipe(toArray()).toPromise(); + expect(plugins).toHaveLength(0); + + const errors = await error$ .pipe( map((error) => error.toString()), toArray() ) - .toPromise() - ).resolves.toEqual([ - `Error: ENOENT (disappeared between "readdir" and "stat"). (invalid-plugin-path, ${resolve( - TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, - '9-inaccessible-dir' - )})`, - `Error: ENOENT (invalid-search-path, ${TEST_PLUGIN_SEARCH_PATHS.nonExistentKibanaExtra})`, - `Error: ENOENT (missing-manifest, ${resolve( - TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, - '2-no-manifest', - 'kibana.json' - )})`, - `Error: Plugin manifest must contain an "id" property. (invalid-manifest, ${resolve( - TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, - '4-incomplete-manifest', - 'kibana.json' - )})`, - `Error: Unexpected token o in JSON at position 1 (invalid-manifest, ${resolve( - TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, - '5-invalid-manifest', - 'kibana.json' - )})`, - `Error: Plugin "plugin" is only compatible with Kibana version "1", but used Kibana version is "1.2.3". (incompatible-version, ${resolve( - TEST_PLUGIN_SEARCH_PATHS.nonEmptySrcPlugins, - '8-incompatible-manifest', - 'kibana.json' - )})`, - ]); -}); + .toPromise(); -test('logs a warning about --plugin-path when used in development', async () => { - mockPackage.raw = { - branch: 'master', - version: '1.2.3', - build: { - distributable: true, - number: 1, - sha: '', - }, - }; - - const env = Env.createDefault( - getEnvOptions({ - cliArgs: { dev: false, envName: 'development' }, - }) - ); - const configService = new ConfigService( - rawConfigServiceMock.create({ rawConfig: { plugins: { paths: [TEST_EXTRA_PLUGIN_PATH] } } }), - env, - logger - ); - await configService.setSchema(config.path, config.schema); - - const rawConfig = await configService - .atPath('plugins') - .pipe(first()) - .toPromise(); - - discover(new PluginsConfig(rawConfig, env), { - coreId: Symbol(), - configService, - env, - logger, + const srcPluginsPath = resolve(KIBANA_ROOT, 'src', 'plugins'); + const xpackPluginsPath = resolve(KIBANA_ROOT, 'x-pack', 'plugins'); + expect(errors).toEqual( + expect.arrayContaining([ + `Error: EACCES, permission denied '${srcPluginsPath}' (invalid-search-path, ${srcPluginsPath})`, + `Error: ENOENT, no such file or directory '${xpackPluginsPath}' (invalid-search-path, ${xpackPluginsPath})`, + ]) + ); }); - expect(loggingSystemMock.collect(logger).warn).toEqual([ - [ - `Explicit plugin paths [${TEST_EXTRA_PLUGIN_PATH}] should only be used in development. Relative imports may not work properly in production.`, - ], - ]); -}); + it('return an error when the manifest file is not accessible', async () => { + const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + mockFs( + { + [`${KIBANA_ROOT}/src/plugins/plugin_a`]: { + ...Plugins.inaccessibleManifest(), + nested_plugin: Plugins.valid('nestedPlugin'), + }, + }, + { createCwd: false } + ); -test('does not log a warning about --plugin-path when used in production', async () => { - mockPackage.raw = { - branch: 'master', - version: '1.2.3', - build: { - distributable: true, - number: 1, - sha: '', - }, - }; - - const env = Env.createDefault( - getEnvOptions({ - cliArgs: { dev: false, envName: 'production' }, - }) - ); - const configService = new ConfigService( - rawConfigServiceMock.create({ rawConfig: { plugins: { paths: [TEST_EXTRA_PLUGIN_PATH] } } }), - env, - logger - ); - await configService.setSchema(config.path, config.schema); - - const rawConfig = await configService - .atPath('plugins') - .pipe(first()) - .toPromise(); - - discover(new PluginsConfig(rawConfig, env), { - coreId: Symbol(), - configService, - env, - logger, + const plugins = await plugin$.pipe(toArray()).toPromise(); + expect(plugins).toHaveLength(0); + + const errors = await error$ + .pipe( + map((error) => error.toString()), + toArray() + ) + .toPromise(); + + const errorPath = manifestPath('plugin_a'); + expect(errors).toEqual( + expect.arrayContaining([ + `Error: EACCES, permission denied '${errorPath}' (missing-manifest, ${errorPath})`, + ]) + ); + }); + + it('discovers plugins in nested directories', async () => { + const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + mockFs( + { + [`${KIBANA_ROOT}/src/plugins/plugin_a`]: Plugins.valid('pluginA'), + [`${KIBANA_ROOT}/src/plugins/sub1/plugin_b`]: Plugins.valid('pluginB'), + [`${KIBANA_ROOT}/src/plugins/sub1/sub2/plugin_c`]: Plugins.valid('pluginC'), + [`${KIBANA_ROOT}/src/plugins/sub1/sub2/plugin_d`]: Plugins.incomplete(), + }, + { createCwd: false } + ); + + const plugins = await plugin$.pipe(toArray()).toPromise(); + const pluginNames = plugins.map((plugin) => plugin.name); + + expect(pluginNames).toHaveLength(3); + expect(pluginNames).toEqual(expect.arrayContaining(['pluginA', 'pluginB', 'pluginC'])); + + const errors = await error$ + .pipe( + map((error) => error.toString()), + toArray() + ) + .toPromise(); + + expect(errors).toEqual( + expect.arrayContaining([ + `Error: Plugin manifest must contain an "id" property. (invalid-manifest, ${manifestPath( + 'sub1', + 'sub2', + 'plugin_d' + )})`, + ]) + ); + }); + + it('does not discover plugins nested inside another plugin', async () => { + const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + mockFs( + { + [`${KIBANA_ROOT}/src/plugins/plugin_a`]: { + ...Plugins.valid('pluginA'), + nested_plugin: Plugins.valid('nestedPlugin'), + }, + }, + { createCwd: false } + ); + + const plugins = await plugin$.pipe(toArray()).toPromise(); + const pluginNames = plugins.map((plugin) => plugin.name); + + expect(pluginNames).toEqual(['pluginA']); + }); + + it('stops scanning when reaching `maxDepth`', async () => { + const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + mockFs( + { + [`${KIBANA_ROOT}/src/plugins/sub1/plugin`]: Plugins.valid('plugin1'), + [`${KIBANA_ROOT}/src/plugins/sub1/sub2/plugin`]: Plugins.valid('plugin2'), + [`${KIBANA_ROOT}/src/plugins/sub1/sub2/sub3/plugin`]: Plugins.valid('plugin3'), + [`${KIBANA_ROOT}/src/plugins/sub1/sub2/sub3/sub4/plugin`]: Plugins.valid('plugin4'), + [`${KIBANA_ROOT}/src/plugins/sub1/sub2/sub3/sub4/sub5/plugin`]: Plugins.valid('plugin5'), + [`${KIBANA_ROOT}/src/plugins/sub1/sub2/sub3/sub4/sub5/sub6/plugin`]: Plugins.valid( + 'plugin6' + ), + }, + { createCwd: false } + ); + + const plugins = await plugin$.pipe(toArray()).toPromise(); + const pluginNames = plugins.map((plugin) => plugin.name); + + expect(pluginNames).toHaveLength(5); + expect(pluginNames).toEqual( + expect.arrayContaining(['plugin1', 'plugin2', 'plugin3', 'plugin4', 'plugin5']) + ); + }); + + it('works with symlinks', async () => { + const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext); + + const pluginFolder = resolve(KIBANA_ROOT, '..', 'ext-plugins'); + + mockFs( + { + [`${KIBANA_ROOT}/plugins`]: mockFs.symlink({ + path: '../ext-plugins', + }), + [pluginFolder]: { + plugin_a: Plugins.valid('pluginA'), + plugin_b: Plugins.valid('pluginB'), + }, + }, + { createCwd: false } + ); + + const plugins = await plugin$.pipe(toArray()).toPromise(); + const pluginNames = plugins.map((plugin) => plugin.name); + + expect(pluginNames).toHaveLength(2); + expect(pluginNames).toEqual(expect.arrayContaining(['pluginA', 'pluginB'])); }); - expect(loggingSystemMock.collect(logger).warn).toEqual([]); + it('logs a warning about --plugin-path when used in development', async () => { + const extraPluginTestPath = resolve(process.cwd(), 'my-extra-plugin'); + + env = Env.createDefault( + getEnvOptions({ + cliArgs: { dev: false, envName: 'development' }, + }) + ); + + discover(new PluginsConfig({ ...pluginConfig, paths: [extraPluginTestPath] }, env), { + coreId: Symbol(), + configService, + env, + logger, + }); + + expect(loggingSystemMock.collect(logger).warn).toEqual([ + [ + `Explicit plugin paths [${extraPluginTestPath}] should only be used in development. Relative imports may not work properly in production.`, + ], + ]); + }); + + test('does not log a warning about --plugin-path when used in production', async () => { + const extraPluginTestPath = resolve(process.cwd(), 'my-extra-plugin'); + + env = Env.createDefault( + getEnvOptions({ + cliArgs: { dev: false, envName: 'production' }, + }) + ); + + discover(new PluginsConfig({ ...pluginConfig, paths: [extraPluginTestPath] }, env), { + coreId: Symbol(), + configService, + env, + logger, + }); + + expect(loggingSystemMock.collect(logger).warn).toEqual([]); + }); }); diff --git a/src/core/server/plugins/discovery/plugins_discovery.ts b/src/core/server/plugins/discovery/plugins_discovery.ts index 1910483211e34c..5e765a9632e55a 100644 --- a/src/core/server/plugins/discovery/plugins_discovery.ts +++ b/src/core/server/plugins/discovery/plugins_discovery.ts @@ -19,7 +19,7 @@ import { readdir, stat } from 'fs'; import { resolve } from 'path'; -import { bindNodeCallback, from, merge } from 'rxjs'; +import { bindNodeCallback, from, merge, Observable } from 'rxjs'; import { catchError, filter, map, mergeMap, shareReplay } from 'rxjs/operators'; import { CoreContext } from '../../core_context'; import { Logger } from '../../logging'; @@ -32,6 +32,13 @@ import { parseManifest } from './plugin_manifest_parser'; const fsReadDir$ = bindNodeCallback(readdir); const fsStat$ = bindNodeCallback(stat); +const maxScanDepth = 5; + +interface PluginSearchPathEntry { + dir: string; + depth: number; +} + /** * Tries to discover all possible plugins based on the provided plugin config. * Discovery result consists of two separate streams, the one (`plugin$`) is @@ -75,34 +82,96 @@ export function discover(config: PluginsConfig, coreContext: CoreContext) { } /** - * Iterates over every plugin search path and returns a merged stream of all - * sub-directories. If directory cannot be read or it's impossible to get stat + * Recursively iterates over every plugin search path and returns a merged stream of all + * sub-directories containing a manifest file. If directory cannot be read or it's impossible to get stat * for any of the nested entries then error is added into the stream instead. + * * @param pluginDirs List of the top-level directories to process. * @param log Plugin discovery logger instance. */ -function processPluginSearchPaths$(pluginDirs: readonly string[], log: Logger) { - return from(pluginDirs).pipe( - mergeMap((dir) => { - log.debug(`Scanning "${dir}" for plugin sub-directories...`); +function processPluginSearchPaths$( + pluginDirs: readonly string[], + log: Logger +): Observable { + function recursiveScanFolder( + ent: PluginSearchPathEntry + ): Observable { + return from([ent]).pipe( + mergeMap((entry) => { + return findManifestInFolder(entry.dir, () => { + if (entry.depth > maxScanDepth) { + return []; + } + return mapSubdirectories(entry.dir, (subDir) => + recursiveScanFolder({ dir: subDir, depth: entry.depth + 1 }) + ); + }); + }) + ); + } - return fsReadDir$(dir).pipe( - mergeMap((subDirs: string[]) => subDirs.map((subDir) => resolve(dir, subDir))), - mergeMap((path) => - fsStat$(path).pipe( - // Filter out non-directory entries from target directories, it's expected that - // these directories may contain files (e.g. `README.md` or `package.json`). - // We shouldn't silently ignore the entries we couldn't get stat for though. - mergeMap((pathStat) => (pathStat.isDirectory() ? [path] : [])), - catchError((err) => [PluginDiscoveryError.invalidPluginPath(path, err)]) - ) - ), - catchError((err) => [PluginDiscoveryError.invalidSearchPath(dir, err)]) + return from(pluginDirs.map((dir) => ({ dir, depth: 0 }))).pipe( + mergeMap((entry) => { + log.debug(`Scanning "${entry.dir}" for plugin sub-directories...`); + return fsReadDir$(entry.dir).pipe( + mergeMap(() => recursiveScanFolder(entry)), + catchError((err) => [PluginDiscoveryError.invalidSearchPath(entry.dir, err)]) ); }) ); } +/** + * Attempts to read manifest file in specified directory or calls `notFound` and returns results if not found. For any + * manifest files that cannot be read, a PluginDiscoveryError is added. + * @param dir + * @param notFound + */ +function findManifestInFolder( + dir: string, + notFound: () => never[] | Observable +): string[] | Observable { + return fsStat$(resolve(dir, 'kibana.json')).pipe( + mergeMap((stats) => { + // `kibana.json` exists in given directory, we got a plugin + if (stats.isFile()) { + return [dir]; + } + return []; + }), + catchError((manifestStatError) => { + // did not find manifest. recursively process sub directories until we reach max depth. + if (manifestStatError.code !== 'ENOENT') { + return [PluginDiscoveryError.invalidPluginPath(dir, manifestStatError)]; + } + return notFound(); + }) + ); +} + +/** + * Finds all subdirectories in `dir` and executed `mapFunc` for each one. For any directories that cannot be read, + * a PluginDiscoveryError is added. + * @param dir + * @param mapFunc + */ +function mapSubdirectories( + dir: string, + mapFunc: (subDir: string) => Observable +): Observable { + return fsReadDir$(dir).pipe( + mergeMap((subDirs: string[]) => subDirs.map((subDir) => resolve(dir, subDir))), + mergeMap((subDir) => + fsStat$(subDir).pipe( + mergeMap((pathStat) => (pathStat.isDirectory() ? mapFunc(subDir) : [])), + catchError((subDirStatError) => [ + PluginDiscoveryError.invalidPluginPath(subDir, subDirStatError), + ]) + ) + ) + ); +} + /** * Tries to load and parse the plugin manifest file located at the provided plugin * directory path and produces an error result if it fails to do so or plugin manifest diff --git a/yarn.lock b/yarn.lock index 955cb6f0bd9bbc..bdace2c42be57f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5500,6 +5500,13 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce" integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w== +"@types/mock-fs@^4.10.0": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@types/mock-fs/-/mock-fs-4.10.0.tgz#460061b186993d76856f669d5317cda8a007c24b" + integrity sha512-FQ5alSzmHMmliqcL36JqIA4Yyn9jyJKvRSGV3mvPh108VFatX7naJDzSG4fnFQNZFq9dIx0Dzoe6ddflMB2Xkg== + dependencies: + "@types/node" "*" + "@types/moment-timezone@^0.5.12": version "0.5.12" resolved "https://registry.yarnpkg.com/@types/moment-timezone/-/moment-timezone-0.5.12.tgz#0fb680c03db194fe8ff4551eaeb1eec8d3d80e9f" @@ -22095,6 +22102,11 @@ mochawesome@^4.1.0: strip-ansi "^5.0.0" uuid "^3.3.2" +mock-fs@^4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.12.0.tgz#a5d50b12d2d75e5bec9dac3b67ffe3c41d31ade4" + integrity sha512-/P/HtrlvBxY4o/PzXY9cCNBrdylDNxg7gnrv2sMNxj+UJ2m8jSpl0/A6fuJeNAWr99ZvGWH8XCbE0vmnM5KupQ== + mock-http-server@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/mock-http-server/-/mock-http-server-1.3.0.tgz#d2c2ffe65f77d3a4da8302c91d3bf687e5b51519" From 4fe9c739c5ce47a6ffd549a51ac5821ac4312e36 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Tue, 30 Jun 2020 10:34:56 +0200 Subject: [PATCH 28/91] [SIEM] Fixes Cypress 'Search Bar' test (#69952) (#70247) * fixes 'Search Bar' test * [DEBUG] executes only Security Cypress tests * Revert "[DEBUG] executes only Security Cypress tests" This reverts commit e727790dbf9b679766f74f9f7ac443fc2f1438d3. * [DEBUG] executes only Security Cypress tests * [DEBUG] fixes jenkins file * [DEBUG] fixes Jenkinsfile * Revert "[DEBUG] fixes Jenkinsfile" This reverts commit 8f42e82edd0e15594668b73eae5f8b3e0396ea69. * Revert "[DEBUG] fixes jenkins file" This reverts commit 98487467eb03928e1ef534eab862efd8e2c962eb. * Revert "[DEBUG] executes only Security Cypress tests" This reverts commit 6a089305e1a89367546b4d03db16a4757c121a32. Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../security_solution/cypress/integration/search_bar.spec.ts | 3 +-- x-pack/plugins/security_solution/cypress/tasks/search_bar.ts | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/search_bar.spec.ts b/x-pack/plugins/security_solution/cypress/integration/search_bar.spec.ts index 10759cc7de6e91..ce053d1ac76166 100644 --- a/x-pack/plugins/security_solution/cypress/integration/search_bar.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/search_bar.spec.ts @@ -12,8 +12,7 @@ import { hostIpFilter } from '../objects/filter'; import { HOSTS_URL } from '../urls/navigation'; import { waitForAllHostsToBeLoaded } from '../tasks/hosts/all_hosts'; -// FAILING: https://github.com/elastic/kibana/issues/69595 -describe.skip('SearchBar', () => { +describe('SearchBar', () => { before(() => { loginAndWaitForPage(HOSTS_URL); waitForAllHostsToBeLoaded(); diff --git a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts index 01d712460b4477..a32c38a97fce50 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts @@ -23,6 +23,8 @@ export const openAddFilterPopover = () => { }; export const fillAddFilterForm = ({ key, value }: SearchBarFilter) => { + cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('exist'); + cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('be.visible'); cy.get(ADD_FILTER_FORM_FIELD_INPUT).type(key); cy.get(ADD_FILTER_FORM_FIELD_INPUT).click(); cy.get(ADD_FILTER_FORM_FIELD_OPTION(key)).click({ force: true }); From 57550cf824d77f801d42bf00e7ee0d4f3a30a7de Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Tue, 30 Jun 2020 10:35:14 +0200 Subject: [PATCH 29/91] renames 'detections' to 'alerts' (#70164) (#70248) --- .../{detections.spec.ts => alerts.spec.ts} | 6 +-- ...spec.ts => alerts_detection_rules.spec.ts} | 16 ++++---- ... => alerts_detection_rules_custom.spec.ts} | 38 +++++++++---------- ... => alerts_detection_rules_export.spec.ts} | 8 ++-- ...c.ts => alerts_detection_rules_ml.spec.ts} | 38 +++++++++---------- ...> alerts_detection_rules_prebuilt.spec.ts} | 20 +++++----- ...meline.spec.ts => alerts_timeline.spec.ts} | 6 +-- .../screens/{detections.ts => alerts.ts} | 0 ...ion_rules.ts => alerts_detection_rules.ts} | 0 .../tasks/{detections.ts => alerts.ts} | 4 +- ...ion_rules.ts => alerts_detection_rules.ts} | 2 +- 11 files changed, 69 insertions(+), 69 deletions(-) rename x-pack/plugins/security_solution/cypress/integration/{detections.spec.ts => alerts.spec.ts} (98%) rename x-pack/plugins/security_solution/cypress/integration/{signal_detection_rules.spec.ts => alerts_detection_rules.spec.ts} (91%) rename x-pack/plugins/security_solution/cypress/integration/{signal_detection_rules_custom.spec.ts => alerts_detection_rules_custom.spec.ts} (97%) rename x-pack/plugins/security_solution/cypress/integration/{signal_detection_rules_export.spec.ts => alerts_detection_rules_export.spec.ts} (88%) rename x-pack/plugins/security_solution/cypress/integration/{signal_detection_rules_ml.spec.ts => alerts_detection_rules_ml.spec.ts} (96%) rename x-pack/plugins/security_solution/cypress/integration/{signal_detection_rules_prebuilt.spec.ts => alerts_detection_rules_prebuilt.spec.ts} (95%) rename x-pack/plugins/security_solution/cypress/integration/{detections_timeline.spec.ts => alerts_timeline.spec.ts} (90%) rename x-pack/plugins/security_solution/cypress/screens/{detections.ts => alerts.ts} (100%) rename x-pack/plugins/security_solution/cypress/screens/{alert_detection_rules.ts => alerts_detection_rules.ts} (100%) rename x-pack/plugins/security_solution/cypress/tasks/{detections.ts => alerts.ts} (97%) rename x-pack/plugins/security_solution/cypress/tasks/{alert_detection_rules.ts => alerts_detection_rules.ts} (98%) diff --git a/x-pack/plugins/security_solution/cypress/integration/detections.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts similarity index 98% rename from x-pack/plugins/security_solution/cypress/integration/detections.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts index 2e727be1fc9b45..c8c18696359f72 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detections.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts @@ -9,7 +9,7 @@ import { SHOWING_ALERTS, ALERTS, TAKE_ACTION_POPOVER_BTN, -} from '../screens/detections'; +} from '../screens/alerts'; import { closeFirstAlert, @@ -24,13 +24,13 @@ import { waitForAlertsToBeLoaded, markInProgressFirstAlert, goToInProgressAlerts, -} from '../tasks/detections'; +} from '../tasks/alerts'; import { esArchiverLoad } from '../tasks/es_archiver'; import { loginAndWaitForPage } from '../tasks/login'; import { ALERTS_URL } from '../urls/navigation'; -describe('Detections', () => { +describe('Alerts', () => { context('Closing alerts', () => { beforeEach(() => { esArchiverLoad('alerts'); diff --git a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules.spec.ts similarity index 91% rename from x-pack/plugins/security_solution/cypress/integration/signal_detection_rules.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules.spec.ts index 72a86e3ffffc56..5cad0b9c3260c2 100644 --- a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules.spec.ts @@ -10,25 +10,25 @@ import { RULE_SWITCH, SECOND_RULE, SEVENTH_RULE, -} from '../screens/alert_detection_rules'; +} from '../screens/alerts_detection_rules'; import { - goToManageAlertDetectionRules, + goToManageAlertsDetectionRules, waitForAlertsPanelToBeLoaded, waitForAlertsIndexToBeCreated, -} from '../tasks/detections'; -import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; -import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; +} from '../tasks/alerts'; import { activateRule, sortByActivatedRules, waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, waitForRuleToBeActivated, -} from '../tasks/alert_detection_rules'; +} from '../tasks/alerts_detection_rules'; +import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; +import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { ALERTS_URL } from '../urls/navigation'; -describe('Detection rules', () => { +describe('Alerts detection rules', () => { before(() => { esArchiverLoad('prebuilt_rules_loaded'); }); @@ -41,7 +41,7 @@ describe('Detection rules', () => { loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); - goToManageAlertDetectionRules(); + goToManageAlertsDetectionRules(); waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); cy.get(RULE_NAME) .eq(FIFTH_RULE) diff --git a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_custom.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts similarity index 97% rename from x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_custom.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts index 48d0c2e7238cd4..9e9732a403f8fc 100644 --- a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_custom.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts @@ -6,6 +6,15 @@ import { newRule, totalNumberOfPrebuiltRulesInEsArchive } from '../objects/rule'; +import { + CUSTOM_RULES_BTN, + RISK_SCORE, + RULE_NAME, + RULES_ROW, + RULES_TABLE, + SEVERITY, + SHOWING_RULES_TEXT, +} from '../screens/alerts_detection_rules'; import { ABOUT_FALSE_POSITIVES, ABOUT_INVESTIGATION_NOTES, @@ -28,26 +37,12 @@ import { SCHEDULE_RUNS, SCHEDULE_STEP, } from '../screens/rule_details'; -import { - CUSTOM_RULES_BTN, - RISK_SCORE, - RULE_NAME, - RULES_ROW, - RULES_TABLE, - SEVERITY, - SHOWING_RULES_TEXT, -} from '../screens/alert_detection_rules'; import { - createAndActivateRule, - fillAboutRuleAndContinue, - fillDefineCustomRuleWithImportedQueryAndContinue, -} from '../tasks/create_new_rule'; -import { - goToManageAlertDetectionRules, + goToManageAlertsDetectionRules, waitForAlertsIndexToBeCreated, waitForAlertsPanelToBeLoaded, -} from '../tasks/detections'; +} from '../tasks/alerts'; import { changeToThreeHundredRowsPerPage, deleteFirstRule, @@ -58,7 +53,12 @@ import { selectNumberOfRules, waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, waitForRulesToBeLoaded, -} from '../tasks/alert_detection_rules'; +} from '../tasks/alerts_detection_rules'; +import { + createAndActivateRule, + fillAboutRuleAndContinue, + fillDefineCustomRuleWithImportedQueryAndContinue, +} from '../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; @@ -77,7 +77,7 @@ describe('Detection rules, custom', () => { loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); - goToManageAlertDetectionRules(); + goToManageAlertsDetectionRules(); waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); goToCreateNewRule(); fillDefineCustomRuleWithImportedQueryAndContinue(newRule); @@ -172,7 +172,7 @@ describe('Deletes custom rules', () => { loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); - goToManageAlertDetectionRules(); + goToManageAlertsDetectionRules(); }); after(() => { diff --git a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_export.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_export.spec.ts similarity index 88% rename from x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_export.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_export.spec.ts index edb559bf6a279e..25fc1fc3a7c110 100644 --- a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_export.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_export.spec.ts @@ -5,13 +5,13 @@ */ import { - goToManageAlertDetectionRules, + goToManageAlertsDetectionRules, waitForAlertsIndexToBeCreated, waitForAlertsPanelToBeLoaded, -} from '../tasks/detections'; +} from '../tasks/alerts'; +import { exportFirstRule } from '../tasks/alerts_detection_rules'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; -import { exportFirstRule } from '../tasks/alert_detection_rules'; import { ALERTS_URL } from '../urls/navigation'; @@ -35,7 +35,7 @@ describe('Export rules', () => { loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); - goToManageAlertDetectionRules(); + goToManageAlertsDetectionRules(); exportFirstRule(); cy.wait('@export').then((xhr) => { cy.readFile(EXPECTED_EXPORTED_RULE_FILE_PATH).then(($expectedExportedJson) => { diff --git a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_ml.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts similarity index 96% rename from x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_ml.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts index 3e0fc2e1b37fd0..19957a53dd701f 100644 --- a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_ml.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts @@ -6,6 +6,15 @@ import { machineLearningRule, totalNumberOfPrebuiltRulesInEsArchive } from '../objects/rule'; +import { + CUSTOM_RULES_BTN, + RISK_SCORE, + RULE_NAME, + RULE_SWITCH, + RULES_ROW, + RULES_TABLE, + SEVERITY, +} from '../screens/alerts_detection_rules'; import { ABOUT_FALSE_POSITIVES, ABOUT_MITRE, @@ -26,27 +35,12 @@ import { SCHEDULE_STEP, RULE_TYPE, } from '../screens/rule_details'; -import { - CUSTOM_RULES_BTN, - RISK_SCORE, - RULE_NAME, - RULE_SWITCH, - RULES_ROW, - RULES_TABLE, - SEVERITY, -} from '../screens/alert_detection_rules'; import { - createAndActivateRule, - fillAboutRuleAndContinue, - fillDefineMachineLearningRuleAndContinue, - selectMachineLearningRuleType, -} from '../tasks/create_new_rule'; -import { - goToManageAlertDetectionRules, + goToManageAlertsDetectionRules, waitForAlertsIndexToBeCreated, waitForAlertsPanelToBeLoaded, -} from '../tasks/detections'; +} from '../tasks/alerts'; import { changeToThreeHundredRowsPerPage, filterByCustomRules, @@ -54,7 +48,13 @@ import { goToRuleDetails, waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, waitForRulesToBeLoaded, -} from '../tasks/alert_detection_rules'; +} from '../tasks/alerts_detection_rules'; +import { + createAndActivateRule, + fillAboutRuleAndContinue, + fillDefineMachineLearningRuleAndContinue, + selectMachineLearningRuleType, +} from '../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; @@ -73,7 +73,7 @@ describe('Detection rules, machine learning', () => { loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); - goToManageAlertDetectionRules(); + goToManageAlertsDetectionRules(); waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); goToCreateNewRule(); selectMachineLearningRuleType(); diff --git a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_prebuilt.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_prebuilt.spec.ts similarity index 95% rename from x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_prebuilt.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_prebuilt.spec.ts index f819c91a773749..d3cbb05d7fc17a 100644 --- a/x-pack/plugins/security_solution/cypress/integration/signal_detection_rules_prebuilt.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_prebuilt.spec.ts @@ -10,8 +10,13 @@ import { RELOAD_PREBUILT_RULES_BTN, RULES_ROW, RULES_TABLE, -} from '../screens/alert_detection_rules'; +} from '../screens/alerts_detection_rules'; +import { + goToManageAlertsDetectionRules, + waitForAlertsIndexToBeCreated, + waitForAlertsPanelToBeLoaded, +} from '../tasks/alerts'; import { changeToThreeHundredRowsPerPage, deleteFirstRule, @@ -22,12 +27,7 @@ import { waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, waitForPrebuiltDetectionRulesToBeLoaded, waitForRulesToBeLoaded, -} from '../tasks/alert_detection_rules'; -import { - goToManageAlertDetectionRules, - waitForAlertsIndexToBeCreated, - waitForAlertsPanelToBeLoaded, -} from '../tasks/detections'; +} from '../tasks/alerts_detection_rules'; import { esArchiverLoadEmptyKibana, esArchiverUnloadEmptyKibana } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; @@ -35,7 +35,7 @@ import { ALERTS_URL } from '../urls/navigation'; import { totalNumberOfPrebuiltRules } from '../objects/rule'; -describe('Detection rules, prebuilt rules', () => { +describe('Alerts rules, prebuilt rules', () => { before(() => { esArchiverLoadEmptyKibana(); }); @@ -51,7 +51,7 @@ describe('Detection rules, prebuilt rules', () => { loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); - goToManageAlertDetectionRules(); + goToManageAlertsDetectionRules(); waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); loadPrebuiltDetectionRules(); waitForPrebuiltDetectionRulesToBeLoaded(); @@ -76,7 +76,7 @@ describe('Deleting prebuilt rules', () => { loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); - goToManageAlertDetectionRules(); + goToManageAlertsDetectionRules(); waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); loadPrebuiltDetectionRules(); waitForPrebuiltDetectionRulesToBeLoaded(); diff --git a/x-pack/plugins/security_solution/cypress/integration/detections_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_timeline.spec.ts similarity index 90% rename from x-pack/plugins/security_solution/cypress/integration/detections_timeline.spec.ts rename to x-pack/plugins/security_solution/cypress/integration/alerts_timeline.spec.ts index 91617981ab14c4..10dc4fdd444869 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detections_timeline.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_timeline.spec.ts @@ -4,20 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ALERT_ID } from '../screens/detections'; +import { ALERT_ID } from '../screens/alerts'; import { PROVIDER_BADGE } from '../screens/timeline'; import { expandFirstAlert, investigateFirstAlertInTimeline, waitForAlertsPanelToBeLoaded, -} from '../tasks/detections'; +} from '../tasks/alerts'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPage } from '../tasks/login'; import { ALERTS_URL } from '../urls/navigation'; -describe('Detections timeline', () => { +describe('Alerts timeline', () => { beforeEach(() => { esArchiverLoad('timeline_alerts'); loginAndWaitForPage(ALERTS_URL); diff --git a/x-pack/plugins/security_solution/cypress/screens/detections.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/screens/detections.ts rename to x-pack/plugins/security_solution/cypress/screens/alerts.ts diff --git a/x-pack/plugins/security_solution/cypress/screens/alert_detection_rules.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/screens/alert_detection_rules.ts rename to x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts diff --git a/x-pack/plugins/security_solution/cypress/tasks/detections.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts similarity index 97% rename from x-pack/plugins/security_solution/cypress/tasks/detections.ts rename to x-pack/plugins/security_solution/cypress/tasks/alerts.ts index 8b1e8b41b6da14..ebd37b522924fd 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/detections.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -22,7 +22,7 @@ import { OPEN_SELECTED_ALERTS_BTN, MARK_ALERT_IN_PROGRESS_BTN, MARK_SELECTED_ALERTS_IN_PROGRESS_BTN, -} from '../screens/detections'; +} from '../screens/alerts'; import { REFRESH_BUTTON } from '../screens/security_header'; export const closeFirstAlert = () => { @@ -43,7 +43,7 @@ export const goToClosedAlerts = () => { cy.get(CLOSED_ALERTS_FILTER_BTN).click({ force: true }); }; -export const goToManageAlertDetectionRules = () => { +export const goToManageAlertsDetectionRules = () => { cy.get(MANAGE_ALERT_DETECTION_RULES_BTN).should('exist').click({ force: true }); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alert_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts similarity index 98% rename from x-pack/plugins/security_solution/cypress/tasks/alert_detection_rules.ts rename to x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index 9710e0e808ac59..79756621ef5028 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alert_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -24,7 +24,7 @@ import { SORT_RULES_BTN, THREE_HUNDRED_ROWS, EXPORT_ACTION_BTN, -} from '../screens/alert_detection_rules'; +} from '../screens/alerts_detection_rules'; export const activateRule = (rulePosition: number) => { cy.get(RULE_SWITCH).eq(rulePosition).click({ force: true }); From 03e721604fc091a72ac19eea82d48e6af157a2b4 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 30 Jun 2020 11:39:36 +0300 Subject: [PATCH 30/91] Use ts-expect-error in platform code (#69883) (#70287) * ts-ignore --> ts-expect-error * fix error with mutable array * fix errors in consumers code * update SOM * fix FeatureConfig & Feature compatibility * do not re-export from code. it breaks built version * update docs * add eslint rule for platform team code * remove test. this is covered by ts-expect-error in unit tests Co-authored-by: Elastic Machine # Conflicts: # src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json --- .eslintrc.js | 17 +++++++ .../core/public/kibana-plugin-core-public.md | 1 - ...na-plugin-core-public.recursivereadonly.md | 14 ------ .../core/server/kibana-plugin-core-server.md | 1 - ...na-plugin-core-server.recursivereadonly.md | 14 ------ ...in-plugins-data-public.querystringinput.md | 2 +- packages/kbn-utility-types/index.ts | 3 +- .../capabilities/capabilities_service.test.ts | 4 +- .../capabilities/capabilities_service.tsx | 3 +- src/core/public/application/types.ts | 2 +- .../recently_accessed/persisted_log.test.ts | 2 +- .../recently_accessed_service.test.ts | 4 +- .../chrome/ui/header/header_help_menu.tsx | 1 - .../public/chrome/ui/header/recent_links.tsx | 1 - src/core/public/http/fetch.test.ts | 4 +- src/core/public/http/http_service.test.ts | 2 +- src/core/public/index.ts | 1 - .../injected_metadata_service.test.ts | 7 ++- .../integrations/styles/styles_service.ts | 2 +- src/core/public/kbn_bootstrap.ts | 1 - src/core/public/public.api.md | 8 +-- .../saved_objects_client.test.ts | 2 +- .../ui_settings/ui_settings_api.test.ts | 2 +- .../legacy/retry_call_cluster.ts | 2 +- .../server/http/cookie_session_storage.ts | 2 +- src/core/server/http/router/request.ts | 5 +- src/core/server/index.ts | 1 - .../legacy/config/get_unused_config_keys.ts | 2 +- src/core/server/legacy/legacy_service.test.ts | 1 - .../legacy/logging/legacy_logging_server.ts | 4 +- .../plugins/find_legacy_plugin_specs.ts | 2 +- src/core/server/plugins/types.ts | 2 +- .../service/lib/decorate_es_error.ts | 6 +-- src/core/server/server.api.md | 13 ++--- src/core/utils/deep_freeze.test.ts | 11 ++-- src/core/utils/deep_freeze.ts | 15 +----- .../frozen_object_mutation/index.ts | 44 ---------------- .../frozen_object_mutation/tsconfig.json | 12 ----- .../integration_tests/deep_freeze.test.ts | 40 --------------- src/plugins/data/public/public.api.md | 3 +- src/plugins/data/server/server.api.md | 2 +- .../object_view/components/field.tsx | 9 +--- .../objects_table/components/flyout.tsx | 1 - .../objects_table/components/table.test.tsx | 2 +- .../objects_table/components/table.tsx | 1 - .../objects_table/saved_objects_table.tsx | 2 +- .../vis_type_timelion/server/plugin.ts | 8 ++- .../lib/adapters/framework/adapter_types.ts | 4 +- .../lib/adapters/framework/adapter_types.ts | 2 +- ...dashboard_mode_request_interceptor.test.ts | 4 +- x-pack/plugins/features/common/feature.ts | 14 +++--- .../common/feature_kibana_privileges.ts | 14 +++--- x-pack/plugins/features/common/sub_feature.ts | 4 +- .../plugins/features/server/feature_schema.ts | 6 +-- x-pack/plugins/features/server/plugin.ts | 3 +- .../embeddable/embeddable_factory.ts | 8 +-- x-pack/plugins/security/common/model/user.ts | 2 +- .../role_combo_box/role_combo_box.tsx | 2 +- .../users/edit_user/edit_user_page.tsx | 2 +- .../authorization/app_authorization.test.ts | 9 ++-- .../feature_privilege_iterator.ts | 2 +- x-pack/plugins/security/server/index.ts | 2 +- .../management/lib/feature_utils.test.ts | 4 +- .../on_post_auth_interceptor.test.ts | 50 +++++++++---------- 64 files changed, 134 insertions(+), 286 deletions(-) delete mode 100644 docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md delete mode 100644 src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts delete mode 100644 src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json delete mode 100644 src/core/utils/integration_tests/deep_freeze.test.ts diff --git a/.eslintrc.js b/.eslintrc.js index 29a16545b0e69c..81ffde03289549 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1043,5 +1043,22 @@ module.exports = { ...require('eslint-config-prettier/@typescript-eslint').rules, }, }, + + { + files: [ + // platform-team owned code + 'src/core/**', + 'x-pack/plugins/features/**', + 'x-pack/plugins/licensing/**', + 'x-pack/plugins/global_search/**', + 'x-pack/plugins/cloud/**', + 'packages/kbn-config-schema', + 'src/plugins/status_page/**', + 'src/plugins/saved_objects_management/**', + ], + rules: { + '@typescript-eslint/prefer-ts-expect-error': 'error', + }, + }, ], }; diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index b0612ff4d5b65f..8f2bde3856019a 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -172,7 +172,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PublicAppInfo](./kibana-plugin-core-public.publicappinfo.md) | Public information about a registered [application](./kibana-plugin-core-public.app.md) | | [PublicLegacyAppInfo](./kibana-plugin-core-public.publiclegacyappinfo.md) | Information about a registered [legacy application](./kibana-plugin-core-public.legacyapp.md) | | [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. | -| [RecursiveReadonly](./kibana-plugin-core-public.recursivereadonly.md) | | | [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | Type definition for a Saved Object attribute value | | [SavedObjectAttributeSingle](./kibana-plugin-core-public.savedobjectattributesingle.md) | Don't use this type, it's simply a helper type for [SavedObjectAttribute](./kibana-plugin-core-public.savedobjectattribute.md) | | [SavedObjectsClientContract](./kibana-plugin-core-public.savedobjectsclientcontract.md) | SavedObjectsClientContract as implemented by the [SavedObjectsClient](./kibana-plugin-core-public.savedobjectsclient.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md b/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md deleted file mode 100644 index 2f47ef1086d717..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.recursivereadonly.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [RecursiveReadonly](./kibana-plugin-core-public.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index cbba61e16798bb..356eb310f1f5ad 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -257,7 +257,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [PluginName](./kibana-plugin-core-server.pluginname.md) | Dedicated type for plugin name/id that is supposed to make Map/Set/Arrays that use it as a key or value more obvious. | | [PluginOpaqueId](./kibana-plugin-core-server.pluginopaqueid.md) | | | [PublicUiSettingsParams](./kibana-plugin-core-server.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) exposed to the client-side. | -| [RecursiveReadonly](./kibana-plugin-core-server.recursivereadonly.md) | | | [RedirectResponseOptions](./kibana-plugin-core-server.redirectresponseoptions.md) | HTTP response parameters for redirection response | | [RequestHandler](./kibana-plugin-core-server.requesthandler.md) | A function executed when route path matched requested resource path. Request handler is expected to return a result of one of [KibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) functions. | | [RequestHandlerContextContainer](./kibana-plugin-core-server.requesthandlercontextcontainer.md) | An object that handles registration of http request context providers. | diff --git a/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md b/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md deleted file mode 100644 index bc9cd4680b17d1..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.recursivereadonly.md +++ /dev/null @@ -1,14 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [RecursiveReadonly](./kibana-plugin-core-server.recursivereadonly.md) - -## RecursiveReadonly type - - -Signature: - -```typescript -export declare type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index 85eb4825bc2e32..a25f4a0c373b2c 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC> ``` diff --git a/packages/kbn-utility-types/index.ts b/packages/kbn-utility-types/index.ts index 9a8a81460f410e..6ccfeb8ab052c9 100644 --- a/packages/kbn-utility-types/index.ts +++ b/packages/kbn-utility-types/index.ts @@ -61,7 +61,8 @@ export type Ensure = T extends X ? T : never; // If we define this inside RecursiveReadonly TypeScript complains. // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RecursiveReadonlyArray extends Array> {} +export interface RecursiveReadonlyArray extends ReadonlyArray> {} + export type RecursiveReadonly = T extends (...args: any) => any ? T : T extends any[] diff --git a/src/core/public/application/capabilities/capabilities_service.test.ts b/src/core/public/application/capabilities/capabilities_service.test.ts index dfbb449b4d58e6..286a93fdc23988 100644 --- a/src/core/public/application/capabilities/capabilities_service.test.ts +++ b/src/core/public/application/capabilities/capabilities_service.test.ts @@ -48,7 +48,7 @@ describe('#start', () => { appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], }); - // @ts-ignore TypeScript knows this shouldn't be possible + // @ts-expect-error TypeScript knows this shouldn't be possible expect(() => (capabilities.foo = 'foo')).toThrowError(); }); @@ -59,7 +59,7 @@ describe('#start', () => { appIds: ['app1', 'app2', 'legacyApp1', 'legacyApp2'], }); - // @ts-ignore TypeScript knows this shouldn't be possible + // @ts-expect-error TypeScript knows this shouldn't be possible expect(() => (capabilities.foo = 'foo')).toThrowError(); }); }); diff --git a/src/core/public/application/capabilities/capabilities_service.tsx b/src/core/public/application/capabilities/capabilities_service.tsx index d602422c146348..7304a8e5a66bc1 100644 --- a/src/core/public/application/capabilities/capabilities_service.tsx +++ b/src/core/public/application/capabilities/capabilities_service.tsx @@ -16,9 +16,10 @@ * specific language governing permissions and limitations * under the License. */ +import { RecursiveReadonly } from '@kbn/utility-types'; import { Capabilities } from '../../../types/capabilities'; -import { deepFreeze, RecursiveReadonly } from '../../../utils'; +import { deepFreeze } from '../../../utils'; import { HttpStart } from '../../http'; interface StartDeps { diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index cd2dd99c30c116..0fe97431b15690 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -19,6 +19,7 @@ import { Observable } from 'rxjs'; import { History } from 'history'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { Capabilities } from './capabilities'; import { ChromeStart } from '../chrome'; @@ -30,7 +31,6 @@ import { NotificationsStart } from '../notifications'; import { OverlayStart } from '../overlays'; import { PluginOpaqueId } from '../plugins'; import { IUiSettingsClient } from '../ui_settings'; -import { RecursiveReadonly } from '../../utils'; import { SavedObjectsStart } from '../saved_objects'; import { AppCategory } from '../../types'; import { ScopedHistory } from './scoped_history'; diff --git a/src/core/public/chrome/recently_accessed/persisted_log.test.ts b/src/core/public/chrome/recently_accessed/persisted_log.test.ts index 9b307a2d25faf4..4229efdf7ca9dc 100644 --- a/src/core/public/chrome/recently_accessed/persisted_log.test.ts +++ b/src/core/public/chrome/recently_accessed/persisted_log.test.ts @@ -59,7 +59,7 @@ describe('PersistedLog', () => { describe('internal functionality', () => { test('reads from storage', () => { - // @ts-ignore + // @ts-expect-error const log = new PersistedLog(historyName, { maxLength: 10 }, storage); expect(storage.getItem).toHaveBeenCalledTimes(1); diff --git a/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts b/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts index 3c9713a93144a9..14c3c581f9f174 100644 --- a/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts +++ b/src/core/public/chrome/recently_accessed/recently_accessed_service.test.ts @@ -55,11 +55,11 @@ describe('RecentlyAccessed#start()', () => { let originalLocalStorage: Storage; beforeAll(() => { originalLocalStorage = window.localStorage; - // @ts-ignore + // @ts-expect-error window.localStorage = new LocalStorageMock(); }); beforeEach(() => localStorage.clear()); - // @ts-ignore + // @ts-expect-error afterAll(() => (window.localStorage = originalLocalStorage)); const getStart = async () => { diff --git a/src/core/public/chrome/ui/header/header_help_menu.tsx b/src/core/public/chrome/ui/header/header_help_menu.tsx index 1023a561a0fe33..6d2938e3345a65 100644 --- a/src/core/public/chrome/ui/header/header_help_menu.tsx +++ b/src/core/public/chrome/ui/header/header_help_menu.tsx @@ -312,7 +312,6 @@ class HeaderHelpMenuUI extends Component { ); return ( - // @ts-ignore repositionOnScroll doesn't exist in EuiPopover { fetchMock.get('*', {}); await expect( fetchInstance.fetch( - // @ts-ignore + // @ts-expect-error { path: '/', headers: { hello: 'world' } }, { headers: { hello: 'mars' } } ) diff --git a/src/core/public/http/http_service.test.ts b/src/core/public/http/http_service.test.ts index 78220af9cc83b5..0afea5aaa506a2 100644 --- a/src/core/public/http/http_service.test.ts +++ b/src/core/public/http/http_service.test.ts @@ -17,7 +17,7 @@ * under the License. */ -// @ts-ignore +// @ts-expect-error import fetchMock from 'fetch-mock/es5/client'; import { loadingServiceMock } from './http_service.test.mocks'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 3a5c55a404d09e..4b2c9a35d1b1f0 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -82,7 +82,6 @@ import { /** @interal */ export { CoreContext, CoreSystem } from './core_system'; export { - RecursiveReadonly, DEFAULT_APP_CATEGORIES, getFlattenedObject, URLMeaningfulParts, diff --git a/src/core/public/injected_metadata/injected_metadata_service.test.ts b/src/core/public/injected_metadata/injected_metadata_service.test.ts index cf4b72114d5ac2..1a8b4d14ee2490 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.test.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.test.ts @@ -58,7 +58,6 @@ describe('setup.getCspConfig()', () => { const csp = injectedMetadata.setup().getCspConfig(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible csp.warnLegacyBrowsers = false; }).toThrowError(); }); @@ -100,11 +99,11 @@ describe('setup.getPlugins()', () => { plugins.push({ id: 'new-plugin', plugin: {} as DiscoveredPlugin }); }).toThrowError(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible plugins[0].name = 'changed'; }).toThrowError(); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible plugins[0].newProp = 'changed'; }).toThrowError(); }); @@ -136,7 +135,7 @@ describe('setup.getLegacyMetadata()', () => { foo: true, }); expect(() => { - // @ts-ignore TS knows this shouldn't be possible + // @ts-expect-error TS knows this shouldn't be possible legacyMetadata.foo = false; }).toThrowError(); }); diff --git a/src/core/public/integrations/styles/styles_service.ts b/src/core/public/integrations/styles/styles_service.ts index 41fc861d6cb39a..d1d7f2170fde39 100644 --- a/src/core/public/integrations/styles/styles_service.ts +++ b/src/core/public/integrations/styles/styles_service.ts @@ -21,7 +21,7 @@ import { Subscription } from 'rxjs'; import { IUiSettingsClient } from '../../ui_settings'; import { CoreService } from '../../../types'; -// @ts-ignore +// @ts-expect-error import disableAnimationsCss from '!!raw-loader!./disable_animations.css'; interface StartDeps { diff --git a/src/core/public/kbn_bootstrap.ts b/src/core/public/kbn_bootstrap.ts index 0f860618167018..a108b5aaa47ec0 100644 --- a/src/core/public/kbn_bootstrap.ts +++ b/src/core/public/kbn_bootstrap.ts @@ -42,7 +42,6 @@ export function __kbnBootstrap__() { const APM_ENABLED = process.env.IS_KIBANA_DISTRIBUTABLE !== 'true' && apmConfig != null; if (APM_ENABLED) { - // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-var-requires const { init, apm } = require('@elastic/apm-rum'); if (apmConfig.globalLabels) { diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a65b9dd9d242a7..86e281a49b744a 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -116,6 +116,7 @@ import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/ser import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import React from 'react'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -1158,13 +1159,6 @@ export type PublicLegacyAppInfo = Omit & { // @public export type PublicUiSettingsParams = Omit; -// Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; - // Warning: (ae-missing-release-tag) "SavedObject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/src/core/public/saved_objects/saved_objects_client.test.ts b/src/core/public/saved_objects/saved_objects_client.test.ts index 0c34a16c68e99d..20824af38af0f6 100644 --- a/src/core/public/saved_objects/saved_objects_client.test.ts +++ b/src/core/public/saved_objects/saved_objects_client.test.ts @@ -432,7 +432,7 @@ describe('SavedObjectsClient', () => { sortOrder: 'sort', // Not currently supported by API }; - // @ts-ignore + // @ts-expect-error savedObjectsClient.find(options); expect(http.fetch.mock.calls).toMatchInlineSnapshot(` Array [ diff --git a/src/core/public/ui_settings/ui_settings_api.test.ts b/src/core/public/ui_settings/ui_settings_api.test.ts index bab7081509d53e..14791407d25508 100644 --- a/src/core/public/ui_settings/ui_settings_api.test.ts +++ b/src/core/public/ui_settings/ui_settings_api.test.ts @@ -17,7 +17,7 @@ * under the License. */ -// @ts-ignore +// @ts-expect-error import fetchMock from 'fetch-mock/es5/client'; import * as Rx from 'rxjs'; import { takeUntil, toArray } from 'rxjs/operators'; diff --git a/src/core/server/elasticsearch/legacy/retry_call_cluster.ts b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts index b12ecc889eb2d7..475a76d4060171 100644 --- a/src/core/server/elasticsearch/legacy/retry_call_cluster.ts +++ b/src/core/server/elasticsearch/legacy/retry_call_cluster.ts @@ -67,7 +67,7 @@ export function migrationsRetryCallCluster( error instanceof esErrors.RequestTimeout || error instanceof esErrors.AuthenticationException || error instanceof esErrors.AuthorizationException || - // @ts-ignore + // @ts-expect-error error instanceof esErrors.Gone || error?.body?.error?.type === 'snapshot_in_progress_exception' ); diff --git a/src/core/server/http/cookie_session_storage.ts b/src/core/server/http/cookie_session_storage.ts index 13f498233f695b..5ca70045f81db6 100644 --- a/src/core/server/http/cookie_session_storage.ts +++ b/src/core/server/http/cookie_session_storage.ts @@ -19,7 +19,7 @@ import { Request, Server } from 'hapi'; import hapiAuthCookie from 'hapi-auth-cookie'; -// @ts-ignore no TS definitions +// @ts-expect-error no TS definitions import Statehood from 'statehood'; import { KibanaRequest, ensureRawRequest } from './router'; diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index f266677c1a1727..fefd75ad9710e9 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -21,8 +21,9 @@ import { Url } from 'url'; import { Request, ApplicationState } from 'hapi'; import { Observable, fromEvent, merge } from 'rxjs'; import { shareReplay, first, takeUntil } from 'rxjs/operators'; +import { RecursiveReadonly } from '@kbn/utility-types'; -import { deepFreeze, RecursiveReadonly } from '../../../utils'; +import { deepFreeze } from '../../../utils'; import { Headers } from './headers'; import { RouteMethod, RouteConfigOptions, validBodyOutput, isSafeMethod } from './route'; import { KibanaSocket, IKibanaSocket } from './socket'; @@ -156,7 +157,7 @@ export class KibanaRequest< public readonly params: Params, public readonly query: Query, public readonly body: Body, - // @ts-ignore we will use this flag as soon as http request proxy is supported in the core + // @ts-expect-error we will use this flag as soon as http request proxy is supported in the core // until that time we have to expose all the headers private readonly withoutSecretHeaders: boolean ) { diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 91c33fac41646b..35aabab4a0b26b 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -307,7 +307,6 @@ export { } from './metrics'; export { - RecursiveReadonly, DEFAULT_APP_CATEGORIES, getFlattenedObject, URLMeaningfulParts, diff --git a/src/core/server/legacy/config/get_unused_config_keys.ts b/src/core/server/legacy/config/get_unused_config_keys.ts index 6cd193d896109d..8e53178142180e 100644 --- a/src/core/server/legacy/config/get_unused_config_keys.ts +++ b/src/core/server/legacy/config/get_unused_config_keys.ts @@ -18,7 +18,7 @@ */ import { difference, get, set } from 'lodash'; -// @ts-ignore +// @ts-expect-error import { getTransform } from '../../../../legacy/deprecation/index'; import { unset } from '../../../../legacy/utils'; import { getFlattenedObject } from '../../../utils'; diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts index ccadae757fe546..ffe3b2375bc901 100644 --- a/src/core/server/legacy/legacy_service.test.ts +++ b/src/core/server/legacy/legacy_service.test.ts @@ -29,7 +29,6 @@ import { import { BehaviorSubject, throwError } from 'rxjs'; -// @ts-ignore: implicit any for JS file import { ClusterManager as MockClusterManager } from '../../../cli/cluster/cluster_manager'; import KbnServer from '../../../legacy/server/kbn_server'; import { Config, Env, ObjectToConfigAdapter } from '../config'; diff --git a/src/core/server/legacy/logging/legacy_logging_server.ts b/src/core/server/legacy/logging/legacy_logging_server.ts index 85a8686b4eded6..4a7fea87cf69f8 100644 --- a/src/core/server/legacy/logging/legacy_logging_server.ts +++ b/src/core/server/legacy/logging/legacy_logging_server.ts @@ -19,9 +19,9 @@ import { ServerExtType } from 'hapi'; import Podium from 'podium'; -// @ts-ignore: implicit any for JS file +// @ts-expect-error: implicit any for JS file import { Config } from '../../../../legacy/server/config'; -// @ts-ignore: implicit any for JS file +// @ts-expect-error: implicit any for JS file import { setupLogging } from '../../../../legacy/server/logging'; import { LogLevel } from '../../logging/log_level'; import { LogRecord } from '../../logging/log_record'; diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts index 5039b3a55cc58f..f3ec2ed8335c5a 100644 --- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts +++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts @@ -23,7 +23,7 @@ import { toArray, tap, distinct, map } from 'rxjs/operators'; import { findPluginSpecs, defaultConfig, - // @ts-ignore + // @ts-expect-error } from '../../../../legacy/plugin_discovery/find_plugin_specs.js'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { collectUiExports as collectLegacyUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports'; diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index 2ca5c9f6ed3c56..9e86ee22c607bf 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -19,8 +19,8 @@ import { Observable } from 'rxjs'; import { Type } from '@kbn/config-schema'; +import { RecursiveReadonly } from '@kbn/utility-types'; -import { RecursiveReadonly } from 'kibana/public'; import { ConfigPath, EnvironmentMode, PackageInfo, ConfigDeprecationProvider } from '../config'; import { LoggerFactory } from '../logging'; import { KibanaConfigType } from '../kibana_config'; 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 e57f08aa7a5274..7d1575798c3575 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 @@ -26,11 +26,11 @@ const { NoConnections, RequestTimeout, Conflict, - // @ts-ignore + // @ts-expect-error 401: NotAuthorized, - // @ts-ignore + // @ts-expect-error 403: Forbidden, - // @ts-ignore + // @ts-expect-error 413: RequestEntityTooLarge, NotFound, BadRequest, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index e8399a48b3bf20..028037420feb6b 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -108,7 +108,7 @@ import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import { Readable } from 'stream'; -import { RecursiveReadonly as RecursiveReadonly_2 } from 'kibana/public'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -299,7 +299,7 @@ export const config: { startupTimeout: import("@kbn/config-schema").Type; logQueries: import("@kbn/config-schema").Type; ssl: import("@kbn/config-schema").ObjectType<{ - verificationMode: import("@kbn/config-schema").Type<"none" | "full" | "certificate">; + verificationMode: import("@kbn/config-schema").Type<"none" | "certificate" | "full">; certificateAuthorities: import("@kbn/config-schema").Type; certificate: import("@kbn/config-schema").Type; key: import("@kbn/config-schema").Type; @@ -1663,13 +1663,6 @@ export interface PluginsServiceStart { // @public export type PublicUiSettingsParams = Omit; -// Warning: (ae-forgotten-export) The symbol "RecursiveReadonlyArray" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export type RecursiveReadonly = T extends (...args: any[]) => any ? T : T extends any[] ? RecursiveReadonlyArray : T extends object ? Readonly<{ - [K in keyof T]: RecursiveReadonly; -}> : T; - // @public export type RedirectResponseOptions = HttpResponseOptions & { headers: { @@ -2552,7 +2545,7 @@ export interface SessionStorageFactory { } // @public (undocumented) -export type SharedGlobalConfig = RecursiveReadonly_2<{ +export type SharedGlobalConfig = RecursiveReadonly<{ kibana: Pick; elasticsearch: Pick; path: Pick; diff --git a/src/core/utils/deep_freeze.test.ts b/src/core/utils/deep_freeze.test.ts index b4531d80d02526..58aa9c9b8c92ba 100644 --- a/src/core/utils/deep_freeze.test.ts +++ b/src/core/utils/deep_freeze.test.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import { deepFreeze } from './deep_freeze'; it('returns the first argument with all original references', () => { @@ -33,7 +32,7 @@ it('returns the first argument with all original references', () => { it('prevents adding properties to argument', () => { const frozen = deepFreeze({}); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo = true; }).toThrowError(`object is not extensible`); }); @@ -41,7 +40,7 @@ it('prevents adding properties to argument', () => { it('prevents changing properties on argument', () => { const frozen = deepFreeze({ foo: false }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo = true; }).toThrowError(`read only property 'foo'`); }); @@ -49,7 +48,7 @@ it('prevents changing properties on argument', () => { it('prevents changing properties on nested children of argument', () => { const frozen = deepFreeze({ foo: { bar: { baz: { box: 1 } } } }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo.bar.baz.box = 2; }).toThrowError(`read only property 'box'`); }); @@ -57,7 +56,7 @@ it('prevents changing properties on nested children of argument', () => { it('prevents adding items to a frozen array', () => { const frozen = deepFreeze({ foo: [1] }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo.push(2); }).toThrowError(`object is not extensible`); }); @@ -65,7 +64,7 @@ it('prevents adding items to a frozen array', () => { it('prevents reassigning items in a frozen array', () => { const frozen = deepFreeze({ foo: [1] }); expect(() => { - // @ts-ignore ts knows this shouldn't be possible, but just making sure + // @ts-expect-error ts knows this shouldn't be possible, but just making sure frozen.foo[0] = 2; }).toThrowError(`read only property '0'`); }); diff --git a/src/core/utils/deep_freeze.ts b/src/core/utils/deep_freeze.ts index b0f283c60d0fc6..fbc35acb45b0f7 100644 --- a/src/core/utils/deep_freeze.ts +++ b/src/core/utils/deep_freeze.ts @@ -16,19 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -// if we define this inside RecursiveReadonly TypeScript complains -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface RecursiveReadonlyArray extends Array> {} - -/** @public */ -export type RecursiveReadonly = T extends (...args: any[]) => any - ? T - : T extends any[] - ? RecursiveReadonlyArray - : T extends object - ? Readonly<{ [K in keyof T]: RecursiveReadonly }> - : T; +import { RecursiveReadonly } from '@kbn/utility-types'; /** @public */ export type Freezable = { [k: string]: any } | any[]; @@ -47,6 +35,5 @@ export function deepFreeze(object: T) { deepFreeze(value); } } - return Object.freeze(object) as RecursiveReadonly; } diff --git a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts b/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts deleted file mode 100644 index d4f001a914d34a..00000000000000 --- a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { deepFreeze } from '../../../../utils/deep_freeze'; - -deepFreeze({ - foo: { - bar: { - baz: 1, - }, - }, -}).foo.bar.baz = 2; - -deepFreeze({ - foo: [ - { - bar: 1, - }, - ], -}).foo[0].bar = 2; - -deepFreeze({ - foo: [1], -}).foo[0] = 2; - -deepFreeze({ - foo: [1], -}).foo.push(2); diff --git a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json b/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json deleted file mode 100644 index 64fcbf1f748815..00000000000000 --- a/src/core/utils/integration_tests/__fixtures__/frozen_object_mutation/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "skipLibCheck": true, - "lib": [ - "esnext" - ] - }, - "files": [ - "index.ts" - ] -} diff --git a/src/core/utils/integration_tests/deep_freeze.test.ts b/src/core/utils/integration_tests/deep_freeze.test.ts deleted file mode 100644 index f58e298fecfbff..00000000000000 --- a/src/core/utils/integration_tests/deep_freeze.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { resolve } from 'path'; - -import execa from 'execa'; - -const MINUTE = 60 * 1000; - -it( - 'types return values to prevent mutations in typescript', - async () => { - await expect( - execa('tsc', ['--noEmit'], { - cwd: resolve(__dirname, '__fixtures__/frozen_object_mutation'), - preferLocal: true, - }).catch((err) => err.stdout) - ).resolves.toMatchInlineSnapshot(` - "index.ts(28,12): error TS2540: Cannot assign to 'baz' because it is a read-only property. - index.ts(36,11): error TS2540: Cannot assign to 'bar' because it is a read-only property." - `); - }, - MINUTE -); diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index b1f151bb09ae68..f69ddb25341811 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -142,6 +142,7 @@ import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import React from 'react'; import * as React_2 from 'react'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; @@ -1541,7 +1542,7 @@ export interface QueryState { // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 1961fe331c5820..9b71cc8ebe41e7 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -109,7 +109,7 @@ import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; -import { RecursiveReadonly } from 'kibana/public'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { ReindexParams } from 'elasticsearch'; import { ReindexRethrottleParams } from 'elasticsearch'; import { RenderSearchTemplateParams } from 'elasticsearch'; diff --git a/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx index fd7967f4128c3a..50358c17e058c3 100644 --- a/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx @@ -18,14 +18,7 @@ */ import React, { PureComponent } from 'react'; -import { - EuiFieldNumber, - EuiFieldText, - EuiFormRow, - EuiSwitch, - // @ts-ignore - EuiCodeEditor, -} from '@elastic/eui'; +import { EuiFieldNumber, EuiFieldText, EuiFormRow, EuiSwitch, EuiCodeEditor } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { FieldState, FieldType } from '../../types'; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx index 6e7397d1058bf8..aac799da6ea67e 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx @@ -31,7 +31,6 @@ import { EuiForm, EuiFormRow, EuiSwitch, - // @ts-ignore EuiFilePicker, EuiInMemoryTable, EuiSelect, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index 6b25a1b0c1f256..6b209a62e1b98b 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; -// @ts-ignore +// @ts-expect-error import { findTestSubject } from '@elastic/eui/lib/test'; import { keyCodes } from '@elastic/eui'; import { httpServiceMock } from '../../../../../../core/public/mocks'; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 51e7525d0e00a1..719729cee26025 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -20,7 +20,6 @@ import { IBasePath } from 'src/core/public'; import React, { PureComponent, Fragment } from 'react'; import { - // @ts-ignore EuiSearchBar, EuiBasicTable, EuiButton, diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 54bc649c33b60b..340c0e3237f91f 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -19,7 +19,7 @@ import React, { Component } from 'react'; import { debounce } from 'lodash'; -// @ts-ignore +// @ts-expect-error import { saveAs } from '@elastic/filesaver'; import { EuiSpacer, diff --git a/src/plugins/vis_type_timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts index 435ec9027eef24..605c6be0a85df3 100644 --- a/src/plugins/vis_type_timelion/server/plugin.ts +++ b/src/plugins/vis_type_timelion/server/plugin.ts @@ -20,11 +20,9 @@ import { i18n } from '@kbn/i18n'; import { first } from 'rxjs/operators'; import { TypeOf } from '@kbn/config-schema'; -import { - CoreSetup, - PluginInitializerContext, - RecursiveReadonly, -} from '../../../../src/core/server'; +import { RecursiveReadonly } from '@kbn/utility-types'; + +import { CoreSetup, PluginInitializerContext } from '../../../../src/core/server'; import { deepFreeze } from '../../../../src/core/server'; import { configSchema } from '../config'; import loadFunctions from './lib/load_functions'; diff --git a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts index e2703cb5786dd8..85a8618be5d181 100644 --- a/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/legacy/plugins/beats_management/server/lib/adapters/framework/adapter_types.ts @@ -126,7 +126,7 @@ export interface KibanaServerRequest extends t.TypeOf { kind: 'authenticated'; [internalAuthData]: AuthDataType; username: string; - roles: string[]; + roles: readonly string[]; full_name: string | null; email: string | null; enabled: boolean; diff --git a/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts index a5904d687b37ee..ce663650409fad 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/framework/adapter_types.ts @@ -43,7 +43,7 @@ export interface FrameworkInfo extends t.TypeOf {} export const RuntimeFrameworkUser = t.interface( { username: t.string, - roles: t.array(t.string), + roles: t.readonlyArray(t.string), full_name: t.union([t.null, t.string]), email: t.union([t.null, t.string]), enabled: t.boolean, diff --git a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts index 2978c48af7414b..67fc1a98ad4d1f 100644 --- a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts +++ b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts @@ -85,9 +85,9 @@ describe('DashboardOnlyModeRequestInterceptor', () => { security.authc.getCurrentUser = jest.fn( (r: KibanaRequest) => - ({ + (({ roles: [DASHBOARD_ONLY_MODE_ROLE], - } as AuthenticatedUser) + } as unknown) as AuthenticatedUser) ); uiSettingsMock = [DASHBOARD_ONLY_MODE_ROLE]; diff --git a/x-pack/plugins/features/common/feature.ts b/x-pack/plugins/features/common/feature.ts index 1b405094d9eda5..4a293e0c962ccc 100644 --- a/x-pack/plugins/features/common/feature.ts +++ b/x-pack/plugins/features/common/feature.ts @@ -49,7 +49,9 @@ export interface FeatureConfig { * This does not restrict access to your feature based on license. * Its only purpose is to inform the space and roles UIs on which features to display. */ - validLicenses?: Array<'basic' | 'standard' | 'gold' | 'platinum' | 'enterprise' | 'trial'>; + validLicenses?: ReadonlyArray< + 'basic' | 'standard' | 'gold' | 'platinum' | 'enterprise' | 'trial' + >; /** * An optional EUI Icon to be used when displaying your feature. @@ -66,7 +68,7 @@ export interface FeatureConfig { * An array of app ids that are enabled when this feature is enabled. * Apps specified here will automatically cascade to the privileges defined below, unless specified differently there. */ - app: string[]; + app: readonly string[]; /** * If this feature includes management sections, you can specify them here to control visibility of those @@ -83,14 +85,14 @@ export interface FeatureConfig { * ``` */ management?: { - [sectionId: string]: string[]; + [sectionId: string]: readonly string[]; }; /** * If this feature includes a catalogue entry, you can specify them here to control visibility based on the current space. * * Items specified here will automatically cascade to the privileges defined below, unless specified differently there. */ - catalogue?: string[]; + catalogue?: readonly string[]; /** * Feature privilege definition. @@ -112,7 +114,7 @@ export interface FeatureConfig { /** * Optional sub-feature privilege definitions. This can only be specified if `privileges` are are also defined. */ - subFeatures?: SubFeatureConfig[]; + subFeatures?: readonly SubFeatureConfig[]; /** * Optional message to display on the Role Management screen when configuring permissions for this feature. @@ -124,7 +126,7 @@ export interface FeatureConfig { */ reserved?: { description: string; - privileges: ReservedKibanaPrivilege[]; + privileges: readonly ReservedKibanaPrivilege[]; }; } diff --git a/x-pack/plugins/features/common/feature_kibana_privileges.ts b/x-pack/plugins/features/common/feature_kibana_privileges.ts index 768c8c6ae10880..a9ba38e36f20b6 100644 --- a/x-pack/plugins/features/common/feature_kibana_privileges.ts +++ b/x-pack/plugins/features/common/feature_kibana_privileges.ts @@ -26,13 +26,13 @@ export interface FeatureKibanaPrivileges { * ``` */ management?: { - [sectionId: string]: string[]; + [sectionId: string]: readonly string[]; }; /** * If this feature includes a catalogue entry, you can specify them here to control visibility based on user permissions. */ - catalogue?: string[]; + catalogue?: readonly string[]; /** * If your feature includes server-side APIs, you can tag those routes to secure access based on user permissions. @@ -60,7 +60,7 @@ export interface FeatureKibanaPrivileges { * A generic tag name like "access:read" could be used elsewhere, and access to that API endpoint would also * extend to any routes you have also tagged with that name. */ - api?: string[]; + api?: readonly string[]; /** * If your feature exposes a client-side application (most of them do!), then you can control access to them here. @@ -73,7 +73,7 @@ export interface FeatureKibanaPrivileges { * ``` * */ - app?: string[]; + app?: readonly string[]; /** * If your feature requires access to specific saved objects, then specify your access needs here. @@ -88,7 +88,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - all: string[]; + all: readonly string[]; /** * List of saved object types which users should have read-only access to when granted this privilege. @@ -99,7 +99,7 @@ export interface FeatureKibanaPrivileges { * } * ``` */ - read: string[]; + read: readonly string[]; }; /** * A list of UI Capabilities that should be granted to users with this privilege. @@ -121,5 +121,5 @@ export interface FeatureKibanaPrivileges { * * @see UICapabilities */ - ui: string[]; + ui: readonly string[]; } diff --git a/x-pack/plugins/features/common/sub_feature.ts b/x-pack/plugins/features/common/sub_feature.ts index 121bb8514c8a29..0651bad883ea56 100644 --- a/x-pack/plugins/features/common/sub_feature.ts +++ b/x-pack/plugins/features/common/sub_feature.ts @@ -15,7 +15,7 @@ export interface SubFeatureConfig { name: string; /** Collection of privilege groups */ - privilegeGroups: SubFeaturePrivilegeGroupConfig[]; + privilegeGroups: readonly SubFeaturePrivilegeGroupConfig[]; } /** @@ -45,7 +45,7 @@ export interface SubFeaturePrivilegeGroupConfig { /** * The privileges which belong to this group. */ - privileges: SubFeaturePrivilegeConfig[]; + privileges: readonly SubFeaturePrivilegeConfig[]; } /** diff --git a/x-pack/plugins/features/server/feature_schema.ts b/x-pack/plugins/features/server/feature_schema.ts index 7497548cf89049..c45788b511cded 100644 --- a/x-pack/plugins/features/server/feature_schema.ts +++ b/x-pack/plugins/features/server/feature_schema.ts @@ -126,7 +126,7 @@ export function validateFeature(feature: FeatureConfig) { const unseenCatalogue = new Set(catalogue); - function validateAppEntry(privilegeId: string, entry: string[] = []) { + function validateAppEntry(privilegeId: string, entry: readonly string[] = []) { entry.forEach((privilegeApp) => unseenApps.delete(privilegeApp)); const unknownAppEntries = difference(entry, app); @@ -139,7 +139,7 @@ export function validateFeature(feature: FeatureConfig) { } } - function validateCatalogueEntry(privilegeId: string, entry: string[] = []) { + function validateCatalogueEntry(privilegeId: string, entry: readonly string[] = []) { entry.forEach((privilegeCatalogue) => unseenCatalogue.delete(privilegeCatalogue)); const unknownCatalogueEntries = difference(entry || [], catalogue); @@ -154,7 +154,7 @@ export function validateFeature(feature: FeatureConfig) { function validateManagementEntry( privilegeId: string, - managementEntry: Record = {} + managementEntry: Record = {} ) { Object.entries(managementEntry).forEach(([managementSectionId, managementSectionEntry]) => { if (unseenManagement.has(managementSectionId)) { diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index bfae416471c2f2..149c1acfb50863 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -3,14 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import { RecursiveReadonly } from '@kbn/utility-types'; import { CoreSetup, CoreStart, SavedObjectsServiceStart, Logger, PluginInitializerContext, - RecursiveReadonly, } from '../../../../src/core/server'; import { Capabilities as UICapabilities } from '../../../../src/core/server'; import { deepFreeze } from '../../../../src/core/server'; diff --git a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts index c23d44aa8e4b60..f9685dac32e23c 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts @@ -4,13 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - Capabilities, - HttpSetup, - RecursiveReadonly, - SavedObjectsClientContract, -} from 'kibana/public'; +import { Capabilities, HttpSetup, SavedObjectsClientContract } from 'kibana/public'; import { i18n } from '@kbn/i18n'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { IndexPatternsContract, IndexPattern, diff --git a/x-pack/plugins/security/common/model/user.ts b/x-pack/plugins/security/common/model/user.ts index 5c852e7a8f03d4..ae6de7f4c5fbc6 100644 --- a/x-pack/plugins/security/common/model/user.ts +++ b/x-pack/plugins/security/common/model/user.ts @@ -8,7 +8,7 @@ export interface User { username: string; email: string; full_name: string; - roles: string[]; + roles: readonly string[]; enabled: boolean; metadata?: { _reserved: boolean; diff --git a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx index 689830e2845ce6..5b24b296b299f9 100644 --- a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx +++ b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx @@ -12,7 +12,7 @@ import { RoleComboBoxOption } from './role_combo_box_option'; interface Props { availableRoles: Role[]; - selectedRoleNames: string[]; + selectedRoleNames: readonly string[]; onChange: (selectedRoleNames: string[]) => void; placeholder?: string; isLoading?: boolean; diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx index eea7edd62fbfaa..9eb2616cebb181 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx @@ -57,7 +57,7 @@ interface State { showDeleteConfirmation: boolean; user: EditUser; roles: Role[]; - selectedRoles: string[]; + selectedRoles: readonly string[]; formError: UserValidationResult | null; } diff --git a/x-pack/plugins/security/server/authorization/app_authorization.test.ts b/x-pack/plugins/security/server/authorization/app_authorization.test.ts index 2d3a981fb32472..1dc072ab2e6e9e 100644 --- a/x-pack/plugins/security/server/authorization/app_authorization.test.ts +++ b/x-pack/plugins/security/server/authorization/app_authorization.test.ts @@ -5,6 +5,7 @@ */ import { PluginSetupContract as FeaturesSetupContract } from '../../../features/server'; +import { featuresPluginMock } from '../../../features/server/mocks'; import { initAppAuthorization } from './app_authorization'; import { @@ -16,9 +17,11 @@ import { import { authorizationMock } from './index.mock'; const createFeaturesSetupContractMock = (): FeaturesSetupContract => { - return { - getFeatures: () => [{ id: 'foo', name: 'Foo', app: ['foo'], privileges: {} }], - } as FeaturesSetupContract; + const mock = featuresPluginMock.createSetup(); + mock.getFeatures.mockReturnValue([ + { id: 'foo', name: 'Foo', app: ['foo'], privileges: {} } as any, + ]); + return mock; }; describe('initAppAuthorization', () => { diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts index e239a6e280aec6..029b2e77f78128 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_iterator/feature_privilege_iterator.ts @@ -76,7 +76,7 @@ function mergeWithSubFeatures( return mergedConfig; } -function mergeArrays(input1: string[] | undefined, input2: string[] | undefined) { +function mergeArrays(input1: readonly string[] | undefined, input2: readonly string[] | undefined) { const first = input1 ?? []; const second = input2 ?? []; return Array.from(new Set([...first, ...second])); diff --git a/x-pack/plugins/security/server/index.ts b/x-pack/plugins/security/server/index.ts index 97ea4526a35ecb..29ca88e91db2f1 100644 --- a/x-pack/plugins/security/server/index.ts +++ b/x-pack/plugins/security/server/index.ts @@ -5,11 +5,11 @@ */ import { TypeOf } from '@kbn/config-schema'; +import { RecursiveReadonly } from '@kbn/utility-types'; import { PluginConfigDescriptor, PluginInitializer, PluginInitializerContext, - RecursiveReadonly, } from '../../../../src/core/server'; import { ConfigSchema } from './config'; import { Plugin, SecurityPluginSetup, PluginSetupDependencies } from './plugin'; diff --git a/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts b/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts index a3360969fb3f27..20d419e5c90e42 100644 --- a/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts +++ b/x-pack/plugins/spaces/public/management/lib/feature_utils.test.ts @@ -5,7 +5,7 @@ */ import { getEnabledFeatures } from './feature_utils'; -import { Feature } from '../../../../features/public'; +import { FeatureConfig } from '../../../../features/public'; const buildFeatures = () => [ @@ -25,7 +25,7 @@ const buildFeatures = () => id: 'feature4', name: 'feature 4', }, - ] as Feature[]; + ] as FeatureConfig[]; const buildSpace = (disabledFeatures = [] as string[]) => ({ id: 'space', diff --git a/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts b/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts index 17a1fbcca73bd2..8375296d869e6d 100644 --- a/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts +++ b/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts @@ -21,7 +21,6 @@ import { coreMock, } from '../../../../../../src/core/server/mocks'; import * as kbnTestServer from '../../../../../../src/test_utils/kbn_server'; -import { PluginsSetup } from '../../plugin'; import { SpacesService } from '../../spaces_service'; import { SpacesAuditLogger } from '../audit_logger'; import { convertSavedObjectToSpace } from '../../routes/lib'; @@ -29,6 +28,7 @@ import { initSpacesOnPostAuthRequestInterceptor } from './on_post_auth_intercept import { Feature } from '../../../../features/server'; import { spacesConfig } from '../__fixtures__'; import { securityMock } from '../../../../security/server/mocks'; +import { featuresPluginMock } from '../../../../features/server/mocks'; // FLAKY: https://github.com/elastic/kibana/issues/55953 describe.skip('onPostAuthInterceptor', () => { @@ -123,31 +123,29 @@ describe.skip('onPostAuthInterceptor', () => { const loggingMock = loggingSystemMock.create().asLoggerFactory().get('xpack', 'spaces'); - const featuresPlugin = { - getFeatures: () => - [ - { - id: 'feature-1', - name: 'feature 1', - app: ['app-1'], - }, - { - id: 'feature-2', - name: 'feature 2', - app: ['app-2'], - }, - { - id: 'feature-4', - name: 'feature 4', - app: ['app-1', 'app-4'], - }, - { - id: 'feature-5', - name: 'feature 4', - app: ['kibana'], - }, - ] as Feature[], - } as PluginsSetup['features']; + const featuresPlugin = featuresPluginMock.createSetup(); + featuresPlugin.getFeatures.mockReturnValue(([ + { + id: 'feature-1', + name: 'feature 1', + app: ['app-1'], + }, + { + id: 'feature-2', + name: 'feature 2', + app: ['app-2'], + }, + { + id: 'feature-4', + name: 'feature 4', + app: ['app-1', 'app-4'], + }, + { + id: 'feature-5', + name: 'feature 4', + app: ['kibana'], + }, + ] as unknown) as Feature[]); const mockRepository = jest.fn().mockImplementation(() => { return { From 3ec4d3a8fc7eb871f98fc40e9c93cf148c4f561a Mon Sep 17 00:00:00 2001 From: Daniil Suleiman <31325372+sulemanof@users.noreply.github.com> Date: Tue, 30 Jun 2020 11:46:02 +0300 Subject: [PATCH 31/91] Reactify visualize app (#67848) (#70205) * Reactify visualize app * Fix typescript failures after merging master * Make sure refresh button works * Subscribe filter manager fetches * Use redirect to landing page * Update savedSearch type * Add check for TSVB is loaded * Fix comments * Fix uiState persistence on vis load * Remove extra div around TableListView * Update DTS selectors * Add error handling for embeddable * Remove extra argument from useEditorUpdates effect * Update comments, fix typos * Remove extra div wrapper * Apply design suggestions * Revert accidental config changes * Apply navigating to dashboard * Apply redirect legacy urls * Apply incoming changes * Apply incoming changes Co-authored-by: Elastic Machine Co-authored-by: Elastic Machine --- .../public/input_control_vis_type.ts | 2 - src/plugins/kibana_utils/common/index.ts | 1 - src/plugins/kibana_utils/public/index.ts | 1 - .../public/top_nav_menu/top_nav_menu_data.tsx | 4 +- .../saved_object/saved_object_loader.ts | 11 +- src/plugins/saved_objects/public/types.ts | 1 + .../public/components/sidebar/sidebar.tsx | 16 +- .../components/sidebar/sidebar_title.tsx | 6 +- .../public/default_editor.tsx | 3 +- .../application/components/vis_editor.js | 3 +- .../components/vis_editor_visualization.js | 2 + .../public/metrics_type.ts | 2 - src/plugins/vis_type_vega/public/vega_type.ts | 2 - src/plugins/visualizations/public/index.ts | 1 + .../public/saved_visualizations/_saved_vis.ts | 1 + .../saved_visualizations.ts | 2 +- src/plugins/visualizations/public/types.ts | 1 + src/plugins/visualizations/public/vis.ts | 17 +- .../public/vis_types/base_vis_type.ts | 9 +- .../vis_types/vis_type_alias_registry.ts | 1 + src/plugins/visualize/kibana.json | 1 - .../visualize/public/application/_app.scss | 5 - .../application/{index.scss => app.scss} | 8 +- .../visualize/public/application/app.tsx | 63 ++ .../public/application/application.ts | 111 --- .../experimental_vis_info.tsx} | 43 +- .../{editor/lib => components}/index.ts | 6 +- .../visualize_editor.scss} | 0 .../components/visualize_editor.tsx | 115 +++ .../visualize_listing.scss} | 0 .../components/visualize_listing.tsx | 154 ++++ .../components/visualize_no_match.tsx | 77 ++ .../components/visualize_top_nav.tsx | 178 ++++ .../public/application/editor/_index.scss | 1 - .../public/application/editor/editor.html | 104 --- .../public/application/editor/editor.js | 763 ------------------ .../application/editor/lib/make_stateful.ts | 58 -- .../application/editor/visualization.js | 61 -- .../editor/visualization_editor.js | 71 -- .../visualize/public/application/index.tsx | 51 ++ .../public/application/legacy_app.js | 261 ------ .../public/application/listing/_index.scss | 1 - .../listing/visualize_listing.html | 13 - .../application/listing/visualize_listing.js | 174 ---- .../listing/visualize_listing_table.js | 233 ------ .../visualize/public/application/types.ts | 80 +- .../application/{ => utils}/breadcrumbs.ts | 28 +- .../create_visualize_app_state.ts} | 31 +- .../application/utils/get_table_columns.tsx | 162 ++++ .../application/utils/get_top_nav_config.tsx | 303 +++++++ .../utils/get_visualization_instance.ts | 90 +++ .../public/application/utils/index.ts} | 14 +- .../lib => utils}/migrate_app_state.ts | 4 +- .../public/application/utils/use/index.ts} | 12 +- .../use/use_chrome_visibility.ts} | 24 +- .../utils/use/use_editor_updates.ts | 182 +++++ .../utils/use/use_linked_search_updates.ts | 74 ++ .../utils/use/use_saved_vis_instance.ts | 199 +++++ .../utils/use/use_visualize_app_state.tsx | 120 +++ .../public/application/utils/utils.ts | 71 ++ .../public/application/visualize_constants.ts | 6 +- src/plugins/visualize/public/index.ts | 2 +- .../visualize/public/kibana_services.ts | 80 -- src/plugins/visualize/public/plugin.ts | 52 +- .../functional/apps/visualize/_shared_item.js | 2 +- .../page_objects/visual_builder_page.ts | 2 + .../functional/page_objects/visualize_page.ts | 10 +- .../common/layouts/preserve_layout.css | 5 +- .../export_types/common/layouts/print.css | 5 +- .../translations/translations/ja-JP.json | 6 - .../translations/translations/zh-CN.json | 5 - .../feature_controls/visualize_security.ts | 6 +- .../apps/visualize/hybrid_visualization.ts | 2 +- 73 files changed, 2092 insertions(+), 2123 deletions(-) delete mode 100644 src/plugins/visualize/public/application/_app.scss rename src/plugins/visualize/public/application/{index.scss => app.scss} (67%) create mode 100644 src/plugins/visualize/public/application/app.tsx delete mode 100644 src/plugins/visualize/public/application/application.ts rename src/plugins/visualize/public/application/{help_menu/help_menu_util.js => components/experimental_vis_info.tsx} (50%) rename src/plugins/visualize/public/application/{editor/lib => components}/index.ts (80%) rename src/plugins/visualize/public/application/{editor/_editor.scss => components/visualize_editor.scss} (100%) create mode 100644 src/plugins/visualize/public/application/components/visualize_editor.tsx rename src/plugins/visualize/public/application/{listing/_listing.scss => components/visualize_listing.scss} (100%) create mode 100644 src/plugins/visualize/public/application/components/visualize_listing.tsx create mode 100644 src/plugins/visualize/public/application/components/visualize_no_match.tsx create mode 100644 src/plugins/visualize/public/application/components/visualize_top_nav.tsx delete mode 100644 src/plugins/visualize/public/application/editor/_index.scss delete mode 100644 src/plugins/visualize/public/application/editor/editor.html delete mode 100644 src/plugins/visualize/public/application/editor/editor.js delete mode 100644 src/plugins/visualize/public/application/editor/lib/make_stateful.ts delete mode 100644 src/plugins/visualize/public/application/editor/visualization.js delete mode 100644 src/plugins/visualize/public/application/editor/visualization_editor.js create mode 100644 src/plugins/visualize/public/application/index.tsx delete mode 100644 src/plugins/visualize/public/application/legacy_app.js delete mode 100644 src/plugins/visualize/public/application/listing/_index.scss delete mode 100644 src/plugins/visualize/public/application/listing/visualize_listing.html delete mode 100644 src/plugins/visualize/public/application/listing/visualize_listing.js delete mode 100644 src/plugins/visualize/public/application/listing/visualize_listing_table.js rename src/plugins/visualize/public/application/{ => utils}/breadcrumbs.ts (69%) rename src/plugins/visualize/public/application/{editor/lib/visualize_app_state.ts => utils/create_visualize_app_state.ts} (86%) create mode 100644 src/plugins/visualize/public/application/utils/get_table_columns.tsx create mode 100644 src/plugins/visualize/public/application/utils/get_top_nav_config.tsx create mode 100644 src/plugins/visualize/public/application/utils/get_visualization_instance.ts rename src/plugins/{kibana_utils/common/default_feedback_message.ts => visualize/public/application/utils/index.ts} (69%) rename src/plugins/visualize/public/application/{editor/lib => utils}/migrate_app_state.ts (94%) rename src/plugins/{kibana_utils/common/default_feedback_message.test.ts => visualize/public/application/utils/use/index.ts} (68%) rename src/plugins/visualize/public/application/{visualize_app.ts => utils/use/use_chrome_visibility.ts} (65%) create mode 100644 src/plugins/visualize/public/application/utils/use/use_editor_updates.ts create mode 100644 src/plugins/visualize/public/application/utils/use/use_linked_search_updates.ts create mode 100644 src/plugins/visualize/public/application/utils/use/use_saved_vis_instance.ts create mode 100644 src/plugins/visualize/public/application/utils/use/use_visualize_app_state.tsx create mode 100644 src/plugins/visualize/public/application/utils/utils.ts delete mode 100644 src/plugins/visualize/public/kibana_services.ts diff --git a/src/plugins/input_control_vis/public/input_control_vis_type.ts b/src/plugins/input_control_vis/public/input_control_vis_type.ts index 8114dbf110f8b3..2af53ea4d28e83 100644 --- a/src/plugins/input_control_vis/public/input_control_vis_type.ts +++ b/src/plugins/input_control_vis/public/input_control_vis_type.ts @@ -23,7 +23,6 @@ import { createInputControlVisController } from './vis_controller'; import { getControlsTab } from './components/editor/controls_tab'; import { OptionsTab } from './components/editor/options_tab'; import { InputControlVisDependencies } from './plugin'; -import { defaultFeedbackMessage } from '../../kibana_utils/public'; export function createInputControlVisTypeDefinition(deps: InputControlVisDependencies) { const InputControlVisController = createInputControlVisController(deps); @@ -39,7 +38,6 @@ export function createInputControlVisTypeDefinition(deps: InputControlVisDepende defaultMessage: 'Create interactive controls for easy dashboard manipulation.', }), stage: 'experimental', - feedbackMessage: defaultFeedbackMessage, visualization: InputControlVisController, visConfig: { defaults: { diff --git a/src/plugins/kibana_utils/common/index.ts b/src/plugins/kibana_utils/common/index.ts index 99daed98dbe640..c94021872b4e10 100644 --- a/src/plugins/kibana_utils/common/index.ts +++ b/src/plugins/kibana_utils/common/index.ts @@ -28,4 +28,3 @@ export { distinctUntilChangedWithInitialValue } from './distinct_until_changed_w export { url } from './url'; export { now } from './now'; export { calculateObjectHash } from './calculate_object_hash'; -export { defaultFeedbackMessage } from './default_feedback_message'; diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts index 6f61e2c228970d..2911a9ae75689d 100644 --- a/src/plugins/kibana_utils/public/index.ts +++ b/src/plugins/kibana_utils/public/index.ts @@ -31,7 +31,6 @@ export { UiComponentInstance, url, createGetterSetter, - defaultFeedbackMessage, } from '../common'; export * from './core'; export * from '../common/errors'; diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx index 2b7466ffd6ab37..a1653c52892554 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx @@ -19,7 +19,7 @@ import { ButtonIconSide } from '@elastic/eui'; -export type TopNavMenuAction = (anchorElement: EventTarget) => void; +export type TopNavMenuAction = (anchorElement: HTMLElement) => void; export interface TopNavMenuData { id?: string; @@ -29,7 +29,7 @@ export interface TopNavMenuData { testId?: string; className?: string; disableButton?: boolean | (() => boolean); - tooltip?: string | (() => string); + tooltip?: string | (() => string | undefined); emphasize?: boolean; iconType?: string; iconSide?: ButtonIconSide; diff --git a/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts b/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts index 53ef1f3f04ad9b..9e7346f3b673cd 100644 --- a/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts +++ b/src/plugins/saved_objects/public/saved_object/saved_object_loader.ts @@ -51,14 +51,17 @@ export class SavedObjectLoader { } /** - * Retrieve a saved object by id. Returns a promise that completes when the object finishes + * Retrieve a saved object by id or create new one. + * Returns a promise that completes when the object finishes * initializing. - * @param id + * @param opts * @returns {Promise} */ - async get(id?: string) { + async get(opts?: Record | string) { + // can accept object as argument in accordance to SavedVis class + // see src/plugins/saved_objects/public/saved_object/saved_object_loader.ts // @ts-ignore - const obj = new this.Class(id); + const obj = new this.Class(opts); return obj.init(); } diff --git a/src/plugins/saved_objects/public/types.ts b/src/plugins/saved_objects/public/types.ts index 973a493c0a15e9..6db72b396a86ae 100644 --- a/src/plugins/saved_objects/public/types.ts +++ b/src/plugins/saved_objects/public/types.ts @@ -63,6 +63,7 @@ export interface SavedObjectSaveOpts { confirmOverwrite?: boolean; isTitleDuplicateConfirmed?: boolean; onTitleDuplicate?: () => void; + returnToOrigin?: boolean; } export interface SavedObjectCreationOpts { diff --git a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx index 837dd9bff2c6de..c41315e7bc0dca 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/sidebar.tsx @@ -23,9 +23,13 @@ import { i18n } from '@kbn/i18n'; import { keyCodes, EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { EventEmitter } from 'events'; -import { Vis, PersistedState } from 'src/plugins/visualizations/public'; -import { SavedSearch } from 'src/plugins/discover/public'; +import { + Vis, + PersistedState, + VisualizeEmbeddableContract, +} from 'src/plugins/visualizations/public'; import { TimeRange } from 'src/plugins/data/public'; +import { SavedObject } from 'src/plugins/saved_objects/public'; import { DefaultEditorNavBar, OptionTab } from './navbar'; import { DefaultEditorControls } from './controls'; import { setStateParamValue, useEditorReducer, useEditorFormState, discardChanges } from './state'; @@ -34,6 +38,7 @@ import { SidebarTitle } from './sidebar_title'; import { Schema } from '../../schemas'; interface DefaultEditorSideBarProps { + embeddableHandler: VisualizeEmbeddableContract; isCollapsed: boolean; onClickCollapse: () => void; optionTabs: OptionTab[]; @@ -41,11 +46,12 @@ interface DefaultEditorSideBarProps { vis: Vis; isLinkedSearch: boolean; eventEmitter: EventEmitter; - savedSearch?: SavedSearch; + savedSearch?: SavedObject; timeRange: TimeRange; } function DefaultEditorSideBar({ + embeddableHandler, isCollapsed, onClickCollapse, optionTabs, @@ -104,12 +110,12 @@ function DefaultEditorSideBar({ aggs: state.data.aggs ? (state.data.aggs.aggs.map((agg) => agg.toJSON()) as any) : [], }, }); - eventEmitter.emit('updateVis'); + embeddableHandler.reload(); eventEmitter.emit('dirtyStateChange', { isDirty: false, }); setTouched(false); - }, [vis, state, formState.invalid, setTouched, isDirty, eventEmitter]); + }, [vis, state, formState.invalid, setTouched, isDirty, eventEmitter, embeddableHandler]); const onSubmit: KeyboardEventHandler = useCallback( (event) => { diff --git a/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx b/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx index ebc92170c87350..6713c2ce2391be 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx +++ b/src/plugins/vis_default_editor/public/components/sidebar/sidebar_title.tsx @@ -36,17 +36,17 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { Vis } from 'src/plugins/visualizations/public'; -import { SavedSearch } from 'src/plugins/discover/public'; +import { SavedObject } from 'src/plugins/saved_objects/public'; import { useKibana } from '../../../../kibana_react/public'; interface LinkedSearchProps { - savedSearch: SavedSearch; + savedSearch: SavedObject; eventEmitter: EventEmitter; } interface SidebarTitleProps { isLinkedSearch: boolean; - savedSearch?: SavedSearch; + savedSearch?: SavedObject; vis: Vis; eventEmitter: EventEmitter; } diff --git a/src/plugins/vis_default_editor/public/default_editor.tsx b/src/plugins/vis_default_editor/public/default_editor.tsx index 731358bdcbdec2..60b6ebab5ad8eb 100644 --- a/src/plugins/vis_default_editor/public/default_editor.tsx +++ b/src/plugins/vis_default_editor/public/default_editor.tsx @@ -59,7 +59,7 @@ function DefaultEditor({ embeddableHandler.render(visRef.current); setTimeout(() => { - eventEmitter.emit('apply'); + eventEmitter.emit('embeddableRendered'); }); return () => embeddableHandler.destroy(); @@ -102,6 +102,7 @@ function DefaultEditor({ initialWidth={editorInitialWidth} > { this.props.vis.params = this.state.model; - this.props.eventEmitter.emit('updateVis'); + this.props.embeddableHandler.reload(); this.props.eventEmitter.emit('dirtyStateChange', { isDirty: false, }); @@ -187,6 +187,7 @@ export class VisEditor extends Component { autoApply={this.state.autoApply} model={model} embeddableHandler={this.props.embeddableHandler} + eventEmitter={this.props.eventEmitter} vis={this.props.vis} timeRange={this.props.timeRange} uiState={this.uiState} diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js b/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js index 0ae1c86ae31175..23a9555da2452c 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_editor_visualization.js @@ -73,6 +73,7 @@ class VisEditorVisualizationUI extends Component { this._handler = embeddableHandler; await this._handler.render(this._visEl.current); + this.props.eventEmitter.emit('embeddableRendered'); this._subscription = this._handler.handler.data$.subscribe((data) => { this.setPanelInterval(data.value.visData); @@ -279,6 +280,7 @@ VisEditorVisualizationUI.propTypes = { uiState: PropTypes.object, onToggleAutoApply: PropTypes.func, embeddableHandler: PropTypes.object, + eventEmitter: PropTypes.object, timeRange: PropTypes.object, dirty: PropTypes.bool, autoApply: PropTypes.bool, diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index c06f94efb3c493..649ee765cc6428 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -24,7 +24,6 @@ import { metricsRequestHandler } from './request_handler'; import { EditorController } from './application'; // @ts-ignore import { PANEL_TYPES } from '../common/panel_types'; -import { defaultFeedbackMessage } from '../../kibana_utils/public'; import { VisEditor } from './application/components/vis_editor_lazy'; export const metricsVisDefinition = { @@ -34,7 +33,6 @@ export const metricsVisDefinition = { defaultMessage: 'Build time-series using a visual pipeline interface', }), icon: 'visVisualBuilder', - feedbackMessage: defaultFeedbackMessage, visConfig: { defaults: { id: '61ca57f0-469d-11e7-af02-69e470af7417', diff --git a/src/plugins/vis_type_vega/public/vega_type.ts b/src/plugins/vis_type_vega/public/vega_type.ts index c864553c118b93..55ad134c053015 100644 --- a/src/plugins/vis_type_vega/public/vega_type.ts +++ b/src/plugins/vis_type_vega/public/vega_type.ts @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { DefaultEditorSize } from '../../vis_default_editor/public'; import { VegaVisualizationDependencies } from './plugin'; import { VegaVisEditor } from './components'; -import { defaultFeedbackMessage } from '../../kibana_utils/public'; import { createVegaRequestHandler } from './vega_request_handler'; // @ts-ignore @@ -56,6 +55,5 @@ export const createVegaTypeDefinition = (dependencies: VegaVisualizationDependen showFilterBar: true, }, stage: 'experimental', - feedbackMessage: defaultFeedbackMessage, }; }; diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 0bbf862216ed5b..2ac53c2c81acc9 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -51,4 +51,5 @@ export { VisSavedObject, VisResponseValue, } from './types'; +export { VisualizationListItem } from './vis_types/vis_type_alias_registry'; export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants'; diff --git a/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts b/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts index eb00dce8aba2fd..8edf494ddc0ece 100644 --- a/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts +++ b/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts @@ -62,6 +62,7 @@ export const convertFromSerializedVis = (vis: SerializedVis): ISavedVis => { title: vis.title, description: vis.description, visState: { + title: vis.title, type: vis.type, aggs: vis.data.aggs, params: vis.params, diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts index c6a25df7615a2b..d44fc2f4a75af0 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts @@ -56,7 +56,7 @@ export function createSavedVisLoader(services: SavedObjectKibanaServicesWithVisu source.icon = source.type.icon; source.image = source.type.image; source.typeTitle = source.type.title; - source.editUrl = `#/edit/${id}`; + source.editUrl = `/edit/${id}`; return source; }; diff --git a/src/plugins/visualizations/public/types.ts b/src/plugins/visualizations/public/types.ts index 3455d88b6ce9e1..daf275297fb822 100644 --- a/src/plugins/visualizations/public/types.ts +++ b/src/plugins/visualizations/public/types.ts @@ -35,6 +35,7 @@ export type VisualizationControllerConstructor = new ( ) => VisualizationController; export interface SavedVisState { + title: string; type: string; params: VisParams; aggs: AggConfigOptions[]; diff --git a/src/plugins/visualizations/public/vis.ts b/src/plugins/visualizations/public/vis.ts index aaab0566af65e6..e8ae48cdce1452 100644 --- a/src/plugins/visualizations/public/vis.ts +++ b/src/plugins/visualizations/public/vis.ts @@ -29,6 +29,7 @@ import { isFunction, defaults, cloneDeep } from 'lodash'; import { Assign } from '@kbn/utility-types'; +import { i18n } from '@kbn/i18n'; import { PersistedState } from './persisted_state'; import { getTypes, getAggs, getSearch, getSavedSearchLoader } from './services'; import { VisType } from './vis_types'; @@ -105,7 +106,13 @@ export class Vis { private getType(visType: string) { const type = getTypes().get(visType); if (!type) { - throw new Error(`Invalid type "${visType}"`); + const errorMessage = i18n.translate('visualizations.visualizationTypeInvalidMessage', { + defaultMessage: 'Invalid visualization type "{visType}"', + values: { + visType, + }, + }); + throw new Error(errorMessage); } return type; } @@ -150,7 +157,13 @@ export class Vis { const configStates = this.initializeDefaultsFromSchemas(aggs, this.type.schemas.all || []); if (!this.data.indexPattern) { if (aggs.length) { - throw new Error('trying to initialize aggs without index pattern'); + const errorMessage = i18n.translate( + 'visualizations.initializeWithoutIndexPatternErrorMessage', + { + defaultMessage: 'Trying to initialize aggs without index pattern', + } + ); + throw new Error(errorMessage); } return; } diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 2464bb72d26957..44b76a52b34fef 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -27,7 +27,6 @@ export interface BaseVisTypeOptions { icon?: string; image?: string; stage?: 'experimental' | 'beta' | 'production'; - feedbackMessage?: string; options?: Record; visualization: VisualizationControllerConstructor; visConfig?: Record; @@ -48,7 +47,7 @@ export class BaseVisType { icon?: string; image?: string; stage: 'experimental' | 'beta' | 'production'; - feedbackMessage: string; + isExperimental: boolean; options: Record; visualization: VisualizationControllerConstructor; visConfig: Record; @@ -87,7 +86,7 @@ export class BaseVisType { this.editorConfig = _.defaultsDeep({}, opts.editorConfig, { collections: {} }); this.options = _.defaultsDeep({}, opts.options, defaultOptions); this.stage = opts.stage || 'production'; - this.feedbackMessage = opts.feedbackMessage || ''; + this.isExperimental = opts.stage === 'experimental'; this.hidden = opts.hidden || false; this.requestHandler = opts.requestHandler || 'courier'; this.responseHandler = opts.responseHandler || 'none'; @@ -97,10 +96,6 @@ export class BaseVisType { this.useCustomNoDataScreen = opts.useCustomNoDataScreen || false; } - shouldMarkAsExperimentalInUI() { - return this.stage === 'experimental'; - } - public get schemas() { if (this.editorConfig && this.editorConfig.schemas) { return this.editorConfig.schemas; diff --git a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index 73e3360004e5a7..bc80d549c81e6f 100644 --- a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -27,6 +27,7 @@ export interface VisualizationListItem { title: string; description?: string; typeTitle: string; + image?: string; } export interface VisualizationsAppExtension { diff --git a/src/plugins/visualize/kibana.json b/src/plugins/visualize/kibana.json index cda45f3acc102d..c27cfec24b332d 100644 --- a/src/plugins/visualize/kibana.json +++ b/src/plugins/visualize/kibana.json @@ -9,7 +9,6 @@ "navigation", "savedObjects", "visualizations", - "dashboard", "embeddable" ], "optionalPlugins": ["home", "share"] diff --git a/src/plugins/visualize/public/application/_app.scss b/src/plugins/visualize/public/application/_app.scss deleted file mode 100644 index 8a52ebf4cc0883..00000000000000 --- a/src/plugins/visualize/public/application/_app.scss +++ /dev/null @@ -1,5 +0,0 @@ -.visAppWrapper { - display: flex; - flex-direction: column; - flex-grow: 1; -} diff --git a/src/plugins/visualize/public/application/index.scss b/src/plugins/visualize/public/application/app.scss similarity index 67% rename from src/plugins/visualize/public/application/index.scss rename to src/plugins/visualize/public/application/app.scss index 620380a77ba46c..f7f68fbc2c3597 100644 --- a/src/plugins/visualize/public/application/index.scss +++ b/src/plugins/visualize/public/application/app.scss @@ -5,6 +5,8 @@ // visChart__legend--small // visChart__legend-isLoading -@import 'app'; -@import 'editor/index'; -@import 'listing/index'; +.visAppWrapper { + display: flex; + flex-direction: column; + flex-grow: 1; +} diff --git a/src/plugins/visualize/public/application/app.tsx b/src/plugins/visualize/public/application/app.tsx new file mode 100644 index 00000000000000..0e71d72a3d4c72 --- /dev/null +++ b/src/plugins/visualize/public/application/app.tsx @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import './app.scss'; +import React, { useEffect } from 'react'; +import { Route, Switch, useLocation } from 'react-router-dom'; + +import { syncQueryStateWithUrl } from '../../../data/public'; +import { useKibana } from '../../../kibana_react/public'; +import { VisualizeServices } from './types'; +import { VisualizeEditor, VisualizeListing, VisualizeNoMatch } from './components'; +import { VisualizeConstants } from './visualize_constants'; + +export const VisualizeApp = () => { + const { + services: { + data: { query }, + kbnUrlStateStorage, + }, + } = useKibana(); + const { pathname } = useLocation(); + + useEffect(() => { + // syncs `_g` portion of url with query services + const { stop } = syncQueryStateWithUrl(query, kbnUrlStateStorage); + + return () => stop(); + + // this effect should re-run when pathname is changed to preserve querystring part, + // so the global state is always preserved + }, [query, kbnUrlStateStorage, pathname]); + + return ( + + + + + + + + + + ); +}; diff --git a/src/plugins/visualize/public/application/application.ts b/src/plugins/visualize/public/application/application.ts deleted file mode 100644 index 60bb73d6de2ccb..00000000000000 --- a/src/plugins/visualize/public/application/application.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import './index.scss'; - -import angular, { IModule } from 'angular'; - -// required for i18nIdDirective -import 'angular-sanitize'; -// required for ngRoute -import 'angular-route'; - -import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; - -import { AppMountContext } from 'kibana/public'; -import { NavigationPublicPluginStart as NavigationStart } from 'src/plugins/navigation/public'; -import { - configureAppAngularModule, - createTopNavDirective, - createTopNavHelper, -} from '../../../kibana_legacy/public'; - -// @ts-ignore -import { initVisualizeApp } from './legacy_app'; -import { VisualizeKibanaServices } from '../kibana_services'; - -let angularModuleInstance: IModule | null = null; - -export const renderApp = ( - element: HTMLElement, - appBasePath: string, - deps: VisualizeKibanaServices -) => { - if (!angularModuleInstance) { - angularModuleInstance = createLocalAngularModule(deps.core, deps.navigation); - // global routing stuff - configureAppAngularModule( - angularModuleInstance, - { core: deps.core, env: deps.pluginInitializerContext.env }, - true, - deps.scopedHistory - ); - initVisualizeApp(angularModuleInstance, deps); - } - const $injector = mountVisualizeApp(appBasePath, element); - return () => $injector.get('$rootScope').$destroy(); -}; - -const mainTemplate = (basePath: string) => `
- -
-`; - -const moduleName = 'app/visualize'; - -const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react']; - -function mountVisualizeApp(appBasePath: string, element: HTMLElement) { - const mountpoint = document.createElement('div'); - mountpoint.setAttribute('class', 'visAppWrapper'); - mountpoint.innerHTML = mainTemplate(appBasePath); - // bootstrap angular into detached element and attach it later to - // make angular-within-angular possible - const $injector = angular.bootstrap(mountpoint, [moduleName]); - // initialize global state handler - element.appendChild(mountpoint); - return $injector; -} - -function createLocalAngularModule(core: AppMountContext['core'], navigation: NavigationStart) { - createLocalI18nModule(); - createLocalTopNavModule(navigation); - - const visualizeAngularModule: IModule = angular.module(moduleName, [ - ...thirdPartyAngularDependencies, - 'app/visualize/I18n', - 'app/visualize/TopNav', - ]); - return visualizeAngularModule; -} - -function createLocalTopNavModule(navigation: NavigationStart) { - angular - .module('app/visualize/TopNav', ['react']) - .directive('kbnTopNav', createTopNavDirective) - .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); -} - -function createLocalI18nModule() { - angular - .module('app/visualize/I18n', []) - .provider('i18n', I18nProvider) - .filter('i18n', i18nFilter) - .directive('i18nId', i18nDirective); -} diff --git a/src/plugins/visualize/public/application/help_menu/help_menu_util.js b/src/plugins/visualize/public/application/components/experimental_vis_info.tsx similarity index 50% rename from src/plugins/visualize/public/application/help_menu/help_menu_util.js rename to src/plugins/visualize/public/application/components/experimental_vis_info.tsx index c297326f2e264e..51abb3ca530a4c 100644 --- a/src/plugins/visualize/public/application/help_menu/help_menu_util.js +++ b/src/plugins/visualize/public/application/components/experimental_vis_info.tsx @@ -17,18 +17,33 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; +import React, { memo } from 'react'; +import { EuiCallOut, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; -export function addHelpMenuToAppChrome(chrome, docLinks) { - chrome.setHelpExtension({ - appName: i18n.translate('visualize.helpMenu.appName', { - defaultMessage: 'Visualize', - }), - links: [ - { - linkType: 'documentation', - href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/visualize.html`, - }, - ], - }); -} +export const InfoComponent = () => { + const title = ( + <> + {' '} + + GitHub + + {'.'} + + ); + + return ( + + ); +}; + +export const ExperimentalVisInfo = memo(InfoComponent); diff --git a/src/plugins/visualize/public/application/editor/lib/index.ts b/src/plugins/visualize/public/application/components/index.ts similarity index 80% rename from src/plugins/visualize/public/application/editor/lib/index.ts rename to src/plugins/visualize/public/application/components/index.ts index 78589383925fb9..a3a7fde1d6569f 100644 --- a/src/plugins/visualize/public/application/editor/lib/index.ts +++ b/src/plugins/visualize/public/application/components/index.ts @@ -17,6 +17,6 @@ * under the License. */ -export { useVisualizeAppState } from './visualize_app_state'; -export { makeStateful } from './make_stateful'; -export { addEmbeddableToDashboardUrl } from '../../../../../dashboard/public/'; +export { VisualizeListing } from './visualize_listing'; +export { VisualizeEditor } from './visualize_editor'; +export { VisualizeNoMatch } from './visualize_no_match'; diff --git a/src/plugins/visualize/public/application/editor/_editor.scss b/src/plugins/visualize/public/application/components/visualize_editor.scss similarity index 100% rename from src/plugins/visualize/public/application/editor/_editor.scss rename to src/plugins/visualize/public/application/components/visualize_editor.scss diff --git a/src/plugins/visualize/public/application/components/visualize_editor.tsx b/src/plugins/visualize/public/application/components/visualize_editor.tsx new file mode 100644 index 00000000000000..c571a5fb078bc5 --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_editor.tsx @@ -0,0 +1,115 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import './visualize_editor.scss'; +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { EventEmitter } from 'events'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiScreenReaderOnly } from '@elastic/eui'; + +import { useKibana } from '../../../../kibana_react/public'; +import { + useChromeVisibility, + useSavedVisInstance, + useVisualizeAppState, + useEditorUpdates, + useLinkedSearchUpdates, +} from '../utils'; +import { VisualizeServices } from '../types'; +import { ExperimentalVisInfo } from './experimental_vis_info'; +import { VisualizeTopNav } from './visualize_top_nav'; + +export const VisualizeEditor = () => { + const { id: visualizationIdFromUrl } = useParams(); + const [originatingApp, setOriginatingApp] = useState(); + const { services } = useKibana(); + const [eventEmitter] = useState(new EventEmitter()); + const [hasUnsavedChanges, setHasUnsavedChanges] = useState(!visualizationIdFromUrl); + + const isChromeVisible = useChromeVisibility(services.chrome); + const { savedVisInstance, visEditorRef, visEditorController } = useSavedVisInstance( + services, + eventEmitter, + isChromeVisible, + visualizationIdFromUrl + ); + const { appState, hasUnappliedChanges } = useVisualizeAppState( + services, + eventEmitter, + savedVisInstance + ); + const { isEmbeddableRendered, currentAppState } = useEditorUpdates( + services, + eventEmitter, + setHasUnsavedChanges, + appState, + savedVisInstance, + visEditorController + ); + useLinkedSearchUpdates(services, eventEmitter, appState, savedVisInstance); + + useEffect(() => { + const { originatingApp: value } = + services.embeddable.getStateTransfer(services.scopedHistory).getIncomingEditorState() || {}; + setOriginatingApp(value); + }, [services]); + + useEffect(() => { + // clean up all registered listeners if any is left + return () => { + eventEmitter.removeAllListeners(); + }; + }, [eventEmitter]); + + return ( +
+ {savedVisInstance && appState && currentAppState && ( + + )} + {savedVisInstance?.vis?.type?.isExperimental && } + {savedVisInstance && ( + +

+ +

+
+ )} +
+
+ ); +}; diff --git a/src/plugins/visualize/public/application/listing/_listing.scss b/src/plugins/visualize/public/application/components/visualize_listing.scss similarity index 100% rename from src/plugins/visualize/public/application/listing/_listing.scss rename to src/plugins/visualize/public/application/components/visualize_listing.scss diff --git a/src/plugins/visualize/public/application/components/visualize_listing.tsx b/src/plugins/visualize/public/application/components/visualize_listing.tsx new file mode 100644 index 00000000000000..cbfbd6e0e3ab6b --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_listing.tsx @@ -0,0 +1,154 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import './visualize_listing.scss'; + +import React, { useCallback, useRef, useMemo, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { useUnmount, useMount } from 'react-use'; +import { useLocation } from 'react-router-dom'; + +import { useKibana, TableListView } from '../../../../kibana_react/public'; +import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public'; +import { VisualizeServices } from '../types'; +import { VisualizeConstants } from '../visualize_constants'; +import { getTableColumns, getNoItemsMessage } from '../utils'; + +export const VisualizeListing = () => { + const { + services: { + application, + chrome, + history, + savedVisualizations, + toastNotifications, + visualizations, + savedObjects, + savedObjectsPublic, + uiSettings, + visualizeCapabilities, + }, + } = useKibana(); + const { pathname } = useLocation(); + const closeNewVisModal = useRef(() => {}); + const listingLimit = savedObjectsPublic.settings.getListingLimit(); + + useEffect(() => { + if (pathname === '/new') { + // In case the user navigated to the page via the /visualize/new URL we start the dialog immediately + closeNewVisModal.current = visualizations.showNewVisModal({ + onClose: () => { + // In case the user came via a URL to this page, change the URL to the regular landing page URL after closing the modal + history.push(VisualizeConstants.LANDING_PAGE_PATH); + }, + }); + } else { + // close modal window if exists + closeNewVisModal.current(); + } + }, [history, pathname, visualizations]); + + useMount(() => { + chrome.setBreadcrumbs([ + { + text: i18n.translate('visualize.visualizeListingBreadcrumbsTitle', { + defaultMessage: 'Visualize', + }), + }, + ]); + chrome.docTitle.change( + i18n.translate('visualize.listingPageTitle', { defaultMessage: 'Visualize' }) + ); + }); + useUnmount(() => closeNewVisModal.current()); + + const createNewVis = useCallback(() => { + closeNewVisModal.current = visualizations.showNewVisModal(); + }, [visualizations]); + + const editItem = useCallback( + ({ editUrl, editApp }) => { + if (editApp) { + application.navigateToApp(editApp, { path: editUrl }); + return; + } + // for visualizations the edit and view URLs are the same + history.push(editUrl); + }, + [application, history] + ); + + const noItemsFragment = useMemo(() => getNoItemsMessage(createNewVis), [createNewVis]); + const tableColumns = useMemo(() => getTableColumns(application, history), [application, history]); + + const fetchItems = useCallback( + (filter) => { + const isLabsEnabled = uiSettings.get(VISUALIZE_ENABLE_LABS_SETTING); + return savedVisualizations + .findListItems(filter, listingLimit) + .then(({ total, hits }: { total: number; hits: object[] }) => ({ + total, + hits: hits.filter((result: any) => isLabsEnabled || result.type.stage !== 'experimental'), + })); + }, + [listingLimit, savedVisualizations, uiSettings] + ); + + const deleteItems = useCallback( + async (selectedItems: object[]) => { + await Promise.all( + selectedItems.map((item: any) => savedObjects.client.delete(item.savedObjectType, item.id)) + ).catch((error) => { + toastNotifications.addError(error, { + title: i18n.translate('visualize.visualizeListingDeleteErrorTitle', { + defaultMessage: 'Error deleting visualization', + }), + }); + }); + }, + [savedObjects.client, toastNotifications] + ); + + return ( + + ); +}; diff --git a/src/plugins/visualize/public/application/components/visualize_no_match.tsx b/src/plugins/visualize/public/application/components/visualize_no_match.tsx new file mode 100644 index 00000000000000..7776c5e8ce4866 --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_no_match.tsx @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCallOut, EuiLink } from '@elastic/eui'; + +import { useKibana, toMountPoint } from '../../../../kibana_react/public'; +import { VisualizeServices } from '../types'; +import { VisualizeConstants } from '../visualize_constants'; + +let bannerId: string; + +export const VisualizeNoMatch = () => { + const { services } = useKibana(); + + useEffect(() => { + services.restorePreviousUrl(); + + const { navigated } = services.kibanaLegacy.navigateToLegacyKibanaUrl( + services.history.location.pathname + ); + + if (!navigated) { + const bannerMessage = i18n.translate('visualize.noMatchRoute.bannerTitleText', { + defaultMessage: 'Page not found', + }); + + bannerId = services.overlays.banners.replace( + bannerId, + toMountPoint( + +

+ + {services.history.location.pathname} + + ), + }} + /> +

+
+ ) + ); + + // hide the message after the user has had a chance to acknowledge it -- so it doesn't permanently stick around + setTimeout(() => { + services.overlays.banners.remove(bannerId); + }, 15000); + + services.history.replace(VisualizeConstants.LANDING_PAGE_PATH); + } + }, [services]); + + return null; +}; diff --git a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx new file mode 100644 index 00000000000000..2e7dba46487ad0 --- /dev/null +++ b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx @@ -0,0 +1,178 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'; +import { isEqual } from 'lodash'; + +import { OverlayRef } from 'kibana/public'; +import { Query } from 'src/plugins/data/public'; +import { useKibana } from '../../../../kibana_react/public'; +import { + VisualizeServices, + VisualizeAppState, + VisualizeAppStateContainer, + SavedVisInstance, +} from '../types'; +import { APP_NAME } from '../visualize_constants'; +import { getTopNavConfig } from '../utils'; + +interface VisualizeTopNavProps { + currentAppState: VisualizeAppState; + isChromeVisible?: boolean; + isEmbeddableRendered: boolean; + hasUnsavedChanges: boolean; + setHasUnsavedChanges: (value: boolean) => void; + hasUnappliedChanges: boolean; + originatingApp?: string; + savedVisInstance: SavedVisInstance; + stateContainer: VisualizeAppStateContainer; + visualizationIdFromUrl?: string; +} + +const TopNav = ({ + currentAppState, + isChromeVisible, + isEmbeddableRendered, + hasUnsavedChanges, + setHasUnsavedChanges, + hasUnappliedChanges, + originatingApp, + savedVisInstance, + stateContainer, + visualizationIdFromUrl, +}: VisualizeTopNavProps) => { + const { services } = useKibana(); + const { TopNavMenu } = services.navigation.ui; + const { embeddableHandler, vis } = savedVisInstance; + const [inspectorSession, setInspectorSession] = useState(); + const openInspector = useCallback(() => { + const session = embeddableHandler.openInspector(); + setInspectorSession(session); + }, [embeddableHandler]); + + const updateQuery = useCallback( + ({ query }: { query?: Query }) => { + if (!isEqual(currentAppState.query, query)) { + stateContainer.transitions.set('query', query || currentAppState.query); + } else { + savedVisInstance.embeddableHandler.reload(); + } + }, + [currentAppState.query, savedVisInstance.embeddableHandler, stateContainer.transitions] + ); + + const config = useMemo(() => { + if (isEmbeddableRendered) { + return getTopNavConfig( + { + hasUnsavedChanges, + setHasUnsavedChanges, + hasUnappliedChanges, + openInspector, + originatingApp, + savedVisInstance, + stateContainer, + visualizationIdFromUrl, + }, + services + ); + } + }, [ + isEmbeddableRendered, + hasUnsavedChanges, + setHasUnsavedChanges, + hasUnappliedChanges, + openInspector, + originatingApp, + savedVisInstance, + stateContainer, + visualizationIdFromUrl, + services, + ]); + const [indexPattern, setIndexPattern] = useState(vis.data.indexPattern); + const showDatePicker = () => { + // tsvb loads without an indexPattern initially (TODO investigate). + // hide timefilter only if timeFieldName is explicitly undefined. + const hasTimeField = vis.data.indexPattern ? !!vis.data.indexPattern.timeFieldName : true; + return vis.type.options.showTimePicker && hasTimeField; + }; + const showFilterBar = vis.type.options.showFilterBar; + const showQueryInput = vis.type.requiresSearch && vis.type.options.showQueryBar; + + useEffect(() => { + return () => { + if (inspectorSession) { + // Close the inspector if this scope is destroyed (e.g. because the user navigates away). + inspectorSession.close(); + } + }; + }, [inspectorSession]); + + useEffect(() => { + if (!vis.data.indexPattern) { + services.data.indexPatterns.getDefault().then((index) => { + if (index) { + setIndexPattern(index); + } + }); + } + }, [services.data.indexPatterns, vis.data.indexPattern]); + + return isChromeVisible ? ( + /** + * Most visualizations have all search bar components enabled. + * Some visualizations have fewer options, but all visualizations have the search bar. + * That's is why the showSearchBar prop is set. + * All visualizations also have the timepicker\autorefresh component, + * it is enabled by default in the TopNavMenu component. + */ + + ) : showFilterBar ? ( + /** + * The top nav is hidden in embed mode, but the filter bar must still be present so + * we show the filter bar on its own here if the chrome is not visible. + */ + + ) : null; +}; + +export const VisualizeTopNav = memo(TopNav); diff --git a/src/plugins/visualize/public/application/editor/_index.scss b/src/plugins/visualize/public/application/editor/_index.scss deleted file mode 100644 index 9d3ca4b5399472..00000000000000 --- a/src/plugins/visualize/public/application/editor/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'editor'; diff --git a/src/plugins/visualize/public/application/editor/editor.html b/src/plugins/visualize/public/application/editor/editor.html deleted file mode 100644 index 3c3455fb34f18c..00000000000000 --- a/src/plugins/visualize/public/application/editor/editor.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - -
-
-

-
-
- - - -

-

- - -
diff --git a/src/plugins/visualize/public/application/editor/editor.js b/src/plugins/visualize/public/application/editor/editor.js deleted file mode 100644 index d7c7828c58f23f..00000000000000 --- a/src/plugins/visualize/public/application/editor/editor.js +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import angular from 'angular'; -import _ from 'lodash'; -import { Subscription } from 'rxjs'; -import { map } from 'rxjs/operators'; -import { i18n } from '@kbn/i18n'; -import { EventEmitter } from 'events'; - -import React from 'react'; -import { makeStateful, useVisualizeAppState } from './lib'; -import { VisualizeConstants } from '../visualize_constants'; -import { getEditBreadcrumbs } from '../breadcrumbs'; - -import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util'; -import { unhashUrl } from '../../../../kibana_utils/public'; -import { MarkdownSimple, toMountPoint } from '../../../../kibana_react/public'; -import { - addFatalError, - subscribeWithScope, - migrateLegacyQuery, -} from '../../../../kibana_legacy/public'; -import { showSaveModal, SavedObjectSaveModalOrigin } from '../../../../saved_objects/public'; -import { - esFilters, - connectToQueryState, - syncQueryStateWithUrl, - UI_SETTINGS, -} from '../../../../data/public'; - -import { initVisEditorDirective } from './visualization_editor'; -import { initVisualizationDirective } from './visualization'; - -import { getServices } from '../../kibana_services'; -import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../visualizations/public'; - -export function initEditorDirective(app, deps) { - app.directive('visualizeApp', function () { - return { - restrict: 'E', - controllerAs: 'visualizeApp', - controller: VisualizeAppController, - }; - }); - - initVisEditorDirective(app, deps); - initVisualizationDirective(app, deps); -} - -function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlStateStorage, history) { - const { - localStorage, - visualizeCapabilities, - share, - data: { query: queryService, indexPatterns }, - toastNotifications, - chrome, - core: { docLinks, fatalErrors, uiSettings, application }, - I18nContext, - setActiveUrl, - visualizations, - embeddable, - scopedHistory, - } = getServices(); - - const { - filterManager, - timefilter: { timefilter }, - } = queryService; - - // starts syncing `_g` portion of url with query services - const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( - queryService, - kbnUrlStateStorage - ); - - // Retrieve the resolved SavedVis instance. - const { vis, savedVis, savedSearch, embeddableHandler } = $route.current.locals.resolved; - $scope.eventEmitter = new EventEmitter(); - const _applyVis = () => { - $scope.$apply(); - }; - // This will trigger a digest cycle. This is needed when vis is updated from a global angular like in visualize_embeddable.js. - $scope.eventEmitter.on('apply', _applyVis); - // vis is instance of src/legacy/ui/public/vis/vis.js. - // SearchSource is a promise-based stream of search results that can inherit from other search sources. - const searchSource = vis.data.searchSource; - - $scope.vis = vis; - $scope.savedSearch = savedSearch; - - const $appStatus = { - dirty: !savedVis.id, - }; - - const defaultQuery = { - query: '', - language: - localStorage.get('kibana.userQueryLanguage') || - uiSettings.get(UI_SETTINGS.SEARCH_QUERY_LANGUAGE), - }; - - const { originatingApp } = - embeddable.getStateTransfer(scopedHistory()).getIncomingEditorState() || {}; - $scope.getOriginatingApp = () => originatingApp; - - const visStateToEditorState = () => { - const savedVisState = visualizations.convertFromSerializedVis(vis.serialize()); - return { - uiState: vis.uiState.toJSON(), - query: vis.data.searchSource.getOwnField('query') || defaultQuery, - filters: vis.data.searchSource.getOwnField('filter') || [], - vis: { ...savedVisState.visState, title: vis.title }, - linked: !!savedVis.savedSearchId, - }; - }; - - const stateDefaults = visStateToEditorState(); - - const { stateContainer, stopStateSync } = useVisualizeAppState({ - stateDefaults, - kbnUrlStateStorage, - }); - - $scope.eventEmitter.on('dirtyStateChange', ({ isDirty }) => { - if (!isDirty) { - stateContainer.transitions.updateVisState(visStateToEditorState().vis); - } - $timeout(() => { - $scope.dirty = isDirty; - }); - }); - - $scope.eventEmitter.on('updateVis', () => { - embeddableHandler.reload(); - }); - - $scope.embeddableHandler = embeddableHandler; - - $scope.topNavMenu = [ - ...($scope.getOriginatingApp() && savedVis.id - ? [ - { - id: 'saveAndReturn', - label: i18n.translate('visualize.topNavMenu.saveAndReturnVisualizationButtonLabel', { - defaultMessage: 'Save and return', - }), - emphasize: true, - iconType: 'check', - description: i18n.translate( - 'visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel', - { - defaultMessage: 'Finish editing visualization and return to the last app', - } - ), - testId: 'visualizesaveAndReturnButton', - disableButton() { - return Boolean($scope.dirty); - }, - tooltip() { - if ($scope.dirty) { - return i18n.translate( - 'visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip', - { - defaultMessage: 'Apply or Discard your changes before finishing', - } - ); - } - }, - run: async () => { - const saveOptions = { - confirmOverwrite: false, - returnToOrigin: true, - }; - return doSave(saveOptions); - }, - }, - ] - : []), - ...(visualizeCapabilities.save - ? [ - { - id: 'save', - label: - savedVis.id && $scope.getOriginatingApp() - ? i18n.translate('visualize.topNavMenu.saveVisualizationAsButtonLabel', { - defaultMessage: 'save as', - }) - : i18n.translate('visualize.topNavMenu.saveVisualizationButtonLabel', { - defaultMessage: 'save', - }), - emphasize: !savedVis.id || !$scope.getOriginatingApp(), - description: i18n.translate('visualize.topNavMenu.saveVisualizationButtonAriaLabel', { - defaultMessage: 'Save Visualization', - }), - testId: 'visualizeSaveButton', - disableButton() { - return Boolean($scope.dirty); - }, - tooltip() { - if ($scope.dirty) { - return i18n.translate( - 'visualize.topNavMenu.saveVisualizationDisabledButtonTooltip', - { - defaultMessage: 'Apply or Discard your changes before saving', - } - ); - } - }, - run: async () => { - const onSave = ({ - newTitle, - newCopyOnSave, - isTitleDuplicateConfirmed, - onTitleDuplicate, - newDescription, - returnToOrigin, - }) => { - const currentTitle = savedVis.title; - savedVis.title = newTitle; - savedVis.copyOnSave = newCopyOnSave; - savedVis.description = newDescription; - const saveOptions = { - confirmOverwrite: false, - isTitleDuplicateConfirmed, - onTitleDuplicate, - returnToOrigin, - }; - return doSave(saveOptions).then((response) => { - // If the save wasn't successful, put the original values back. - if (!response.id || response.error) { - savedVis.title = currentTitle; - } - return response; - }); - }; - - const saveModal = ( - {}} - originatingApp={$scope.getOriginatingApp()} - /> - ); - showSaveModal(saveModal, I18nContext); - }, - }, - ] - : []), - { - id: 'share', - label: i18n.translate('visualize.topNavMenu.shareVisualizationButtonLabel', { - defaultMessage: 'share', - }), - description: i18n.translate('visualize.topNavMenu.shareVisualizationButtonAriaLabel', { - defaultMessage: 'Share Visualization', - }), - testId: 'shareTopNavButton', - run: (anchorElement) => { - const hasUnappliedChanges = $scope.dirty; - const hasUnsavedChanges = $appStatus.dirty; - share.toggleShareContextMenu({ - anchorElement, - allowEmbed: true, - allowShortUrl: visualizeCapabilities.createShortUrl, - shareableUrl: unhashUrl(window.location.href), - objectId: savedVis.id, - objectType: 'visualization', - sharingData: { - title: savedVis.title, - }, - isDirty: hasUnappliedChanges || hasUnsavedChanges, - }); - }, - // disable the Share button if no action specified - disableButton: !share, - }, - { - id: 'inspector', - label: i18n.translate('visualize.topNavMenu.openInspectorButtonLabel', { - defaultMessage: 'inspect', - }), - description: i18n.translate('visualize.topNavMenu.openInspectorButtonAriaLabel', { - defaultMessage: 'Open Inspector for visualization', - }), - testId: 'openInspectorButton', - disableButton() { - return !embeddableHandler.hasInspector || !embeddableHandler.hasInspector(); - }, - run() { - const inspectorSession = embeddableHandler.openInspector(); - - if (inspectorSession) { - // Close the inspector if this scope is destroyed (e.g. because the user navigates away). - const removeWatch = $scope.$on('$destroy', () => inspectorSession.close()); - // Remove that watch in case the user closes the inspector session herself. - inspectorSession.onClose.finally(removeWatch); - } - }, - tooltip() { - if (!embeddableHandler.hasInspector || !embeddableHandler.hasInspector()) { - return i18n.translate('visualize.topNavMenu.openInspectorDisabledButtonTooltip', { - defaultMessage: `This visualization doesn't support any inspectors.`, - }); - } - }, - }, - ]; - - if (savedVis.id) { - chrome.docTitle.change(savedVis.title); - } - - // sync initial app filters from state to filterManager - filterManager.setAppFilters(_.cloneDeep(stateContainer.getState().filters)); - // setup syncing of app filters between appState and filterManager - const stopSyncingAppFilters = connectToQueryState( - queryService, - { - set: ({ filters }) => stateContainer.transitions.set('filters', filters), - get: () => ({ filters: stateContainer.getState().filters }), - state$: stateContainer.state$.pipe(map((state) => ({ filters: state.filters }))), - }, - { - filters: esFilters.FilterStateStore.APP_STATE, - } - ); - - const stopAllSyncing = () => { - stopStateSync(); - stopSyncingQueryServiceStateWithUrl(); - stopSyncingAppFilters(); - }; - - // The savedVis is pulled from elasticsearch, but the appState is pulled from the url, with the - // defaults applied. If the url was from a previous session which included modifications to the - // appState then they won't be equal. - if (!_.isEqual(stateContainer.getState().vis, stateDefaults.vis)) { - try { - const { aggs, ...visState } = stateContainer.getState().vis; - vis.setState({ ...visState, data: { aggs } }); - } catch (error) { - // stop syncing url updtes with the state to prevent extra syncing - stopAllSyncing(); - - toastNotifications.addWarning({ - title: i18n.translate('visualize.visualizationTypeInvalidNotificationMessage', { - defaultMessage: 'Invalid visualization type', - }), - text: toMountPoint({error.message}), - }); - - history.replace(`${VisualizeConstants.LANDING_PAGE_PATH}?notFound=visualization`); - - // prevent further controller execution - return; - } - } - - $scope.filters = filterManager.getFilters(); - - $scope.onFiltersUpdated = (filters) => { - // The filters will automatically be set when the filterManager emits an update event (see below) - filterManager.setFilters(filters); - }; - - $scope.showSaveQuery = visualizeCapabilities.saveQuery; - - $scope.$watch( - () => visualizeCapabilities.saveQuery, - (newCapability) => { - $scope.showSaveQuery = newCapability; - } - ); - - const updateSavedQueryFromUrl = (savedQueryId) => { - if (!savedQueryId) { - delete $scope.savedQuery; - - return; - } - - if ($scope.savedQuery && $scope.savedQuery.id === savedQueryId) { - return; - } - - queryService.savedQueries.getSavedQuery(savedQueryId).then((savedQuery) => { - $scope.$evalAsync(() => { - $scope.updateSavedQuery(savedQuery); - }); - }); - }; - - function init() { - if (vis.data.indexPattern) { - $scope.indexPattern = vis.data.indexPattern; - } else { - indexPatterns.getDefault().then((defaultIndexPattern) => { - $scope.indexPattern = defaultIndexPattern; - }); - } - - const initialState = stateContainer.getState(); - - const handleLinkedSearch = (linked) => { - if (linked && !savedVis.savedSearchId && savedSearch) { - savedVis.savedSearchId = savedSearch.id; - vis.data.savedSearchId = savedSearch.id; - searchSource.setParent(savedSearch.searchSource); - } else if (!linked && savedVis.savedSearchId) { - delete savedVis.savedSearchId; - delete vis.data.savedSearchId; - } - }; - - // Create a PersistedState instance for uiState. - const { persistedState, unsubscribePersisted, persistOnChange } = makeStateful( - 'uiState', - stateContainer - ); - vis.uiState = persistedState; - vis.uiState.on('reload', embeddableHandler.reload); - $scope.uiState = persistedState; - $scope.savedVis = savedVis; - $scope.query = initialState.query; - $scope.searchSource = searchSource; - $scope.refreshInterval = timefilter.getRefreshInterval(); - handleLinkedSearch(initialState.linked); - - $scope.showFilterBar = () => { - return vis.type.options.showFilterBar; - }; - - $scope.showQueryInput = () => { - return vis.type.requiresSearch && vis.type.options.showQueryBar; - }; - - $scope.showQueryBarTimePicker = () => { - // tsvb loads without an indexPattern initially (TODO investigate). - // hide timefilter only if timeFieldName is explicitly undefined. - const hasTimeField = vis.data.indexPattern ? !!vis.data.indexPattern.timeFieldName : true; - return vis.type.options.showTimePicker && hasTimeField; - }; - - $scope.timeRange = timefilter.getTime(); - - const unsubscribeStateUpdates = stateContainer.subscribe((state) => { - const newQuery = migrateLegacyQuery(state.query); - if (!_.isEqual(state.query, newQuery)) { - stateContainer.transitions.set('query', newQuery); - } - persistOnChange(state); - updateSavedQueryFromUrl(state.savedQuery); - - // if the browser history was changed manually we need to reflect changes in the editor - if ( - !_.isEqual( - { - ...visualizations.convertFromSerializedVis(vis.serialize()).visState, - title: vis.title, - }, - state.vis - ) - ) { - const { aggs, ...visState } = state.vis; - vis.setState({ - ...visState, - data: { - aggs, - }, - }); - embeddableHandler.reload(); - $scope.eventEmitter.emit('updateEditor'); - } - - $appStatus.dirty = true; - $scope.fetch(); - }); - - const updateTimeRange = () => { - $scope.timeRange = timefilter.getTime(); - $scope.$broadcast('render'); - }; - - // update the query if savedQuery is stored - updateSavedQueryFromUrl(initialState.savedQuery); - - const subscriptions = new Subscription(); - - subscriptions.add( - subscribeWithScope( - $scope, - timefilter.getRefreshIntervalUpdate$(), - { - next: () => { - $scope.refreshInterval = timefilter.getRefreshInterval(); - }, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - subscriptions.add( - subscribeWithScope( - $scope, - timefilter.getTimeUpdate$(), - { - next: updateTimeRange, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - - subscriptions.add( - chrome.getIsVisible$().subscribe((isVisible) => { - $scope.$evalAsync(() => { - $scope.isVisible = isVisible; - }); - }) - ); - - // update the searchSource when query updates - $scope.fetch = function () { - const { query, linked, filters } = stateContainer.getState(); - $scope.query = query; - handleLinkedSearch(linked); - vis.data.searchSource.setField('query', query); - vis.data.searchSource.setField('filter', filters); - $scope.$broadcast('render'); - }; - - // update the searchSource when filters update - subscriptions.add( - subscribeWithScope( - $scope, - filterManager.getUpdates$(), - { - next: () => { - $scope.filters = filterManager.getFilters(); - }, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - subscriptions.add( - subscribeWithScope( - $scope, - filterManager.getFetches$(), - { - next: $scope.fetch, - }, - (error) => addFatalError(fatalErrors, error) - ) - ); - - $scope.$on('$destroy', () => { - if ($scope._handler) { - $scope._handler.destroy(); - } - savedVis.destroy(); - subscriptions.unsubscribe(); - $scope.eventEmitter.off('apply', _applyVis); - - unsubscribePersisted(); - vis.uiState.off('reload', embeddableHandler.reload); - unsubscribeStateUpdates(); - - stopAllSyncing(); - }); - - $timeout(() => { - $scope.$broadcast('render'); - }); - } - - $scope.updateQueryAndFetch = function ({ query, dateRange }) { - const isUpdate = - (query && !_.isEqual(query, stateContainer.getState().query)) || - (dateRange && !_.isEqual(dateRange, $scope.timeRange)); - - stateContainer.transitions.set('query', query); - timefilter.setTime(dateRange); - - // If nothing has changed, trigger the fetch manually, otherwise it will happen as a result of the changes - if (!isUpdate) { - embeddableHandler.reload(); - } - }; - - $scope.onRefreshChange = function ({ isPaused, refreshInterval }) { - timefilter.setRefreshInterval({ - pause: isPaused, - value: refreshInterval ? refreshInterval : $scope.refreshInterval.value, - }); - }; - - $scope.onClearSavedQuery = () => { - delete $scope.savedQuery; - stateContainer.transitions.removeSavedQuery(defaultQuery); - filterManager.setFilters(filterManager.getGlobalFilters()); - }; - - const updateStateFromSavedQuery = (savedQuery) => { - stateContainer.transitions.updateFromSavedQuery(savedQuery); - - const savedQueryFilters = savedQuery.attributes.filters || []; - const globalFilters = filterManager.getGlobalFilters(); - filterManager.setFilters([...globalFilters, ...savedQueryFilters]); - - if (savedQuery.attributes.timefilter) { - timefilter.setTime({ - from: savedQuery.attributes.timefilter.from, - to: savedQuery.attributes.timefilter.to, - }); - if (savedQuery.attributes.timefilter.refreshInterval) { - timefilter.setRefreshInterval(savedQuery.attributes.timefilter.refreshInterval); - } - } - }; - - $scope.updateSavedQuery = (savedQuery) => { - $scope.savedQuery = savedQuery; - updateStateFromSavedQuery(savedQuery); - }; - - /** - * Called when the user clicks "Save" button. - */ - function doSave(saveOptions) { - // vis.title was not bound and it's needed to reflect title into visState - const newlyCreated = !Boolean(savedVis.id) || savedVis.copyOnSave; - stateContainer.transitions.setVis({ - title: savedVis.title, - type: savedVis.type || stateContainer.getState().vis.type, - }); - savedVis.searchSourceFields = searchSource.getSerializedFields(); - savedVis.visState = stateContainer.getState().vis; - savedVis.uiStateJSON = angular.toJson($scope.uiState.toJSON()); - $appStatus.dirty = false; - - return savedVis.save(saveOptions).then( - function (id) { - $scope.$evalAsync(() => { - if (id) { - toastNotifications.addSuccess({ - title: i18n.translate( - 'visualize.topNavMenu.saveVisualization.successNotificationText', - { - defaultMessage: `Saved '{visTitle}'`, - values: { - visTitle: savedVis.title, - }, - } - ), - 'data-test-subj': 'saveVisualizationSuccess', - }); - - if ($scope.getOriginatingApp() && saveOptions.returnToOrigin) { - const appPath = `${VisualizeConstants.EDIT_PATH}/${encodeURIComponent(savedVis.id)}`; - - // Manually insert a new url so the back button will open the saved visualization. - history.replace(appPath); - setActiveUrl(appPath); - if (newlyCreated && embeddable) { - embeddable - .getStateTransfer() - .navigateToWithEmbeddablePackage($scope.getOriginatingApp(), { - state: { id: savedVis.id, type: VISUALIZE_EMBEDDABLE_TYPE }, - }); - } else { - application.navigateToApp($scope.getOriginatingApp()); - } - } else if (savedVis.id === $route.current.params.id) { - chrome.docTitle.change(savedVis.lastSavedTitle); - chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs)); - savedVis.vis.title = savedVis.title; - savedVis.vis.description = savedVis.description; - } else { - history.replace({ - ...history.location, - pathname: `${VisualizeConstants.EDIT_PATH}/${savedVis.id}`, - }); - } - } - }); - return { id }; - }, - (error) => { - // eslint-disable-next-line - console.error(error); - toastNotifications.addDanger({ - title: i18n.translate('visualize.topNavMenu.saveVisualization.failureNotificationText', { - defaultMessage: `Error on saving '{visTitle}'`, - values: { - visTitle: savedVis.title, - }, - }), - text: error.message, - 'data-test-subj': 'saveVisualizationError', - }); - return { error }; - } - ); - } - - const unlinkFromSavedSearch = () => { - const searchSourceParent = savedSearch.searchSource; - const searchSourceGrandparent = searchSourceParent.getParent(); - const currentIndex = searchSourceParent.getField('index'); - - searchSource.setField('index', currentIndex); - searchSource.setParent(searchSourceGrandparent); - - stateContainer.transitions.unlinkSavedSearch({ - query: searchSourceParent.getField('query'), - parentFilters: searchSourceParent.getOwnField('filter'), - }); - - toastNotifications.addSuccess( - i18n.translate('visualize.linkedToSearch.unlinkSuccessNotificationText', { - defaultMessage: `Unlinked from saved search '{searchTitle}'`, - values: { - searchTitle: savedSearch.title, - }, - }) - ); - }; - - $scope.getAdditionalMessage = () => { - return ( - '' + - i18n.translate('visualize.experimentalVisInfoText', { - defaultMessage: 'This visualization is marked as experimental.', - }) + - ' ' + - vis.type.feedbackMessage - ); - }; - - $scope.eventEmitter.on('unlinkFromSavedSearch', unlinkFromSavedSearch); - - addHelpMenuToAppChrome(chrome, docLinks); - - init(); -} diff --git a/src/plugins/visualize/public/application/editor/lib/make_stateful.ts b/src/plugins/visualize/public/application/editor/lib/make_stateful.ts deleted file mode 100644 index c7163f9b7705d4..00000000000000 --- a/src/plugins/visualize/public/application/editor/lib/make_stateful.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { PersistedState } from '../../../../../visualizations/public'; -import { ReduxLikeStateContainer } from '../../../../../kibana_utils/public'; -import { VisualizeAppState, VisualizeAppStateTransitions } from '../../types'; - -/** - * @returns Create a PersistedState instance, initialize state changes subscriber/unsubscriber - */ -export function makeStateful( - prop: keyof VisualizeAppState, - stateContainer: ReduxLikeStateContainer -) { - // set up the persistedState state - const persistedState = new PersistedState(); - - // update the appState when the stateful instance changes - const updateOnChange = function () { - stateContainer.transitions.set(prop, persistedState.getChanges()); - }; - - const handlerOnChange = (method: 'on' | 'off') => - persistedState[method]('change', updateOnChange); - - handlerOnChange('on'); - const unsubscribePersisted = () => handlerOnChange('off'); - - // update the stateful object when the app state changes - const persistOnChange = function (state: VisualizeAppState) { - if (state[prop]) { - persistedState.set(state[prop]); - } - }; - - const appState = stateContainer.getState(); - - // if the thing we're making stateful has an appState value, write to persisted state - if (appState[prop]) persistedState.setSilent(appState[prop]); - - return { persistedState, unsubscribePersisted, persistOnChange }; -} diff --git a/src/plugins/visualize/public/application/editor/visualization.js b/src/plugins/visualize/public/application/editor/visualization.js deleted file mode 100644 index 26f61f3f0a2c2b..00000000000000 --- a/src/plugins/visualize/public/application/editor/visualization.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export function initVisualizationDirective(app) { - app.directive('visualizationEmbedded', function ($timeout) { - return { - restrict: 'E', - scope: { - embeddableHandler: '=', - uiState: '=?', - timeRange: '=', - filters: '=', - query: '=', - appState: '=', - }, - link: function ($scope, element) { - $scope.renderFunction = async () => { - if (!$scope.rendered) { - $scope.embeddableHandler.render(element[0]); - $scope.rendered = true; - } - - $scope.embeddableHandler.updateInput({ - timeRange: $scope.timeRange, - filters: $scope.filters || [], - query: $scope.query, - }); - }; - - $scope.$on('render', (event) => { - event.preventDefault(); - $timeout(() => { - $scope.renderFunction(); - }); - }); - - $scope.$on('$destroy', () => { - if ($scope.embeddableHandler) { - $scope.embeddableHandler.destroy(); - } - }); - }, - }; - }); -} diff --git a/src/plugins/visualize/public/application/editor/visualization_editor.js b/src/plugins/visualize/public/application/editor/visualization_editor.js deleted file mode 100644 index 4963d9bc5ed72e..00000000000000 --- a/src/plugins/visualize/public/application/editor/visualization_editor.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { DefaultEditorController } from '../../../../vis_default_editor/public'; - -export function initVisEditorDirective(app, deps) { - app.directive('visualizationEditor', function ($timeout) { - return { - restrict: 'E', - scope: { - vis: '=', - uiState: '=?', - timeRange: '=', - filters: '=', - query: '=', - savedSearch: '=', - embeddableHandler: '=', - eventEmitter: '=', - }, - link: function ($scope, element) { - const Editor = $scope.vis.type.editor || DefaultEditorController; - const editor = new Editor( - element[0], - $scope.vis, - $scope.eventEmitter, - $scope.embeddableHandler - ); - - $scope.renderFunction = () => { - editor.render({ - core: deps.core, - data: deps.data, - uiState: $scope.uiState, - timeRange: $scope.timeRange, - filters: $scope.filters, - query: $scope.query, - linked: !!$scope.vis.data.savedSearchId, - savedSearch: $scope.savedSearch, - }); - }; - - $scope.$on('render', (event) => { - event.preventDefault(); - $timeout(() => { - $scope.renderFunction(); - }); - }); - - $scope.$on('$destroy', () => { - editor.destroy(); - }); - }, - }; - }); -} diff --git a/src/plugins/visualize/public/application/index.tsx b/src/plugins/visualize/public/application/index.tsx new file mode 100644 index 00000000000000..4bec244e6efc94 --- /dev/null +++ b/src/plugins/visualize/public/application/index.tsx @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Router } from 'react-router-dom'; + +import { AppMountParameters } from 'kibana/public'; +import { KibanaContextProvider } from '../../../kibana_react/public'; +import { VisualizeApp } from './app'; +import { VisualizeServices } from './types'; +import { addHelpMenuToAppChrome, addBadgeToAppChrome } from './utils'; + +export const renderApp = ({ element }: AppMountParameters, services: VisualizeServices) => { + // add help link to visualize docs into app chrome menu + addHelpMenuToAppChrome(services.chrome, services.docLinks); + // add readonly badge if saving restricted + if (!services.visualizeCapabilities.save) { + addBadgeToAppChrome(services.chrome); + } + + const app = ( + + + + + + + + ); + + ReactDOM.render(app, element); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/src/plugins/visualize/public/application/legacy_app.js b/src/plugins/visualize/public/application/legacy_app.js deleted file mode 100644 index 452118f8097da0..00000000000000 --- a/src/plugins/visualize/public/application/legacy_app.js +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { find } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { createHashHistory } from 'history'; - -import { createKbnUrlStateStorage, redirectWhenMissing } from '../../../kibana_utils/public'; -import { createSavedSearchesLoader } from '../../../discover/public'; - -import editorTemplate from './editor/editor.html'; -import visualizeListingTemplate from './listing/visualize_listing.html'; - -import { initVisualizeAppDirective } from './visualize_app'; -import { VisualizeConstants } from './visualize_constants'; -import { VisualizeListingController } from './listing/visualize_listing'; - -import { - getLandingBreadcrumbs, - getWizardStep1Breadcrumbs, - getCreateBreadcrumbs, - getEditBreadcrumbs, -} from './breadcrumbs'; - -const getResolvedResults = (deps) => { - const { core, data, visualizations, createVisEmbeddableFromObject } = deps; - - const results = {}; - - return (savedVis) => { - results.savedVis = savedVis; - const serializedVis = visualizations.convertToSerializedVis(savedVis); - return visualizations - .createVis(serializedVis.type, serializedVis) - .then((vis) => { - if (vis.type.setup) { - return vis.type.setup(vis).catch(() => vis); - } - return vis; - }) - .then((vis) => { - results.vis = vis; - return createVisEmbeddableFromObject(vis, { - timeRange: data.query.timefilter.timefilter.getTime(), - filters: data.query.filterManager.getFilters(), - }); - }) - .then((embeddableHandler) => { - results.embeddableHandler = embeddableHandler; - - embeddableHandler.getOutput$().subscribe((output) => { - if (output.error) { - core.notifications.toasts.addError(output.error, { - title: i18n.translate('visualize.error.title', { - defaultMessage: 'Visualization error', - }), - }); - } - }); - - if (results.vis.data.savedSearchId) { - return createSavedSearchesLoader({ - savedObjectsClient: core.savedObjects.client, - indexPatterns: data.indexPatterns, - search: data.search, - chrome: core.chrome, - overlays: core.overlays, - }).get(results.vis.data.savedSearchId); - } - }) - .then((savedSearch) => { - if (savedSearch) { - results.savedSearch = savedSearch; - } - return results; - }); - }; -}; - -export function initVisualizeApp(app, deps) { - initVisualizeAppDirective(app, deps); - - app.factory('history', () => createHashHistory()); - app.factory('kbnUrlStateStorage', (history) => - createKbnUrlStateStorage({ - history, - useHash: deps.core.uiSettings.get('state:storeInSessionStorage'), - }) - ); - - app.config(function ($routeProvider) { - const defaults = { - reloadOnSearch: false, - requireUICapability: 'visualize.show', - badge: () => { - if (deps.visualizeCapabilities.save) { - return undefined; - } - - return { - text: i18n.translate('visualize.badge.readOnly.text', { - defaultMessage: 'Read only', - }), - tooltip: i18n.translate('visualize.badge.readOnly.tooltip', { - defaultMessage: 'Unable to save visualizations', - }), - iconType: 'glasses', - }; - }, - }; - - $routeProvider - .when(VisualizeConstants.LANDING_PAGE_PATH, { - ...defaults, - template: visualizeListingTemplate, - k7Breadcrumbs: getLandingBreadcrumbs, - controller: VisualizeListingController, - controllerAs: 'listingController', - resolve: { - createNewVis: () => false, - hasDefaultIndex: (history) => deps.data.indexPatterns.ensureDefaultIndexPattern(history), - }, - }) - .when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, { - ...defaults, - template: visualizeListingTemplate, - k7Breadcrumbs: getWizardStep1Breadcrumbs, - controller: VisualizeListingController, - controllerAs: 'listingController', - resolve: { - createNewVis: () => true, - hasDefaultIndex: (history) => deps.data.indexPatterns.ensureDefaultIndexPattern(history), - }, - }) - .when(VisualizeConstants.CREATE_PATH, { - ...defaults, - template: editorTemplate, - k7Breadcrumbs: getCreateBreadcrumbs, - resolve: { - resolved: function ($route, history) { - const { data, savedVisualizations, visualizations, toastNotifications } = deps; - const visTypes = visualizations.all(); - const visType = find(visTypes, { name: $route.current.params.type }); - const shouldHaveIndex = visType.requiresSearch && visType.options.showIndexSelection; - const hasIndex = - $route.current.params.indexPattern || $route.current.params.savedSearchId; - if (shouldHaveIndex && !hasIndex) { - throw new Error( - i18n.translate( - 'visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage', - { - defaultMessage: 'You must provide either an indexPattern or a savedSearchId', - } - ) - ); - } - - // This delay is needed to prevent some navigation issues in Firefox/Safari. - // see https://github.com/elastic/kibana/issues/65161 - const delay = (res) => { - return new Promise((resolve) => { - setTimeout(() => resolve(res), 0); - }); - }; - - return data.indexPatterns - .ensureDefaultIndexPattern(history) - .then(() => savedVisualizations.get($route.current.params)) - .then((savedVis) => { - savedVis.searchSourceFields = { index: $route.current.params.indexPattern }; - return savedVis; - }) - .then(getResolvedResults(deps)) - .then(delay) - .catch( - redirectWhenMissing({ - history, - mapping: VisualizeConstants.LANDING_PAGE_PATH, - toastNotifications, - }) - ); - }, - }, - }) - .when(`${VisualizeConstants.EDIT_PATH}/:id`, { - ...defaults, - template: editorTemplate, - k7Breadcrumbs: getEditBreadcrumbs, - resolve: { - resolved: function ($route, history) { - const { chrome, data, savedVisualizations, toastNotifications } = deps; - - return data.indexPatterns - .ensureDefaultIndexPattern(history) - .then(() => savedVisualizations.get($route.current.params.id)) - .then((savedVis) => { - chrome.recentlyAccessed.add(savedVis.getFullPath(), savedVis.title, savedVis.id); - return savedVis; - }) - .then(getResolvedResults(deps)) - .catch( - redirectWhenMissing({ - history, - navigateToApp: deps.core.application.navigateToApp, - basePath: deps.core.http.basePath, - mapping: { - visualization: VisualizeConstants.LANDING_PAGE_PATH, - search: { - app: 'management', - path: 'kibana/objects/savedVisualizations/' + $route.current.params.id, - }, - 'index-pattern': { - app: 'management', - path: 'kibana/objects/savedVisualizations/' + $route.current.params.id, - }, - 'index-pattern-field': { - app: 'management', - path: 'kibana/objects/savedVisualizations/' + $route.current.params.id, - }, - }, - toastNotifications, - onBeforeRedirect() { - deps.setActiveUrl(VisualizeConstants.LANDING_PAGE_PATH); - }, - }) - ); - }, - }, - }) - .otherwise({ - resolveRedirectTo: function ($rootScope) { - const path = window.location.hash.substr(1); - deps.restorePreviousUrl(); - $rootScope.$applyAsync(() => { - const { navigated } = deps.kibanaLegacy.navigateToLegacyKibanaUrl(path); - if (!navigated) { - deps.kibanaLegacy.navigateToDefaultApp(); - } - }); - // prevent angular from completing the navigation - return new Promise(() => {}); - }, - }); - }); -} diff --git a/src/plugins/visualize/public/application/listing/_index.scss b/src/plugins/visualize/public/application/listing/_index.scss deleted file mode 100644 index 924c164e467d88..00000000000000 --- a/src/plugins/visualize/public/application/listing/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'listing'; diff --git a/src/plugins/visualize/public/application/listing/visualize_listing.html b/src/plugins/visualize/public/application/listing/visualize_listing.html deleted file mode 100644 index 8838348e0b6796..00000000000000 --- a/src/plugins/visualize/public/application/listing/visualize_listing.html +++ /dev/null @@ -1,13 +0,0 @@ -
- -
diff --git a/src/plugins/visualize/public/application/listing/visualize_listing.js b/src/plugins/visualize/public/application/listing/visualize_listing.js deleted file mode 100644 index e8e8d92034113a..00000000000000 --- a/src/plugins/visualize/public/application/listing/visualize_listing.js +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util'; -import { withI18nContext } from './visualize_listing_table'; - -import { VisualizeConstants } from '../visualize_constants'; -import { i18n } from '@kbn/i18n'; - -import { getServices } from '../../kibana_services'; -import { syncQueryStateWithUrl } from '../../../../data/public'; -import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public'; - -import { EuiLink } from '@elastic/eui'; -import React from 'react'; - -export function initListingDirective(app, I18nContext) { - app.directive('visualizeListingTable', (reactDirective) => - reactDirective(withI18nContext(I18nContext)) - ); -} - -export function VisualizeListingController($scope, createNewVis, kbnUrlStateStorage, history) { - const { - addBasePath, - chrome, - savedObjectsClient, - savedVisualizations, - data: { query }, - toastNotifications, - visualizations, - core: { docLinks, savedObjects, uiSettings, application }, - savedObjects: savedObjectsPublic, - } = getServices(); - - chrome.docTitle.change( - i18n.translate('visualize.listingPageTitle', { defaultMessage: 'Visualize' }) - ); - - // syncs `_g` portion of url with query services - const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( - query, - kbnUrlStateStorage - ); - - const { - timefilter: { timefilter }, - } = query; - - timefilter.disableAutoRefreshSelector(); - timefilter.disableTimeRangeSelector(); - - this.addBasePath = addBasePath; - this.uiSettings = uiSettings; - this.savedObjects = savedObjects; - - this.createNewVis = () => { - this.closeNewVisModal = visualizations.showNewVisModal(); - }; - - this.editItem = ({ editUrl, editApp }) => { - if (editApp) { - application.navigateToApp(editApp, { path: editUrl }); - return; - } - // for visualizations the edit and view URLs are the same - window.location.href = addBasePath(editUrl); - }; - - this.getViewElement = (field, record) => { - const dataTestSubj = `visListingTitleLink-${record.title.split(' ').join('-')}`; - if (record.editApp) { - return ( - { - application.navigateToApp(record.editApp, { path: record.editUrl }); - }} - data-test-subj={dataTestSubj} - > - {field} - - ); - } else if (record.editUrl) { - return ( - - {field} - - ); - } else { - return {field}; - } - }; - - if (createNewVis) { - // In case the user navigated to the page via the /visualize/new URL we start the dialog immediately - this.closeNewVisModal = visualizations.showNewVisModal({ - onClose: () => { - // In case the user came via a URL to this page, change the URL to the regular landing page URL after closing the modal - history.push({ - // Should preserve querystring part so the global state is preserved. - ...history.location, - pathname: VisualizeConstants.LANDING_PAGE_PATH, - }); - }, - }); - } - - this.fetchItems = (filter) => { - const isLabsEnabled = uiSettings.get(VISUALIZE_ENABLE_LABS_SETTING); - return savedVisualizations - .findListItems(filter, savedObjectsPublic.settings.getListingLimit()) - .then((result) => { - this.totalItems = result.total; - - return { - total: result.total, - hits: result.hits.filter( - (result) => isLabsEnabled || result.type.stage !== 'experimental' - ), - }; - }); - }; - - this.deleteSelectedItems = function deleteSelectedItems(selectedItems) { - return Promise.all( - selectedItems.map((item) => { - return savedObjectsClient.delete(item.savedObjectType, item.id); - }) - ).catch((error) => { - toastNotifications.addError(error, { - title: i18n.translate('visualize.visualizeListingDeleteErrorTitle', { - defaultMessage: 'Error deleting visualization', - }), - }); - }); - }; - - chrome.setBreadcrumbs([ - { - text: i18n.translate('visualize.visualizeListingBreadcrumbsTitle', { - defaultMessage: 'Visualize', - }), - }, - ]); - - this.listingLimit = savedObjectsPublic.settings.getListingLimit(); - this.initialPageSize = savedObjectsPublic.settings.getPerPage(); - - addHelpMenuToAppChrome(chrome, docLinks); - - $scope.$on('$destroy', () => { - if (this.closeNewVisModal) { - this.closeNewVisModal(); - } - - stopSyncingQueryServiceStateWithUrl(); - }); -} diff --git a/src/plugins/visualize/public/application/listing/visualize_listing_table.js b/src/plugins/visualize/public/application/listing/visualize_listing_table.js deleted file mode 100644 index fcd62d7ddee732..00000000000000 --- a/src/plugins/visualize/public/application/listing/visualize_listing_table.js +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { TableListView } from '../../../../kibana_react/public'; - -import { EuiIcon, EuiBetaBadge, EuiButton, EuiEmptyPrompt } from '@elastic/eui'; - -import { getServices } from '../../kibana_services'; - -class VisualizeListingTable extends Component { - constructor(props) { - super(props); - } - - render() { - const { visualizeCapabilities, core, toastNotifications } = getServices(); - return ( - item.canDelete} - initialFilter={''} - noItemsFragment={this.getNoItemsMessage()} - entityName={i18n.translate('visualize.listing.table.entityName', { - defaultMessage: 'visualization', - })} - entityNamePlural={i18n.translate('visualize.listing.table.entityNamePlural', { - defaultMessage: 'visualizations', - })} - tableListTitle={i18n.translate('visualize.listing.table.listTitle', { - defaultMessage: 'Visualizations', - })} - toastNotifications={toastNotifications} - uiSettings={core.uiSettings} - /> - ); - } - - getTableColumns() { - const tableColumns = [ - { - field: 'title', - name: i18n.translate('visualize.listing.table.titleColumnName', { - defaultMessage: 'Title', - }), - sortable: true, - render: (field, record) => this.props.getViewElement(field, record), - }, - { - field: 'typeTitle', - name: i18n.translate('visualize.listing.table.typeColumnName', { - defaultMessage: 'Type', - }), - sortable: true, - render: (field, record) => ( - - {this.renderItemTypeIcon(record)} - {record.typeTitle} - {this.getBadge(record)} - - ), - }, - { - field: 'description', - name: i18n.translate('visualize.listing.table.descriptionColumnName', { - defaultMessage: 'Description', - }), - sortable: true, - render: (field, record) => {record.description}, - }, - ]; - - return tableColumns; - } - - getNoItemsMessage() { - if (this.props.hideWriteControls) { - return ( -
- - - - } - /> -
- ); - } - - return ( -
- - - - } - body={ - -

- -

-
- } - actions={ - - - - } - /> -
- ); - } - - renderItemTypeIcon(item) { - let icon; - if (item.image) { - icon = ( - - ); - } else { - icon = ( -