From 31cc2015b73e1035acf409373890ffef7d475b60 Mon Sep 17 00:00:00 2001 From: David Roberts Date: Tue, 25 Feb 2020 12:18:35 +0000 Subject: [PATCH 01/11] [ML] Use event.timezone instead of beat.timezone in file upload (#58447) This is because beat.timezone was renamed to event.timezone in elastic/beats#9458 The corresponding file structure finder change is elastic/elasticsearch#52720 --- .../components/import_view/importer/importer.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.js index 710fa49e64167..27899a58beed2 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.js +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.js @@ -148,17 +148,17 @@ function populateFailures(error, failures, chunkCount) { } } -// The file structure endpoint sets the timezone to be {{ beat.timezone }} +// The file structure endpoint sets the timezone to be {{ event.timezone }} // as that's the variable Filebeat would send the client timezone in. // In this data import function the UI is effectively performing the role of Filebeat, // i.e. doing basic parsing, processing and conversion to JSON before forwarding to the ingest pipeline. // But it's not sending every single field that Filebeat would add, so the ingest pipeline -// cannot look for a beat.timezone variable in each input record. -// Therefore we need to replace {{ beat.timezone }} with the actual browser timezone +// cannot look for a event.timezone variable in each input record. +// Therefore we need to replace {{ event.timezone }} with the actual browser timezone function updatePipelineTimezone(ingestPipeline) { if (ingestPipeline !== undefined && ingestPipeline.processors && ingestPipeline.processors) { const dateProcessor = ingestPipeline.processors.find( - p => p.date !== undefined && p.date.timezone === '{{ beat.timezone }}' + p => p.date !== undefined && p.date.timezone === '{{ event.timezone }}' ); if (dateProcessor) { From 6fc6cb8b363b4a1ea7e07ce8d491874ca4fbb864 Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Tue, 25 Feb 2020 13:22:29 +0100 Subject: [PATCH 02/11] [ML] Functional tests - adjust classification model memory (#58445) This PR increases the model memory setting in the classification creation test. --- .../data_frame_analytics/classification_creation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts index 798a04cae3740..1bcdeef394c00 100644 --- a/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts +++ b/x-pack/test/functional/apps/machine_learning/data_frame_analytics/classification_creation.ts @@ -36,7 +36,7 @@ export default function({ getService }: FtrProviderContext) { }, dependentVariable: 'y', trainingPercent: '20', - modelMemory: '105mb', + modelMemory: '200mb', createIndexPattern: true, expected: { row: { From db276d18945246421068e480c7dd5322487cb276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez?= Date: Tue, 25 Feb 2020 13:39:13 +0100 Subject: [PATCH 03/11] =?UTF-8?q?[Logs=20/=20Metrics=20UI]=20Remove=20path?= =?UTF-8?q?=20prefix=20from=20ViewSourceConfigur=E2=80=A6=20(#58238)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the NP the routes have already the app name on them. Adding it to this button made the app name double /app/metrics/metrics/settings /app/logs/logs/settings The button only needs to go to the settings page within the app where it's being loaded, so we can safely drop the prefix. Closes #58233 --- .../public/components/source_configuration/index.ts | 5 +---- .../view_source_configuration_button.tsx | 9 +-------- .../public/pages/infrastructure/snapshot/index.tsx | 10 ++-------- .../pages/logs/stream/page_no_indices_content.tsx | 10 ++-------- .../public/pages/metrics/components/invalid_node.tsx | 10 ++-------- 5 files changed, 8 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/infra/public/components/source_configuration/index.ts b/x-pack/plugins/infra/public/components/source_configuration/index.ts index 4879a53ca329d..98825567cc204 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/index.ts +++ b/x-pack/plugins/infra/public/components/source_configuration/index.ts @@ -5,7 +5,4 @@ */ export { SourceConfigurationSettings } from './source_configuration_settings'; -export { - ViewSourceConfigurationButton, - ViewSourceConfigurationButtonHrefBase, -} from './view_source_configuration_button'; +export { ViewSourceConfigurationButton } from './view_source_configuration_button'; diff --git a/x-pack/plugins/infra/public/components/source_configuration/view_source_configuration_button.tsx b/x-pack/plugins/infra/public/components/source_configuration/view_source_configuration_button.tsx index 9b584b2ef3bd0..9c3a40fb7ecf0 100644 --- a/x-pack/plugins/infra/public/components/source_configuration/view_source_configuration_button.tsx +++ b/x-pack/plugins/infra/public/components/source_configuration/view_source_configuration_button.tsx @@ -8,23 +8,16 @@ import { EuiButton } from '@elastic/eui'; import React from 'react'; import { Route } from 'react-router-dom'; -export enum ViewSourceConfigurationButtonHrefBase { - infrastructure = 'infrastructure', - logs = 'logs', -} - interface ViewSourceConfigurationButtonProps { 'data-test-subj'?: string; - hrefBase: ViewSourceConfigurationButtonHrefBase; children: React.ReactNode; } export const ViewSourceConfigurationButton = ({ 'data-test-subj': dataTestSubj, - hrefBase, children, }: ViewSourceConfigurationButtonProps) => { - const href = `/${hrefBase}/settings`; + const href = '/settings'; return ( { {uiCapabilities?.infrastructure?.configureSource ? ( - + {i18n.translate('xpack.infra.configureSourceActionLabel', { defaultMessage: 'Change source configuration', })} diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_no_indices_content.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_no_indices_content.tsx index 1294007240027..739bad5689a96 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_no_indices_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_no_indices_content.tsx @@ -10,10 +10,7 @@ import { identity } from 'fp-ts/lib/function'; import React from 'react'; import { NoIndices } from '../../../components/empty_states/no_indices'; -import { - ViewSourceConfigurationButton, - ViewSourceConfigurationButtonHrefBase, -} from '../../../components/source_configuration'; +import { ViewSourceConfigurationButton } from '../../../components/source_configuration'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; export const LogsPageNoIndicesContent = () => { @@ -49,10 +46,7 @@ export const LogsPageNoIndicesContent = () => { {canConfigureSource ? ( - + {i18n.translate('xpack.infra.configureSourceActionLabel', { defaultMessage: 'Change source configuration', })} diff --git a/x-pack/plugins/infra/public/pages/metrics/components/invalid_node.tsx b/x-pack/plugins/infra/public/pages/metrics/components/invalid_node.tsx index fde3b61de50b5..43f684cd5a585 100644 --- a/x-pack/plugins/infra/public/pages/metrics/components/invalid_node.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/components/invalid_node.tsx @@ -10,10 +10,7 @@ import { identity } from 'fp-ts/lib/function'; import React from 'react'; import { euiStyled } from '../../../../../observability/public'; -import { - ViewSourceConfigurationButton, - ViewSourceConfigurationButtonHrefBase, -} from '../../../components/source_configuration'; +import { ViewSourceConfigurationButton } from '../../../components/source_configuration'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; interface InvalidNodeErrorProps { @@ -59,10 +56,7 @@ export const InvalidNodeError: React.FunctionComponent = - + Date: Tue, 25 Feb 2020 07:18:04 -0600 Subject: [PATCH 04/11] [Uptime] Improve refresh handling when generating test data (#58285) When generating test data we refresh excessively, this can fill up the ES queues and break the tests if we run massive tests. I originally ran into this with https://github.com/elastic/kibana/pull/58078/ which I closed due to finding a better approach. While none of our current tests have the scale to expose this problem, we certainly will add tests that do later, so we should keep this change. Co-authored-by: Elastic Machine --- .../uptime/graphql/helpers/make_checks.ts | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/x-pack/test/api_integration/apis/uptime/graphql/helpers/make_checks.ts b/x-pack/test/api_integration/apis/uptime/graphql/helpers/make_checks.ts index f89905f0da04f..4d3167b14b86f 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/helpers/make_checks.ts +++ b/x-pack/test/api_integration/apis/uptime/graphql/helpers/make_checks.ts @@ -13,7 +13,8 @@ export const makePing = async ( es: any, monitorId: string, fields: { [key: string]: any }, - mogrify: (doc: any) => any + mogrify: (doc: any) => any, + refresh: boolean = true ) => { const baseDoc = { tcp: { @@ -103,7 +104,7 @@ export const makePing = async ( await es.index({ index: INDEX_NAME, - refresh: true, + refresh, body: doc, }); @@ -115,7 +116,8 @@ export const makeCheck = async ( monitorId: string, numIps: number, fields: { [key: string]: any }, - mogrify: (doc: any) => any + mogrify: (doc: any) => any, + refresh: boolean = true ) => { const cgFields = { monitor: { @@ -137,11 +139,16 @@ export const makeCheck = async ( if (i === numIps - 1) { pingFields.summary = summary; } - const doc = await makePing(es, monitorId, pingFields, mogrify); + const doc = await makePing(es, monitorId, pingFields, mogrify, false); docs.push(doc); // @ts-ignore summary[doc.monitor.status]++; } + + if (refresh) { + es.indices.refresh(); + } + return docs; }; @@ -152,7 +159,8 @@ export const makeChecks = async ( numIps: number, every: number, // number of millis between checks fields: { [key: string]: any } = {}, - mogrify: (doc: any) => any = d => d + mogrify: (doc: any) => any = d => d, + refresh: boolean = true ) => { const checks = []; const oldestTime = new Date().getTime() - numChecks * every; @@ -169,7 +177,11 @@ export const makeChecks = async ( }, }, }); - checks.push(await makeCheck(es, monitorId, numIps, fields, mogrify)); + checks.push(await makeCheck(es, monitorId, numIps, fields, mogrify, false)); + } + + if (refresh) { + es.indices.refresh(); } return checks; @@ -183,19 +195,29 @@ export const makeChecksWithStatus = async ( every: number, fields: { [key: string]: any } = {}, status: 'up' | 'down', - mogrify: (doc: any) => any = d => d + mogrify: (doc: any) => any = d => d, + refresh: boolean = true ) => { const oppositeStatus = status === 'up' ? 'down' : 'up'; - return await makeChecks(es, monitorId, numChecks, numIps, every, fields, d => { - d.monitor.status = status; - if (d.summary) { - d.summary[status] += d.summary[oppositeStatus]; - d.summary[oppositeStatus] = 0; - } - - return mogrify(d); - }); + return await makeChecks( + es, + monitorId, + numChecks, + numIps, + every, + fields, + d => { + d.monitor.status = status; + if (d.summary) { + d.summary[status] += d.summary[oppositeStatus]; + d.summary[oppositeStatus] = 0; + } + + return mogrify(d); + }, + refresh + ); }; // Helper for processing a list of checks to find the time picker bounds. From b756cc3915fe62d405f006fd32bf8678f4c5e402 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 25 Feb 2020 13:39:50 +0000 Subject: [PATCH 05/11] [ML] Adding filebeat config to file dataviz (#58152) * [ML] Adding filebeat config to file dataviz * adding extra help text * removing commented out code * adding extra blank line to processors section * cleaning up types * moving hosts line out of function * typo in config text * updating config based on review * tiny refactor * translating paths text --- .../ml/common/types/file_datavisualizer.ts | 31 +++ .../plugins/ml/public/application/app.tsx | 4 + .../contexts/kibana/kibana_context.ts | 2 + .../filebeat_config_flyout/filebeat_config.ts | 71 +++++++ .../filebeat_config_flyout.tsx | 162 +++++++++++++++ .../filebeat_config_flyout/index.ts | 7 + .../components/import_view/import_view.js | 24 +++ .../import_view/importer/message_importer.js | 5 + .../results_links/{index.js => index.ts} | 0 .../components/results_links/results_links.js | 182 ----------------- .../results_links/results_links.tsx | 190 ++++++++++++++++++ .../application/util/dependency_cache.ts | 10 + x-pack/legacy/plugins/ml/public/legacy.ts | 4 +- x-pack/legacy/plugins/ml/public/plugin.ts | 3 +- .../file_data_visualizer.ts | 27 +-- 15 files changed, 513 insertions(+), 209 deletions(-) create mode 100644 x-pack/legacy/plugins/ml/common/types/file_datavisualizer.ts create mode 100644 x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config.ts create mode 100644 x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config_flyout.tsx create mode 100644 x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/index.ts rename x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/{index.js => index.ts} (100%) delete mode 100644 x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.js create mode 100644 x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx diff --git a/x-pack/legacy/plugins/ml/common/types/file_datavisualizer.ts b/x-pack/legacy/plugins/ml/common/types/file_datavisualizer.ts new file mode 100644 index 0000000000000..bc03f82673a1f --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/types/file_datavisualizer.ts @@ -0,0 +1,31 @@ +/* + * 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 interface FindFileStructureResponse { + charset: string; + has_header_row: boolean; + has_byte_order_marker: boolean; + format: string; + field_stats: { + [fieldName: string]: { + count: number; + cardinality: number; + top_hits: Array<{ count: number; value: any }>; + }; + }; + sample_start: string; + num_messages_analyzed: number; + mappings: { + [fieldName: string]: { + type: string; + }; + }; + quote: string; + delimiter: string; + need_client_timezone: boolean; + num_lines_analyzed: number; + column_names: string[]; +} diff --git a/x-pack/legacy/plugins/ml/public/application/app.tsx b/x-pack/legacy/plugins/ml/public/application/app.tsx index 24cbfbfb346dd..add27193deb77 100644 --- a/x-pack/legacy/plugins/ml/public/application/app.tsx +++ b/x-pack/legacy/plugins/ml/public/application/app.tsx @@ -12,6 +12,7 @@ import 'ace'; import { AppMountParameters, CoreStart } from 'kibana/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { SecurityPluginSetup } from '../../../../../plugins/security/public'; import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; import { setDependencyCache, clearCache } from './util/dependency_cache'; @@ -20,6 +21,7 @@ import { MlRouter } from './routing'; export interface MlDependencies extends AppMountParameters { data: DataPublicPluginStart; + security: SecurityPluginSetup; __LEGACY: { XSRF: string; APP_URL: string; @@ -49,6 +51,7 @@ const App: FC = ({ coreStart, deps }) => { APP_URL: deps.__LEGACY.APP_URL, application: coreStart.application, http: coreStart.http, + security: deps.security, }); deps.onAppLeave(actions => { clearCache(); @@ -64,6 +67,7 @@ const App: FC = ({ coreStart, deps }) => { const services = { appName: 'ML', data: deps.data, + security: deps.security, ...coreStart, }; diff --git a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts index aaf539322809b..5fcd7c5473d3b 100644 --- a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -10,9 +10,11 @@ import { useKibana, KibanaReactContextValue, } from '../../../../../../../../src/plugins/kibana_react/public'; +import { SecurityPluginSetup } from '../../../../../../../plugins/security/public'; interface StartPlugins { data: DataPublicPluginStart; + security: SecurityPluginSetup; } export type StartServices = CoreStart & StartPlugins; // eslint-disable-next-line react-hooks/rules-of-hooks diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config.ts b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config.ts new file mode 100644 index 0000000000000..3344cdf991e6b --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config.ts @@ -0,0 +1,71 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { FindFileStructureResponse } from '../../../../../../common/types/file_datavisualizer'; + +export function createFilebeatConfig( + index: string, + results: FindFileStructureResponse, + ingestPipelineId: string, + username: string | null +) { + return [ + 'filebeat.inputs:', + '- type: log', + ...getPaths(), + ...getEncoding(results), + ...getExcludeLines(results), + ...getMultiline(results), + '', + ...getProcessors(results), + 'output.elasticsearch:', + ' hosts: [""]', + ...getUserDetails(username), + ` index: "${index}"`, + ` pipeline: "${ingestPipelineId}"`, + '', + 'setup:', + ' template.enabled: false', + ' ilm.enabled: false', + ].join('\n'); +} + +function getPaths() { + const txt = i18n.translate('xpack.ml.fileDatavisualizer.fileBeatConfig.paths', { + defaultMessage: 'add path to your files here', + }); + return [' paths:', ` - '<${txt}>'`]; +} + +function getEncoding(results: any) { + return results.charset !== 'UTF-8' ? [` encoding: ${results.charset}`] : []; +} + +function getExcludeLines(results: any) { + return results.exclude_lines_pattern !== undefined + ? [` exclude_lines: ['${results.exclude_lines_pattern.replace(/'/g, "''")}']`] + : []; +} + +function getMultiline(results: any) { + return results.multiline_start_pattern !== undefined + ? [ + ' multiline:', + ` pattern: '${results.multiline_start_pattern.replace(/'/g, "''")}'`, + ' match: after', + ' negate: true', + ] + : []; +} + +function getProcessors(results: any) { + return results.need_client_timezone === true ? ['processors:', '- add_locale: ~', ''] : []; +} + +function getUserDetails(username: string | null) { + return username !== null ? [` username: "${username}"`, ' password: ""'] : []; +} diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config_flyout.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config_flyout.tsx new file mode 100644 index 0000000000000..30fc74acbabf4 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/filebeat_config_flyout.tsx @@ -0,0 +1,162 @@ +/* + * 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. + */ +/* + * 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, { FC, useState, useEffect } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiFlyout, + EuiFlyoutFooter, + EuiFlexGroup, + EuiFlexItem, + EuiButton, + EuiButtonEmpty, + EuiTitle, + EuiFlyoutBody, + EuiSpacer, + EuiCodeBlock, + EuiCode, + EuiCopy, +} from '@elastic/eui'; +import { createFilebeatConfig } from './filebeat_config'; +import { useMlKibana } from '../../../../contexts/kibana'; +import { FindFileStructureResponse } from '../../../../../../common/types/file_datavisualizer'; + +export enum EDITOR_MODE { + HIDDEN, + READONLY, + EDITABLE, +} +interface Props { + index: string; + results: FindFileStructureResponse; + indexPatternId: string; + ingestPipelineId: string; + closeFlyout(): void; +} +export const FilebeatConfigFlyout: FC = ({ + index, + results, + indexPatternId, + ingestPipelineId, + closeFlyout, +}) => { + const [fileBeatConfig, setFileBeatConfig] = useState(''); + const [username, setUsername] = useState(null); + const { + services: { security }, + } = useMlKibana(); + + useEffect(() => { + security.authc.getCurrentUser().then(user => { + setUsername(user.username === undefined ? null : user.username); + }); + }, []); + + useEffect(() => { + const config = createFilebeatConfig(index, results, ingestPipelineId, username); + setFileBeatConfig(config); + }, [username]); + + return ( + + + + + + + + + + + + + + + + {copy => ( + + + + )} + + + + + + ); +}; + +const Contents: FC<{ + value: string; + index: string; + username: string | null; +}> = ({ value, index, username }) => { + return ( + + +
+ +
+
+ +

+ {index} }} + /> +

+

+ filebeat.yml }} + /> +

+ + + + {value} + + +

+ {username === null ? ( + {''}, + }} + /> + ) : ( + {username}, + password: {''}, + esUrl: {''}, + }} + /> + )} +

+
+ ); +}; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/index.ts b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/index.ts new file mode 100644 index 0000000000000..9286b92c2ab97 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/filebeat_config_flyout/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 { FilebeatConfigFlyout } from './filebeat_config_flyout'; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js index beb5918e277ae..bdfc27099a185 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js @@ -20,6 +20,7 @@ import { import { i18n } from '@kbn/i18n'; import { importerFactory } from './importer'; import { ResultsLinks } from '../results_links'; +import { FilebeatConfigFlyout } from '../filebeat_config_flyout'; import { ImportProgress, IMPORT_STATUS } from '../import_progress'; import { ImportErrors } from '../import_errors'; import { ImportSummary } from '../import_summary'; @@ -64,6 +65,7 @@ const DEFAULT_STATE = { indexNameError: '', indexPatternNameError: '', timeFieldName: undefined, + isFilebeatFlyoutVisible: false, }; export class ImportView extends Component { @@ -384,6 +386,16 @@ export class ImportView extends Component { }); }; + showFilebeatFlyout = () => { + this.setState({ isFilebeatFlyoutVisible: true }); + this.props.hideBottomBar(); + }; + + closeFilebeatFlyout = () => { + this.setState({ isFilebeatFlyoutVisible: false }); + this.props.showBottomBar(); + }; + async loadIndexNames() { const indices = await ml.getIndices(); const indexNames = indices.map(i => i.name); @@ -424,6 +436,7 @@ export class ImportView extends Component { indexNameError, indexPatternNameError, timeFieldName, + isFilebeatFlyoutVisible, } = this.state; const createPipeline = pipelineString !== ''; @@ -549,7 +562,18 @@ export class ImportView extends Component { indexPatternId={indexPatternId} timeFieldName={timeFieldName} createIndexPattern={createIndexPattern} + showFilebeatFlyout={this.showFilebeatFlyout} /> + + {isFilebeatFlyoutVisible && ( + + )} )} diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.js index 840248817945a..c2d3ac69f0963 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.js +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.js @@ -77,6 +77,11 @@ export class MessageImporter extends Importer { if (this.multilineStartRegex === null || line.match(this.multilineStartRegex) !== null) { this.addMessage(data, message); message = ''; + } else if (data.length === 0) { + // discard everything before the first line that is considered the first line of a message + // as it could be left over partial data from a spilt or rolled over log, + // or could be a blank line after the header in a csv file + return ''; } else { message += '\n'; } diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/index.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/index.ts similarity index 100% rename from x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/index.js rename to x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/index.ts diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.js deleted file mode 100644 index aaebca2f58963..0000000000000 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.js +++ /dev/null @@ -1,182 +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 { FormattedMessage } from '@kbn/i18n/react'; -import React, { Component } from 'react'; - -import { EuiFlexGroup, EuiFlexItem, EuiCard, EuiIcon } from '@elastic/eui'; - -import moment from 'moment'; - -import { ml } from '../../../../services/ml_api_service'; -import { isFullLicense } from '../../../../license/check_license'; -import { checkPermission } from '../../../../privilege/check_privilege'; -import { mlNodesAvailable } from '../../../../ml_nodes_check/check_ml_nodes'; -import { withKibana } from '../../../../../../../../../../src/plugins/kibana_react/public'; - -const RECHECK_DELAY_MS = 3000; - -class ResultsLinksUI extends Component { - constructor(props) { - super(props); - - this.state = { - from: 'now-30m', - to: 'now', - }; - - this.recheckTimeout = null; - this.showCreateJobLink = true; - } - - componentDidMount() { - this.showCreateJobLink = checkPermission('canCreateJob') && mlNodesAvailable(); - // if this data has a time field, - // find the start and end times - if (this.props.timeFieldName !== undefined) { - this.updateTimeValues(); - } - } - - componentWillUnmount() { - clearTimeout(this.recheckTimeout); - } - - async updateTimeValues(recheck = true) { - const { index, timeFieldName } = this.props; - - const { from, to } = await getFullTimeRange(index, timeFieldName); - this.setState({ - from: from === null ? this.state.from : from, - to: to === null ? this.state.to : to, - }); - - // these links may have been drawn too quickly for the index to be ready - // to give us the correct start and end times. - // especially if the data was small. - // so if the start and end were null, try again in 3s - // the timeout is cleared when this component unmounts. just in case the user - // resets the form or navigates away within 3s - if (recheck && (from === null || to === null)) { - this.recheckTimeout = setTimeout(() => { - this.updateTimeValues(false); - }, RECHECK_DELAY_MS); - } - } - - render() { - const { index, indexPatternId, timeFieldName, createIndexPattern } = this.props; - - const { from, to } = this.state; - - const _g = - this.props.timeFieldName !== undefined - ? `&_g=(time:(from:'${from}',mode:quick,to:'${to}'))` - : ''; - - const { basePath } = this.props.kibana.services.http; - return ( - - {createIndexPattern && ( - - } - title={ - - } - description="" - href={`${basePath.get()}/app/kibana#/discover?&_a=(index:'${indexPatternId}')${_g}`} - /> - - )} - - {isFullLicense() === true && - timeFieldName !== undefined && - this.showCreateJobLink && - createIndexPattern && ( - - } - title={ - - } - description="" - href={`#/jobs/new_job/step/job_type?index=${indexPatternId}${_g}`} - /> - - )} - - {createIndexPattern && ( - - } - title={ - - } - description="" - href={`#/jobs/new_job/datavisualizer?index=${indexPatternId}${_g}`} - /> - - )} - - - } - title={ - - } - description="" - href={`${basePath.get()}/app/kibana#/management/elasticsearch/index_management/indices/filter/${index}`} - /> - - - - } - title={ - - } - description="" - href={`${basePath.get()}/app/kibana#/management/kibana/index_patterns/${ - createIndexPattern ? indexPatternId : '' - }`} - /> - - - ); - } -} - -export const ResultsLinks = withKibana(ResultsLinksUI); - -async function getFullTimeRange(index, timeFieldName) { - const query = { bool: { must: [{ query_string: { analyze_wildcard: true, query: '*' } }] } }; - const resp = await ml.getTimeFieldRange({ - index, - timeFieldName, - query, - }); - - return { - from: moment(resp.start.epoch).toISOString(), - to: moment(resp.end.epoch).toISOString(), - }; -} diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx new file mode 100644 index 0000000000000..debadba19051b --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx @@ -0,0 +1,190 @@ +/* + * 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, { FC, useState, useEffect } from 'react'; +import moment from 'moment'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFlexGroup, EuiFlexItem, EuiCard, EuiIcon } from '@elastic/eui'; +import { ml } from '../../../../services/ml_api_service'; +import { isFullLicense } from '../../../../license/check_license'; +import { checkPermission } from '../../../../privilege/check_privilege'; +import { mlNodesAvailable } from '../../../../ml_nodes_check/check_ml_nodes'; +import { useMlKibana } from '../../../../contexts/kibana'; + +const RECHECK_DELAY_MS = 3000; + +interface Props { + index: string; + indexPatternId: string; + timeFieldName?: string; + createIndexPattern: boolean; + showFilebeatFlyout(): void; +} + +export const ResultsLinks: FC = ({ + index, + indexPatternId, + timeFieldName, + createIndexPattern, + showFilebeatFlyout, +}) => { + const [duration, setDuration] = useState({ + from: 'now-30m', + to: 'now', + }); + const [showCreateJobLink, setShowCreateJobLink] = useState(false); + const [globalStateString, setGlobalStateString] = useState(''); + const { + services: { + http: { basePath }, + }, + } = useMlKibana(); + + useEffect(() => { + setShowCreateJobLink(checkPermission('canCreateJob') && mlNodesAvailable()); + updateTimeValues(); + }, []); + + useEffect(() => { + const _g = + timeFieldName !== undefined + ? `&_g=(time:(from:'${duration.from}',mode:quick,to:'${duration.to}'))` + : ''; + setGlobalStateString(_g); + }, [duration]); + + async function updateTimeValues(recheck = true) { + if (timeFieldName !== undefined) { + const { from, to } = await getFullTimeRange(index, timeFieldName); + setDuration({ + from: from === null ? duration.from : from, + to: to === null ? duration.to : to, + }); + + // these links may have been drawn too quickly for the index to be ready + // to give us the correct start and end times. + // especially if the data was small. + // so if the start and end were null, try again in 3s + if (recheck && (from === null || to === null)) { + setTimeout(() => { + updateTimeValues(false); + }, RECHECK_DELAY_MS); + } + } + } + + return ( + + {createIndexPattern && ( + + } + title={ + + } + description="" + href={`${basePath.get()}/app/kibana#/discover?&_a=(index:'${indexPatternId}')${globalStateString}`} + /> + + )} + + {isFullLicense() === true && + timeFieldName !== undefined && + showCreateJobLink && + createIndexPattern && ( + + } + title={ + + } + description="" + href={`#/jobs/new_job/step/job_type?index=${indexPatternId}${globalStateString}`} + /> + + )} + + {createIndexPattern && ( + + } + title={ + + } + description="" + href={`#/jobs/new_job/datavisualizer?index=${indexPatternId}${globalStateString}`} + /> + + )} + + + } + title={ + + } + description="" + href={`${basePath.get()}/app/kibana#/management/elasticsearch/index_management/indices/filter/${index}`} + /> + + + + } + title={ + + } + description="" + href={`${basePath.get()}/app/kibana#/management/kibana/index_patterns/${ + createIndexPattern ? indexPatternId : '' + }`} + /> + + + } + title={ + + } + description="" + onClick={showFilebeatFlyout} + /> + + + ); +}; + +async function getFullTimeRange(index: string, timeFieldName: string) { + const query = { bool: { must: [{ query_string: { analyze_wildcard: true, query: '*' } }] } }; + const resp = await ml.getTimeFieldRange({ + index, + timeFieldName, + query, + }); + + return { + from: moment(resp.start.epoch).toISOString(), + to: moment(resp.end.epoch).toISOString(), + }; +} diff --git a/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts index 8857485a58644..f837d90dba8fe 100644 --- a/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/legacy/plugins/ml/public/application/util/dependency_cache.ts @@ -20,6 +20,7 @@ import { ChromeRecentlyAccessed, IBasePath, } from 'kibana/public'; +import { SecurityPluginSetup } from '../../../../../../plugins/security/public'; export interface DependencyCache { timefilter: TimefilterSetup | null; @@ -38,6 +39,7 @@ export interface DependencyCache { APP_URL: string | null; application: ApplicationStart | null; http: HttpStart | null; + security: SecurityPluginSetup | null; } const cache: DependencyCache = { @@ -57,6 +59,7 @@ const cache: DependencyCache = { APP_URL: null, application: null, http: null, + security: null, }; export function setDependencyCache(deps: Partial) { @@ -189,6 +192,13 @@ export function getHttp() { return cache.http; } +export function getSecurity() { + if (cache.security === null) { + throw new Error("security hasn't been initialized"); + } + return cache.security; +} + export function clearCache() { console.log('clearing dependency cache'); // eslint-disable-line no-console Object.keys(cache).forEach(k => { diff --git a/x-pack/legacy/plugins/ml/public/legacy.ts b/x-pack/legacy/plugins/ml/public/legacy.ts index bf431f0986d68..40a1afa06b5a6 100644 --- a/x-pack/legacy/plugins/ml/public/legacy.ts +++ b/x-pack/legacy/plugins/ml/public/legacy.ts @@ -6,14 +6,16 @@ import chrome from 'ui/chrome'; import { npSetup, npStart } from 'ui/new_platform'; - import { PluginInitializerContext } from 'src/core/public'; +import { SecurityPluginSetup } from '../../../../plugins/security/public'; + import { plugin } from '.'; const pluginInstance = plugin({} as PluginInitializerContext); export const setup = pluginInstance.setup(npSetup.core, { data: npStart.plugins.data, + security: ((npSetup.plugins as unknown) as { security: SecurityPluginSetup }).security, // security isn't in the PluginsSetup interface, but does exist __LEGACY: { XSRF: chrome.getXsrfToken(), // @ts-ignore getAppUrl is missing from chrome's definition diff --git a/x-pack/legacy/plugins/ml/public/plugin.ts b/x-pack/legacy/plugins/ml/public/plugin.ts index 79af300bce4ec..cb39b31a32b14 100644 --- a/x-pack/legacy/plugins/ml/public/plugin.ts +++ b/x-pack/legacy/plugins/ml/public/plugin.ts @@ -8,7 +8,7 @@ import { Plugin, CoreStart, CoreSetup } from 'src/core/public'; import { MlDependencies } from './application/app'; export class MlPlugin implements Plugin { - setup(core: CoreSetup, { data, __LEGACY }: MlDependencies) { + setup(core: CoreSetup, { data, security, __LEGACY }: MlDependencies) { core.application.register({ id: 'ml', title: 'Machine learning', @@ -21,6 +21,7 @@ export class MlPlugin implements Plugin { onAppLeave: params.onAppLeave, data, __LEGACY, + security, }); }, }); diff --git a/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts b/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts index fd5b5221393fc..9f30f609c60b6 100644 --- a/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts +++ b/x-pack/legacy/plugins/ml/server/models/file_data_visualizer/file_data_visualizer.ts @@ -6,6 +6,7 @@ import Boom from 'boom'; import { RequestHandlerContext } from 'kibana/server'; +import { FindFileStructureResponse } from '../../../common/types/file_datavisualizer'; export type InputData = any[]; @@ -20,31 +21,7 @@ export type FormattedOverrides = InputOverrides & { }; export interface AnalysisResult { - results: { - charset: string; - has_header_row: boolean; - has_byte_order_marker: boolean; - format: string; - field_stats: { - [fieldName: string]: { - count: number; - cardinality: number; - top_hits: Array<{ count: number; value: any }>; - }; - }; - sample_start: string; - num_messages_analyzed: number; - mappings: { - [fieldName: string]: { - type: string; - }; - }; - quote: string; - delimiter: string; - need_client_timezone: boolean; - num_lines_analyzed: number; - column_names: string[]; - }; + results: FindFileStructureResponse; overrides?: FormattedOverrides; } From afb5d8fa5847cdb7e4f7d6d8742a73486815007f Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Tue, 25 Feb 2020 07:43:46 -0600 Subject: [PATCH 06/11] Fix service map popover transaction duration (#58422) It's already microseconds, so not converting it fixes it. Checked services to see if all metrics match now and they do! Fixes #55679 --- .../app/ServiceMap/Popover/ServiceMetricList.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx index 50ce918ea7037..3a6b4c5ebcaac 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx @@ -16,12 +16,7 @@ import { isNumber } from 'lodash'; import React from 'react'; import styled from 'styled-components'; import { ServiceNodeMetrics } from '../../../../../../../../plugins/apm/common/service_map'; -import { - asDuration, - asPercent, - toMicroseconds, - tpmUnit -} from '../../../../utils/formatters'; +import { asDuration, asPercent, tpmUnit } from '../../../../utils/formatters'; function LoadingSpinner() { return ( @@ -70,7 +65,7 @@ export function ServiceMetricList({ } ), description: isNumber(avgTransactionDuration) - ? asDuration(toMicroseconds(avgTransactionDuration, 'milliseconds')) + ? asDuration(avgTransactionDuration) : null }, { From db05fb6738cd906bf231a28d58d5c17d6efe201c Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Tue, 25 Feb 2020 15:00:28 +0100 Subject: [PATCH 07/11] Don't mutate error message (#58452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 🐛 don't mutate error object in-place This avoids mutating error thrown by an expression function in-place. The error might not even be an object, in which case mutating it will throw. * test: 💍 capture in test that thrown error is not mutated Co-authored-by: Elastic Machine --- src/plugins/expressions/common/execution/execution.test.ts | 1 + src/plugins/expressions/common/execution/execution.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/expressions/common/execution/execution.test.ts b/src/plugins/expressions/common/execution/execution.test.ts index f6ff9efca848b..4776204a8ab2f 100644 --- a/src/plugins/expressions/common/execution/execution.test.ts +++ b/src/plugins/expressions/common/execution/execution.test.ts @@ -630,6 +630,7 @@ describe('Execution', () => { }, }); expect(node2.debug?.rawError).toBeInstanceOf(Error); + expect(node2.debug?.rawError).toEqual(new Error('foo')); }); test('sets .debug object to expected shape', async () => { diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index 7e7df822724ae..272448870e817 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -230,8 +230,8 @@ export class Execution< input = output; } catch (rawError) { const timeEnd: number = this.params.debug ? performance.now() : 0; - rawError.message = `[${fnName}] > ${rawError.message}`; const error = createError(rawError) as ExpressionValueError; + error.error.message = `[${fnName}] > ${error.error.message}`; if (this.params.debug) { (link as ExpressionAstFunction).debug = { From 418c44a47ed7c5b6807e31aa4be24f4dbc9d6b5b Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Tue, 25 Feb 2020 15:00:50 +0100 Subject: [PATCH 08/11] [SIEM] Fix unnecessary re-renders on the Overview page (#56587) --- .../__snapshots__/barchart.test.tsx.snap | 2 - .../components/charts/areachart.test.tsx | 4 +- .../public/components/charts/areachart.tsx | 4 - .../components/charts/barchart.test.tsx | 11 +- .../siem/public/components/charts/common.tsx | 11 +- .../drag_and_drop/draggable_wrapper.tsx | 4 +- .../events_viewer/events_viewer.tsx | 10 +- .../public/components/events_viewer/index.tsx | 18 +- .../siem/public/components/flyout/index.tsx | 55 +++--- .../siem/public/components/inspect/index.tsx | 8 +- .../public/components/navigation/index.tsx | 7 +- .../hosts/authentications_table/index.tsx | 6 +- .../page/hosts/hosts_table/index.tsx | 1 + .../components/page/hosts/kpi_hosts/index.tsx | 1 + .../hosts/uncommon_process_table/index.tsx | 6 +- .../page/network/kpi_network/index.tsx | 1 + .../network/network_dns_table/columns.tsx | 3 +- .../page/network/network_dns_table/index.tsx | 10 +- .../page/network/network_http_table/index.tsx | 6 +- .../network_top_countries_table/index.tsx | 5 +- .../network_top_n_flow_table/index.tsx | 5 +- .../page/network/tls_table/index.tsx | 10 +- .../page/network/users_table/index.tsx | 13 +- .../overview/overview_host_stats/index.tsx | 2 - .../overview/overview_network_stats/index.tsx | 6 +- .../public/components/query_bar/index.tsx | 6 +- .../public/components/search_bar/index.tsx | 6 +- .../source_destination_ip.tsx | 5 +- .../__snapshots__/index.test.tsx.snap | 3 - .../__snapshots__/timeline.test.tsx.snap | 2 +- .../components/timeline/header/index.tsx | 8 +- .../siem/public/components/timeline/index.tsx | 12 +- .../components/timeline/query_bar/index.tsx | 5 +- .../timeline/search_or_filter/index.tsx | 21 ++- .../public/components/timeline/timeline.tsx | 4 - .../public/components/url_state/index.tsx | 4 +- .../components/url_state/use_url_state.tsx | 7 +- .../rules/fetch_index_patterns.tsx | 5 +- .../public/containers/global_time/index.tsx | 18 +- .../containers/query_template_paginated.tsx | 4 +- .../siem/public/containers/source/index.tsx | 1 + .../signals_histogram.tsx | 29 +-- .../rules/components/query_bar/index.tsx | 12 +- .../rules/components/rule_status/index.tsx | 4 +- .../components/step_about_rule/index.tsx | 4 +- .../components/step_define_rule/index.tsx | 13 +- .../components/step_schedule_rule/index.tsx | 4 +- .../pages/hosts/details/details_tabs.tsx | 45 ++--- .../siem/public/pages/hosts/hosts_tabs.tsx | 75 ++++---- .../network/navigation/network_routes.tsx | 171 +++++++++--------- x-pack/legacy/plugins/siem/public/routes.tsx | 8 +- .../siem/public/utils/kql/use_update_kql.tsx | 4 +- .../siem/public/utils/route/spy_routes.tsx | 3 +- x-pack/package.json | 1 + x-pack/tsconfig.json | 2 +- yarn.lock | 9 +- 56 files changed, 374 insertions(+), 330 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap index 12b9afb661da1..c330676e9219e 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/charts/__snapshots__/barchart.test.tsx.snap @@ -1,5 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`BarChartBaseComponent render with customized configs should 2 render BarSeries 1`] = `[Function]`; - exports[`BarChartBaseComponent render with default configs if no customized configs given should 2 render BarSeries 1`] = `[Function]`; diff --git a/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx index 27f0222b96b77..3c2de28ae423c 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/areachart.test.tsx @@ -331,7 +331,7 @@ describe('AreaChart', () => { }); it(`should render area chart`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(1); + expect(shallowWrapper.find('AreaChartBase')).toHaveLength(1); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(0); }); }); @@ -344,7 +344,7 @@ describe('AreaChart', () => { }); it(`should render a chart place holder`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(0); + expect(shallowWrapper.find('AreaChartBase')).toHaveLength(0); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(1); }); } diff --git a/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx b/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx index b66cc77e30aad..f3b2b736ed87d 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/areachart.tsx @@ -146,8 +146,4 @@ export const AreaChartComponent: React.FC = ({ areaChar ); }; -AreaChartComponent.displayName = 'AreaChartComponent'; - export const AreaChart = React.memo(AreaChartComponent); - -AreaChart.displayName = 'AreaChart'; diff --git a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx index 0b6635b04d380..272c41833f368 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/barchart.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { BarChartBaseComponent, BarChartComponent } from './barchart'; import { ChartSeriesData } from './common'; -import { BarSeries, ScaleType, Axis } from '@elastic/charts'; +import { Chart, BarSeries, Axis, ScaleType } from '@elastic/charts'; jest.mock('../../lib/kibana'); @@ -139,7 +139,7 @@ describe('BarChartBaseComponent', () => { }); it('should render two bar series', () => { - expect(shallowWrapper.find('Chart')).toHaveLength(1); + expect(shallowWrapper.find(Chart)).toHaveLength(1); }); }); @@ -167,7 +167,6 @@ describe('BarChartBaseComponent', () => { }); it(`should ${mockBarChartData.length} render BarSeries`, () => { - expect(shallow).toMatchSnapshot(); expect(shallowWrapper.find(BarSeries)).toHaveLength(mockBarChartData.length); }); @@ -265,7 +264,7 @@ describe('BarChartBaseComponent', () => { }); it('should not render without height and width', () => { - expect(shallowWrapper.find('Chart')).toHaveLength(0); + expect(shallowWrapper.find(Chart)).toHaveLength(0); }); }); }); @@ -278,7 +277,7 @@ describe.each(chartDataSets)('BarChart with valid data [%o]', data => { }); it(`should render chart`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(1); + expect(shallowWrapper.find('BarChartBase')).toHaveLength(1); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(0); }); }); @@ -291,7 +290,7 @@ describe.each(chartHolderDataSets)('BarChart with invalid data [%o]', data => { }); it(`should render a ChartPlaceHolder`, () => { - expect(shallowWrapper.find('WrappedByAutoSizer')).toHaveLength(0); + expect(shallowWrapper.find('BarChartBase')).toHaveLength(0); expect(shallowWrapper.find('ChartPlaceHolder')).toHaveLength(1); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/charts/common.tsx b/x-pack/legacy/plugins/siem/public/components/charts/common.tsx index 03b412f575646..7377bcbe7050f 100644 --- a/x-pack/legacy/plugins/siem/public/components/charts/common.tsx +++ b/x-pack/legacy/plugins/siem/public/components/charts/common.tsx @@ -16,7 +16,9 @@ import { TickFormatter, Position, } from '@elastic/charts'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; + import { useUiSetting } from '../../lib/kibana'; import { DEFAULT_DARK_MODE } from '../../../common/constants'; @@ -54,7 +56,7 @@ export interface ChartSeriesData { color?: string | undefined; } -export const WrappedByAutoSizer = styled.div<{ height?: string }>` +const WrappedByAutoSizerComponent = styled.div<{ height?: string }>` ${style => ` height: ${style.height != null ? style.height : defaultChartHeight}; @@ -66,7 +68,9 @@ export const WrappedByAutoSizer = styled.div<{ height?: string }>` } `; -WrappedByAutoSizer.displayName = 'WrappedByAutoSizer'; +WrappedByAutoSizerComponent.displayName = 'WrappedByAutoSizer'; + +export const WrappedByAutoSizer = React.memo(WrappedByAutoSizerComponent); export enum SeriesType { BAR = 'bar', @@ -96,8 +100,9 @@ const theme: PartialTheme = { export const useTheme = () => { const isDarkMode = useUiSetting(DEFAULT_DARK_MODE); const defaultTheme = isDarkMode ? DARK_THEME : LIGHT_THEME; + const themeValue = useMemo(() => mergeWithDefaultTheme(theme, defaultTheme), []); - return mergeWithDefaultTheme(theme, defaultTheme); + return themeValue; }; export const chartDefaultSettings = { diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index cf958bfd75d3b..7d84403b87f8d 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { createContext, useContext, useEffect } from 'react'; import { Draggable, @@ -14,6 +13,7 @@ import { } from 'react-beautiful-dnd'; import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { EuiPortal } from '@elastic/eui'; import { dragAndDropActions } from '../../store/drag_and_drop'; @@ -122,7 +122,7 @@ const DraggableWrapperComponent = React.memo( }, (prevProps, nextProps) => { return ( - isEqual(prevProps.dataProvider, nextProps.dataProvider) && + deepEqual(prevProps.dataProvider, nextProps.dataProvider) && prevProps.render !== nextProps.render && prevProps.truncate === nextProps.truncate ); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx index 2a4d08ea214bc..a913186d9ad3b 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/events_viewer.tsx @@ -5,10 +5,10 @@ */ import { EuiPanel } from '@elastic/eui'; -import deepEqual from 'fast-deep-equal'; -import { getOr, isEmpty, isEqual, union } from 'lodash/fp'; +import { getOr, isEmpty, union } from 'lodash/fp'; import React, { useMemo } from 'react'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import useResizeObserver from 'use-resize-observer/polyfilled'; import { BrowserFields } from '../../containers/source'; @@ -228,7 +228,7 @@ const EventsViewerComponent: React.FC = ({ export const EventsViewer = React.memo( EventsViewerComponent, (prevProps, nextProps) => - isEqual(prevProps.browserFields, nextProps.browserFields) && + deepEqual(prevProps.browserFields, nextProps.browserFields) && prevProps.columns === nextProps.columns && prevProps.dataProviders === nextProps.dataProviders && prevProps.deletedEventIds === nextProps.deletedEventIds && @@ -241,9 +241,9 @@ export const EventsViewer = React.memo( prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.itemsPerPageOptions === nextProps.itemsPerPageOptions && prevProps.kqlMode === nextProps.kqlMode && - isEqual(prevProps.query, nextProps.query) && + deepEqual(prevProps.query, nextProps.query) && prevProps.start === nextProps.start && prevProps.sort === nextProps.sort && - isEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && + deepEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && prevProps.utilityBar === nextProps.utilityBar ); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx index 762ae8497dadb..9b31be40dd955 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { useCallback, useMemo, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; import { inputsActions, timelineActions } from '../../store/actions'; @@ -197,23 +197,23 @@ export const StatefulEventsViewer = connector( StatefulEventsViewerComponent, (prevProps, nextProps) => prevProps.id === nextProps.id && - isEqual(prevProps.columns, nextProps.columns) && - isEqual(prevProps.dataProviders, nextProps.dataProviders) && + deepEqual(prevProps.columns, nextProps.columns) && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && prevProps.deletedEventIds === nextProps.deletedEventIds && prevProps.end === nextProps.end && - isEqual(prevProps.filters, nextProps.filters) && + deepEqual(prevProps.filters, nextProps.filters) && prevProps.isLive === nextProps.isLive && prevProps.itemsPerPage === nextProps.itemsPerPage && - isEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && + deepEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && prevProps.kqlMode === nextProps.kqlMode && - isEqual(prevProps.query, nextProps.query) && - isEqual(prevProps.sort, nextProps.sort) && + deepEqual(prevProps.query, nextProps.query) && + deepEqual(prevProps.sort, nextProps.sort) && prevProps.start === nextProps.start && - isEqual(prevProps.pageFilters, nextProps.pageFilters) && + deepEqual(prevProps.pageFilters, nextProps.pageFilters) && prevProps.showCheckboxes === nextProps.showCheckboxes && prevProps.showRowRenderers === nextProps.showRowRenderers && prevProps.start === nextProps.start && - isEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && + deepEqual(prevProps.timelineTypeContext, nextProps.timelineTypeContext) && prevProps.utilityBar === nextProps.utilityBar ) ); diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx index eb41773bb21c8..22fc9f27ce26c 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx @@ -6,7 +6,7 @@ import { EuiBadge } from '@elastic/eui'; import { defaultTo, getOr } from 'lodash/fp'; -import React from 'react'; +import React, { useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; @@ -58,28 +58,39 @@ export const FlyoutComponent = React.memo( timelineId, usersViewing, width, - }) => ( - <> - - showTimeline({ id: timelineId, show: false })} + }) => { + const handleClose = useCallback(() => showTimeline({ id: timelineId, show: false }), [ + showTimeline, + timelineId, + ]); + const handleOpen = useCallback(() => showTimeline({ id: timelineId, show: true }), [ + showTimeline, + timelineId, + ]); + + return ( + <> + + + {children} + + + - {children} - - - showTimeline({ id: timelineId, show: true })} - /> - - ) + onOpen={handleOpen} + /> + + ); + } ); FlyoutComponent.displayName = 'FlyoutComponent'; diff --git a/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx b/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx index 405a8f060948e..d6f8143745356 100644 --- a/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/inspect/index.tsx @@ -5,7 +5,7 @@ */ import { EuiButtonEmpty, EuiButtonIcon } from '@elastic/eui'; -import { getOr } from 'lodash/fp'; +import { getOr, omit } from 'lodash/fp'; import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; @@ -162,7 +162,11 @@ const makeMapStateToProps = () => { const getGlobalQuery = inputsSelectors.globalQueryByIdSelector(); const getTimelineQuery = inputsSelectors.timelineQueryByIdSelector(); const mapStateToProps = (state: State, { inputId = 'global', queryId }: OwnProps) => { - return inputId === 'global' ? getGlobalQuery(state, queryId) : getTimelineQuery(state, queryId); + const props = + inputId === 'global' ? getGlobalQuery(state, queryId) : getTimelineQuery(state, queryId); + // refetch caused unnecessary component rerender and it was even not used + const propsWithoutRefetch = omit('refetch', props); + return propsWithoutRefetch; }; return mapStateToProps; }; diff --git a/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx b/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx index e40cc887ab5ff..8a754cb47475f 100644 --- a/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/navigation/index.tsx @@ -4,11 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import isEqual from 'lodash/fp/isEqual'; -import deepEqual from 'fast-deep-equal'; import React, { useEffect } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; +import deepEqual from 'fast-deep-equal'; import { useKibana } from '../../lib/kibana'; import { RouteSpyState } from '../../utils/route/types'; @@ -81,8 +80,8 @@ export const SiemNavigationRedux = compose< (prevProps, nextProps) => prevProps.pathName === nextProps.pathName && prevProps.search === nextProps.search && - isEqual(prevProps.navTabs, nextProps.navTabs) && - isEqual(prevProps.urlState, nextProps.urlState) && + deepEqual(prevProps.navTabs, nextProps.navTabs) && + deepEqual(prevProps.urlState, nextProps.urlState) && deepEqual(prevProps.state, nextProps.state) ) ); diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx index 853ba7ae23414..678faff7654db 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx @@ -7,7 +7,7 @@ /* eslint-disable react/display-name */ import { has } from 'lodash/fp'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { hostsActions } from '../../../../store/hosts'; @@ -100,10 +100,12 @@ const AuthenticationTableComponent = React.memo( [type, updateTableActivePage] ); + const columns = useMemo(() => getAuthenticationColumnsCurated(type), [type]); + return ( ( [type, updateTableActivePage] ); + const columns = useMemo(() => getUncommonColumnsCurated(type), [type]); + return ( ]; -export const getNetworkDnsColumns = (type: networkModel.NetworkType): NetworkDnsColumns => [ +export const getNetworkDnsColumns = (): NetworkDnsColumns => [ { field: `node.${NetworkDnsFields.dnsName}`, name: i18n.REGISTERED_DOMAIN, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx index f3fe98936a55d..c1dd96c5c96f9 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { networkActions } from '../../../../store/actions'; import { @@ -93,7 +93,7 @@ export const NetworkDnsTableComponent = React.memo( field: criteria.sort.field.split('.')[1] as NetworkDnsFields, direction: criteria.sort.direction as Direction, }; - if (!isEqual(newDnsSortField, sort)) { + if (!deepEqual(newDnsSortField, sort)) { updateNetworkTable({ networkType: type, tableType, @@ -115,10 +115,12 @@ export const NetworkDnsTableComponent = React.memo( [type, updateNetworkTable, isPtrIncluded] ); + const columns = useMemo(() => getNetworkDnsColumns(), []); + return ( = ({ const sorting = { field: `node.${NetworkHttpFields.requestCount}`, direction: sort.direction }; + const columns = useMemo(() => getNetworkHttpColumns(tableType), [tableType]); + return ( = ({ field: field as NetworkTopTablesFields, direction: newSortDirection as Direction, }; - if (!isEqual(newTopNFlowSort, sort)) { + if (!deepEqual(newTopNFlowSort, sort)) { updateNetworkTable({ networkType: type, tableType, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx index 77abae68b76bf..d1512699cc709 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { networkActions } from '../../../../store/network'; import { TlsEdges, TlsSortField, TlsFields, Direction } from '../../../../graphql/types'; @@ -91,7 +91,7 @@ const TlsTableComponent = React.memo( field: getSortFromString(splitField[splitField.length - 1]), direction: criteria.sort.direction as Direction, }; - if (!isEqual(newTlsSort, sort)) { + if (!deepEqual(newTlsSort, sort)) { updateNetworkTable({ networkType: type, tableType, @@ -103,10 +103,12 @@ const TlsTableComponent = React.memo( [sort, type, tableType, updateNetworkTable] ); + const columns = useMemo(() => getTlsColumns(tlsTableId), [tlsTableId]); + return ( ( field: getSortFromString(splitField[splitField.length - 1]), direction: criteria.sort.direction as Direction, }; - if (!isEqual(newUsersSort, sort)) { + if (!deepEqual(newUsersSort, sort)) { updateNetworkTable({ networkType: type, tableType, @@ -109,10 +109,15 @@ const UsersTableComponent = React.memo( [sort, type, updateNetworkTable] ); + const columns = useMemo(() => getUsersColumns(flowTarget, usersTableId), [ + flowTarget, + usersTableId, + ]); + return ( = ({ data, loading ); }; -OverviewHostStatsComponent.displayName = 'OverviewHostStatsComponent'; - export const OverviewHostStats = React.memo(OverviewHostStatsComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx index 260b1d6895140..ca947c29bc382 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/overview/overview_network_stats/index.tsx @@ -130,7 +130,7 @@ const AccordionContent = styled.div` margin-top: 8px; `; -export const OverviewNetworkStats = React.memo(({ data, loading }) => { +const OverviewNetworkStatsComponent: React.FC = ({ data, loading }) => { const allNetworkStats = getOverviewNetworkStats(data); const allNetworkStatsCount = allNetworkStats.reduce((total, stat) => total + stat.count, 0); @@ -190,6 +190,6 @@ export const OverviewNetworkStats = React.memo(({ data, lo })} ); -}); +}; -OverviewNetworkStats.displayName = 'OverviewNetworkStats'; +export const OverviewNetworkStats = React.memo(OverviewNetworkStatsComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx index 03a8143c89517..557d389aefee9 100644 --- a/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/query_bar/index.tsx @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { memo, useState, useEffect, useMemo, useCallback } from 'react'; +import deepEqual from 'fast-deep-equal'; import { Filter, @@ -64,7 +64,7 @@ export const QueryBar = memo( const onQuerySubmit = useCallback( (payload: { dateRange: TimeRange; query?: Query }) => { - if (payload.query != null && !isEqual(payload.query, filterQuery)) { + if (payload.query != null && !deepEqual(payload.query, filterQuery)) { onSubmitQuery(payload.query); } }, @@ -73,7 +73,7 @@ export const QueryBar = memo( const onQueryChange = useCallback( (payload: { dateRange: TimeRange; query?: Query }) => { - if (payload.query != null && !isEqual(payload.query, draftQuery)) { + if (payload.query != null && !deepEqual(payload.query, draftQuery)) { setDraftQuery(payload.query); onChangedQuery(payload.query); } diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx index cb5729ad8e26e..2513004af84dd 100644 --- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getOr, isEqual, set } from 'lodash/fp'; +import { getOr, set } from 'lodash/fp'; import React, { memo, useEffect, useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { Subscription } from 'rxjs'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { FilterManager, IIndexPattern, TimeRange, Query, Filter } from 'src/plugins/data/public'; import { SavedQuery } from 'src/legacy/core_plugins/data/public'; @@ -60,7 +61,6 @@ const SearchBarComponent = memo( setSavedQuery, setSearchBarFilter, start, - timelineId, toStr, updateSearch, dataTestSubj, @@ -108,7 +108,7 @@ const SearchBarComponent = memo( updateSearchBar.start = payload.dateRange.from; } - if (payload.query != null && !isEqual(payload.query, filterQuery)) { + if (payload.query != null && !deepEqual(payload.query, filterQuery)) { isStateUpdated = true; updateSearchBar = set('query', payload.query, updateSearchBar); } diff --git a/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx b/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx index 33159387214e4..b8192cce11e5a 100644 --- a/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx +++ b/x-pack/legacy/plugins/siem/public/components/source_destination/source_destination_ip.tsx @@ -5,8 +5,9 @@ */ import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { isEmpty, isEqual, uniqWith } from 'lodash/fp'; +import { isEmpty, uniqWith } from 'lodash/fp'; import React from 'react'; +import deepEqual from 'fast-deep-equal'; import { DESTINATION_IP_FIELD_NAME, SOURCE_IP_FIELD_NAME } from '../ip'; import { DESTINATION_PORT_FIELD_NAME, SOURCE_PORT_FIELD_NAME, Port } from '../port'; @@ -115,7 +116,7 @@ const IpAdressesWithPorts = React.memo<{ return ( - {uniqWith(isEqual, ipPortPairs).map( + {uniqWith(deepEqual, ipPortPairs).map( ipPortPair => ipPortPair.ip != null && ( diff --git a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap index 69596ba8f3325..ef077ece19f92 100644 --- a/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/stat_items/__snapshots__/index.test.tsx.snap @@ -94,7 +94,6 @@ exports[`Stat Items Component disable charts it renders the default widget 1`] = isInspected={false} loading={false} queryId="statItems" - refetch={null} selectedInspectIndex={0} setIsInspected={[Function]} title="KPI HOSTS" @@ -328,7 +327,6 @@ exports[`Stat Items Component disable charts it renders the default widget 2`] = isInspected={false} loading={false} queryId="statItems" - refetch={null} selectedInspectIndex={0} setIsInspected={[Function]} title="KPI HOSTS" @@ -632,7 +630,6 @@ exports[`Stat Items Component rendering kpis with charts it renders the default isInspected={false} loading={false} queryId="statItems" - refetch={null} selectedInspectIndex={0} setIsInspected={[Function]} title="KPI UNIQUE_PRIVATE_IPS" diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap index 3fcd258b79147..372930ee3167d 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap @@ -8,7 +8,7 @@ exports[`Timeline rendering renders correctly against snapshot 1`] = ` justifyContent="flexStart" > - = ({ browserFields, id, indexPattern, @@ -60,7 +60,7 @@ export const TimelineHeaderComponent = ({ onToggleDataProviderExcluded, show, showCallOutUnauthorizedMsg, -}: Props) => ( +}) => ( {showCallOutUnauthorizedMsg && ( ); -TimelineHeaderComponent.displayName = 'TimelineHeaderComponent'; - export const TimelineHeader = React.memo(TimelineHeaderComponent); - -TimelineHeader.displayName = 'TimelineHeader'; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx index d782d0366f041..0ce6bc16f1325 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React, { useEffect, useCallback, useMemo } from 'react'; import { connect, ConnectedProps } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { WithSource } from '../../containers/source'; import { useSignalIndex } from '../../containers/detection_engine/signals/use_signal_index'; @@ -215,11 +215,11 @@ const StatefulTimelineComponent = React.memo( prevProps.show === nextProps.show && prevProps.showCallOutUnauthorizedMsg === nextProps.showCallOutUnauthorizedMsg && prevProps.start === nextProps.start && - isEqual(prevProps.columns, nextProps.columns) && - isEqual(prevProps.dataProviders, nextProps.dataProviders) && - isEqual(prevProps.filters, nextProps.filters) && - isEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && - isEqual(prevProps.sort, nextProps.sort) + deepEqual(prevProps.columns, nextProps.columns) && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + deepEqual(prevProps.filters, nextProps.filters) && + deepEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && + deepEqual(prevProps.sort, nextProps.sort) ); } ); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx index 96b8df6d8ada7..7f662cdb2f1b4 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/query_bar/index.tsx @@ -4,9 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual, isEmpty } from 'lodash/fp'; +import { isEmpty } from 'lodash/fp'; import React, { memo, useCallback, useState, useEffect } from 'react'; import { Subscription } from 'rxjs'; +import deepEqual from 'fast-deep-equal'; import { IIndexPattern, @@ -127,7 +128,7 @@ export const QueryBarTimeline = memo( const filterWithoutDropArea = filterManager .getFilters() .filter((f: Filter) => f.meta.controlledBy !== timelineFilterDropArea); - if (!isEqual(filters, filterWithoutDropArea)) { + if (!deepEqual(filters, filterWithoutDropArea)) { filterManager.setFilters(filters); } }, [filters]); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx index d1904fd5d9aac..87061bdbb5d02 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getOr, isEqual } from 'lodash/fp'; +import { getOr } from 'lodash/fp'; import React, { useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; +import deepEqual from 'fast-deep-equal'; import { Filter, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; import { BrowserFields } from '../../../containers/source'; @@ -152,15 +153,15 @@ const StatefulSearchOrFilterComponent = React.memo( prevProps.isRefreshPaused === nextProps.isRefreshPaused && prevProps.refreshInterval === nextProps.refreshInterval && prevProps.timelineId === nextProps.timelineId && - isEqual(prevProps.browserFields, nextProps.browserFields) && - isEqual(prevProps.dataProviders, nextProps.dataProviders) && - isEqual(prevProps.filters, nextProps.filters) && - isEqual(prevProps.filterQuery, nextProps.filterQuery) && - isEqual(prevProps.filterQueryDraft, nextProps.filterQueryDraft) && - isEqual(prevProps.indexPattern, nextProps.indexPattern) && - isEqual(prevProps.kqlMode, nextProps.kqlMode) && - isEqual(prevProps.savedQueryId, nextProps.savedQueryId) && - isEqual(prevProps.timelineId, nextProps.timelineId) + deepEqual(prevProps.browserFields, nextProps.browserFields) && + deepEqual(prevProps.dataProviders, nextProps.dataProviders) && + deepEqual(prevProps.filters, nextProps.filters) && + deepEqual(prevProps.filterQuery, nextProps.filterQuery) && + deepEqual(prevProps.filterQueryDraft, nextProps.filterQueryDraft) && + deepEqual(prevProps.indexPattern, nextProps.indexPattern) && + deepEqual(prevProps.kqlMode, nextProps.kqlMode) && + deepEqual(prevProps.savedQueryId, nextProps.savedQueryId) && + deepEqual(prevProps.timelineId, nextProps.timelineId) ); } ); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index c9ff0296a40e2..58bbbef328ddf 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -229,8 +229,4 @@ export const TimelineComponent: React.FC = ({ ); }; -TimelineComponent.displayName = 'TimelineComponent'; - export const Timeline = React.memo(TimelineComponent); - -Timeline.displayName = 'Timeline'; diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx index e656ec3496d8d..294e41a1faa7b 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/index.tsx @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import React from 'react'; import { compose, Dispatch } from 'redux'; import { connect } from 'react-redux'; +import deepEqual from 'fast-deep-equal'; import { timelineActions } from '../../store/actions'; import { RouteSpyState } from '../../utils/route/types'; @@ -39,7 +39,7 @@ export const UrlStateRedux = compose - prevProps.pathName === nextProps.pathName && isEqual(prevProps.urlState, nextProps.urlState) + prevProps.pathName === nextProps.pathName && deepEqual(prevProps.urlState, nextProps.urlState) ) ); diff --git a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx index deaf9bbf5011d..a7704e0e86970 100644 --- a/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx +++ b/x-pack/legacy/plugins/siem/public/components/url_state/use_url_state.tsx @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual, difference, isEmpty } from 'lodash/fp'; +import { difference, isEmpty } from 'lodash/fp'; import { useEffect, useRef, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; import { useKibana } from '../../lib/kibana'; import { useApolloClient } from '../../utils/apollo_context'; @@ -77,7 +78,7 @@ export const useUrlStateHooks = ({ const updatedUrlStateString = getParamFromQueryString(getQueryStringFromLocation(mySearch), urlKey) ?? newUrlStateString; - if (isInitializing || !isEqual(updatedUrlStateString, newUrlStateString)) { + if (isInitializing || !deepEqual(updatedUrlStateString, newUrlStateString)) { urlStateToUpdate = [ ...urlStateToUpdate, { @@ -157,7 +158,7 @@ export const useUrlStateHooks = ({ if (isInitializing && pageName != null && pageName !== '') { handleInitialize(type); setIsInitializing(false); - } else if (!isEqual(urlState, prevProps.urlState) && !isInitializing) { + } else if (!deepEqual(urlState, prevProps.urlState) && !isInitializing) { let mySearch = search; URL_STATE_KEYS[type].forEach((urlKey: KeyUrlState) => { if ( diff --git a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx index b7ad41b8ba1bb..06c4d1054bca4 100644 --- a/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/detection_engine/rules/fetch_index_patterns.tsx @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEmpty, isEqual, get } from 'lodash/fp'; +import { isEmpty, get } from 'lodash/fp'; import { useEffect, useState, Dispatch, SetStateAction } from 'react'; +import deepEqual from 'fast-deep-equal'; import { IIndexPattern } from '../../../../../../../../src/plugins/data/public'; import { @@ -41,7 +42,7 @@ export const useFetchIndexPatterns = (defaultIndices: string[] = []): Return => const [, dispatchToaster] = useStateToaster(); useEffect(() => { - if (!isEqual(defaultIndices, indices)) { + if (!deepEqual(defaultIndices, indices)) { setIndices(defaultIndices); } }, [defaultIndices, indices]); diff --git a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx index caf597d02c835..4632e9aee3fdd 100644 --- a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useEffect } from 'react'; +import React, { useCallback, useState, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { inputsModel, inputsSelectors, State } from '../../store'; @@ -41,6 +41,17 @@ export const GlobalTimeComponent: React.FC = ({ }) => { const [isInitializing, setIsInitializing] = useState(true); + const setQuery = useCallback( + ({ id, inspect, loading, refetch }: SetQuery) => + setGlobalQuery({ inputId: 'global', id, inspect, loading, refetch }), + [setGlobalQuery] + ); + + const deleteQuery = useCallback( + ({ id }: { id: string }) => deleteOneQuery({ inputId: 'global', id }), + [deleteOneQuery] + ); + useEffect(() => { if (isInitializing) { setIsInitializing(false); @@ -56,9 +67,8 @@ export const GlobalTimeComponent: React.FC = ({ isInitializing, from, to, - setQuery: ({ id, inspect, loading, refetch }: SetQuery) => - setGlobalQuery({ inputId: 'global', id, inspect, loading, refetch }), - deleteQuery: ({ id }: { id: string }) => deleteOneQuery({ inputId: 'global', id }), + setQuery, + deleteQuery, })} ); diff --git a/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx b/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx index 4d6ab757fdea7..db618f216d83e 100644 --- a/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/query_template_paginated.tsx @@ -5,10 +5,10 @@ */ import { ApolloQueryResult, NetworkStatus } from 'apollo-client'; -import { isEqual } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React from 'react'; import { FetchMoreOptions, FetchMoreQueryOptions, OperationVariables } from 'react-apollo'; +import deepEqual from 'fast-deep-equal'; import { ESQuery } from '../../common/typed_json'; import { inputsModel } from '../store/model'; @@ -85,7 +85,7 @@ export class QueryTemplatePaginated< public isItAValidLoading(loading: boolean, variables: TVariables, networkStatus: NetworkStatus) { if ( !this.myLoading && - (!isEqual(variables, this.queryVariables) || networkStatus === NetworkStatus.refetch) && + (!deepEqual(variables, this.queryVariables) || networkStatus === NetworkStatus.refetch) && loading ) { this.myLoading = true; diff --git a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx index 0336e4a9a977b..e454421ca955d 100644 --- a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx @@ -10,6 +10,7 @@ import { Query } from 'react-apollo'; import React, { useEffect, useMemo, useState } from 'react'; import memoizeOne from 'memoize-one'; import { IIndexPattern } from 'src/plugins/data/public'; + import { useUiSetting$ } from '../../lib/kibana'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx index 92f6740e4d767..2d9b1ee844b4b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram.tsx @@ -12,9 +12,11 @@ import { HistogramBarSeries, Position, Settings, + ChartSizeArray, } from '@elastic/charts'; -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiProgress } from '@elastic/eui'; + import { useTheme } from '../../../../components/charts/common'; import { histogramDateTimeFormatter } from '../../../../components/utils'; import { HistogramData } from './types'; @@ -43,6 +45,14 @@ export const SignalsHistogram = React.memo( }) => { const theme = useTheme(); + const chartSize: ChartSizeArray = useMemo(() => ['100%', chartHeight], [chartHeight]); + const xAxisId = useMemo(() => getAxisId('signalsHistogramAxisX'), []); + const yAxisId = useMemo(() => getAxisId('signalsHistogramAxisY'), []); + const id = useMemo(() => getSpecId('signalsHistogram'), []); + const yAccessors = useMemo(() => ['y'], []); + const splitSeriesAccessors = useMemo(() => ['g'], []); + const tickFormat = useMemo(() => histogramDateTimeFormatter([from, to]), [from, to]); + return ( <> {loading && ( @@ -54,7 +64,7 @@ export const SignalsHistogram = React.memo( /> )} - + ( theme={theme} /> - + - + @@ -84,4 +90,5 @@ export const SignalsHistogram = React.memo( ); } ); + SignalsHistogram.displayName = 'SignalsHistogram'; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx index 88795f9195e68..fbe854c1ee346 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/query_bar/index.tsx @@ -5,10 +5,10 @@ */ import { EuiFormRow, EuiMutationObserver } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Subscription } from 'rxjs'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { Filter, @@ -99,7 +99,7 @@ export const QueryBarDefineRule = ({ const newFilters = filterManager.getFilters(); const { filters } = field.value as FieldValueQueryBar; - if (!isEqual(filters, newFilters)) { + if (!deepEqual(filters, newFilters)) { field.setValue({ ...(field.value as FieldValueQueryBar), filters: newFilters }); } } @@ -117,10 +117,10 @@ export const QueryBarDefineRule = ({ let isSubscribed = true; async function updateFilterQueryFromValue() { const { filters, query, saved_id: savedId } = field.value as FieldValueQueryBar; - if (!isEqual(query, queryDraft)) { + if (!deepEqual(query, queryDraft)) { setQueryDraft(query); } - if (!isEqual(filters, filterManager.getFilters())) { + if (!deepEqual(filters, filterManager.getFilters())) { filterManager.setFilters(filters); } if ( @@ -148,7 +148,7 @@ export const QueryBarDefineRule = ({ const onSubmitQuery = useCallback( (newQuery: Query, timefilter?: SavedQueryTimeFilter) => { const { query } = field.value as FieldValueQueryBar; - if (!isEqual(query, newQuery)) { + if (!deepEqual(query, newQuery)) { field.setValue({ ...(field.value as FieldValueQueryBar), query: newQuery }); } }, @@ -158,7 +158,7 @@ export const QueryBarDefineRule = ({ const onChangedQuery = useCallback( (newQuery: Query) => { const { query } = field.value as FieldValueQueryBar; - if (!isEqual(query, newQuery)) { + if (!deepEqual(query, newQuery)) { field.setValue({ ...(field.value as FieldValueQueryBar), query: newQuery }); } }, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx index 2c9173cbeb694..ac457d7345c29 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/rule_status/index.tsx @@ -12,8 +12,8 @@ import { EuiLoadingSpinner, EuiText, } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { memo, useCallback, useEffect, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; import { useRuleStatus, RuleInfoStatus } from '../../../../../containers/detection_engine/rules'; import { FormattedDate } from '../../../../../components/formatted_date'; @@ -43,7 +43,7 @@ const RuleStatusComponent: React.FC = ({ ruleId, ruleEnabled }) }, [fetchRuleStatus, myRuleEnabled, ruleId, ruleEnabled, setMyRuleEnabled]); useEffect(() => { - if (!isEqual(currentStatus, ruleStatus?.current_status)) { + if (!deepEqual(currentStatus, ruleStatus?.current_status)) { setCurrentStatus(ruleStatus?.current_status ?? null); } }, [currentStatus, ruleStatus, setCurrentStatus]); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx index 45da7d081333e..431d793d6e68a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_about_rule/index.tsx @@ -13,9 +13,9 @@ import { EuiSpacer, EuiButtonEmpty, } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { FC, memo, useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { setFieldValue } from '../../helpers'; import { RuleStepProps, RuleStep, AboutStepRule } from '../../types'; @@ -103,7 +103,7 @@ const StepAboutRuleComponent: FC = ({ useEffect(() => { const { isNew, ...initDefaultValue } = myStepData; - if (defaultValues != null && !isEqual(initDefaultValue, defaultValues)) { + if (defaultValues != null && !deepEqual(initDefaultValue, defaultValues)) { const myDefaultValues = { ...defaultValues, isNew: false, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx index 920a9f2dfe56c..773eb44efb26c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_define_rule/index.tsx @@ -11,9 +11,10 @@ import { EuiFlexItem, EuiButton, } from '@elastic/eui'; -import { isEmpty, isEqual } from 'lodash/fp'; +import { isEmpty } from 'lodash/fp'; import React, { FC, memo, useCallback, useState, useEffect } from 'react'; import styled from 'styled-components'; +import deepEqual from 'fast-deep-equal'; import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/public'; import { useFetchIndexPatterns } from '../../../../../containers/detection_engine/rules'; @@ -126,9 +127,9 @@ const StepDefineRuleComponent: FC = ({ useEffect(() => { if (indicesConfig != null && defaultValues != null) { const myDefaultValues = getStepDefaultValue(indicesConfig, defaultValues); - if (!isEqual(myDefaultValues, myStepData)) { + if (!deepEqual(myDefaultValues, myStepData)) { setMyStepData(myDefaultValues); - setLocalUseIndicesConfig(isEqual(myDefaultValues.index, indicesConfig)); + setLocalUseIndicesConfig(deepEqual(myDefaultValues.index, indicesConfig)); setFieldValue(form, schema, myDefaultValues); } } @@ -212,13 +213,13 @@ const StepDefineRuleComponent: FC = ({ {({ index }) => { if (index != null) { - if (isEqual(index, indicesConfig) && !localUseIndicesConfig) { + if (deepEqual(index, indicesConfig) && !localUseIndicesConfig) { setLocalUseIndicesConfig(true); } - if (!isEqual(index, indicesConfig) && localUseIndicesConfig) { + if (!deepEqual(index, indicesConfig) && localUseIndicesConfig) { setLocalUseIndicesConfig(false); } - if (index != null && !isEmpty(index) && !isEqual(index, mylocalIndicesConfig)) { + if (index != null && !isEmpty(index) && !deepEqual(index, mylocalIndicesConfig)) { setMyLocalIndicesConfig(index); } } diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx index cfbb0a622c721..2e2c7e068dd85 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/step_schedule_rule/index.tsx @@ -5,8 +5,8 @@ */ import { EuiHorizontalRule, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; -import { isEqual } from 'lodash/fp'; import React, { FC, memo, useCallback, useEffect, useState } from 'react'; +import deepEqual from 'fast-deep-equal'; import { setFieldValue } from '../../helpers'; import { RuleStep, RuleStepProps, ScheduleStepRule } from '../../types'; @@ -62,7 +62,7 @@ const StepScheduleRuleComponent: FC = ({ useEffect(() => { const { isNew, ...initDefaultValue } = myStepData; - if (defaultValues != null && !isEqual(initDefaultValue, defaultValues)) { + if (defaultValues != null && !deepEqual(initDefaultValue, defaultValues)) { const myDefaultValues = { ...defaultValues, isNew: false, diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx index 41eb620850a7f..f5efd9248029d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx @@ -73,32 +73,25 @@ export const HostDetailsTabs = React.memo( return ( - } - /> - } - /> - } - /> - ( - - )} - /> - } - /> - } - /> + + + + + + + + + + + + + + + + + + + ); } diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx index 0b83710a13293..80c35e5563c1d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import { Route, Switch } from 'react-router-dom'; import { HostsTabsProps } from './types'; @@ -22,7 +22,7 @@ import { } from './navigation'; import { HostAlertsQueryTabBody } from './navigation/alerts_query_tab_body'; -const HostsTabs = memo( +export const HostsTabs = memo( ({ deleteQuery, filterQuery, @@ -44,49 +44,48 @@ const HostsTabs = memo( startDate: from, type, indexPattern, - narrowDateRange: (score: Anomaly, interval: string) => { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }, + narrowDateRange: useCallback( + (score: Anomaly, interval: string) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + [setAbsoluteRangeDatePicker] + ), + updateDateRange: useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker] + ), }; return ( - } - /> - } - /> - } - /> - ( - - )} - /> - } - /> - } - /> + + + + + + + + + + + + + + + + + + ); } ); HostsTabs.displayName = 'HostsTabs'; - -export { HostsTabs }; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx index 23a619db97ee4..b6b54b68ac06a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx @@ -23,77 +23,82 @@ import { TlsQueryTabBody } from './tls_query_tab_body'; import { Anomaly } from '../../../components/ml/types'; import { NetworkAlertsQueryTabBody } from './alerts_query_tab_body'; -export const NetworkRoutes = ({ - networkPagePath, - type, - to, - filterQuery, - isInitializing, - from, - indexPattern, - setQuery, - setAbsoluteRangeDatePicker, -}: NetworkRoutesProps) => { - const narrowDateRange = useCallback( - (score: Anomaly, interval: string) => { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }, - [setAbsoluteRangeDatePicker] - ); +export const NetworkRoutes = React.memo( + ({ + networkPagePath, + type, + to, + filterQuery, + isInitializing, + from, + indexPattern, + setQuery, + setAbsoluteRangeDatePicker, + }) => { + const narrowDateRange = useCallback( + (score: Anomaly, interval: string) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + [setAbsoluteRangeDatePicker] + ); + const updateDateRange = useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker] + ); - const networkAnomaliesFilterQuery = { - bool: { - should: [ - { - exists: { - field: 'source.ip', + const networkAnomaliesFilterQuery = { + bool: { + should: [ + { + exists: { + field: 'source.ip', + }, }, - }, - { - exists: { - field: 'destination.ip', + { + exists: { + field: 'destination.ip', + }, }, - }, - ], - minimum_should_match: 1, - }, - }; + ], + minimum_should_match: 1, + }, + }; - const commonProps = { - startDate: from, - endDate: to, - skip: isInitializing, - type, - narrowDateRange, - setQuery, - filterQuery, - }; + const commonProps = { + startDate: from, + endDate: to, + skip: isInitializing, + type, + narrowDateRange, + setQuery, + filterQuery, + }; - const tabProps = { - ...commonProps, - indexPattern, - }; + const tabProps = { + ...commonProps, + indexPattern, + updateDateRange, + }; - const anomaliesProps = { - ...commonProps, - anomaliesFilterQuery: networkAnomaliesFilterQuery, - AnomaliesTableComponent: AnomaliesNetworkTable, - }; + const anomaliesProps = { + ...commonProps, + anomaliesFilterQuery: networkAnomaliesFilterQuery, + AnomaliesTableComponent: AnomaliesNetworkTable, + }; - return ( - - } - /> - ( + return ( + + + + + <> @@ -118,31 +123,25 @@ export const NetworkRoutes = ({ - )} - /> - } - /> - } - /> - ( + + + + + + + + - )} - /> - } - /> - - ); -}; + + + + + + ); + } +); NetworkRoutes.displayName = 'NetworkRoutes'; diff --git a/x-pack/legacy/plugins/siem/public/routes.tsx b/x-pack/legacy/plugins/siem/public/routes.tsx index cbb58a473e8ea..a989fa9873435 100644 --- a/x-pack/legacy/plugins/siem/public/routes.tsx +++ b/x-pack/legacy/plugins/siem/public/routes.tsx @@ -20,8 +20,12 @@ const PageRouterComponent: FC = ({ history }) => ( - } /> - } /> + + + + + + diff --git a/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx b/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx index 213b881bd2084..af993588f7e0d 100644 --- a/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx +++ b/x-pack/legacy/plugins/siem/public/utils/kql/use_update_kql.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { isEqual } from 'lodash/fp'; import { Dispatch } from 'redux'; import { IIndexPattern } from 'src/plugins/data/public'; +import deepEqual from 'fast-deep-equal'; import { KueryFilterQuery } from '../../store'; import { applyKqlFilterQuery as dispatchApplyTimelineFilterQuery } from '../../store/timeline/actions'; @@ -29,7 +29,7 @@ export const useUpdateKql = ({ timelineId, }: UseUpdateKqlProps): RefetchKql => { const updateKql: RefetchKql = (dispatch: Dispatch) => { - if (kueryFilterQueryDraft != null && !isEqual(kueryFilterQuery, kueryFilterQueryDraft)) { + if (kueryFilterQueryDraft != null && !deepEqual(kueryFilterQuery, kueryFilterQueryDraft)) { if (storeType === 'timelineType' && timelineId != null) { dispatch( dispatchApplyTimelineFilterQuery({ diff --git a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx index c88562abef6ae..ddee2359b28ba 100644 --- a/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx +++ b/x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx @@ -5,7 +5,6 @@ */ import * as H from 'history'; -import { isEqual } from 'lodash/fp'; import { memo, useEffect, useState } from 'react'; import { withRouter } from 'react-router-dom'; import deepEqual from 'fast-deep-equal'; @@ -35,7 +34,7 @@ export const SpyRouteComponent = memo( } }, [search]); useEffect(() => { - if (pageName && !isEqual(route.pathName, pathname)) { + if (pageName && !deepEqual(route.pathName, pathname)) { if (isInitializing && detailName == null) { dispatch({ type: 'updateRouteWithOutSearch', diff --git a/x-pack/package.json b/x-pack/package.json index f76b0182ea228..b8fe0326903b6 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -106,6 +106,7 @@ "@types/uuid": "^3.4.4", "@types/xml-crypto": "^1.4.0", "@types/xml2js": "^0.4.5", + "@welldone-software/why-did-you-render": "^4.0.0", "abab": "^1.0.4", "axios": "^0.19.0", "babel-jest": "^24.9.0", diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index 978271166cc05..723da7cef6a77 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -36,7 +36,7 @@ "x-pack/test_utils/*" ], "plugins/*": ["src/legacy/core_plugins/*/public/"], - "fixtures/*": ["src/fixtures/*"] + "fixtures/*": ["src/fixtures/*"], }, "types": [ "node", diff --git a/yarn.lock b/yarn.lock index f46e869909e2e..7906f363813b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5684,6 +5684,13 @@ text-table "^0.2.0" webpack-log "^1.1.2" +"@welldone-software/why-did-you-render@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-4.0.0.tgz#cc98c996f5a06ea55bd07dc99ba4b4d68af93332" + integrity sha512-PjqriZ8Ak9biP2+kOcIrg+NwsFwWVhGV03Hm+ns84YBCArn+hWBKM9rMBEU6e62I1qyrYF2/G9yktNpEmfWfJA== + dependencies: + lodash "^4" + "@wry/context@^0.4.0": version "0.4.1" resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.1.tgz#b3e23ca036035cbad0bd9711269352dd03a6fe3c" @@ -19767,7 +19774,7 @@ lodash.uniqby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI= -lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: +lodash@4.17.11, lodash@4.17.15, lodash@>4.17.4, lodash@^4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.10.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.6.1, lodash@~4.17.10, lodash@~4.17.15, lodash@~4.17.5: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== From d339740c2de9f61d7140cd9bc983383f2843df67 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 25 Feb 2020 09:27:18 -0500 Subject: [PATCH 09/11] [Uptime] Migrate server to new platform (#53939) * Move uptime legacy server to plugins directory. * Re-add feature registration code. * Move feature registration back to kibana bootstrap file. * Delete obsolete test file. * Remove i18n call from untracked file. * Implement feedback. Co-authored-by: Elastic Machine --- .../plugins/uptime/common/constants/plugin.ts | 7 ++- x-pack/legacy/plugins/uptime/index.ts | 19 -------- .../plugins/uptime/scripts/graphql_schemas.ts | 15 ------ .../__tests__/find_potential_matches_test.ts | 5 -- x-pack/legacy/plugins/uptime/server/plugin.ts | 19 -------- x-pack/plugins/uptime/kibana.json | 9 ++++ .../uptime/server/graphql/constants.ts | 0 .../plugins/uptime/server/graphql/index.ts | 0 .../server/graphql/monitor_states/index.ts | 0 .../graphql/monitor_states/resolvers.ts | 6 +-- .../graphql/monitor_states/schema.gql.ts | 0 .../uptime/server/graphql/monitors/index.ts | 0 .../server/graphql/monitors/resolvers.ts | 10 +++- .../server/graphql/monitors/schema.gql.ts | 0 .../uptime/server/graphql/pings/index.ts | 0 .../uptime/server/graphql/pings/resolvers.ts | 7 ++- .../uptime/server/graphql/pings/schema.gql.ts | 0 .../plugins/uptime/server/graphql/types.ts | 0 .../__tests__/parse_literal.test.ts | 0 .../__tests__/parse_value.test.ts | 0 .../__tests__/serialize.test.ts | 0 .../graphql/unsigned_int_scalar/index.ts | 0 .../graphql/unsigned_int_scalar/resolvers.ts | 0 .../graphql/unsigned_int_scalar/schema.gql.ts | 0 .../plugins/uptime/server/index.ts | 6 ++- .../plugins/uptime/server/kibana.index.ts | 17 +++---- .../lib/adapters/framework/adapter_types.ts | 11 ++--- .../server/lib/adapters/framework/index.ts | 0 .../framework/kibana_framework_adapter.ts | 0 .../uptime/server/lib/adapters/index.ts | 0 .../kibana_telemetry_adapter.test.ts.snap | 0 .../kibana_telemetry_adapter.test.ts | 0 .../server/lib/adapters/telemetry/index.ts | 0 .../telemetry/kibana_telemetry_adapter.ts | 0 .../uptime/server/lib/compose/kibana.ts | 4 +- .../__snapshots__/license.test.ts.snap | 0 .../lib/domains/__tests__/license.test.ts | 2 +- .../uptime/server/lib/domains/index.ts | 0 .../uptime/server/lib/domains/license.ts | 2 +- .../assert_close_to.test.ts.snap | 0 .../get_filter_clause.test.ts.snap | 0 .../helper/__test__/assert_close_to.test.ts | 0 .../helper/__test__/get_filter_clause.test.ts | 0 .../__test__/get_histogram_interval.test.ts | 0 .../get_histogram_interval_formatted.test.ts | 0 .../__test__/parse_relative_date.test.ts | 0 .../server/lib/helper/assert_close_to.ts | 0 .../server/lib/helper/get_filter_clause.ts | 0 .../lib/helper/get_histogram_interval.ts | 2 +- .../get_histogram_interval_formatted.ts | 0 .../plugins/uptime/server/lib/helper/index.ts | 0 .../lib/helper/make_date_rate_filter.ts | 0 .../server/lib/helper/object_to_array.ts | 0 .../plugins/uptime/server/lib/lib.ts | 0 .../extract_filter_aggs_results.test.ts.snap | 0 .../generate_filter_aggs.test.ts.snap | 0 .../get_monitor_charts.test.ts.snap | 0 .../get_ping_histogram.test.ts.snap | 0 .../combine_range_with_filters.test.ts | 0 .../extract_filter_aggs_results.test.ts | 0 .../__tests__/generate_filter_aggs.test.ts | 0 .../__tests__/get_latest_monitor.test.ts | 0 .../__tests__/get_monitor_charts.test.ts | 0 .../__tests__/get_ping_histogram.test.ts | 0 .../lib/requests/__tests__/get_pings.test.ts | 0 .../__tests__/monitor_charts_mock.json | 0 .../lib/requests/generate_filter_aggs.ts | 0 .../server/lib/requests/get_filter_bar.ts | 4 +- .../server/lib/requests/get_index_pattern.ts | 4 +- .../server/lib/requests/get_index_status.ts | 4 +- .../server/lib/requests/get_latest_monitor.ts | 4 +- .../uptime/server/lib/requests/get_monitor.ts | 4 +- .../server/lib/requests/get_monitor_charts.ts | 7 ++- .../lib/requests/get_monitor_details.ts | 7 ++- .../lib/requests/get_monitor_locations.ts | 10 +++- .../server/lib/requests/get_monitor_states.ts | 8 +++- .../server/lib/requests/get_ping_histogram.ts | 4 +- .../uptime/server/lib/requests/get_pings.ts | 8 +++- .../lib/requests/get_snapshot_counts.ts | 7 ++- .../uptime/server/lib/requests/index.ts | 0 .../search/__tests__/fetch_page.test.ts | 2 +- .../__tests__/monitor_group_iterator.test.ts | 0 .../search/__tests__/query_context.test.ts | 5 +- .../requests/search/__tests__/test_helpers.ts | 5 +- .../requests/search/enrich_monitor_groups.ts | 4 +- .../server/lib/requests/search/fetch_chunk.ts | 0 .../server/lib/requests/search/fetch_page.ts | 8 +++- .../requests/search/find_potential_matches.ts | 4 +- .../server/lib/requests/search/index.ts | 0 .../requests/search/monitor_group_iterator.ts | 2 +- .../lib/requests/search/query_context.ts | 2 +- .../search/refine_potential_matches.ts | 4 +- .../server/lib/requests/search/types.ts | 5 +- .../uptime/server/lib/requests/types.ts | 7 ++- .../server/lib/requests/uptime_requests.ts | 11 +++-- x-pack/plugins/uptime/server/plugin.ts | 17 +++++++ .../server/rest_api/create_route_with_auth.ts | 0 .../plugins/uptime/server/rest_api/index.ts | 0 .../index_pattern/get_index_pattern.ts | 0 .../server/rest_api/index_pattern/index.ts | 0 .../uptime/server/rest_api/monitors/index.ts | 0 .../rest_api/monitors/monitor_locations.ts | 0 .../rest_api/monitors/monitors_details.ts | 0 .../uptime/server/rest_api/monitors/status.ts | 0 .../overview_filters/get_overview_filters.ts | 0 .../server/rest_api/overview_filters/index.ts | 0 .../uptime/server/rest_api/pings/get_all.ts | 48 +++++++++++++++++++ .../rest_api/pings/get_ping_histogram.ts | 0 .../uptime/server/rest_api/pings/get_pings.ts | 0 .../uptime/server/rest_api/pings/index.ts | 0 .../rest_api/snapshot/get_snapshot_count.ts | 0 .../uptime/server/rest_api/snapshot/index.ts | 0 .../uptime/server/rest_api/telemetry/index.ts | 0 .../rest_api/telemetry/log_monitor_page.ts | 0 .../rest_api/telemetry/log_overview_page.ts | 0 .../plugins/uptime/server/rest_api/types.ts | 0 .../server/rest_api/uptime_route_wrapper.ts | 0 .../plugins/uptime/server/uptime_server.ts | 0 .../apis/uptime/rest/ping_histogram.ts | 2 +- 119 files changed, 204 insertions(+), 134 deletions(-) delete mode 100644 x-pack/legacy/plugins/uptime/scripts/graphql_schemas.ts delete mode 100644 x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/find_potential_matches_test.ts delete mode 100644 x-pack/legacy/plugins/uptime/server/plugin.ts create mode 100644 x-pack/plugins/uptime/kibana.json rename x-pack/{legacy => }/plugins/uptime/server/graphql/constants.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/monitor_states/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/monitor_states/resolvers.ts (89%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/monitor_states/schema.gql.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/monitors/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/monitors/resolvers.ts (71%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/monitors/schema.gql.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/pings/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/pings/resolvers.ts (84%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/pings/schema.gql.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/types.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/index.ts (59%) rename x-pack/{legacy => }/plugins/uptime/server/kibana.index.ts (82%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/framework/adapter_types.ts (85%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/framework/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/telemetry/__tests__/__snapshots__/kibana_telemetry_adapter.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/telemetry/__tests__/kibana_telemetry_adapter.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/telemetry/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/compose/kibana.ts (80%) rename x-pack/{legacy => }/plugins/uptime/server/lib/domains/__tests__/__snapshots__/license.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/domains/__tests__/license.test.ts (93%) rename x-pack/{legacy => }/plugins/uptime/server/lib/domains/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/domains/license.ts (93%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/__test__/__snapshots__/assert_close_to.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filter_clause.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/__test__/assert_close_to.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/__test__/get_filter_clause.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/__test__/parse_relative_date.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/assert_close_to.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/get_filter_clause.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/get_histogram_interval.ts (95%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/make_date_rate_filter.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/helper/object_to_array.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/lib.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/__snapshots__/extract_filter_aggs_results.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/__snapshots__/generate_filter_aggs.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/combine_range_with_filters.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/extract_filter_aggs_results.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/generate_filter_aggs.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/generate_filter_aggs.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_filter_bar.ts (94%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_index_pattern.ts (92%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_index_status.ts (76%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_latest_monitor.ts (91%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_monitor.ts (87%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_monitor_charts.ts (96%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_monitor_details.ts (88%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_monitor_locations.ts (92%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_monitor_states.ts (89%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_ping_histogram.ts (93%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_pings.ts (93%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/get_snapshot_counts.ts (96%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts (96%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/__tests__/monitor_group_iterator.test.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts (95%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts (88%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts (98%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/fetch_chunk.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/fetch_page.ts (96%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/find_potential_matches.ts (95%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts (98%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/query_context.ts (97%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts (96%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/search/types.ts (76%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/types.ts (89%) rename x-pack/{legacy => }/plugins/uptime/server/lib/requests/uptime_requests.ts (83%) create mode 100644 x-pack/plugins/uptime/server/plugin.ts rename x-pack/{legacy => }/plugins/uptime/server/rest_api/create_route_with_auth.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/index_pattern/get_index_pattern.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/index_pattern/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/monitors/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/monitors/monitor_locations.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/monitors/monitors_details.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/monitors/status.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/overview_filters/get_overview_filters.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/overview_filters/index.ts (100%) create mode 100644 x-pack/plugins/uptime/server/rest_api/pings/get_all.ts rename x-pack/{legacy => }/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/pings/get_pings.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/pings/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/snapshot/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/telemetry/index.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/telemetry/log_monitor_page.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/telemetry/log_overview_page.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/types.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/rest_api/uptime_route_wrapper.ts (100%) rename x-pack/{legacy => }/plugins/uptime/server/uptime_server.ts (100%) diff --git a/x-pack/legacy/plugins/uptime/common/constants/plugin.ts b/x-pack/legacy/plugins/uptime/common/constants/plugin.ts index f6fa569a50315..00781726941d5 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/plugin.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/plugin.ts @@ -4,11 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; + export const PLUGIN = { APP_ROOT_ID: 'react-uptime-root', DESCRIPTION: 'Uptime monitoring', ID: 'uptime', - ROUTER_BASE_NAME: '/app/uptime#', LOCAL_STORAGE_KEY: 'xpack.uptime', + NAME: i18n.translate('xpack.uptime.featureRegistry.uptimeFeatureName', { + defaultMessage: 'Uptime', + }), + ROUTER_BASE_NAME: '/app/uptime#', TITLE: 'uptime', }; diff --git a/x-pack/legacy/plugins/uptime/index.ts b/x-pack/legacy/plugins/uptime/index.ts index cf7332f97d466..feecef5857895 100644 --- a/x-pack/legacy/plugins/uptime/index.ts +++ b/x-pack/legacy/plugins/uptime/index.ts @@ -6,9 +6,7 @@ import { i18n } from '@kbn/i18n'; import { resolve } from 'path'; -import { PluginInitializerContext } from 'src/core/server'; import { PLUGIN } from './common/constants'; -import { KibanaServer, plugin } from './server'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; export const uptime = (kibana: any) => @@ -35,21 +33,4 @@ export const uptime = (kibana: any) => }, home: ['plugins/uptime/register_feature'], }, - init(server: KibanaServer) { - const initializerContext = {} as PluginInitializerContext; - const { savedObjects } = server; - const { xpack_main } = server.plugins; - const { usageCollection } = server.newPlatform.setup.plugins; - - plugin(initializerContext).setup( - { - route: server.newPlatform.setup.core.http.createRouter(), - }, - { - savedObjects, - usageCollection, - xpack: xpack_main, - } - ); - }, }); diff --git a/x-pack/legacy/plugins/uptime/scripts/graphql_schemas.ts b/x-pack/legacy/plugins/uptime/scripts/graphql_schemas.ts deleted file mode 100644 index c337cf098e48d..0000000000000 --- a/x-pack/legacy/plugins/uptime/scripts/graphql_schemas.ts +++ /dev/null @@ -1,15 +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 { buildSchemaFromTypeDefinitions } from 'graphql-tools'; -import { typeDefs } from '../server/graphql'; - -export const schemas = [...typeDefs]; - -// this default export is used to feed the combined types to the gql-gen tool -// which generates the corresponding typescript types -// eslint-disable-next-line import/no-default-export -export default buildSchemaFromTypeDefinitions(schemas); diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/find_potential_matches_test.ts b/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/find_potential_matches_test.ts deleted file mode 100644 index 41bc2aa258807..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/find_potential_matches_test.ts +++ /dev/null @@ -1,5 +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. - */ diff --git a/x-pack/legacy/plugins/uptime/server/plugin.ts b/x-pack/legacy/plugins/uptime/server/plugin.ts deleted file mode 100644 index acecce305e7cb..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/plugin.ts +++ /dev/null @@ -1,19 +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 { PluginInitializerContext } from 'src/core/server'; -import { initServerWithKibana } from './kibana.index'; -import { UptimeCoreSetup, UptimeCorePlugins } from './lib/adapters/framework'; - -export function plugin(initializerContext: PluginInitializerContext) { - return new Plugin(); -} - -export class Plugin { - public setup(core: UptimeCoreSetup, plugins: UptimeCorePlugins) { - initServerWithKibana(core, plugins); - } -} diff --git a/x-pack/plugins/uptime/kibana.json b/x-pack/plugins/uptime/kibana.json new file mode 100644 index 0000000000000..dd61716325afc --- /dev/null +++ b/x-pack/plugins/uptime/kibana.json @@ -0,0 +1,9 @@ +{ + "configPath": ["xpack"], + "id": "uptime", + "kibanaVersion": "kibana", + "requiredPlugins": ["features", "licensing", "usageCollection"], + "server": true, + "ui": false, + "version": "8.0.0" +} diff --git a/x-pack/legacy/plugins/uptime/server/graphql/constants.ts b/x-pack/plugins/uptime/server/graphql/constants.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/constants.ts rename to x-pack/plugins/uptime/server/graphql/constants.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/index.ts b/x-pack/plugins/uptime/server/graphql/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/index.ts rename to x-pack/plugins/uptime/server/graphql/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitor_states/index.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/monitor_states/index.ts rename to x-pack/plugins/uptime/server/graphql/monitor_states/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitor_states/resolvers.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/resolvers.ts similarity index 89% rename from x-pack/legacy/plugins/uptime/server/graphql/monitor_states/resolvers.ts rename to x-pack/plugins/uptime/server/graphql/monitor_states/resolvers.ts index e2b076d570843..6ac42f7717259 100644 --- a/x-pack/legacy/plugins/uptime/server/graphql/monitor_states/resolvers.ts +++ b/x-pack/plugins/uptime/server/graphql/monitor_states/resolvers.ts @@ -6,13 +6,13 @@ import { CreateUMGraphQLResolvers, UMContext } from '../types'; import { UMServerLibs } from '../../lib/lib'; -import { UMResolver } from '../../../common/graphql/resolver_types'; +import { UMResolver } from '../../../../../legacy/plugins/uptime/common/graphql/resolver_types'; import { GetMonitorStatesQueryArgs, MonitorSummaryResult, StatesIndexStatus, -} from '../../../common/graphql/types'; -import { CONTEXT_DEFAULTS } from '../../../common/constants/context_defaults'; +} from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { CONTEXT_DEFAULTS } from '../../../../../legacy/plugins/uptime/common/constants/context_defaults'; export type UMGetMonitorStatesResolver = UMResolver< MonitorSummaryResult | Promise, diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitor_states/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/monitor_states/schema.gql.ts rename to x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/index.ts b/x-pack/plugins/uptime/server/graphql/monitors/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/monitors/index.ts rename to x-pack/plugins/uptime/server/graphql/monitors/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts b/x-pack/plugins/uptime/server/graphql/monitors/resolvers.ts similarity index 71% rename from x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts rename to x-pack/plugins/uptime/server/graphql/monitors/resolvers.ts index 19f23fa1bb934..b39c5f42bfd75 100644 --- a/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts +++ b/x-pack/plugins/uptime/server/graphql/monitors/resolvers.ts @@ -4,11 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UMResolver } from '../../../common/graphql/resolver_types'; -import { GetMonitorChartsDataQueryArgs, MonitorChart } from '../../../common/graphql/types'; +import { UMGqlRange } from '../../../../../legacy/plugins/uptime/common/domain_types'; +import { UMResolver } from '../../../../../legacy/plugins/uptime/common/graphql/resolver_types'; +import { + GetMonitorChartsDataQueryArgs, + MonitorChart, +} from '../../../../../legacy/plugins/uptime/common/graphql/types'; import { UMServerLibs } from '../../lib/lib'; import { CreateUMGraphQLResolvers, UMContext } from '../types'; +export type UMMonitorsResolver = UMResolver, any, UMGqlRange, UMContext>; + export type UMGetMonitorChartsResolver = UMResolver< any | Promise, any, diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/monitors/schema.gql.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts rename to x-pack/plugins/uptime/server/graphql/monitors/schema.gql.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/pings/index.ts b/x-pack/plugins/uptime/server/graphql/pings/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/pings/index.ts rename to x-pack/plugins/uptime/server/graphql/pings/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/pings/resolvers.ts b/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts similarity index 84% rename from x-pack/legacy/plugins/uptime/server/graphql/pings/resolvers.ts rename to x-pack/plugins/uptime/server/graphql/pings/resolvers.ts index de83a9ced16b2..b383fc5d5fb15 100644 --- a/x-pack/legacy/plugins/uptime/server/graphql/pings/resolvers.ts +++ b/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts @@ -4,8 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UMResolver } from '../../../common/graphql/resolver_types'; -import { AllPingsQueryArgs, PingResults } from '../../../common/graphql/types'; +import { UMResolver } from '../../../../../legacy/plugins/uptime/common/graphql/resolver_types'; +import { + AllPingsQueryArgs, + PingResults, +} from '../../../../../legacy/plugins/uptime/common/graphql/types'; import { UMServerLibs } from '../../lib/lib'; import { UMContext } from '../types'; import { CreateUMGraphQLResolvers } from '../types'; diff --git a/x-pack/legacy/plugins/uptime/server/graphql/pings/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/pings/schema.gql.ts rename to x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/types.ts b/x-pack/plugins/uptime/server/graphql/types.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/types.ts rename to x-pack/plugins/uptime/server/graphql/types.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts rename to x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_literal.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts rename to x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/parse_value.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts rename to x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/__tests__/serialize.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts rename to x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts rename to x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/resolvers.ts diff --git a/x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts rename to x-pack/plugins/uptime/server/graphql/unsigned_int_scalar/schema.gql.ts diff --git a/x-pack/legacy/plugins/uptime/server/index.ts b/x-pack/plugins/uptime/server/index.ts similarity index 59% rename from x-pack/legacy/plugins/uptime/server/index.ts rename to x-pack/plugins/uptime/server/index.ts index d063f0d8c2288..bec47fa9db4cf 100644 --- a/x-pack/legacy/plugins/uptime/server/index.ts +++ b/x-pack/plugins/uptime/server/index.ts @@ -4,5 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import { PluginInitializerContext } from '../../../../src/core/server'; +import { Plugin } from './plugin'; + export { initServerWithKibana, KibanaServer } from './kibana.index'; -export { plugin } from './plugin'; +export const plugin = (initializerContext: PluginInitializerContext) => + new Plugin(initializerContext); diff --git a/x-pack/legacy/plugins/uptime/server/kibana.index.ts b/x-pack/plugins/uptime/server/kibana.index.ts similarity index 82% rename from x-pack/legacy/plugins/uptime/server/kibana.index.ts rename to x-pack/plugins/uptime/server/kibana.index.ts index 73fabc629946b..c7ac3a70c0494 100644 --- a/x-pack/legacy/plugins/uptime/server/kibana.index.ts +++ b/x-pack/plugins/uptime/server/kibana.index.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import { Request, Server } from 'hapi'; -import { PLUGIN } from '../common/constants'; +import { PLUGIN } from '../../../legacy/plugins/uptime/common/constants'; import { KibanaTelemetryAdapter } from './lib/adapters/telemetry'; import { compose } from './lib/compose/kibana'; import { initUptimeServer } from './uptime_server'; @@ -25,17 +24,13 @@ export interface KibanaServer extends Server { } export const initServerWithKibana = (server: UptimeCoreSetup, plugins: UptimeCorePlugins) => { - const { usageCollection, xpack } = plugins; - const libs = compose(server, plugins); + const { features, usageCollection } = plugins; + const libs = compose(server); KibanaTelemetryAdapter.registerUsageCollector(usageCollection); - initUptimeServer(libs); - - xpack.registerFeature({ + features.registerFeature({ id: PLUGIN.ID, - name: i18n.translate('xpack.uptime.featureRegistry.uptimeFeatureName', { - defaultMessage: 'Uptime', - }), + name: PLUGIN.NAME, navLinkId: PLUGIN.ID, icon: 'uptimeApp', app: ['uptime', 'kibana'], @@ -59,4 +54,6 @@ export const initServerWithKibana = (server: UptimeCoreSetup, plugins: UptimeCor }, }, }); + + initUptimeServer(libs); }; diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts similarity index 85% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/framework/adapter_types.ts rename to x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts index fb2052bb4c87f..8dde6050d5d36 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/uptime/server/lib/adapters/framework/adapter_types.ts @@ -6,13 +6,9 @@ import { GraphQLSchema } from 'graphql'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { - SavedObjectsLegacyService, - IRouter, - CallAPIOptions, - SavedObjectsClientContract, -} from 'src/core/server'; +import { IRouter, CallAPIOptions, SavedObjectsClientContract } from 'src/core/server'; import { UMKibanaRoute } from '../../../rest_api'; +import { PluginSetupContract } from '../../../../../features/server'; type APICaller = ( endpoint: string, @@ -34,9 +30,8 @@ export interface UptimeCoreSetup { } export interface UptimeCorePlugins { - savedObjects: SavedObjectsLegacyService; + features: PluginSetupContract; usageCollection: UsageCollectionSetup; - xpack: any; } export interface UMBackendFrameworkAdapter { diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/index.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/framework/index.ts rename to x-pack/plugins/uptime/server/lib/adapters/framework/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts rename to x-pack/plugins/uptime/server/lib/adapters/framework/kibana_framework_adapter.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/index.ts b/x-pack/plugins/uptime/server/lib/adapters/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/index.ts rename to x-pack/plugins/uptime/server/lib/adapters/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/__tests__/__snapshots__/kibana_telemetry_adapter.test.ts.snap b/x-pack/plugins/uptime/server/lib/adapters/telemetry/__tests__/__snapshots__/kibana_telemetry_adapter.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/__tests__/__snapshots__/kibana_telemetry_adapter.test.ts.snap rename to x-pack/plugins/uptime/server/lib/adapters/telemetry/__tests__/__snapshots__/kibana_telemetry_adapter.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/__tests__/kibana_telemetry_adapter.test.ts b/x-pack/plugins/uptime/server/lib/adapters/telemetry/__tests__/kibana_telemetry_adapter.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/__tests__/kibana_telemetry_adapter.test.ts rename to x-pack/plugins/uptime/server/lib/adapters/telemetry/__tests__/kibana_telemetry_adapter.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/index.ts b/x-pack/plugins/uptime/server/lib/adapters/telemetry/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/index.ts rename to x-pack/plugins/uptime/server/lib/adapters/telemetry/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts b/x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts rename to x-pack/plugins/uptime/server/lib/adapters/telemetry/kibana_telemetry_adapter.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/compose/kibana.ts b/x-pack/plugins/uptime/server/lib/compose/kibana.ts similarity index 80% rename from x-pack/legacy/plugins/uptime/server/lib/compose/kibana.ts rename to x-pack/plugins/uptime/server/lib/compose/kibana.ts index 875a5d9dc8c5c..edda5cb283323 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/compose/kibana.ts +++ b/x-pack/plugins/uptime/server/lib/compose/kibana.ts @@ -8,9 +8,9 @@ import { UMKibanaBackendFrameworkAdapter } from '../adapters/framework'; import * as requests from '../requests'; import { licenseCheck } from '../domains'; import { UMDomainLibs, UMServerLibs } from '../lib'; -import { UptimeCorePlugins, UptimeCoreSetup } from '../adapters/framework'; +import { UptimeCoreSetup } from '../adapters/framework'; -export function compose(server: UptimeCoreSetup, plugins: UptimeCorePlugins): UMServerLibs { +export function compose(server: UptimeCoreSetup): UMServerLibs { const framework = new UMKibanaBackendFrameworkAdapter(server); const domainLibs: UMDomainLibs = { diff --git a/x-pack/legacy/plugins/uptime/server/lib/domains/__tests__/__snapshots__/license.test.ts.snap b/x-pack/plugins/uptime/server/lib/domains/__tests__/__snapshots__/license.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/domains/__tests__/__snapshots__/license.test.ts.snap rename to x-pack/plugins/uptime/server/lib/domains/__tests__/__snapshots__/license.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/domains/__tests__/license.test.ts b/x-pack/plugins/uptime/server/lib/domains/__tests__/license.test.ts similarity index 93% rename from x-pack/legacy/plugins/uptime/server/lib/domains/__tests__/license.test.ts rename to x-pack/plugins/uptime/server/lib/domains/__tests__/license.test.ts index 8c47b318da9bd..b842f55fc7579 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/domains/__tests__/license.test.ts +++ b/x-pack/plugins/uptime/server/lib/domains/__tests__/license.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ILicense } from '../../../../../../../plugins/licensing/server'; +import { ILicense } from '../../../../../licensing/server'; import { licenseCheck } from '../license'; describe('license check', () => { diff --git a/x-pack/legacy/plugins/uptime/server/lib/domains/index.ts b/x-pack/plugins/uptime/server/lib/domains/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/domains/index.ts rename to x-pack/plugins/uptime/server/lib/domains/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/domains/license.ts b/x-pack/plugins/uptime/server/lib/domains/license.ts similarity index 93% rename from x-pack/legacy/plugins/uptime/server/lib/domains/license.ts rename to x-pack/plugins/uptime/server/lib/domains/license.ts index b8b5722d79877..d272424379e48 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/domains/license.ts +++ b/x-pack/plugins/uptime/server/lib/domains/license.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ILicense } from '../../../../../../plugins/licensing/server'; +import { ILicense } from '../../../../licensing/server'; export interface UMLicenseStatusResponse { statusCode: number; diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/assert_close_to.test.ts.snap b/x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/assert_close_to.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/assert_close_to.test.ts.snap rename to x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/assert_close_to.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filter_clause.test.ts.snap b/x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filter_clause.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filter_clause.test.ts.snap rename to x-pack/plugins/uptime/server/lib/helper/__test__/__snapshots__/get_filter_clause.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/assert_close_to.test.ts b/x-pack/plugins/uptime/server/lib/helper/__test__/assert_close_to.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/__test__/assert_close_to.test.ts rename to x-pack/plugins/uptime/server/lib/helper/__test__/assert_close_to.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_filter_clause.test.ts b/x-pack/plugins/uptime/server/lib/helper/__test__/get_filter_clause.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_filter_clause.test.ts rename to x-pack/plugins/uptime/server/lib/helper/__test__/get_filter_clause.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts b/x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts rename to x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts b/x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts rename to x-pack/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/parse_relative_date.test.ts b/x-pack/plugins/uptime/server/lib/helper/__test__/parse_relative_date.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/__test__/parse_relative_date.test.ts rename to x-pack/plugins/uptime/server/lib/helper/__test__/parse_relative_date.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/assert_close_to.ts b/x-pack/plugins/uptime/server/lib/helper/assert_close_to.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/assert_close_to.ts rename to x-pack/plugins/uptime/server/lib/helper/assert_close_to.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/get_filter_clause.ts b/x-pack/plugins/uptime/server/lib/helper/get_filter_clause.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/get_filter_clause.ts rename to x-pack/plugins/uptime/server/lib/helper/get_filter_clause.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval.ts b/x-pack/plugins/uptime/server/lib/helper/get_histogram_interval.ts similarity index 95% rename from x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval.ts rename to x-pack/plugins/uptime/server/lib/helper/get_histogram_interval.ts index 26515fb4b4c63..fb44f5727aab3 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval.ts +++ b/x-pack/plugins/uptime/server/lib/helper/get_histogram_interval.ts @@ -5,7 +5,7 @@ */ import DateMath from '@elastic/datemath'; -import { QUERY } from '../../../common/constants'; +import { QUERY } from '../../../../../legacy/plugins/uptime/common/constants'; export const parseRelativeDate = (dateStr: string, options = {}) => { // We need this this parsing because if user selects This week or this date diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts b/x-pack/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts rename to x-pack/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts b/x-pack/plugins/uptime/server/lib/helper/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/index.ts rename to x-pack/plugins/uptime/server/lib/helper/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/make_date_rate_filter.ts b/x-pack/plugins/uptime/server/lib/helper/make_date_rate_filter.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/make_date_rate_filter.ts rename to x-pack/plugins/uptime/server/lib/helper/make_date_rate_filter.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/object_to_array.ts b/x-pack/plugins/uptime/server/lib/helper/object_to_array.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/helper/object_to_array.ts rename to x-pack/plugins/uptime/server/lib/helper/object_to_array.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/lib.ts b/x-pack/plugins/uptime/server/lib/lib.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/lib.ts rename to x-pack/plugins/uptime/server/lib/lib.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/extract_filter_aggs_results.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/extract_filter_aggs_results.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/extract_filter_aggs_results.test.ts.snap rename to x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/extract_filter_aggs_results.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/generate_filter_aggs.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/generate_filter_aggs.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/generate_filter_aggs.test.ts.snap rename to x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/generate_filter_aggs.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap rename to x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_monitor_charts.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap rename to x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/combine_range_with_filters.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/combine_range_with_filters.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/combine_range_with_filters.test.ts rename to x-pack/plugins/uptime/server/lib/requests/__tests__/combine_range_with_filters.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/extract_filter_aggs_results.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/extract_filter_aggs_results.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/extract_filter_aggs_results.test.ts rename to x-pack/plugins/uptime/server/lib/requests/__tests__/extract_filter_aggs_results.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/generate_filter_aggs.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/generate_filter_aggs.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/generate_filter_aggs.test.ts rename to x-pack/plugins/uptime/server/lib/requests/__tests__/generate_filter_aggs.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts rename to x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts rename to x-pack/plugins/uptime/server/lib/requests/__tests__/get_monitor_charts.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts rename to x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts rename to x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json b/x-pack/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json rename to x-pack/plugins/uptime/server/lib/requests/__tests__/monitor_charts_mock.json diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/generate_filter_aggs.ts b/x-pack/plugins/uptime/server/lib/requests/generate_filter_aggs.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/generate_filter_aggs.ts rename to x-pack/plugins/uptime/server/lib/requests/generate_filter_aggs.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_filter_bar.ts b/x-pack/plugins/uptime/server/lib/requests/get_filter_bar.ts similarity index 94% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_filter_bar.ts rename to x-pack/plugins/uptime/server/lib/requests/get_filter_bar.ts index 79259afe2b9eb..affe205a46844 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_filter_bar.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_filter_bar.ts @@ -5,9 +5,9 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { OverviewFilters } from '../../../common/runtime_types'; +import { OverviewFilters } from '../../../../../legacy/plugins/uptime/common/runtime_types'; import { generateFilterAggs } from './generate_filter_aggs'; -import { INDEX_NAMES } from '../../../common/constants'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; export interface GetFilterBarParams { /** @param dateRangeStart timestamp bounds */ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_index_pattern.ts b/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts similarity index 92% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_index_pattern.ts rename to x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts index 4b40f800b6779..1ba1eb62e8439 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_index_pattern.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_index_pattern.ts @@ -6,8 +6,8 @@ import { APICaller } from 'src/core/server'; import { UMElasticsearchQueryFn } from '../adapters'; -import { IndexPatternsFetcher, IIndexPattern } from '../../../../../../../src/plugins/data/server'; -import { INDEX_NAMES } from '../../../common/constants'; +import { IndexPatternsFetcher, IIndexPattern } from '../../../../../../src/plugins/data/server'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; export const getUptimeIndexPattern: UMElasticsearchQueryFn = async callES => { const indexPatternsFetcher = new IndexPatternsFetcher((...rest: Parameters) => diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_index_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts similarity index 76% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_index_status.ts rename to x-pack/plugins/uptime/server/lib/requests/get_index_status.ts index e801b05d057f4..95aa7eeef88e1 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_index_status.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts @@ -5,8 +5,8 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { StatesIndexStatus } from '../../../common/graphql/types'; -import { INDEX_NAMES } from '../../../common/constants'; +import { StatesIndexStatus } from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; export const getIndexStatus: UMElasticsearchQueryFn<{}, StatesIndexStatus> = async ({ callES }) => { const { diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts similarity index 91% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_latest_monitor.ts rename to x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts index bfaee3f2bf7ee..2d549fce06884 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_latest_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts @@ -5,8 +5,8 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Ping } from '../../../common/graphql/types'; -import { INDEX_NAMES } from '../../../common/constants'; +import { Ping } from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; export interface GetLatestMonitorParams { /** @member dateRangeStart timestamp bounds */ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor.ts similarity index 87% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor.ts rename to x-pack/plugins/uptime/server/lib/requests/get_monitor.ts index 94175616f374e..20103042f19ab 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor.ts @@ -5,8 +5,8 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Ping } from '../../../common/graphql/types'; -import { INDEX_NAMES } from '../../../common/constants'; +import { Ping } from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; export interface GetMonitorParams { /** @member monitorId optional limit to monitorId */ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_charts.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_charts.ts similarity index 96% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_charts.ts rename to x-pack/plugins/uptime/server/lib/requests/get_monitor_charts.ts index b97cc7287e921..7dd17ef9aa80f 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_charts.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_charts.ts @@ -5,9 +5,12 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { INDEX_NAMES } from '../../../common/constants'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; import { getHistogramIntervalFormatted } from '../helper'; -import { MonitorChart, LocationDurationLine } from '../../../common/graphql/types'; +import { + MonitorChart, + LocationDurationLine, +} from '../../../../../legacy/plugins/uptime/common/graphql/types'; export interface GetMonitorChartsParams { /** @member monitorId ID value for the selected monitor */ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_details.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts similarity index 88% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_details.ts rename to x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts index b516fde1ce844..eb3657e60a7bb 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_details.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts @@ -5,8 +5,11 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { MonitorDetails, MonitorError } from '../../../common/runtime_types'; -import { INDEX_NAMES } from '../../../common/constants'; +import { + MonitorDetails, + MonitorError, +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; export interface GetMonitorDetailsParams { monitorId: string; diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_locations.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_locations.ts similarity index 92% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_locations.ts rename to x-pack/plugins/uptime/server/lib/requests/get_monitor_locations.ts index e1a0e14fe951d..328ef54c404d3 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_locations.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_locations.ts @@ -5,8 +5,14 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { INDEX_NAMES, UNNAMED_LOCATION } from '../../../common/constants'; -import { MonitorLocations, MonitorLocation } from '../../../common/runtime_types'; +import { + INDEX_NAMES, + UNNAMED_LOCATION, +} from '../../../../../legacy/plugins/uptime/common/constants'; +import { + MonitorLocations, + MonitorLocation, +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; /** * Fetch data for the monitor page title. diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_states.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts similarity index 89% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_states.ts rename to x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts index 32c82b1fa2098..5b02e2502a27e 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_monitor_states.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_states.ts @@ -4,10 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CONTEXT_DEFAULTS } from '../../../common/constants'; +import { CONTEXT_DEFAULTS } from '../../../../../legacy/plugins/uptime/common/constants'; import { fetchPage } from './search'; import { UMElasticsearchQueryFn } from '../adapters'; -import { MonitorSummary, SortOrder, CursorDirection } from '../../../common/graphql/types'; +import { + MonitorSummary, + SortOrder, + CursorDirection, +} from '../../../../../legacy/plugins/uptime/common/graphql/types'; import { QueryContext } from './search'; export interface CursorPagination { diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_ping_histogram.ts b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts similarity index 93% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_ping_histogram.ts rename to x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts index 7b8ca4708255c..339409b63a4f6 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_ping_histogram.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts @@ -5,10 +5,10 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; +import { INDEX_NAMES, QUERY } from '../../../../../legacy/plugins/uptime/common/constants'; import { getFilterClause } from '../helper'; -import { INDEX_NAMES, QUERY } from '../../../common/constants'; import { HistogramQueryResult } from './types'; -import { HistogramResult } from '../../../common/types'; +import { HistogramResult } from '../../../../../legacy/plugins/uptime/common/types'; export interface GetPingHistogramParams { /** @member dateRangeStart timestamp bounds */ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_pings.ts b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts similarity index 93% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_pings.ts rename to x-pack/plugins/uptime/server/lib/requests/get_pings.ts index 381aca720dc1d..ddca27d782066 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_pings.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts @@ -5,8 +5,12 @@ */ import { UMElasticsearchQueryFn } from '../adapters/framework'; -import { PingResults, Ping, HttpBody } from '../../../common/graphql/types'; -import { INDEX_NAMES } from '../../../common/constants'; +import { + PingResults, + Ping, + HttpBody, +} from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { INDEX_NAMES } from '../../../../../legacy/plugins/uptime/common/constants'; export interface GetPingsParams { /** @member dateRangeStart timestamp bounds */ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/get_snapshot_counts.ts b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts similarity index 96% rename from x-pack/legacy/plugins/uptime/server/lib/requests/get_snapshot_counts.ts rename to x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts index 8d84c0f4d6769..050e906f01c62 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/get_snapshot_counts.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts @@ -5,9 +5,12 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Snapshot } from '../../../common/runtime_types'; +import { Snapshot } from '../../../../../legacy/plugins/uptime/common/runtime_types'; +import { + CONTEXT_DEFAULTS, + INDEX_NAMES, +} from '../../../../../legacy/plugins/uptime/common/constants'; import { QueryContext } from './search'; -import { CONTEXT_DEFAULTS, INDEX_NAMES } from '../../../common/constants'; export interface GetSnapshotCountParams { dateRangeStart: string; diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/index.ts b/x-pack/plugins/uptime/server/lib/requests/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/index.ts rename to x-pack/plugins/uptime/server/lib/requests/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts similarity index 96% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts rename to x-pack/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts index d519a4e75463f..f542773f32796 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/fetch_page.test.ts @@ -12,7 +12,7 @@ import { MonitorGroupsPage, } from '../fetch_page'; import { QueryContext } from '../query_context'; -import { MonitorSummary } from '../../../../../common/graphql/types'; +import { MonitorSummary } from '../../../../../../../legacy/plugins/uptime/common/graphql/types'; import { nextPagination, prevPagination, simpleQueryContext } from './test_helpers'; const simpleFixture: MonitorGroups[] = [ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/monitor_group_iterator.test.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/monitor_group_iterator.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/monitor_group_iterator.test.ts rename to x-pack/plugins/uptime/server/lib/requests/search/__tests__/monitor_group_iterator.test.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts similarity index 95% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts rename to x-pack/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts index 86506c2c4c044..ea81ec623e01c 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/query_context.test.ts @@ -6,7 +6,10 @@ import { QueryContext } from '../query_context'; import { CursorPagination } from '../types'; -import { CursorDirection, SortOrder } from '../../../../../common/graphql/types'; +import { + CursorDirection, + SortOrder, +} from '../../../../../../../legacy/plugins/uptime/common/graphql/types'; describe(QueryContext, () => { // 10 minute range diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts similarity index 88% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts rename to x-pack/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts index 98b192d14f91a..d96f8dc95aa72 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/test_helpers.ts @@ -5,7 +5,10 @@ */ import { CursorPagination } from '../types'; -import { CursorDirection, SortOrder } from '../../../../../common/graphql/types'; +import { + CursorDirection, + SortOrder, +} from '../../../../../../../legacy/plugins/uptime/common/graphql/types'; import { QueryContext } from '../query_context'; export const prevPagination = (key: any): CursorPagination => { diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts b/x-pack/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts similarity index 98% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts rename to x-pack/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts index e37c749e63566..9ad3928a3b1b2 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/enrich_monitor_groups.ts @@ -7,14 +7,14 @@ import { get, sortBy } from 'lodash'; import { QueryContext } from './query_context'; import { getHistogramIntervalFormatted } from '../../helper'; -import { INDEX_NAMES, STATES } from '../../../../common/constants'; +import { INDEX_NAMES, STATES } from '../../../../../../legacy/plugins/uptime/common/constants'; import { MonitorSummary, SummaryHistogram, Check, CursorDirection, SortOrder, -} from '../../../../common/graphql/types'; +} from '../../../../../../legacy/plugins/uptime/common/graphql/types'; import { MonitorEnricher } from './fetch_page'; export const enrichMonitorGroups: MonitorEnricher = async ( diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/fetch_chunk.ts b/x-pack/plugins/uptime/server/lib/requests/search/fetch_chunk.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/fetch_chunk.ts rename to x-pack/plugins/uptime/server/lib/requests/search/fetch_chunk.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/fetch_page.ts b/x-pack/plugins/uptime/server/lib/requests/search/fetch_page.ts similarity index 96% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/fetch_page.ts rename to x-pack/plugins/uptime/server/lib/requests/search/fetch_page.ts index 6440850dc0ffc..62144dacbd377 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/fetch_page.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/fetch_page.ts @@ -7,8 +7,12 @@ import { flatten } from 'lodash'; import { CursorPagination } from './types'; import { QueryContext } from './query_context'; -import { QUERY } from '../../../../common/constants'; -import { CursorDirection, MonitorSummary, SortOrder } from '../../../../common/graphql/types'; +import { QUERY } from '../../../../../../legacy/plugins/uptime/common/constants'; +import { + CursorDirection, + MonitorSummary, + SortOrder, +} from '../../../../../../legacy/plugins/uptime/common/graphql/types'; import { enrichMonitorGroups } from './enrich_monitor_groups'; import { MonitorGroupIterator } from './monitor_group_iterator'; diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/find_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts similarity index 95% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/find_potential_matches.ts rename to x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts index fc0e35b279e0b..9b3b1186472be 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/find_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts @@ -5,8 +5,8 @@ */ import { get, set } from 'lodash'; -import { CursorDirection } from '../../../../common/graphql/types'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/graphql/types'; +import { INDEX_NAMES } from '../../../../../../legacy/plugins/uptime/common/constants'; import { QueryContext } from './query_context'; // This is the first phase of the query. In it, we find the most recent check groups that matched the given query. diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/index.ts b/x-pack/plugins/uptime/server/lib/requests/search/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/index.ts rename to x-pack/plugins/uptime/server/lib/requests/search/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts b/x-pack/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts similarity index 98% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts rename to x-pack/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts index ced557dbf62e0..267551907c5e8 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/monitor_group_iterator.ts @@ -6,7 +6,7 @@ import { QueryContext } from './query_context'; import { fetchChunk } from './fetch_chunk'; -import { CursorDirection } from '../../../../common/graphql/types'; +import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/graphql/types'; import { MonitorGroups } from './fetch_page'; import { CursorPagination } from './types'; diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/query_context.ts b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts similarity index 97% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/query_context.ts rename to x-pack/plugins/uptime/server/lib/requests/search/query_context.ts index f5b13c165d87d..c1f5d89ec1a38 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/query_context.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/query_context.ts @@ -6,7 +6,7 @@ import moment from 'moment'; import { APICaller } from 'src/core/server'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../../../../legacy/plugins/uptime/common/constants'; import { CursorPagination } from './types'; import { parseRelativeDate } from '../../helper'; diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts similarity index 96% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts rename to x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts index a55301555c8bf..c55aff3e8c4cd 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../../../../legacy/plugins/uptime/common/constants'; import { QueryContext } from './query_context'; -import { CursorDirection } from '../../../../common/graphql/types'; +import { CursorDirection } from '../../../../../../legacy/plugins/uptime/common/graphql/types'; import { MonitorGroups, MonitorLocCheckGroup } from './fetch_page'; /** diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/search/types.ts b/x-pack/plugins/uptime/server/lib/requests/search/types.ts similarity index 76% rename from x-pack/legacy/plugins/uptime/server/lib/requests/search/types.ts rename to x-pack/plugins/uptime/server/lib/requests/search/types.ts index dc6021a91146a..42c98ace6e8f5 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/search/types.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/types.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CursorDirection, SortOrder } from '../../../../common/graphql/types'; +import { + CursorDirection, + SortOrder, +} from '../../../../../../legacy/plugins/uptime/common/graphql/types'; export interface CursorPagination { cursorKey?: any; diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/types.ts b/x-pack/plugins/uptime/server/lib/requests/types.ts similarity index 89% rename from x-pack/legacy/plugins/uptime/server/lib/requests/types.ts rename to x-pack/plugins/uptime/server/lib/requests/types.ts index e17eb546712a9..53a4e989e3789 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/types.ts +++ b/x-pack/plugins/uptime/server/lib/requests/types.ts @@ -4,9 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Ping, PingResults } from '../../../common/graphql/types'; +import { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/graphql/types'; import { UMElasticsearchQueryFn } from '../adapters'; -import { GetPingHistogramParams, HistogramResult } from '../../../common/types'; +import { + GetPingHistogramParams, + HistogramResult, +} from '../../../../../legacy/plugins/uptime/common/types'; export interface GetAllParams { /** @member dateRangeStart timestamp bounds */ diff --git a/x-pack/legacy/plugins/uptime/server/lib/requests/uptime_requests.ts b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts similarity index 83% rename from x-pack/legacy/plugins/uptime/server/lib/requests/uptime_requests.ts rename to x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts index 73be850306202..8a411368c228f 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/requests/uptime_requests.ts +++ b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts @@ -5,7 +5,12 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Ping, MonitorChart, PingResults, StatesIndexStatus } from '../../../common/graphql/types'; +import { + Ping, + MonitorChart, + PingResults, + StatesIndexStatus, +} from '../../../../../legacy/plugins/uptime/common/graphql/types'; import { GetFilterBarParams, GetLatestMonitorParams, @@ -22,10 +27,10 @@ import { MonitorDetails, MonitorLocations, Snapshot, -} from '../../../common/runtime_types'; +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; import { GetMonitorStatesResult } from './get_monitor_states'; import { GetSnapshotCountParams } from './get_snapshot_counts'; -import { HistogramResult } from '../../../common/types'; +import { HistogramResult } from '../../../../../legacy/plugins/uptime/common/types'; type ESQ = UMElasticsearchQueryFn; diff --git a/x-pack/plugins/uptime/server/plugin.ts b/x-pack/plugins/uptime/server/plugin.ts new file mode 100644 index 0000000000000..e217b0e2f1ad8 --- /dev/null +++ b/x-pack/plugins/uptime/server/plugin.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializerContext, CoreStart, CoreSetup } from '../../../../src/core/server'; +import { initServerWithKibana } from './kibana.index'; +import { UptimeCorePlugins } from './lib/adapters'; + +export class Plugin { + constructor(_initializerContext: PluginInitializerContext) {} + public setup(core: CoreSetup, plugins: UptimeCorePlugins) { + initServerWithKibana({ route: core.http.createRouter() }, plugins); + } + public start(_core: CoreStart, _plugins: any) {} +} diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/create_route_with_auth.ts b/x-pack/plugins/uptime/server/rest_api/create_route_with_auth.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/create_route_with_auth.ts rename to x-pack/plugins/uptime/server/rest_api/create_route_with_auth.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/index.ts rename to x-pack/plugins/uptime/server/rest_api/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/index_pattern/get_index_pattern.ts b/x-pack/plugins/uptime/server/rest_api/index_pattern/get_index_pattern.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/index_pattern/get_index_pattern.ts rename to x-pack/plugins/uptime/server/rest_api/index_pattern/get_index_pattern.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/index_pattern/index.ts b/x-pack/plugins/uptime/server/rest_api/index_pattern/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/index_pattern/index.ts rename to x-pack/plugins/uptime/server/rest_api/index_pattern/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/monitors/index.ts b/x-pack/plugins/uptime/server/rest_api/monitors/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/monitors/index.ts rename to x-pack/plugins/uptime/server/rest_api/monitors/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/monitors/monitor_locations.ts b/x-pack/plugins/uptime/server/rest_api/monitors/monitor_locations.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/monitors/monitor_locations.ts rename to x-pack/plugins/uptime/server/rest_api/monitors/monitor_locations.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/monitors/monitors_details.ts b/x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/monitors/monitors_details.ts rename to x-pack/plugins/uptime/server/rest_api/monitors/monitors_details.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/monitors/status.ts b/x-pack/plugins/uptime/server/rest_api/monitors/status.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/monitors/status.ts rename to x-pack/plugins/uptime/server/rest_api/monitors/status.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/overview_filters/get_overview_filters.ts b/x-pack/plugins/uptime/server/rest_api/overview_filters/get_overview_filters.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/overview_filters/get_overview_filters.ts rename to x-pack/plugins/uptime/server/rest_api/overview_filters/get_overview_filters.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/overview_filters/index.ts b/x-pack/plugins/uptime/server/rest_api/overview_filters/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/overview_filters/index.ts rename to x-pack/plugins/uptime/server/rest_api/overview_filters/index.ts diff --git a/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts new file mode 100644 index 0000000000000..21168edfc9744 --- /dev/null +++ b/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts @@ -0,0 +1,48 @@ +/* + * 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 } from '@kbn/config-schema'; +import { UMServerLibs } from '../../lib/lib'; +import { UMRestApiRouteFactory } from '../types'; + +export const createGetAllRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({ + method: 'GET', + path: '/api/uptime/pings', + validate: { + query: schema.object({ + dateRangeStart: schema.string(), + dateRangeEnd: schema.string(), + location: schema.maybe(schema.string()), + monitorId: schema.maybe(schema.string()), + size: schema.maybe(schema.number()), + sort: schema.maybe(schema.string()), + status: schema.maybe(schema.string()), + }), + }, + options: { + tags: ['access:uptime'], + }, + handler: async ({ callES }, _context, request, response): Promise => { + const { dateRangeStart, dateRangeEnd, location, monitorId, size, sort, status } = request.query; + + const result = await libs.requests.getPings({ + callES, + dateRangeStart, + dateRangeEnd, + monitorId, + status, + sort, + size, + location, + }); + + return response.ok({ + body: { + ...result, + }, + }); + }, +}); diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts rename to x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/pings/get_pings.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/pings/get_pings.ts rename to x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/pings/index.ts b/x-pack/plugins/uptime/server/rest_api/pings/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/pings/index.ts rename to x-pack/plugins/uptime/server/rest_api/pings/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts b/x-pack/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts rename to x-pack/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/snapshot/index.ts b/x-pack/plugins/uptime/server/rest_api/snapshot/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/snapshot/index.ts rename to x-pack/plugins/uptime/server/rest_api/snapshot/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/telemetry/index.ts b/x-pack/plugins/uptime/server/rest_api/telemetry/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/telemetry/index.ts rename to x-pack/plugins/uptime/server/rest_api/telemetry/index.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/telemetry/log_monitor_page.ts b/x-pack/plugins/uptime/server/rest_api/telemetry/log_monitor_page.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/telemetry/log_monitor_page.ts rename to x-pack/plugins/uptime/server/rest_api/telemetry/log_monitor_page.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/telemetry/log_overview_page.ts b/x-pack/plugins/uptime/server/rest_api/telemetry/log_overview_page.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/telemetry/log_overview_page.ts rename to x-pack/plugins/uptime/server/rest_api/telemetry/log_overview_page.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/types.ts b/x-pack/plugins/uptime/server/rest_api/types.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/types.ts rename to x-pack/plugins/uptime/server/rest_api/types.ts diff --git a/x-pack/legacy/plugins/uptime/server/rest_api/uptime_route_wrapper.ts b/x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/rest_api/uptime_route_wrapper.ts rename to x-pack/plugins/uptime/server/rest_api/uptime_route_wrapper.ts diff --git a/x-pack/legacy/plugins/uptime/server/uptime_server.ts b/x-pack/plugins/uptime/server/uptime_server.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/server/uptime_server.ts rename to x-pack/plugins/uptime/server/uptime_server.ts diff --git a/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts b/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts index 429f50ec0aa5b..0982d5fef7cb4 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/ping_histogram.ts @@ -6,7 +6,7 @@ import { expectFixtureEql } from '../graphql/helpers/expect_fixture_eql'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { assertCloseTo } from '../../../../../legacy/plugins/uptime/server/lib/helper'; +import { assertCloseTo } from '../../../../../plugins/uptime/server/lib/helper'; export default function({ getService }: FtrProviderContext) { describe('pingHistogram', () => { From 899270a108c5e47f5602c0f5c3b67a8502e47173 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 25 Feb 2020 15:31:04 +0100 Subject: [PATCH 10/11] [Upgrade Assistant] Move out of legacy folder (#58034) * Create x-pack/plugins skeleton for upgrade assistant * Move public folder contents Move the public folder of Upgrade Assistant and migrate public to use HttpSetup (remove axios) * Include stylesheets in public * Move server side out of legacy Begin migration of Reindex worker to new platform Move imports around so that it satsifies new platform constraints like not importing server side code (even types) in client. * Updated the routes with new dependencies and removed server shim * Fix router unit tests * Fix server lib tests After changing function signatures for the reindex server factory (and others) all of the tests needed to be revisited and brought in line with the new APIs. Also used core/server mocks where appropriate * Clean up types issues * Fix setting credentials on request header * Removed the security plugin from Upgrade Assistant The security plugin is a potential future consumer of the Upgrade Assistant's deprecation feature and we would therefore not want to create a circular depedency here. We pull in the licensing plugin rather (as it is less likely that we will depend on that) and use it to determine whether security is available and enabled. * Migrate to config to new platform config xpack.upgrade_assistant.enabled * Remove unused types * Fix import issue * Move upgrade assistant back to Elasticsearch management section * Update dotfiles Added elasticsearch ui team as upgrade assistant code owner Updated i18nrc.json path * Alphabetical ordering in xpack/i18nrc.json * Implemented PR feedback Renamed callCluster -> callAsUser to be more consistent with platform naming. Added comment about why we are not using security plugin directly inside of Upgrade Assistant. Fixed long path imports and use 'src/core/..' throughout. Fixed import ordering. Renamed variables inside of telemetry lib. * Revert to longer import path In plugin.ts importing from 'kibana/server' or 'src/core/server' results in a module not found error. Co-authored-by: Elastic Machine --- .github/CODEOWNERS | 2 + x-pack/.i18nrc.json | 2 +- .../legacy/plugins/upgrade_assistant/index.ts | 44 +--- .../plugins/upgrade_assistant/public/index.ts | 7 - .../upgrade_assistant/public/legacy.ts | 106 --------- .../public/np_ready/application/app.tsx | 40 ---- .../reindex/polling_service.test.mocks.ts | 24 -- .../public/np_ready/plugin.ts | 24 -- .../plugins/upgrade_assistant/server/index.ts | 7 - .../np_ready/lib/telemetry/es_ui_open_apis.ts | 47 ---- .../lib/telemetry/es_ui_reindex_apis.ts | 58 ----- .../server/np_ready/plugin.ts | 49 ---- .../server/np_ready/routes/cluster_checkup.ts | 46 ---- .../np_ready/routes/create_request_shim.ts | 16 -- .../np_ready/routes/deprecation_logging.ts | 57 ----- .../server/np_ready/routes/reindex_indices.ts | 207 ----------------- .../server/np_ready/types.ts | 29 --- .../upgrade_assistant/common/config.ts} | 10 +- .../plugins/upgrade_assistant/common/types.ts | 13 ++ .../upgrade_assistant/common/version.ts | 0 x-pack/plugins/upgrade_assistant/kibana.json | 9 + .../public/application/_index.scss} | 0 .../public/application/app.tsx | 44 ++++ .../public}/application/app_context.tsx | 1 - .../application/components/_index.scss | 0 .../application/components/error_banner.tsx | 0 .../components/latest_minor_banner.tsx | 2 +- .../application/components/tabs.test.tsx | 28 +-- .../public}/application/components/tabs.tsx | 9 +- .../__fixtures__/checkup_api_response.json | 0 .../__snapshots__/checkup_tab.test.tsx.snap | 0 .../__snapshots__/filter_bar.test.tsx.snap | 0 .../__snapshots__/group_by_bar.test.tsx.snap | 0 .../components/tabs/checkup/_index.scss | 0 .../tabs/checkup/checkup_tab.test.tsx | 0 .../components/tabs/checkup/checkup_tab.tsx | 2 +- .../components/tabs/checkup/constants.tsx | 0 .../components/tabs/checkup/controls.tsx | 0 .../tabs/checkup/deprecations/_cell.scss | 0 .../checkup/deprecations/_deprecations.scss | 0 .../tabs/checkup/deprecations/_index.scss | 0 .../tabs/checkup/deprecations/cell.tsx | 4 +- .../checkup/deprecations/count_summary.tsx | 2 +- .../checkup/deprecations/grouped.test.tsx | 2 +- .../tabs/checkup/deprecations/grouped.tsx | 2 +- .../tabs/checkup/deprecations/health.tsx | 0 .../tabs/checkup/deprecations/index.tsx | 0 .../checkup/deprecations/index_table.test.tsx | 0 .../tabs/checkup/deprecations/index_table.tsx | 4 +- .../tabs/checkup/deprecations/list.test.tsx | 2 +- .../tabs/checkup/deprecations/list.tsx | 2 +- .../checkup/deprecations/reindex/_button.scss | 0 .../checkup/deprecations/reindex/_index.scss | 0 .../checkup/deprecations/reindex/button.tsx | 7 +- .../checklist_step.test.tsx.snap | 0 .../__snapshots__/warning_step.test.tsx.snap | 0 .../deprecations/reindex/flyout/_index.scss | 0 .../reindex/flyout/_step_progress.scss | 0 .../reindex/flyout/_warnings_step.scss | 0 .../reindex/flyout/checklist_step.test.tsx | 2 +- .../reindex/flyout/checklist_step.tsx | 2 +- .../deprecations/reindex/flyout/container.tsx | 0 .../deprecations/reindex/flyout/index.tsx | 0 .../reindex/flyout/progress.test.tsx | 2 +- .../deprecations/reindex/flyout/progress.tsx | 2 +- .../reindex/flyout/step_progress.tsx | 0 .../reindex/flyout/warning_step.test.tsx | 2 +- .../reindex/flyout/warnings_step.tsx | 2 +- .../checkup/deprecations/reindex/index.tsx | 0 .../reindex/polling_service.test.ts | 67 ++---- .../deprecations/reindex/polling_service.ts | 29 +-- .../tabs/checkup/filter_bar.test.tsx | 0 .../components/tabs/checkup/filter_bar.tsx | 0 .../tabs/checkup/group_by_bar.test.tsx | 0 .../components/tabs/checkup/group_by_bar.tsx | 0 .../components/tabs/checkup/index.tsx | 0 .../components/tabs/overview/_index.scss | 0 .../components/tabs/overview/_steps.scss | 0 .../overview/deprecation_logging_toggle.tsx | 25 +- .../components/tabs/overview/index.tsx | 2 +- .../components/tabs/overview/steps.tsx | 6 +- .../public}/application/components/types.ts | 5 +- .../public/application/render_app.tsx | 20 ++ .../public}/application/utils.test.ts | 0 .../public}/application/utils.ts | 0 .../upgrade_assistant/public/index.scss | 1 + .../upgrade_assistant/public}/index.ts | 7 +- .../upgrade_assistant/public/plugin.ts | 48 ++++ .../plugins/upgrade_assistant/server/index.ts | 19 ++ .../lib/__fixtures__/fake_deprecations.json | 0 .../lib/__mocks__/es_version_precheck.ts | 0 .../es_migration_apis.test.ts.snap | 0 .../lib/es_deprecation_logging_apis.test.ts | 20 +- .../lib/es_deprecation_logging_apis.ts | 14 +- .../server}/lib/es_migration_apis.test.ts | 26 ++- .../server}/lib/es_migration_apis.ts | 27 +-- .../server}/lib/es_version_precheck.test.ts | 2 +- .../server}/lib/es_version_precheck.ts | 2 +- .../lib/reindexing/credential_store.test.ts | 2 +- .../lib/reindexing/credential_store.ts | 5 +- .../server}/lib/reindexing/index.ts | 0 .../lib/reindexing/index_settings.test.ts | 2 +- .../server}/lib/reindexing/index_settings.ts | 4 +- .../lib/reindexing/reindex_actions.test.ts | 4 +- .../server}/lib/reindexing/reindex_actions.ts | 9 +- .../lib/reindexing/reindex_service.test.ts | 93 ++++---- .../server}/lib/reindexing/reindex_service.ts | 70 +++--- .../server}/lib/reindexing/types.ts | 0 .../server}/lib/reindexing/worker.ts | 61 +++-- .../lib/telemetry/es_ui_open_apis.test.ts | 50 ++-- .../server/lib/telemetry/es_ui_open_apis.ts | 58 +++++ .../lib/telemetry/es_ui_reindex_apis.test.ts | 56 ++--- .../lib/telemetry/es_ui_reindex_apis.ts | 64 ++++++ .../server}/lib/telemetry/index.ts | 0 .../lib/telemetry/usage_collector.test.ts | 37 +-- .../server}/lib/telemetry/usage_collector.ts | 44 ++-- .../upgrade_assistant/server/plugin.ts | 125 ++++++++++ .../server}/routes/__mocks__/request.mock.ts | 2 +- .../server}/routes/__mocks__/routes.mock.ts | 16 +- .../server}/routes/cluster_checkup.test.ts | 44 ++-- .../server/routes/cluster_checkup.ts | 43 ++++ .../routes/deprecation_logging.test.ts | 52 +++-- .../server/routes/deprecation_logging.ts | 72 ++++++ .../server}/routes/reindex_indices.test.ts | 93 ++++---- .../server/routes/reindex_indices.ts | 217 ++++++++++++++++++ .../server}/routes/telemetry.test.ts | 58 +++-- .../server}/routes/telemetry.ts | 32 ++- .../plugins/upgrade_assistant/server/types.ts | 19 ++ .../upgrade_assistant/reindexing.js | 5 +- 129 files changed, 1234 insertions(+), 1343 deletions(-) delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/index.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/index.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts delete mode 100644 x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready/index.ts => plugins/upgrade_assistant/common/config.ts} (54%) rename x-pack/{legacy => }/plugins/upgrade_assistant/common/types.ts (88%) rename x-pack/{legacy => }/plugins/upgrade_assistant/common/version.ts (100%) create mode 100644 x-pack/plugins/upgrade_assistant/kibana.json rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss => plugins/upgrade_assistant/public/application/_index.scss} (100%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/app.tsx rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/app_context.tsx (98%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/_index.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/error_banner.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/latest_minor_banner.tsx (98%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs.test.tsx (82%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs.tsx (96%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/__fixtures__/checkup_api_response.json (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/_index.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/checkup_tab.test.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/checkup_tab.tsx (99%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/constants.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/controls.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/_cell.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/_deprecations.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/_index.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/cell.tsx (94%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/count_summary.tsx (93%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/grouped.test.tsx (98%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/grouped.tsx (98%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/health.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/index.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/index_table.test.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/index_table.tsx (96%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/list.test.tsx (96%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/list.tsx (97%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/_button.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/_index.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/button.tsx (97%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/__snapshots__/warning_step.test.tsx.snap (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/_index.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/_step_progress.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/_warnings_step.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/checklist_step.test.tsx (98%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/checklist_step.tsx (98%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/container.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/index.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/progress.test.tsx (99%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/progress.tsx (99%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/step_progress.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/warning_step.test.tsx (95%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx (99%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/index.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts (63%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/deprecations/reindex/polling_service.ts (82%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/filter_bar.test.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/filter_bar.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/group_by_bar.test.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/group_by_bar.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/checkup/index.tsx (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/overview/_index.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/overview/_steps.scss (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/overview/deprecation_logging_toggle.tsx (86%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/overview/index.tsx (96%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/tabs/overview/steps.tsx (98%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/components/types.ts (89%) create mode 100644 x-pack/plugins/upgrade_assistant/public/application/render_app.tsx rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/utils.test.ts (100%) rename x-pack/{legacy/plugins/upgrade_assistant/public/np_ready => plugins/upgrade_assistant/public}/application/utils.ts (100%) create mode 100644 x-pack/plugins/upgrade_assistant/public/index.scss rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/public}/index.ts (62%) create mode 100644 x-pack/plugins/upgrade_assistant/public/plugin.ts create mode 100644 x-pack/plugins/upgrade_assistant/server/index.ts rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/__fixtures__/fake_deprecations.json (100%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/__mocks__/es_version_precheck.ts (100%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/__snapshots__/es_migration_apis.test.ts.snap (100%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/es_deprecation_logging_apis.test.ts (75%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/es_deprecation_logging_apis.ts (75%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/es_migration_apis.test.ts (73%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/es_migration_apis.ts (75%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/es_version_precheck.test.ts (98%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/es_version_precheck.ts (98%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/credential_store.test.ts (95%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/credential_store.ts (91%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/index.ts (100%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/index_settings.test.ts (99%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/index_settings.ts (97%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/reindex_actions.test.ts (99%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/reindex_actions.ts (97%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/reindex_service.test.ts (95%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/reindex_service.ts (90%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/types.ts (100%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/reindexing/worker.ts (76%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/telemetry/es_ui_open_apis.test.ts (51%) create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/telemetry/es_ui_reindex_apis.test.ts (52%) create mode 100644 x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/telemetry/index.ts (100%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/telemetry/usage_collector.test.ts (78%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/lib/telemetry/usage_collector.ts (72%) create mode 100644 x-pack/plugins/upgrade_assistant/server/plugin.ts rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/routes/__mocks__/request.mock.ts (92%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/routes/__mocks__/routes.mock.ts (72%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/routes/cluster_checkup.test.ts (73%) create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/routes/deprecation_logging.test.ts (56%) create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/routes/reindex_indices.test.ts (80%) create mode 100644 x-pack/plugins/upgrade_assistant/server/routes/reindex_indices.ts rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/routes/telemetry.test.ts (79%) rename x-pack/{legacy/plugins/upgrade_assistant/server/np_ready => plugins/upgrade_assistant/server}/routes/telemetry.ts (66%) create mode 100644 x-pack/plugins/upgrade_assistant/server/types.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 51433f598ac16..b924c7a1a2c29 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -179,6 +179,8 @@ /x-pack/legacy/plugins/rollup/ @elastic/es-ui /x-pack/plugins/searchprofiler/ @elastic/es-ui /x-pack/legacy/plugins/snapshot_restore/ @elastic/es-ui +/x-pack/legacy/plugins/upgrade_assistant/ @elastic/es-ui +/x-pack/plugins/upgrade_assistant/ @elastic/es-ui /x-pack/plugins/watcher/ @elastic/es-ui # Endpoint diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index b1cb9075434e8..bb084b3bb72a1 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -40,7 +40,7 @@ "xpack.taskManager": "legacy/plugins/task_manager", "xpack.transform": "legacy/plugins/transform", "xpack.triggersActionsUI": "plugins/triggers_actions_ui", - "xpack.upgradeAssistant": "legacy/plugins/upgrade_assistant", + "xpack.upgradeAssistant": "plugins/upgrade_assistant", "xpack.uptime": "legacy/plugins/uptime", "xpack.watcher": "plugins/watcher" }, diff --git a/x-pack/legacy/plugins/upgrade_assistant/index.ts b/x-pack/legacy/plugins/upgrade_assistant/index.ts index 3f98ff60a91ce..b5e8ce4750215 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/index.ts +++ b/x-pack/legacy/plugins/upgrade_assistant/index.ts @@ -3,25 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; -import Joi from 'joi'; import { Legacy } from 'kibana'; -import { resolve } from 'path'; import mappings from './mappings.json'; -import { plugin } from './server/np_ready'; -import { CloudSetup } from '../../../plugins/cloud/server'; export function upgradeAssistant(kibana: any) { - const publicSrc = resolve(__dirname, 'public'); - const npSrc = resolve(publicSrc, 'np_ready'); - const config: Legacy.PluginSpecOptions = { id: 'upgrade_assistant', - configPrefix: 'xpack.upgrade_assistant', - require: ['elasticsearch'], uiExports: { // @ts-ignore - managementSections: ['plugins/upgrade_assistant'], savedObjectSchemas: { 'upgrade-assistant-reindex-operation': { isNamespaceAgnostic: true, @@ -30,41 +19,10 @@ export function upgradeAssistant(kibana: any) { isNamespaceAgnostic: true, }, }, - styleSheetPaths: resolve(npSrc, 'application/index.scss'), mappings, }, - publicDir: publicSrc, - - config() { - return Joi.object({ - enabled: Joi.boolean().default(true), - }).default(); - }, - - init(server: Legacy.Server) { - // Add server routes and initialize the plugin here - const instance = plugin({} as any); - const { usageCollection, cloud } = server.newPlatform.setup.plugins; - instance.setup(server.newPlatform.setup.core, { - usageCollection, - cloud: cloud as CloudSetup, - __LEGACY: { - // Legacy objects - events: server.events, - savedObjects: server.savedObjects, - - // Legacy functions - log: server.log.bind(server), - - // Legacy plugins - plugins: { - elasticsearch: server.plugins.elasticsearch, - xpack_main: server.plugins.xpack_main, - }, - }, - }); - }, + init() {}, }; return new kibana.Plugin(config); } diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/index.ts b/x-pack/legacy/plugins/upgrade_assistant/public/index.ts deleted file mode 100644 index d22b5d64b6b46..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/index.ts +++ /dev/null @@ -1,7 +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 * from './legacy'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts b/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts deleted file mode 100644 index b6bc6a14de224..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/legacy.ts +++ /dev/null @@ -1,106 +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 { ComponentType } from 'react'; -import { i18n } from '@kbn/i18n'; - -/* LEGACY IMPORTS */ -import { npSetup } from 'ui/new_platform'; -import { wrapInI18nContext } from 'ui/i18n'; -import { management } from 'ui/management'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -import routes from 'ui/routes'; -import chrome from 'ui/chrome'; -/* LEGACY IMPORTS */ - -import { NEXT_MAJOR_VERSION } from '../common/version'; -import { plugin } from './np_ready'; -import { CloudSetup } from '../../../../plugins/cloud/public'; - -const BASE_PATH = `/management/elasticsearch/upgrade_assistant`; - -export interface LegacyAppMountParameters { - __LEGACY: { renderToElement: (RootComponent: ComponentType) => void }; -} - -export interface LegacyApp { - mount(ctx: any, params: LegacyAppMountParameters): void; -} - -export interface LegacyManagementPlugin { - sections: { - get( - name: string - ): { - registerApp(app: LegacyApp): void; - }; - }; -} - -// Based on /rfcs/text/0006_management_section_service.md -export interface LegacyPlugins { - cloud?: CloudSetup; - management: LegacyManagementPlugin; - __LEGACY: { - XSRF: string; - }; -} - -function startApp() { - routes.when(`${BASE_PATH}/:view?`, { - template: - '', - }); - const { cloud } = npSetup.plugins as any; - const legacyPluginsShim: LegacyPlugins = { - cloud: cloud as CloudSetup, - __LEGACY: { - XSRF: chrome.getXsrfToken(), - }, - management: { - sections: { - get(_: string) { - return { - registerApp(app) { - management.getSection('elasticsearch').register('upgrade_assistant', { - visible: true, - display: i18n.translate('xpack.upgradeAssistant.appTitle', { - defaultMessage: '{version} Upgrade Assistant', - values: { version: `${NEXT_MAJOR_VERSION}.0` }, - }), - order: 100, - url: `#${BASE_PATH}`, - }); - - app.mount( - {}, - { - __LEGACY: { - // While there is not an NP API for registering management section apps yet - renderToElement: RootComponent => { - uiModules - .get('kibana') - .directive('upgradeAssistant', (reactDirective: any) => { - return reactDirective(wrapInI18nContext(RootComponent)); - }); - }, - }, - } - ); - }, - }; - }, - }, - }, - }; - - const pluginInstance = plugin(); - - pluginInstance.setup(npSetup.core, legacyPluginsShim); -} - -startApp(); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx deleted file mode 100644 index 571967ab114c9..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app.tsx +++ /dev/null @@ -1,40 +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 { EuiPageHeader, EuiPageHeaderSection, EuiTitle } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { NEXT_MAJOR_VERSION } from '../../../common/version'; -import { UpgradeAssistantTabs } from './components/tabs'; -import { AppContextProvider, ContextValue, AppContext } from './app_context'; - -type AppDependencies = ContextValue; - -export const RootComponent = (deps: AppDependencies) => { - return ( - -
- - - -

- -

-
-
-
- - {({ http }) => } - -
-
- ); -}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts deleted file mode 100644 index dc7a758839fe5..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.mocks.ts +++ /dev/null @@ -1,24 +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 { ReindexStatus, ReindexStep } from '../../../../../../../../common/types'; - -export const mockClient = { - post: jest.fn().mockResolvedValue({ - lastCompletedStep: ReindexStep.created, - status: ReindexStatus.inProgress, - }), - get: jest.fn().mockResolvedValue({ - status: 200, - data: { - warnings: [], - reindexOp: null, - }, - }), -}; -jest.mock('axios', () => ({ - create: jest.fn().mockReturnValue(mockClient), -})); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts deleted file mode 100644 index ed85b988c25d6..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/plugin.ts +++ /dev/null @@ -1,24 +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 { Plugin, CoreSetup } from 'src/core/public'; -import { RootComponent } from './application/app'; -import { LegacyPlugins } from '../legacy'; - -export class UpgradeAssistantUIPlugin implements Plugin { - async setup({ http }: CoreSetup, { cloud, management, __LEGACY: { XSRF } }: LegacyPlugins) { - const appRegistrar = management.sections.get('kibana'); - const isCloudEnabled = !!(cloud && cloud.isCloudEnabled); - - return appRegistrar.registerApp({ - mount(__, { __LEGACY: { renderToElement } }) { - return renderToElement(() => RootComponent({ http, XSRF, isCloudEnabled })); - }, - }); - } - async start() {} - async stop() {} -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/index.ts b/x-pack/legacy/plugins/upgrade_assistant/server/index.ts deleted file mode 100644 index 8b0704283509d..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/index.ts +++ /dev/null @@ -1,7 +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 { plugin } from './np_ready'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts deleted file mode 100644 index b52b3b812b7f9..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - UIOpen, - UIOpenOption, - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, -} from '../../../../common/types'; -import { RequestShim, ServerShim } from '../../types'; - -async function incrementUIOpenOptionCounter(server: ServerShim, uiOpenOptionCounter: UIOpenOption) { - const { getSavedObjectsRepository } = server.savedObjects; - const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); - const internalRepository = getSavedObjectsRepository(callWithInternalUser); - - await internalRepository.incrementCounter( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - `ui_open.${uiOpenOptionCounter}` - ); -} - -export async function upsertUIOpenOption(server: ServerShim, req: RequestShim): Promise { - const { overview, cluster, indices } = req.payload as UIOpen; - - if (overview) { - await incrementUIOpenOptionCounter(server, 'overview'); - } - - if (cluster) { - await incrementUIOpenOptionCounter(server, 'cluster'); - } - - if (indices) { - await incrementUIOpenOptionCounter(server, 'indices'); - } - - return { - overview, - cluster, - indices, - }; -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts deleted file mode 100644 index 626d51b298e72..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.ts +++ /dev/null @@ -1,58 +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 { - UIReindex, - UIReindexOption, - UPGRADE_ASSISTANT_DOC_ID, - UPGRADE_ASSISTANT_TYPE, -} from '../../../../common/types'; -import { RequestShim, ServerShim } from '../../types'; - -async function incrementUIReindexOptionCounter( - server: ServerShim, - uiOpenOptionCounter: UIReindexOption -) { - const { getSavedObjectsRepository } = server.savedObjects; - const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin'); - const internalRepository = getSavedObjectsRepository(callWithInternalUser); - - await internalRepository.incrementCounter( - UPGRADE_ASSISTANT_TYPE, - UPGRADE_ASSISTANT_DOC_ID, - `ui_reindex.${uiOpenOptionCounter}` - ); -} - -export async function upsertUIReindexOption( - server: ServerShim, - req: RequestShim -): Promise { - const { close, open, start, stop } = req.payload as UIReindex; - - if (close) { - await incrementUIReindexOptionCounter(server, 'close'); - } - - if (open) { - await incrementUIReindexOptionCounter(server, 'open'); - } - - if (start) { - await incrementUIReindexOptionCounter(server, 'start'); - } - - if (stop) { - await incrementUIReindexOptionCounter(server, 'stop'); - } - - return { - close, - open, - start, - stop, - }; -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts deleted file mode 100644 index fae369fa59394..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/plugin.ts +++ /dev/null @@ -1,49 +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 { Plugin, CoreSetup, CoreStart } from 'src/core/server'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { ServerShim, ServerShimWithRouter } from './types'; -import { credentialStoreFactory } from './lib/reindexing/credential_store'; -import { registerUpgradeAssistantUsageCollector } from './lib/telemetry'; -import { registerClusterCheckupRoutes } from './routes/cluster_checkup'; -import { registerDeprecationLoggingRoutes } from './routes/deprecation_logging'; -import { registerReindexIndicesRoutes, registerReindexWorker } from './routes/reindex_indices'; -import { CloudSetup } from '../../../../../plugins/cloud/server'; -import { registerTelemetryRoutes } from './routes/telemetry'; - -interface PluginsSetup { - __LEGACY: ServerShim; - usageCollection: UsageCollectionSetup; - cloud?: CloudSetup; -} - -export class UpgradeAssistantServerPlugin implements Plugin { - setup({ http }: CoreSetup, { __LEGACY, usageCollection, cloud }: PluginsSetup) { - const router = http.createRouter(); - const shimWithRouter: ServerShimWithRouter = { ...__LEGACY, router }; - registerClusterCheckupRoutes(shimWithRouter, { cloud }); - registerDeprecationLoggingRoutes(shimWithRouter); - - // The ReindexWorker uses a map of request headers that contain the authentication credentials - // for a given reindex. We cannot currently store these in an the .kibana index b/c we do not - // want to expose these credentials to any unauthenticated users. We also want to avoid any need - // to add a user for a special index just for upgrading. This in-memory cache allows us to - // process jobs without the browser staying on the page, but will require that jobs go into - // a paused state if no Kibana nodes have the required credentials. - const credentialStore = credentialStoreFactory(); - - const worker = registerReindexWorker(__LEGACY, credentialStore); - registerReindexIndicesRoutes(shimWithRouter, worker, credentialStore); - - // Bootstrap the needed routes and the collector for the telemetry - registerTelemetryRoutes(shimWithRouter); - registerUpgradeAssistantUsageCollector(usageCollection, __LEGACY); - } - - start(core: CoreStart, plugins: any) {} - - stop(): void {} -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts deleted file mode 100644 index 81cf690d813ad..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.ts +++ /dev/null @@ -1,46 +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 _ from 'lodash'; -import { ServerShimWithRouter } from '../types'; -import { getUpgradeAssistantStatus } from '../lib/es_migration_apis'; -import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; -import { CloudSetup } from '../../../../../../plugins/cloud/server'; -import { createRequestShim } from './create_request_shim'; - -interface PluginsSetup { - cloud?: CloudSetup; -} - -export function registerClusterCheckupRoutes( - server: ServerShimWithRouter, - pluginsSetup: PluginsSetup -) { - const { cloud } = pluginsSetup; - const isCloudEnabled = !!(cloud && cloud.isCloudEnabled); - const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); - - server.router.get( - { - path: '/api/upgrade_assistant/status', - validate: false, - }, - versionCheckHandlerWrapper(async (ctx, request, response) => { - const reqShim = createRequestShim(request); - try { - return response.ok({ - body: await getUpgradeAssistantStatus(callWithRequest, reqShim, isCloudEnabled), - }); - } catch (e) { - if (e.status === 403) { - return response.forbidden(e.message); - } - - return response.internalError({ body: e }); - } - }) - ); -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts deleted file mode 100644 index b1a5c8b72d0e0..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/create_request_shim.ts +++ /dev/null @@ -1,16 +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 { KibanaRequest } from 'kibana/server'; -import { RequestShim } from '../types'; - -export const createRequestShim = (req: KibanaRequest): RequestShim => { - return { - headers: req.headers as Record, - payload: req.body || (req as any).payload, - params: req.params, - }; -}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts deleted file mode 100644 index 7e19ef3fb6047..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.ts +++ /dev/null @@ -1,57 +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 { schema } from '@kbn/config-schema'; - -import { - getDeprecationLoggingStatus, - setDeprecationLogging, -} from '../lib/es_deprecation_logging_apis'; -import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; -import { ServerShimWithRouter } from '../types'; -import { createRequestShim } from './create_request_shim'; - -export function registerDeprecationLoggingRoutes(server: ServerShimWithRouter) { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); - - server.router.get( - { - path: '/api/upgrade_assistant/deprecation_logging', - validate: false, - }, - versionCheckHandlerWrapper(async (ctx, request, response) => { - const reqShim = createRequestShim(request); - try { - const result = await getDeprecationLoggingStatus(callWithRequest, reqShim); - return response.ok({ body: result }); - } catch (e) { - return response.internalError({ body: e }); - } - }) - ); - - server.router.put( - { - path: '/api/upgrade_assistant/deprecation_logging', - validate: { - body: schema.object({ - isEnabled: schema.boolean(), - }), - }, - }, - versionCheckHandlerWrapper(async (ctx, request, response) => { - const reqShim = createRequestShim(request); - try { - const { isEnabled } = reqShim.payload as { isEnabled: boolean }; - return response.ok({ - body: await setDeprecationLogging(callWithRequest, reqShim, isEnabled), - }); - } catch (e) { - return response.internalError({ body: e }); - } - }) - ); -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts deleted file mode 100644 index c22f12316bd02..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.ts +++ /dev/null @@ -1,207 +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 { schema } from '@kbn/config-schema'; -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { SavedObjectsClientContract } from 'kibana/server'; -import { ReindexStatus } from '../../../common/types'; -import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; -import { reindexServiceFactory, ReindexWorker } from '../lib/reindexing'; -import { CredentialStore } from '../lib/reindexing/credential_store'; -import { reindexActionsFactory } from '../lib/reindexing/reindex_actions'; -import { ServerShim, ServerShimWithRouter } from '../types'; -import { createRequestShim } from './create_request_shim'; - -export function registerReindexWorker(server: ServerShim, credentialStore: CredentialStore) { - const { callWithRequest, callWithInternalUser } = server.plugins.elasticsearch.getCluster( - 'admin' - ); - const xpackInfo = server.plugins.xpack_main.info; - const savedObjectsRepository = server.savedObjects.getSavedObjectsRepository( - callWithInternalUser - ); - const savedObjectsClient = new server.savedObjects.SavedObjectsClient( - savedObjectsRepository - ) as SavedObjectsClientContract; - - // Cannot pass server.log directly because it's value changes during startup (?). - // Use this function to proxy through. - const log = (tags: string | string[], data?: string | object | (() => any), timestamp?: number) => - server.log(tags, data, timestamp); - - const worker = new ReindexWorker( - savedObjectsClient, - credentialStore, - callWithRequest, - callWithInternalUser, - xpackInfo, - log - ); - - // Wait for ES connection before starting the polling loop. - server.plugins.elasticsearch.waitUntilReady().then(() => { - worker.start(); - server.events.on('stop', () => worker.stop()); - }); - - return worker; -} - -export function registerReindexIndicesRoutes( - server: ServerShimWithRouter, - worker: ReindexWorker, - credentialStore: CredentialStore -) { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('admin'); - const xpackInfo = server.plugins.xpack_main.info; - const BASE_PATH = '/api/upgrade_assistant/reindex'; - - // Start reindex for an index - server.router.post( - { - path: `${BASE_PATH}/{indexName}`, - validate: { - params: schema.object({ - indexName: schema.string(), - }), - }, - }, - versionCheckHandlerWrapper(async (ctx, request, response) => { - const reqShim = createRequestShim(request); - const { indexName } = reqShim.params; - const { client } = ctx.core.savedObjects; - const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; - const reindexActions = reindexActionsFactory(client, callCluster); - const reindexService = reindexServiceFactory( - callCluster, - xpackInfo, - reindexActions, - server.log - ); - - try { - if (!(await reindexService.hasRequiredPrivileges(indexName))) { - return response.forbidden({ - body: `You do not have adequate privileges to reindex this index.`, - }); - } - - const existingOp = await reindexService.findReindexOperation(indexName); - - // If the reindexOp already exists and it's paused, resume it. Otherwise create a new one. - const reindexOp = - existingOp && existingOp.attributes.status === ReindexStatus.paused - ? await reindexService.resumeReindexOperation(indexName) - : await reindexService.createReindexOperation(indexName); - - // Add users credentials for the worker to use - credentialStore.set(reindexOp, reqShim.headers); - - // Kick the worker on this node to immediately pickup the new reindex operation. - worker.forceRefresh(); - - return response.ok({ body: reindexOp.attributes }); - } catch (e) { - return response.internalError({ body: e }); - } - }) - ); - - // Get status - server.router.get( - { - path: `${BASE_PATH}/{indexName}`, - validate: { - params: schema.object({ - indexName: schema.string(), - }), - }, - }, - versionCheckHandlerWrapper(async (ctx, request, response) => { - const reqShim = createRequestShim(request); - const { client } = ctx.core.savedObjects; - const { indexName } = reqShim.params; - const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; - const reindexActions = reindexActionsFactory(client, callCluster); - const reindexService = reindexServiceFactory( - callCluster, - xpackInfo, - reindexActions, - server.log - ); - - try { - const hasRequiredPrivileges = await reindexService.hasRequiredPrivileges(indexName); - const reindexOp = await reindexService.findReindexOperation(indexName); - // If the user doesn't have privileges than querying for warnings is going to fail. - const warnings = hasRequiredPrivileges - ? await reindexService.detectReindexWarnings(indexName) - : []; - const indexGroup = reindexService.getIndexGroup(indexName); - - return response.ok({ - body: { - reindexOp: reindexOp ? reindexOp.attributes : null, - warnings, - indexGroup, - hasRequiredPrivileges, - }, - }); - } catch (e) { - if (!e.isBoom) { - return response.internalError({ body: e }); - } - return response.customError({ - body: { - message: e.message, - }, - statusCode: e.statusCode, - }); - } - }) - ); - - // Cancel reindex - server.router.post( - { - path: `${BASE_PATH}/{indexName}/cancel`, - validate: { - params: schema.object({ - indexName: schema.string(), - }), - }, - }, - versionCheckHandlerWrapper(async (ctx, request, response) => { - const reqShim = createRequestShim(request); - const { indexName } = reqShim.params; - const { client } = ctx.core.savedObjects; - const callCluster = callWithRequest.bind(null, reqShim) as CallCluster; - const reindexActions = reindexActionsFactory(client, callCluster); - const reindexService = reindexServiceFactory( - callCluster, - xpackInfo, - reindexActions, - server.log - ); - - try { - await reindexService.cancelReindexing(indexName); - - return response.ok({ body: { acknowledged: true } }); - } catch (e) { - if (!e.isBoom) { - return response.internalError({ body: e }); - } - return response.customError({ - body: { - message: e.message, - }, - statusCode: e.statusCode, - }); - } - }) - ); -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts b/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts deleted file mode 100644 index 77ba97529c32f..0000000000000 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/types.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { Legacy } from 'kibana'; -import { IRouter } from 'src/core/server'; -import { ElasticsearchPlugin } from 'src/legacy/core_plugins/elasticsearch'; -import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main'; - -export interface ServerShim { - plugins: { - elasticsearch: ElasticsearchPlugin; - xpack_main: XPackMainPlugin; - }; - log: any; - events: any; - savedObjects: Legacy.SavedObjectsService; -} - -export interface ServerShimWithRouter extends ServerShim { - router: IRouter; -} - -export interface RequestShim { - headers: Record; - payload: any; - params: any; -} diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts b/x-pack/plugins/upgrade_assistant/common/config.ts similarity index 54% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts rename to x-pack/plugins/upgrade_assistant/common/config.ts index 020d6972f8280..8a13aedd5fdd8 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/index.ts +++ b/x-pack/plugins/upgrade_assistant/common/config.ts @@ -4,8 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UpgradeAssistantUIPlugin } from './plugin'; +import { schema, TypeOf } from '@kbn/config-schema'; -export const plugin = () => { - return new UpgradeAssistantUIPlugin(); -}; +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), +}); + +export type Config = TypeOf; diff --git a/x-pack/legacy/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts similarity index 88% rename from x-pack/legacy/plugins/upgrade_assistant/common/types.ts rename to x-pack/plugins/upgrade_assistant/common/types.ts index 0e65506bb584d..a0c12154988a1 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; import { SavedObject, SavedObjectAttributes } from 'src/core/public'; export enum ReindexStep { @@ -114,3 +115,15 @@ export interface UpgradeAssistantTelemetry { export interface UpgradeAssistantTelemetrySavedObjectAttributes { [key: string]: any; } + +export interface EnrichedDeprecationInfo extends DeprecationInfo { + index?: string; + node?: string; + reindex?: boolean; +} + +export interface UpgradeAssistantStatus { + readyForUpgrade: boolean; + cluster: EnrichedDeprecationInfo[]; + indices: EnrichedDeprecationInfo[]; +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/common/version.ts b/x-pack/plugins/upgrade_assistant/common/version.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/common/version.ts rename to x-pack/plugins/upgrade_assistant/common/version.ts diff --git a/x-pack/plugins/upgrade_assistant/kibana.json b/x-pack/plugins/upgrade_assistant/kibana.json new file mode 100644 index 0000000000000..273036a653aeb --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "upgradeAssistant", + "version": "kibana", + "server": true, + "ui": true, + "configPath": ["xpack", "upgrade_assistant"], + "requiredPlugins": ["management", "licensing"], + "optionalPlugins": ["cloud", "usageCollection"] +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss b/x-pack/plugins/upgrade_assistant/public/application/_index.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/index.scss rename to x-pack/plugins/upgrade_assistant/public/application/_index.scss diff --git a/x-pack/plugins/upgrade_assistant/public/application/app.tsx b/x-pack/plugins/upgrade_assistant/public/application/app.tsx new file mode 100644 index 0000000000000..17eff71f1039b --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/app.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { I18nStart } from 'src/core/public'; +import { EuiPageHeader, EuiPageHeaderSection, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NEXT_MAJOR_VERSION } from '../../common/version'; +import { UpgradeAssistantTabs } from './components/tabs'; +import { AppContextProvider, ContextValue, AppContext } from './app_context'; + +export interface AppDependencies extends ContextValue { + i18n: I18nStart; +} + +export const RootComponent = ({ i18n, ...contexValue }: AppDependencies) => { + return ( + + +
+ + + +

+ +

+
+
+
+ + {({ http }) => } + +
+
+
+ ); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx rename to x-pack/plugins/upgrade_assistant/public/application/app_context.tsx index a48a4efa3bbdf..1ae9dabd69481 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/app_context.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/app_context.tsx @@ -9,7 +9,6 @@ import React, { createContext, useContext } from 'react'; export interface ContextValue { http: HttpSetup; isCloudEnabled: boolean; - XSRF: string; } export const AppContext = createContext({} as any); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/_index.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/_index.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/_index.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/error_banner.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/error_banner.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/error_banner.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/error_banner.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/latest_minor_banner.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/latest_minor_banner.tsx index 864df292fbffe..43d0364425cbb 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/latest_minor_banner.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/latest_minor_banner.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { EuiCallOut, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../common/version'; +import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../common/version'; export const LatestMinorBanner: React.FunctionComponent = () => ( ({ - get: jest.fn(), - create: jest.fn(), -})); - +import { httpServiceMock } from 'src/core/public/mocks'; import { UpgradeAssistantTabs } from './tabs'; import { LoadingState } from './types'; -import axios from 'axios'; import { OverviewTab } from './tabs/overview'; // Used to wait for promises to resolve and renders to finish before reading updates const promisesToResolve = () => new Promise(resolve => setTimeout(resolve, 0)); -const mockHttp = { - basePath: { - prepend: () => 'test', - }, - fetch() {}, -}; +const mockHttp = httpServiceMock.createSetupContract(); describe('UpgradeAssistantTabs', () => { test('renders loading state', async () => { - // @ts-ignore - axios.get.mockReturnValue( + mockHttp.get.mockReturnValue( new Promise(resolve => { /* never resolve */ }) ); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); // Should pass down loading status to child component expect(wrapper.find(OverviewTab).prop('loadingState')).toEqual(LoadingState.Loading); }); test('successful data fetch', async () => { // @ts-ignore - axios.get.mockResolvedValue({ + mockHttp.get.mockResolvedValue({ data: { cluster: [], indices: [], }, }); const wrapper = mountWithIntl(); - expect(axios.get).toHaveBeenCalled(); + expect(mockHttp.get).toHaveBeenCalled(); await promisesToResolve(); wrapper.update(); // Should pass down success status to child component @@ -59,7 +47,7 @@ describe('UpgradeAssistantTabs', () => { test('network failure', async () => { // @ts-ignore - axios.get.mockRejectedValue(new Error(`oh no!`)); + mockHttp.get.mockRejectedValue(new Error(`oh no!`)); const wrapper = mountWithIntl(); await promisesToResolve(); wrapper.update(); @@ -69,7 +57,7 @@ describe('UpgradeAssistantTabs', () => { it('upgrade error', async () => { // @ts-ignore - axios.get.mockRejectedValue({ response: { status: 426 } }); + mockHttp.get.mockRejectedValue({ response: { status: 426 } }); const wrapper = mountWithIntl(); await promisesToResolve(); wrapper.update(); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs.tsx index 0b154fb20404d..43ec5554aaaee 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import axios from 'axios'; import { findIndex, get, set } from 'lodash'; import React from 'react'; @@ -18,7 +17,7 @@ import { import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; import { HttpSetup } from 'src/core/public'; -import { UpgradeAssistantStatus } from '../../../../server/np_ready/lib/es_migration_apis'; +import { UpgradeAssistantStatus } from '../../../common/types'; import { LatestMinorBanner } from './latest_minor_banner'; import { CheckupTab } from './tabs/checkup'; import { OverviewTab } from './tabs/overview'; @@ -153,12 +152,10 @@ export class UpgradeAssistantTabsUI extends React.Component { private loadData = async () => { try { this.setState({ loadingState: LoadingState.Loading }); - const resp = await axios.get( - this.props.http.basePath.prepend('/api/upgrade_assistant/status') - ); + const resp = await this.props.http.get('/api/upgrade_assistant/status'); this.setState({ loadingState: LoadingState.Success, - checkupData: resp.data, + checkupData: resp, }); } catch (e) { if (get(e, 'response.status') === 426) { diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/__fixtures__/checkup_api_response.json b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/__fixtures__/checkup_api_response.json similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/__fixtures__/checkup_api_response.json rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/__fixtures__/checkup_api_response.json diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/__snapshots__/filter_bar.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/__snapshots__/group_by_bar.test.tsx.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/_index.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/_index.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/_index.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/checkup_tab.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/checkup_tab.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/checkup_tab.tsx similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/checkup_tab.tsx index 7e862a846290b..b047427174e08 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/checkup_tab.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/checkup_tab.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NEXT_MAJOR_VERSION } from '../../../../../../common/version'; +import { NEXT_MAJOR_VERSION } from '../../../../../common/version'; import { LoadingErrorBanner } from '../../error_banner'; import { GroupByOption, diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/constants.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/constants.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/constants.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/constants.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/controls.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/controls.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/controls.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/controls.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_cell.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/_cell.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_cell.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/_cell.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/_deprecations.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_deprecations.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/_deprecations.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/_index.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/_index.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/_index.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/cell.tsx similarity index 94% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/cell.tsx index 4bd2f7c4bf62c..879bb695ca60a 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/cell.tsx @@ -79,9 +79,7 @@ export const DeprecationCell: FunctionComponent = ({ {reindexIndexName && ( - {({ http, XSRF }) => ( - - )} + {({ http }) => } )} diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/count_summary.tsx similarity index 93% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/count_summary.tsx index a0e55dc55c865..7e5172a361a56 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/count_summary.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/count_summary.tsx @@ -8,7 +8,7 @@ import React, { Fragment, FunctionComponent } from 'react'; import { EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../common/types'; export const DeprecationCountSummary: FunctionComponent<{ deprecations: EnrichedDeprecationInfo[]; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.test.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.test.tsx index 28f5f6894b78f..c6309fb57d786 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.test.tsx @@ -11,7 +11,7 @@ import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { EuiBadge, EuiPagination } from '@elastic/eui'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationAccordion, filterDeps, GroupedDeprecations } from './grouped'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.tsx index 74f66b6c4fb35..8fa78639c39d3 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/grouped.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/grouped.tsx @@ -19,7 +19,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GroupByOption, LevelFilterOption } from '../../../types'; import { DeprecationCountSummary } from './count_summary'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/health.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/health.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/health.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/health.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/index_table.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/index_table.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/index_table.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/index_table.tsx index 835affce59070..5506528a3ded0 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/index_table.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/index_table.tsx @@ -148,9 +148,7 @@ export class IndexDeprecationTableUI extends React.Component< render(indexDep: IndexDeprecationDetails) { return ( - {({ XSRF, http }) => ( - - )} + {({ http }) => } ); }, diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.test.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.test.tsx index 78ded73593464..a1e173737bab0 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.test.tsx @@ -7,7 +7,7 @@ import { shallow } from 'enzyme'; import React from 'react'; -import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GroupByOption } from '../../../types'; import { DeprecationList } from './list'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.tsx similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.tsx index 15a3d94974dcd..a46bc0d12fad4 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/list.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/list.tsx @@ -7,7 +7,7 @@ import React, { FunctionComponent } from 'react'; import { DeprecationInfo } from 'src/legacy/core_plugins/elasticsearch'; -import { EnrichedDeprecationInfo } from '../../../../../../../server/np_ready/lib/es_migration_apis'; +import { EnrichedDeprecationInfo } from '../../../../../../common/types'; import { GroupByOption } from '../../../types'; import { COLOR_MAP, LEVEL_MAP } from '../constants'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_button.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/_button.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_button.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/_button.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/_index.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/_index.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/_index.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/button.tsx similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/button.tsx index 2a28018a3ae81..30b46e0c15213 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/button.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/button.tsx @@ -11,14 +11,13 @@ import { Subscription } from 'rxjs'; import { EuiButton, EuiLoadingSpinner } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { HttpSetup } from 'src/core/public'; -import { ReindexStatus, UIReindexOption } from '../../../../../../../../common/types'; +import { ReindexStatus, UIReindexOption } from '../../../../../../../common/types'; import { LoadingState } from '../../../../types'; import { ReindexFlyout } from './flyout'; import { ReindexPollingService, ReindexState } from './polling_service'; interface ReindexButtonProps { indexName: string; - xsrf: string; http: HttpSetup; } @@ -154,8 +153,8 @@ export class ReindexButton extends React.Component { diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx index 91e35c0bd7dc0..643dd2e9b6efc 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/flyout/warnings_step.tsx @@ -21,7 +21,7 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ReindexWarning } from '../../../../../../../../../common/types'; +import { ReindexWarning } from '../../../../../../../../common/types'; interface CheckedIds { [id: string]: boolean; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/index.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/index.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts similarity index 63% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts index cb2a0856f0f2e..4228426d62159 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/polling_service.test.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { mockClient } from './polling_service.test.mocks'; - -import { ReindexStatus, ReindexStep } from '../../../../../../../../common/types'; +import { ReindexStatus, ReindexStep } from '../../../../../../../common/types'; import { ReindexPollingService } from './polling_service'; import { httpServiceMock } from 'src/core/public/http/http_service.mock'; +const mockClient = httpServiceMock.createSetupContract(); + describe('ReindexPollingService', () => { beforeEach(() => { mockClient.post.mockReset(); @@ -18,18 +18,11 @@ describe('ReindexPollingService', () => { it('does not poll when reindexOp is null', async () => { mockClient.get.mockResolvedValueOnce({ - status: 200, - data: { - warnings: [], - reindexOp: null, - }, + warnings: [], + reindexOp: null, }); - const service = new ReindexPollingService( - 'myIndex', - 'myXsrf', - httpServiceMock.createSetupContract() - ); + const service = new ReindexPollingService('myIndex', mockClient); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -39,22 +32,15 @@ describe('ReindexPollingService', () => { it('does not poll when first check is a 200 and status is failed', async () => { mockClient.get.mockResolvedValue({ - status: 200, - data: { - warnings: [], - reindexOp: { - lastCompletedStep: ReindexStep.created, - status: ReindexStatus.failed, - errorMessage: `Oh no!`, - }, + warnings: [], + reindexOp: { + lastCompletedStep: ReindexStep.created, + status: ReindexStatus.failed, + errorMessage: `Oh no!`, }, }); - const service = new ReindexPollingService( - 'myIndex', - 'myXsrf', - httpServiceMock.createSetupContract() - ); + const service = new ReindexPollingService('myIndex', mockClient); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -65,21 +51,14 @@ describe('ReindexPollingService', () => { it('begins to poll when first check is a 200 and status is inProgress', async () => { mockClient.get.mockResolvedValue({ - status: 200, - data: { - warnings: [], - reindexOp: { - lastCompletedStep: ReindexStep.created, - status: ReindexStatus.inProgress, - }, + warnings: [], + reindexOp: { + lastCompletedStep: ReindexStep.created, + status: ReindexStatus.inProgress, }, }); - const service = new ReindexPollingService( - 'myIndex', - 'myXsrf', - httpServiceMock.createSetupContract() - ); + const service = new ReindexPollingService('myIndex', mockClient); service.updateStatus(); await new Promise(resolve => setTimeout(resolve, 1200)); // wait for poll interval @@ -89,11 +68,7 @@ describe('ReindexPollingService', () => { describe('startReindex', () => { it('posts to endpoint', async () => { - const service = new ReindexPollingService( - 'myIndex', - 'myXsrf', - httpServiceMock.createSetupContract() - ); + const service = new ReindexPollingService('myIndex', mockClient); await service.startReindex(); expect(mockClient.post).toHaveBeenCalledWith('/api/upgrade_assistant/reindex/myIndex'); @@ -102,11 +77,7 @@ describe('ReindexPollingService', () => { describe('cancelReindex', () => { it('posts to cancel endpoint', async () => { - const service = new ReindexPollingService( - 'myIndex', - 'myXsrf', - httpServiceMock.createSetupContract() - ); + const service = new ReindexPollingService('myIndex', mockClient); await service.cancelReindex(); expect(mockClient.post).toHaveBeenCalledWith('/api/upgrade_assistant/reindex/myIndex/cancel'); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/polling_service.ts similarity index 82% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/polling_service.ts index 879fafe610982..6fe6a85905706 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/deprecations/reindex/polling_service.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/deprecations/reindex/polling_service.ts @@ -3,8 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import axios, { AxiosInstance } from 'axios'; - import { BehaviorSubject } from 'rxjs'; import { HttpSetup } from 'src/core/public'; @@ -14,7 +12,7 @@ import { ReindexStatus, ReindexStep, ReindexWarning, -} from '../../../../../../../../common/types'; +} from '../../../../../../../common/types'; import { LoadingState } from '../../../../types'; const POLL_INTERVAL = 1000; @@ -45,24 +43,13 @@ interface StatusResponse { export class ReindexPollingService { public status$: BehaviorSubject; private pollTimeout?: NodeJS.Timeout; - private APIClient: AxiosInstance; - constructor(private indexName: string, private xsrf: string, private http: HttpSetup) { + constructor(private indexName: string, private http: HttpSetup) { this.status$ = new BehaviorSubject({ loadingState: LoadingState.Loading, errorMessage: null, reindexTaskPercComplete: null, }); - - this.APIClient = axios.create({ - headers: { - Accept: 'application/json', - credentials: 'same-origin', - 'Content-Type': 'application/json', - 'kbn-version': this.xsrf, - 'kbn-xsrf': this.xsrf, - }, - }); } public updateStatus = async () => { @@ -70,8 +57,8 @@ export class ReindexPollingService { this.stopPolling(); try { - const { data } = await this.APIClient.get( - this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}`) + const data = await this.http.get( + `/api/upgrade_assistant/reindex/${this.indexName}` ); this.updateWithResponse(data); @@ -107,8 +94,8 @@ export class ReindexPollingService { errorMessage: null, cancelLoadingState: undefined, }); - const { data } = await this.APIClient.post( - this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}`) + const data = await this.http.post( + `/api/upgrade_assistant/reindex/${this.indexName}` ); this.updateWithResponse({ reindexOp: data }); @@ -125,9 +112,7 @@ export class ReindexPollingService { cancelLoadingState: LoadingState.Loading, }); - await this.APIClient.post( - this.http.basePath.prepend(`/api/upgrade_assistant/reindex/${this.indexName}/cancel`) - ); + await this.http.post(`/api/upgrade_assistant/reindex/${this.indexName}/cancel`); } catch (e) { this.status$.next({ ...this.status$.value, diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/filter_bar.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/filter_bar.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/group_by_bar.test.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.test.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/group_by_bar.test.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/group_by_bar.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/group_by_bar.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/group_by_bar.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/index.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/index.tsx similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/index.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/checkup/index.tsx diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/_index.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_index.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/_index.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_steps.scss b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/_steps.scss similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/_steps.scss rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/_steps.scss diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/deprecation_logging_toggle.tsx similarity index 86% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/deprecation_logging_toggle.tsx index db37bc58904ec..0e6c79dc47b53 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/deprecation_logging_toggle.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/deprecation_logging_toggle.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import axios from 'axios'; import React from 'react'; import { EuiLoadingSpinner, EuiSwitch } from '@elastic/eui'; @@ -15,7 +14,6 @@ import { HttpSetup } from 'src/core/public'; import { LoadingState } from '../../types'; interface DeprecationLoggingTabProps extends ReactIntl.InjectedIntlProps { - xsrf: string; http: HttpSetup; } @@ -88,12 +86,10 @@ export class DeprecationLoggingToggleUI extends React.Component< private loadData = async () => { try { this.setState({ loadingState: LoadingState.Loading }); - const resp = await axios.get( - this.props.http.basePath.prepend('/api/upgrade_assistant/deprecation_logging') - ); + const resp = await this.props.http.get('/api/upgrade_assistant/deprecation_logging'); this.setState({ loadingState: LoadingState.Success, - loggingEnabled: resp.data.isEnabled, + loggingEnabled: resp.isEnabled, }); } catch (e) { this.setState({ loadingState: LoadingState.Error }); @@ -102,26 +98,19 @@ export class DeprecationLoggingToggleUI extends React.Component< private toggleLogging = async () => { try { - const { http, xsrf } = this.props; // Optimistically toggle the UI const newEnabled = !this.state.loggingEnabled; this.setState({ loadingState: LoadingState.Loading, loggingEnabled: newEnabled }); - const resp = await axios.put( - http.basePath.prepend('/api/upgrade_assistant/deprecation_logging'), - { + const resp = await this.props.http.put('/api/upgrade_assistant/deprecation_logging', { + body: JSON.stringify({ isEnabled: newEnabled, - }, - { - headers: { - 'kbn-xsrf': xsrf, - }, - } - ); + }), + }); this.setState({ loadingState: LoadingState.Success, - loggingEnabled: resp.data.isEnabled, + loggingEnabled: resp.isEnabled, }); } catch (e) { this.setState({ loadingState: LoadingState.Error }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/index.tsx similarity index 96% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/index.tsx index 284265bb31f14..aede377fa8d45 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/index.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/index.tsx @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { NEXT_MAJOR_VERSION } from '../../../../../../common/version'; +import { NEXT_MAJOR_VERSION } from '../../../../../common/version'; import { LoadingErrorBanner } from '../../error_banner'; import { LoadingState, UpgradeAssistantTabProps } from '../../types'; import { Steps } from './steps'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/steps.tsx similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx rename to x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/steps.tsx index ccba51c73c136..85d275b080e13 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/overview/steps.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/tabs/overview/steps.tsx @@ -19,7 +19,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; -import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../../../common/version'; +import { CURRENT_MAJOR_VERSION, NEXT_MAJOR_VERSION } from '../../../../../common/version'; import { UpgradeAssistantTabProps } from '../../types'; import { DeprecationLoggingToggle } from './deprecation_logging_toggle'; import { useAppContext } from '../../../app_context'; @@ -104,7 +104,7 @@ export const StepsUI: FunctionComponent - + ), diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts similarity index 89% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts rename to x-pack/plugins/upgrade_assistant/public/application/components/types.ts index 2d9a373f20b7e..86d1486543596 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/types.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/components/types.ts @@ -6,10 +6,7 @@ import React from 'react'; -import { - EnrichedDeprecationInfo, - UpgradeAssistantStatus, -} from '../../../../server/np_ready/lib/es_migration_apis'; +import { EnrichedDeprecationInfo, UpgradeAssistantStatus } from '../../../common/types'; export interface UpgradeAssistantTabProps { alertBanner?: React.ReactNode; diff --git a/x-pack/plugins/upgrade_assistant/public/application/render_app.tsx b/x-pack/plugins/upgrade_assistant/public/application/render_app.tsx new file mode 100644 index 0000000000000..97120cfc3333a --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/application/render_app.tsx @@ -0,0 +1,20 @@ +/* + * 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 { render, unmountComponentAtNode } from 'react-dom'; +import { AppDependencies, RootComponent } from './app'; + +interface BootDependencies extends AppDependencies { + element: HTMLElement; +} + +export const renderApp = (deps: BootDependencies) => { + const { element, ...appDependencies } = deps; + render(, element); + return () => { + unmountComponentAtNode(element); + }; +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts b/x-pack/plugins/upgrade_assistant/public/application/utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts rename to x-pack/plugins/upgrade_assistant/public/application/utils.test.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts b/x-pack/plugins/upgrade_assistant/public/application/utils.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts rename to x-pack/plugins/upgrade_assistant/public/application/utils.ts diff --git a/x-pack/plugins/upgrade_assistant/public/index.scss b/x-pack/plugins/upgrade_assistant/public/index.scss new file mode 100644 index 0000000000000..9bd47b6473372 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/index.scss @@ -0,0 +1 @@ +@import './application/index'; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts b/x-pack/plugins/upgrade_assistant/public/index.ts similarity index 62% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts rename to x-pack/plugins/upgrade_assistant/public/index.ts index cf1b78e1e3920..2b1860167ef5d 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/index.ts +++ b/x-pack/plugins/upgrade_assistant/public/index.ts @@ -3,9 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { PluginInitializerContext } from 'src/core/server'; -import { UpgradeAssistantServerPlugin } from './plugin'; +import './index.scss'; +import { PluginInitializerContext } from 'src/core/public'; +import { UpgradeAssistantUIPlugin } from './plugin'; export const plugin = (ctx: PluginInitializerContext) => { - return new UpgradeAssistantServerPlugin(); + return new UpgradeAssistantUIPlugin(ctx); }; diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts new file mode 100644 index 0000000000000..614221272dd5c --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts @@ -0,0 +1,48 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Plugin, CoreSetup, PluginInitializerContext } from 'src/core/public'; + +import { CloudSetup } from '../../cloud/public'; +import { ManagementSetup } from '../../../../src/plugins/management/public'; + +import { NEXT_MAJOR_VERSION } from '../common/version'; +import { Config } from '../common/config'; + +import { renderApp } from './application/render_app'; + +interface Dependencies { + cloud: CloudSetup; + management: ManagementSetup; +} + +export class UpgradeAssistantUIPlugin implements Plugin { + constructor(private ctx: PluginInitializerContext) {} + setup({ http, getStartServices }: CoreSetup, { cloud, management }: Dependencies) { + const { enabled } = this.ctx.config.get(); + if (!enabled) { + return; + } + const appRegistrar = management.sections.getSection('elasticsearch')!; + const isCloudEnabled = Boolean(cloud?.isCloudEnabled); + + appRegistrar.registerApp({ + id: 'upgrade_assistant', + title: i18n.translate('xpack.upgradeAssistant.appTitle', { + defaultMessage: '{version} Upgrade Assistant', + values: { version: `${NEXT_MAJOR_VERSION}.0` }, + }), + order: 1000, + async mount({ element }) { + const [{ i18n: i18nDep }] = await getStartServices(); + return renderApp({ element, isCloudEnabled, http, i18n: i18nDep }); + }, + }); + } + + start() {} + stop() {} +} diff --git a/x-pack/plugins/upgrade_assistant/server/index.ts b/x-pack/plugins/upgrade_assistant/server/index.ts new file mode 100644 index 0000000000000..cab7eb613f74c --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { PluginInitializerContext, PluginConfigDescriptor } from 'src/core/server'; +import { UpgradeAssistantServerPlugin } from './plugin'; +import { configSchema } from '../common/config'; + +export const plugin = (ctx: PluginInitializerContext) => { + return new UpgradeAssistantServerPlugin(ctx); +}; + +export const config: PluginConfigDescriptor = { + schema: configSchema, + exposeToBrowser: { + enabled: true, + }, +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__fixtures__/fake_deprecations.json b/x-pack/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__fixtures__/fake_deprecations.json rename to x-pack/plugins/upgrade_assistant/server/lib/__fixtures__/fake_deprecations.json diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__mocks__/es_version_precheck.ts b/x-pack/plugins/upgrade_assistant/server/lib/__mocks__/es_version_precheck.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__mocks__/es_version_precheck.ts rename to x-pack/plugins/upgrade_assistant/server/lib/__mocks__/es_version_precheck.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__snapshots__/es_migration_apis.test.ts.snap b/x-pack/plugins/upgrade_assistant/server/lib/__snapshots__/es_migration_apis.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/__snapshots__/es_migration_apis.test.ts.snap rename to x-pack/plugins/upgrade_assistant/server/lib/__snapshots__/es_migration_apis.test.ts.snap diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts similarity index 75% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.test.ts index 317e2a7554e03..862f64e232370 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.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 { elasticsearchServiceMock } from 'src/core/server/mocks'; import { getDeprecationLoggingStatus, isDeprecationLoggingEnabled, @@ -12,9 +12,9 @@ import { describe('getDeprecationLoggingStatus', () => { it('calls cluster.getSettings', async () => { - const callWithRequest = jest.fn(); - await getDeprecationLoggingStatus(callWithRequest, {} as any); - expect(callWithRequest).toHaveBeenCalledWith({}, 'cluster.getSettings', { + const dataClient = elasticsearchServiceMock.createScopedClusterClient(); + await getDeprecationLoggingStatus(dataClient); + expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('cluster.getSettings', { includeDefaults: true, }); }); @@ -23,9 +23,9 @@ describe('getDeprecationLoggingStatus', () => { describe('setDeprecationLogging', () => { describe('isEnabled = true', () => { it('calls cluster.putSettings with logger.deprecation = WARN', async () => { - const callWithRequest = jest.fn(); - await setDeprecationLogging(callWithRequest, {} as any, true); - expect(callWithRequest).toHaveBeenCalledWith({}, 'cluster.putSettings', { + const dataClient = elasticsearchServiceMock.createScopedClusterClient(); + await setDeprecationLogging(dataClient, true); + expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('cluster.putSettings', { body: { transient: { 'logger.deprecation': 'WARN' } }, }); }); @@ -33,9 +33,9 @@ describe('setDeprecationLogging', () => { describe('isEnabled = false', () => { it('calls cluster.putSettings with logger.deprecation = ERROR', async () => { - const callWithRequest = jest.fn(); - await setDeprecationLogging(callWithRequest, {} as any, false); - expect(callWithRequest).toHaveBeenCalledWith({}, 'cluster.putSettings', { + const dataClient = elasticsearchServiceMock.createScopedClusterClient(); + await setDeprecationLogging(dataClient, false); + expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('cluster.putSettings', { body: { transient: { 'logger.deprecation': 'ERROR' } }, }); }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts similarity index 75% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts index 199d389408442..8f25533c0afb1 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_deprecation_logging_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecation_logging_apis.ts @@ -4,19 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; - -import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; -import { RequestShim } from '../types'; +import { IScopedClusterClient } from 'src/core/server'; interface DeprecationLoggingStatus { isEnabled: boolean; } export async function getDeprecationLoggingStatus( - callWithRequest: CallClusterWithRequest, - req: RequestShim + dataClient: IScopedClusterClient ): Promise { - const response = await callWithRequest(req, 'cluster.getSettings', { + const response = await dataClient.callAsCurrentUser('cluster.getSettings', { includeDefaults: true, }); @@ -26,11 +23,10 @@ export async function getDeprecationLoggingStatus( } export async function setDeprecationLogging( - callWithRequest: CallClusterWithRequest, - req: RequestShim, + dataClient: IScopedClusterClient, isEnabled: boolean ): Promise { - const response = await callWithRequest(req, 'cluster.putSettings', { + const response = await dataClient.callAsCurrentUser('cluster.putSettings', { body: { transient: { 'logger.deprecation': isEnabled ? 'WARN' : 'ERROR', diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts similarity index 73% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts index a1d7049e4171f..4ab4227ba3e91 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.test.ts @@ -5,6 +5,7 @@ */ import _ from 'lodash'; +import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { getUpgradeAssistantStatus } from './es_migration_apis'; import { DeprecationAPIResponse } from 'src/legacy/core_plugins/elasticsearch'; @@ -13,7 +14,8 @@ import fakeDeprecations from './__fixtures__/fake_deprecations.json'; describe('getUpgradeAssistantStatus', () => { let deprecationsResponse: DeprecationAPIResponse; - const callWithRequest = jest.fn().mockImplementation(async (req, api, { path }) => { + const dataClient = elasticsearchServiceMock.createScopedClusterClient(); + (dataClient.callAsCurrentUser as jest.Mock).mockImplementation(async (api, { path }) => { if (path === '/_migration/deprecations') { return deprecationsResponse; } else if (api === 'indices.getMapping') { @@ -28,15 +30,15 @@ describe('getUpgradeAssistantStatus', () => { }); it('calls /_migration/deprecations', async () => { - await getUpgradeAssistantStatus(callWithRequest, {} as any, false); - expect(callWithRequest).toHaveBeenCalledWith({}, 'transport.request', { + await getUpgradeAssistantStatus(dataClient, false); + expect(dataClient.callAsCurrentUser).toHaveBeenCalledWith('transport.request', { path: '/_migration/deprecations', method: 'GET', }); }); it('returns the correct shape of data', async () => { - const resp = await getUpgradeAssistantStatus(callWithRequest, {} as any, false); + const resp = await getUpgradeAssistantStatus(dataClient, false); expect(resp).toMatchSnapshot(); }); @@ -48,9 +50,10 @@ describe('getUpgradeAssistantStatus', () => { index_settings: {}, }; - await expect( - getUpgradeAssistantStatus(callWithRequest, {} as any, false) - ).resolves.toHaveProperty('readyForUpgrade', false); + await expect(getUpgradeAssistantStatus(dataClient, false)).resolves.toHaveProperty( + 'readyForUpgrade', + false + ); }); it('returns readyForUpgrade === true when no critical issues found', async () => { @@ -61,9 +64,10 @@ describe('getUpgradeAssistantStatus', () => { index_settings: {}, }; - await expect( - getUpgradeAssistantStatus(callWithRequest, {} as any, false) - ).resolves.toHaveProperty('readyForUpgrade', true); + await expect(getUpgradeAssistantStatus(dataClient, false)).resolves.toHaveProperty( + 'readyForUpgrade', + true + ); }); it('filters out security realm deprecation on Cloud', async () => { @@ -80,7 +84,7 @@ describe('getUpgradeAssistantStatus', () => { index_settings: {}, }; - const result = await getUpgradeAssistantStatus(callWithRequest, {} as any, true); + const result = await getUpgradeAssistantStatus(dataClient, true); expect(result).toHaveProperty('readyForUpgrade', true); expect(result).toHaveProperty('cluster', []); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts similarity index 75% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts index b52c4c374266f..68f21c1fd93b5 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_migration_apis.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts @@ -4,32 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - CallClusterWithRequest, - DeprecationAPIResponse, - DeprecationInfo, -} from 'src/legacy/core_plugins/elasticsearch'; - -import { RequestShim } from '../types'; - -export interface EnrichedDeprecationInfo extends DeprecationInfo { - index?: string; - node?: string; - reindex?: boolean; -} - -export interface UpgradeAssistantStatus { - readyForUpgrade: boolean; - cluster: EnrichedDeprecationInfo[]; - indices: EnrichedDeprecationInfo[]; -} +import { IScopedClusterClient } from 'src/core/server'; +import { DeprecationAPIResponse } from 'src/legacy/core_plugins/elasticsearch'; +import { EnrichedDeprecationInfo, UpgradeAssistantStatus } from '../../common/types'; export async function getUpgradeAssistantStatus( - callWithRequest: CallClusterWithRequest, - req: RequestShim, + dataClient: IScopedClusterClient, isCloudEnabled: boolean ): Promise { - const deprecations = await callWithRequest(req, 'transport.request', { + const deprecations = await dataClient.callAsCurrentUser('transport.request', { path: '/_migration/deprecations', method: 'GET', }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts index bbabe557df4d4..51cb776ef4e0b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.test.ts @@ -6,7 +6,7 @@ import { SemVer } from 'semver'; import { IScopedClusterClient, kibanaResponseFactory } from 'src/core/server'; -import { CURRENT_VERSION } from '../../../common/version'; +import { CURRENT_VERSION } from '../../common/version'; import { esVersionCheck, getAllNodeVersions, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts similarity index 98% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts rename to x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts index 2fb3effe43793..e7636eea66479 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/es_version_precheck.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_version_precheck.ts @@ -13,7 +13,7 @@ import { RequestHandler, RequestHandlerContext, } from 'src/core/server'; -import { CURRENT_VERSION } from '../../../common/version'; +import { CURRENT_VERSION } from '../../common/version'; /** * Returns an array of all the unique Elasticsearch Node Versions in the Elasticsearch cluster. diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts similarity index 95% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts index 06fa755472238..ce892df0de946 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ReindexSavedObject } from '../../../../common/types'; +import { ReindexSavedObject } from '../../../common/types'; import { Credential, credentialStoreFactory } from './credential_store'; describe('credentialStore', () => { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts similarity index 91% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts index a051d16b5779f..0958559910be6 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/credential_store.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/credential_store.ts @@ -5,12 +5,11 @@ */ import { createHash } from 'crypto'; -import { Request } from 'hapi'; import stringify from 'json-stable-stringify'; -import { ReindexSavedObject } from '../../../../common/types'; +import { ReindexSavedObject } from '../../../common/types'; -export type Credential = Request['headers']; +export type Credential = Record; /** * An in-memory cache for user credentials to be used for reindexing operations. When looking up diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/index.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts index 7b346cc87edf6..9ec06b72f02e2 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; import { generateNewIndexName, getReindexWarnings, diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts index 0b95bc628fbb4..f6dc471d0945d 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/index_settings.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts @@ -5,8 +5,8 @@ */ import { flow, omit } from 'lodash'; -import { ReindexWarning } from '../../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; +import { ReindexWarning } from '../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; import { FlatSettings } from './types'; export interface ParsedIndexName { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts similarity index 99% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts index 3fb855958a5d0..4569fdfa33a83 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts @@ -13,8 +13,8 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; +} from '../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; import { LOCK_WINDOW, ReindexActions, reindexActionsFactory } from './reindex_actions'; describe('ReindexActions', () => { diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts similarity index 97% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts index 6683f80c8e779..2ae340f12d80c 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_actions.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts @@ -6,8 +6,7 @@ import moment from 'moment'; -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { SavedObjectsFindResponse, SavedObjectsClientContract } from 'kibana/server'; +import { SavedObjectsFindResponse, SavedObjectsClientContract, APICaller } from 'src/core/server'; import { IndexGroup, REINDEX_OP_TYPE, @@ -15,7 +14,7 @@ import { ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../../common/types'; +} from '../../../common/types'; import { generateNewIndexName } from './index_settings'; import { FlatSettings } from './types'; @@ -111,7 +110,7 @@ export interface ReindexActions { export const reindexActionsFactory = ( client: SavedObjectsClientContract, - callCluster: CallCluster + callAsUser: APICaller ): ReindexActions => { // ----- Internal functions const isLocked = (reindexOp: ReindexSavedObject) => { @@ -230,7 +229,7 @@ export const reindexActionsFactory = ( }, async getFlatSettings(indexName: string) { - const flatSettings = (await callCluster('transport.request', { + const flatSettings = (await callAsUser('transport.request', { path: `/${encodeURIComponent(indexName)}?flat_settings=true`, })) as { [indexName: string]: FlatSettings }; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts similarity index 95% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index 9cd41c8cbe826..6c3b2c869dc7f 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -4,14 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ +import { BehaviorSubject } from 'rxjs'; +import { Logger } from 'src/core/server'; +import { loggingServiceMock } from 'src/core/server/mocks'; + import { IndexGroup, ReindexOperation, ReindexSavedObject, ReindexStatus, ReindexStep, -} from '../../../../common/types'; -import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../../common/version'; +} from '../../../common/types'; +import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/version'; +import { licensingMock } from '../../../../licensing/server/mocks'; +import { LicensingPluginSetup } from '../../../../licensing/server'; + import { isMlIndex, isWatcherIndex, @@ -22,9 +29,9 @@ import { describe('reindexService', () => { let actions: jest.Mocked; let callCluster: jest.Mock; - let log: jest.Mock; - let xpackInfo: { feature: jest.Mocked }; + let log: Logger; let service: ReindexService; + let licensingPluginSetup: LicensingPluginSetup; const updateMockImpl = (reindexOp: ReindexSavedObject, attrs: Partial = {}) => Promise.resolve({ @@ -50,32 +57,24 @@ describe('reindexService', () => { runWhileIndexGroupLocked: jest.fn(async (group: string, f: any) => f({ attributes: {} })), }; callCluster = jest.fn(); - log = jest.fn(); - xpackInfo = { - feature: jest.fn(() => ({ - isAvailable() { - return true; - }, - isEnabled() { - return true; - }, - })), - }; - - service = reindexServiceFactory(callCluster as any, xpackInfo as any, actions, log); + log = loggingServiceMock.create().get(); + licensingPluginSetup = licensingMock.createSetup(); + licensingPluginSetup.license$ = new BehaviorSubject( + licensingMock.createLicense({ + features: { security: { isAvailable: true, isEnabled: true } }, + }) + ); + + service = reindexServiceFactory(callCluster as any, actions, log, licensingPluginSetup); }); describe('hasRequiredPrivileges', () => { it('returns true if security is disabled', async () => { - xpackInfo.feature.mockReturnValueOnce({ - isAvailable() { - return true; - }, - isEnabled() { - return false; - }, - }); - + licensingPluginSetup.license$ = new BehaviorSubject( + licensingMock.createLicense({ + features: { security: { isAvailable: true, isEnabled: false } }, + }) + ); const hasRequired = await service.hasRequiredPrivileges('anIndex'); expect(hasRequired).toBe(true); }); @@ -584,7 +583,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_ml/set_upgrade_mode?enabled=true', method: 'POST', @@ -599,7 +598,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_ml/set_upgrade_mode?enabled=true', method: 'POST', @@ -623,7 +622,7 @@ describe('reindexService', () => { expect( updatedOp.attributes.errorMessage!.includes('Could not stop ML jobs') ).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).toHaveBeenCalledWith('transport.request', { path: '/_ml/set_upgrade_mode?enabled=true', method: 'POST', @@ -645,7 +644,7 @@ describe('reindexService', () => { expect( updatedOp.attributes.errorMessage!.includes('Some nodes are not on minimum version') ).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); // Should not have called ML endpoint at all expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_ml/set_upgrade_mode?enabled=true', @@ -698,7 +697,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_watcher/_stop', method: 'POST', @@ -713,7 +712,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.created); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_watcher/_stop', method: 'POST', @@ -735,7 +734,7 @@ describe('reindexService', () => { expect( updatedOp.attributes.errorMessage!.includes('Could not stop Watcher') ).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).toHaveBeenCalledWith('transport.request', { path: '/_watcher/_stop', method: 'POST', @@ -771,7 +770,7 @@ describe('reindexService', () => { ); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); }); it('fails if setting updates fail', async () => { @@ -782,7 +781,7 @@ describe('reindexService', () => { ); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); }); }); @@ -817,7 +816,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.readonly); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); }); it('fails if create index fails', async () => { @@ -829,7 +828,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.readonly); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); // Original index should have been set back to allow reads. expect(callCluster).toHaveBeenCalledWith('indices.putSettings', { @@ -874,7 +873,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.newIndexCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); }); }); @@ -931,7 +930,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexStarted); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); }); }); @@ -1014,7 +1013,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexCompleted); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); }); it('fails if switching aliases fails', async () => { @@ -1023,7 +1022,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.reindexCompleted); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage).not.toBeNull(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); }); }); @@ -1092,7 +1091,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_ml/set_upgrade_mode?enabled=false', method: 'POST', @@ -1108,7 +1107,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_ml/set_upgrade_mode?enabled=false', method: 'POST', @@ -1129,7 +1128,7 @@ describe('reindexService', () => { expect( updatedOp.attributes.errorMessage!.includes('Could not resume ML jobs') ).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).toHaveBeenCalledWith('transport.request', { path: '/_ml/set_upgrade_mode?enabled=false', method: 'POST', @@ -1196,7 +1195,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_watcher/_start', method: 'POST', @@ -1212,7 +1211,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.aliasCreated); expect(updatedOp.attributes.status).toEqual(ReindexStatus.failed); expect(updatedOp.attributes.errorMessage!.includes(`Can't lock!`)).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).not.toHaveBeenCalledWith('transport.request', { path: '/_watcher/_start', method: 'POST', @@ -1233,7 +1232,7 @@ describe('reindexService', () => { expect( updatedOp.attributes.errorMessage!.includes('Could not start Watcher') ).toBeTruthy(); - expect(log).toHaveBeenCalledWith(['upgrade_assistant', 'error'], expect.any(String)); + expect(log.error).toHaveBeenCalledWith(expect.any(String)); expect(callCluster).toHaveBeenCalledWith('transport.request', { path: '/_watcher/_start', method: 'POST', diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts similarity index 90% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts index 0e6095f98b6ff..8f1df5b34372b 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/reindex_service.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts @@ -5,17 +5,16 @@ */ import Boom from 'boom'; +import { APICaller, Logger } from 'src/core/server'; +import { first } from 'rxjs/operators'; -import { Server } from 'hapi'; -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; -import { XPackInfo } from '../../../../../xpack_main/server/lib/xpack_info'; import { IndexGroup, ReindexSavedObject, ReindexStatus, ReindexStep, ReindexWarning, -} from '../../../../common/types'; +} from '../../../common/types'; import { generateNewIndexName, getReindexWarnings, @@ -23,6 +22,7 @@ import { transformFlatSettings, } from './index_settings'; import { ReindexActions } from './reindex_actions'; +import { LicensingPluginSetup } from '../../../../licensing/server'; const VERSION_REGEX = new RegExp(/^([1-9]+)\.([0-9]+)\.([0-9]+)/); const ML_INDICES = ['.ml-state', '.ml-anomalies', '.ml-config']; @@ -97,10 +97,10 @@ export interface ReindexService { } export const reindexServiceFactory = ( - callCluster: CallCluster, - xpackInfo: XPackInfo, + callAsUser: APICaller, actions: ReindexActions, - log: Server['log'] + log: Logger, + licensing: LicensingPluginSetup ): ReindexService => { // ------ Utility functions @@ -114,7 +114,7 @@ export const reindexServiceFactory = ( await actions.runWhileIndexGroupLocked(IndexGroup.ml, async mlDoc => { await validateNodesMinimumVersion(6, 7); - const res = await callCluster('transport.request', { + const res = await callAsUser('transport.request', { path: '/_ml/set_upgrade_mode?enabled=true', method: 'POST', }); @@ -134,7 +134,7 @@ export const reindexServiceFactory = ( await actions.decrementIndexGroupReindexes(IndexGroup.ml); await actions.runWhileIndexGroupLocked(IndexGroup.ml, async mlDoc => { if (mlDoc.attributes.runningReindexCount === 0) { - const res = await callCluster('transport.request', { + const res = await callAsUser('transport.request', { path: '/_ml/set_upgrade_mode?enabled=false', method: 'POST', }); @@ -154,7 +154,7 @@ export const reindexServiceFactory = ( const stopWatcher = async () => { await actions.incrementIndexGroupReindexes(IndexGroup.watcher); await actions.runWhileIndexGroupLocked(IndexGroup.watcher, async watcherDoc => { - const { acknowledged } = await callCluster('transport.request', { + const { acknowledged } = await callAsUser('transport.request', { path: '/_watcher/_stop', method: 'POST', }); @@ -174,7 +174,7 @@ export const reindexServiceFactory = ( await actions.decrementIndexGroupReindexes(IndexGroup.watcher); await actions.runWhileIndexGroupLocked(IndexGroup.watcher, async watcherDoc => { if (watcherDoc.attributes.runningReindexCount === 0) { - const { acknowledged } = await callCluster('transport.request', { + const { acknowledged } = await callAsUser('transport.request', { path: '/_watcher/_start', method: 'POST', }); @@ -191,14 +191,14 @@ export const reindexServiceFactory = ( const cleanupChanges = async (reindexOp: ReindexSavedObject) => { // Cancel reindex task if it was started but not completed if (reindexOp.attributes.lastCompletedStep === ReindexStep.reindexStarted) { - await callCluster('tasks.cancel', { + await callAsUser('tasks.cancel', { taskId: reindexOp.attributes.reindexTaskId, }).catch(e => undefined); // Ignore any exceptions trying to cancel (it may have already completed). } // Set index back to writable if we ever got past this point. if (reindexOp.attributes.lastCompletedStep >= ReindexStep.readonly) { - await callCluster('indices.putSettings', { + await callAsUser('indices.putSettings', { index: reindexOp.attributes.indexName, body: { 'index.blocks.write': false }, }); @@ -208,7 +208,7 @@ export const reindexServiceFactory = ( reindexOp.attributes.lastCompletedStep >= ReindexStep.newIndexCreated && reindexOp.attributes.lastCompletedStep < ReindexStep.aliasCreated ) { - await callCluster('indices.delete', { index: reindexOp.attributes.newIndexName }); + await callAsUser('indices.delete', { index: reindexOp.attributes.newIndexName }); } // Resume consumers if we ever got past this point. @@ -222,7 +222,7 @@ export const reindexServiceFactory = ( // ------ Functions used to process the state machine const validateNodesMinimumVersion = async (minMajor: number, minMinor: number) => { - const nodesResponse = await callCluster('transport.request', { + const nodesResponse = await callAsUser('transport.request', { path: '/_nodes', method: 'GET', }); @@ -263,7 +263,7 @@ export const reindexServiceFactory = ( */ const setReadonly = async (reindexOp: ReindexSavedObject) => { const { indexName } = reindexOp.attributes; - const putReadonly = await callCluster('indices.putSettings', { + const putReadonly = await callAsUser('indices.putSettings', { index: indexName, body: { 'index.blocks.write': true }, }); @@ -289,7 +289,7 @@ export const reindexServiceFactory = ( const { settings, mappings } = transformFlatSettings(flatSettings); - const createIndex = await callCluster('indices.create', { + const createIndex = await callAsUser('indices.create', { index: newIndexName, body: { settings, @@ -313,7 +313,7 @@ export const reindexServiceFactory = ( const startReindexing = async (reindexOp: ReindexSavedObject) => { const { indexName } = reindexOp.attributes; - const startReindex = (await callCluster('reindex', { + const startReindex = (await callAsUser('reindex', { refresh: true, waitForCompletion: false, body: { @@ -337,7 +337,7 @@ export const reindexServiceFactory = ( const taskId = reindexOp.attributes.reindexTaskId; // Check reindexing task progress - const taskResponse = await callCluster('tasks.get', { + const taskResponse = await callAsUser('tasks.get', { taskId, waitForCompletion: false, }); @@ -358,7 +358,7 @@ export const reindexServiceFactory = ( reindexOp = await cleanupChanges(reindexOp); } else { // Check that it reindexed all documents - const { count } = await callCluster('count', { index: reindexOp.attributes.indexName }); + const { count } = await callAsUser('count', { index: reindexOp.attributes.indexName }); if (taskResponse.task.status.created < count) { // Include the entire task result in the error message. This should be guaranteed @@ -374,7 +374,7 @@ export const reindexServiceFactory = ( } // Delete the task from ES .tasks index - const deleteTaskResp = await callCluster('delete', { + const deleteTaskResp = await callAsUser('delete', { index: '.tasks', id: taskId, }); @@ -394,7 +394,7 @@ export const reindexServiceFactory = ( const { indexName, newIndexName } = reindexOp.attributes; const existingAliases = ( - await callCluster('indices.getAlias', { + await callAsUser('indices.getAlias', { index: indexName, }) )[indexName].aliases; @@ -403,7 +403,7 @@ export const reindexServiceFactory = ( add: { index: newIndexName, alias: aliasName, ...existingAliases[aliasName] }, })); - const aliasResponse = await callCluster('indices.updateAliases', { + const aliasResponse = await callAsUser('indices.updateAliases', { body: { actions: [ { add: { index: newIndexName, alias: indexName } }, @@ -443,9 +443,18 @@ export const reindexServiceFactory = ( return { async hasRequiredPrivileges(indexName: string) { + /** + * To avoid a circular dependency on Security we use a work around + * here to detect whether Security is available and enabled + * (i.e., via the licensing plugin). This enables Security to use + * functionality exposed through Upgrade Assistant. + */ + const license = await licensing.license$.pipe(first()).toPromise(); + + const securityFeature = license.getFeature('security'); + // If security is disabled or unavailable, return true. - const security = xpackInfo.feature('security'); - if (!security.isAvailable() || !security.isEnabled()) { + if (!securityFeature || !(securityFeature.isAvailable && securityFeature.isEnabled)) { return true; } @@ -482,7 +491,7 @@ export const reindexServiceFactory = ( body.cluster = [...body.cluster, 'manage_watcher']; } - const resp = await callCluster('transport.request', { + const resp = await callAsUser('transport.request', { path: '/_security/user/_has_privileges', method: 'POST', body, @@ -509,7 +518,7 @@ export const reindexServiceFactory = ( }, async createReindexOperation(indexName: string) { - const indexExists = await callCluster('indices.exists', { index: indexName }); + const indexExists = await callAsUser('indices.exists', { index: indexName }); if (!indexExists) { throw Boom.notFound(`Index ${indexName} does not exist in this cluster.`); } @@ -579,10 +588,7 @@ export const reindexServiceFactory = ( break; } } catch (e) { - log( - ['upgrade_assistant', 'error'], - `Reindexing step failed: ${e instanceof Error ? e.stack : e.toString()}` - ); + log.error(`Reindexing step failed: ${e instanceof Error ? e.stack : e.toString()}`); // Trap the exception and add the message to the object so the UI can display it. lockedReindexOp = await actions.updateReindexOp(lockedReindexOp, { @@ -647,7 +653,7 @@ export const reindexServiceFactory = ( throw new Error(`Reindex operation is not current waiting for reindex task to complete`); } - const resp = await callCluster('tasks.cancel', { + const resp = await callAsUser('tasks.cancel', { taskId: reindexOp.attributes.reindexTaskId, }); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/types.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/types.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/types.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/types.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts similarity index 76% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts rename to x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts index 628a47be9f5e7..bad6db62efe41 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/reindexing/worker.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/worker.ts @@ -3,23 +3,19 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CallCluster, CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch'; -import { Request, Server } from 'src/legacy/server/kbn_server'; -import { SavedObjectsClientContract } from 'kibana/server'; - +import { IClusterClient, Logger, SavedObjectsClientContract, FakeRequest } from 'src/core/server'; import moment from 'moment'; -import { XPackInfo } from '../../../../../xpack_main/server/lib/xpack_info'; -import { ReindexSavedObject, ReindexStatus } from '../../../../common/types'; + +import { ReindexSavedObject, ReindexStatus } from '../../../common/types'; import { CredentialStore } from './credential_store'; import { reindexActionsFactory } from './reindex_actions'; import { ReindexService, reindexServiceFactory } from './reindex_service'; +import { LicensingPluginSetup } from '../../../../licensing/server'; const POLL_INTERVAL = 30000; // If no nodes have been able to update this index in 2 minutes (due to missing credentials), set to paused. const PAUSE_WINDOW = POLL_INTERVAL * 4; -const LOG_TAGS = ['upgrade_assistant', 'reindex_worker']; - /** * A singleton worker that will coordinate two polling loops: * (1) A longer loop that polls for reindex operations that are in progress. If any are found, loop (2) is started. @@ -41,24 +37,27 @@ export class ReindexWorker { private timeout?: NodeJS.Timeout; private inProgressOps: ReindexSavedObject[] = []; private readonly reindexService: ReindexService; + private readonly log: Logger; constructor( private client: SavedObjectsClientContract, private credentialStore: CredentialStore, - private callWithRequest: CallClusterWithRequest, - private callWithInternalUser: CallCluster, - private xpackInfo: XPackInfo, - private readonly log: Server['log'] + private clusterClient: IClusterClient, + log: Logger, + private licensing: LicensingPluginSetup ) { + this.log = log.get('reindex_worker'); if (ReindexWorker.workerSingleton) { throw new Error(`More than one ReindexWorker cannot be created.`); } + const callAsInternalUser = this.clusterClient.callAsInternalUser.bind(this.clusterClient); + this.reindexService = reindexServiceFactory( - this.callWithInternalUser, - this.xpackInfo, - reindexActionsFactory(this.client, this.callWithInternalUser), - this.log + callAsInternalUser, + reindexActionsFactory(this.client, callAsInternalUser), + log, + this.licensing ); ReindexWorker.workerSingleton = this; @@ -68,7 +67,7 @@ export class ReindexWorker { * Begins loop (1) to begin checking for in progress reindex operations. */ public start = () => { - this.log(['debug', ...LOG_TAGS], `Starting worker...`); + this.log.debug('Starting worker...'); this.continuePolling = true; this.pollForOperations(); }; @@ -77,7 +76,7 @@ export class ReindexWorker { * Stops the worker from processing any further reindex operations. */ public stop = () => { - this.log(['debug', ...LOG_TAGS], `Stopping worker...`); + this.log.debug('Stopping worker...'); if (this.timeout) { clearTimeout(this.timeout); } @@ -107,7 +106,7 @@ export class ReindexWorker { this.updateOperationLoopRunning = true; while (this.inProgressOps.length > 0) { - this.log(['debug', ...LOG_TAGS], `Updating ${this.inProgressOps.length} reindex operations`); + this.log.debug(`Updating ${this.inProgressOps.length} reindex operations`); // Push each operation through the state machine and refresh. await Promise.all(this.inProgressOps.map(this.processNextStep)); @@ -118,7 +117,7 @@ export class ReindexWorker { }; private pollForOperations = async () => { - this.log(['debug', ...LOG_TAGS], `Polling for reindex operations`); + this.log.debug(`Polling for reindex operations`); await this.refresh(); @@ -131,7 +130,7 @@ export class ReindexWorker { try { this.inProgressOps = await this.reindexService.findAllByStatus(ReindexStatus.inProgress); } catch (e) { - this.log(['debug', ...LOG_TAGS], `Could not fetch riendex operations from Elasticsearch`); + this.log.debug(`Could not fetch reindex operations from Elasticsearch`); this.inProgressOps = []; } @@ -159,10 +158,13 @@ export class ReindexWorker { } // Setup a ReindexService specific to these credentials. - const fakeRequest = { headers: credential } as Request; - const callCluster = this.callWithRequest.bind(null, fakeRequest) as CallCluster; - const actions = reindexActionsFactory(this.client, callCluster); - const service = reindexServiceFactory(callCluster, this.xpackInfo, actions, this.log); + const fakeRequest: FakeRequest = { headers: credential }; + + const scopedClusterClient = this.clusterClient.asScoped(fakeRequest); + const callAsCurrentUser = scopedClusterClient.callAsCurrentUser.bind(scopedClusterClient); + const actions = reindexActionsFactory(this.client, callAsCurrentUser); + + const service = reindexServiceFactory(callAsCurrentUser, actions, this.log, this.licensing); reindexOp = await swallowExceptions(service.processNextStep, this.log)(reindexOp); // Update credential store with most recent state. @@ -176,18 +178,15 @@ export class ReindexWorker { */ const swallowExceptions = ( func: (reindexOp: ReindexSavedObject) => Promise, - log: Server['log'] + log: Logger ) => async (reindexOp: ReindexSavedObject) => { try { return await func(reindexOp); } catch (e) { if (reindexOp.attributes.locked) { - log(['debug', ...LOG_TAGS], `Skipping reindexOp with unexpired lock: ${reindexOp.id}`); + log.debug(`Skipping reindexOp with unexpired lock: ${reindexOp.id}`); } else { - log( - ['warning', ...LOG_TAGS], - `Error when trying to process reindexOp (${reindexOp.id}): ${e.toString()}` - ); + log.warn(`Error when trying to process reindexOp (${reindexOp.id}): ${e.toString()}`); } return reindexOp; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts similarity index 51% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts index 5f95f6e9fd555..703351c45ba5a 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_open_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.test.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; -import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../../common/types'; import { upsertUIOpenOption } from './es_ui_open_apis'; /** @@ -13,54 +14,29 @@ import { upsertUIOpenOption } from './es_ui_open_apis'; * more thoroughly in the lib/telemetry tests. */ describe('Upgrade Assistant Telemetry SavedObject UIOpen', () => { - const mockIncrementCounter = jest.fn(); - const server = jest.fn().mockReturnValue({ - savedObjects: { - getSavedObjectsRepository: jest.fn().mockImplementation(() => { - return { - incrementCounter: mockIncrementCounter, - }; - }), - }, - plugins: { - elasticsearch: { - getCluster: () => { - return { - callWithInternalUser: {}, - }; - }, - }, - }, - }); - - const request = jest.fn().mockReturnValue({ - payload: { - overview: true, - cluster: true, - indices: true, - }, - }); - describe('Upsert UIOpen Option', () => { it('call saved objects internal repository with the correct info', async () => { - const serverMock = server(); - const incCounterSORepoFunc = serverMock.savedObjects.getSavedObjectsRepository() - .incrementCounter; + const internalRepo = savedObjectsRepositoryMock.create(); - await upsertUIOpenOption(serverMock, request()); + await upsertUIOpenOption({ + overview: true, + cluster: true, + indices: true, + savedObjects: { createInternalRepository: () => internalRepo } as any, + }); - expect(incCounterSORepoFunc).toHaveBeenCalledTimes(3); - expect(incCounterSORepoFunc).toHaveBeenCalledWith( + expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(3); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, `ui_open.overview` ); - expect(incCounterSORepoFunc).toHaveBeenCalledWith( + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, `ui_open.cluster` ); - expect(incCounterSORepoFunc).toHaveBeenCalledWith( + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, `ui_open.indices` diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts new file mode 100644 index 0000000000000..64e9b0f217555 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_open_apis.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedObjectsServiceStart } from 'src/core/server'; +import { + UIOpen, + UIOpenOption, + UPGRADE_ASSISTANT_DOC_ID, + UPGRADE_ASSISTANT_TYPE, +} from '../../../common/types'; + +interface IncrementUIOpenDependencies { + uiOpenOptionCounter: UIOpenOption; + savedObjects: SavedObjectsServiceStart; +} + +async function incrementUIOpenOptionCounter({ + savedObjects, + uiOpenOptionCounter, +}: IncrementUIOpenDependencies) { + const internalRepository = savedObjects.createInternalRepository(); + + await internalRepository.incrementCounter( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + `ui_open.${uiOpenOptionCounter}` + ); +} + +type UpsertUIOpenOptionDependencies = UIOpen & { savedObjects: SavedObjectsServiceStart }; + +export async function upsertUIOpenOption({ + overview, + cluster, + indices, + savedObjects, +}: UpsertUIOpenOptionDependencies): Promise { + if (overview) { + await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'overview' }); + } + + if (cluster) { + await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'cluster' }); + } + + if (indices) { + await incrementUIOpenOptionCounter({ savedObjects, uiOpenOptionCounter: 'indices' }); + } + + return { + overview, + cluster, + indices, + }; +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts similarity index 52% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts index 3f2c80f7d6b75..31e4e3f07b5de 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/es_ui_reindex_apis.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.test.ts @@ -3,8 +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 { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../../common/types'; +import { savedObjectsRepositoryMock } from 'src/core/server/mocks'; +import { UPGRADE_ASSISTANT_DOC_ID, UPGRADE_ASSISTANT_TYPE } from '../../../common/types'; import { upsertUIReindexOption } from './es_ui_reindex_apis'; /** @@ -13,60 +13,34 @@ import { upsertUIReindexOption } from './es_ui_reindex_apis'; * more thoroughly in the lib/telemetry tests. */ describe('Upgrade Assistant Telemetry SavedObject UIReindex', () => { - const mockIncrementCounter = jest.fn(); - const server = jest.fn().mockReturnValue({ - savedObjects: { - getSavedObjectsRepository: jest.fn().mockImplementation(() => { - return { - incrementCounter: mockIncrementCounter, - }; - }), - }, - plugins: { - elasticsearch: { - getCluster: () => { - return { - callWithInternalUser: {}, - }; - }, - }, - }, - }); - - const request = jest.fn().mockReturnValue({ - payload: { - close: true, - open: true, - start: true, - stop: true, - }, - }); - describe('Upsert UIReindex Option', () => { it('call saved objects internal repository with the correct info', async () => { - const serverMock = server(); - const incCounterSORepoFunc = serverMock.savedObjects.getSavedObjectsRepository() - .incrementCounter; - - await upsertUIReindexOption(serverMock, request()); + const internalRepo = savedObjectsRepositoryMock.create(); + await upsertUIReindexOption({ + close: true, + open: true, + start: true, + stop: true, + savedObjects: { createInternalRepository: () => internalRepo } as any, + }); - expect(incCounterSORepoFunc).toHaveBeenCalledTimes(4); - expect(incCounterSORepoFunc).toHaveBeenCalledWith( + expect(internalRepo.incrementCounter).toHaveBeenCalledTimes(4); + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, `ui_reindex.close` ); - expect(incCounterSORepoFunc).toHaveBeenCalledWith( + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, `ui_reindex.open` ); - expect(incCounterSORepoFunc).toHaveBeenCalledWith( + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, `ui_reindex.start` ); - expect(incCounterSORepoFunc).toHaveBeenCalledWith( + expect(internalRepo.incrementCounter).toHaveBeenCalledWith( UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID, `ui_reindex.stop` diff --git a/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts new file mode 100644 index 0000000000000..0aaaf63196d67 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/es_ui_reindex_apis.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedObjectsServiceStart } from 'src/core/server'; +import { + UIReindex, + UIReindexOption, + UPGRADE_ASSISTANT_DOC_ID, + UPGRADE_ASSISTANT_TYPE, +} from '../../../common/types'; + +interface IncrementUIReindexOptionDependencies { + uiReindexOptionCounter: UIReindexOption; + savedObjects: SavedObjectsServiceStart; +} + +async function incrementUIReindexOptionCounter({ + savedObjects, + uiReindexOptionCounter, +}: IncrementUIReindexOptionDependencies) { + const internalRepository = savedObjects.createInternalRepository(); + + await internalRepository.incrementCounter( + UPGRADE_ASSISTANT_TYPE, + UPGRADE_ASSISTANT_DOC_ID, + `ui_reindex.${uiReindexOptionCounter}` + ); +} + +type UpsertUIReindexOptionDepencies = UIReindex & { savedObjects: SavedObjectsServiceStart }; + +export async function upsertUIReindexOption({ + start, + close, + open, + stop, + savedObjects, +}: UpsertUIReindexOptionDepencies): Promise { + if (close) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'close' }); + } + + if (open) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'open' }); + } + + if (start) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'start' }); + } + + if (stop) { + await incrementUIReindexOptionCounter({ savedObjects, uiReindexOptionCounter: 'stop' }); + } + + return { + close, + open, + start, + stop, + }; +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/index.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/index.ts similarity index 100% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/index.ts rename to x-pack/plugins/upgrade_assistant/server/lib/telemetry/index.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts similarity index 78% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.test.ts rename to x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts index 27a0eef0d16f6..a4833d9a3d7fe 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.test.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { registerUpgradeAssistantUsageCollector } from './usage_collector'; +import { IClusterClient } from 'src/core/server'; /** * Since these route callbacks are so thin, these serve simply as integration tests @@ -14,20 +15,31 @@ import { registerUpgradeAssistantUsageCollector } from './usage_collector'; describe('Upgrade Assistant Usage Collector', () => { let makeUsageCollectorStub: any; let registerStub: any; - let server: any; + let dependencies: any; let callClusterStub: any; let usageCollection: any; + let clusterClient: IClusterClient; beforeEach(() => { + clusterClient = elasticsearchServiceMock.createClusterClient(); + (clusterClient.callAsInternalUser as jest.Mock).mockResolvedValue({ + persistent: {}, + transient: { + logger: { + deprecation: 'WARN', + }, + }, + }); makeUsageCollectorStub = jest.fn(); registerStub = jest.fn(); usageCollection = { makeUsageCollector: makeUsageCollectorStub, registerCollector: registerStub, }; - server = jest.fn().mockReturnValue({ + dependencies = { + usageCollection, savedObjects: { - getSavedObjectsRepository: jest.fn().mockImplementation(() => { + createInternalRepository: jest.fn().mockImplementation(() => { return { get: () => { return { @@ -45,31 +57,26 @@ describe('Upgrade Assistant Usage Collector', () => { }; }), }, - }); - callClusterStub = jest.fn().mockResolvedValue({ - persistent: {}, - transient: { - logger: { - deprecation: 'WARN', - }, + elasticsearch: { + adminClient: clusterClient, }, - }); + }; }); describe('registerUpgradeAssistantUsageCollector', () => { it('should registerCollector', () => { - registerUpgradeAssistantUsageCollector(usageCollection, server()); + registerUpgradeAssistantUsageCollector(dependencies); expect(registerStub).toHaveBeenCalledTimes(1); }); it('should call makeUsageCollector with type = upgrade-assistant', () => { - registerUpgradeAssistantUsageCollector(usageCollection, server()); + registerUpgradeAssistantUsageCollector(dependencies); expect(makeUsageCollectorStub).toHaveBeenCalledTimes(1); expect(makeUsageCollectorStub.mock.calls[0][0].type).toBe('upgrade-assistant-telemetry'); }); it('fetchUpgradeAssistantMetrics should return correct info', async () => { - registerUpgradeAssistantUsageCollector(usageCollection, server()); + registerUpgradeAssistantUsageCollector(dependencies); const upgradeAssistantStats = await makeUsageCollectorStub.mock.calls[0][0].fetch( callClusterStub ); diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts similarity index 72% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts rename to x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts index 1d24d190fa9f2..79d6e53c64ec0 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/lib/telemetry/usage_collector.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/telemetry/usage_collector.ts @@ -5,8 +5,12 @@ */ import { set } from 'lodash'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { SavedObjectsRepository } from 'src/core/server/saved_objects/service/lib/repository'; +import { + APICaller, + ElasticsearchServiceSetup, + ISavedObjectsRepository, + SavedObjectsServiceStart, +} from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { UPGRADE_ASSISTANT_DOC_ID, @@ -14,12 +18,11 @@ import { UpgradeAssistantTelemetry, UpgradeAssistantTelemetrySavedObject, UpgradeAssistantTelemetrySavedObjectAttributes, -} from '../../../../common/types'; -import { ServerShim } from '../../types'; +} from '../../../common/types'; import { isDeprecationLoggingEnabled } from '../es_deprecation_logging_apis'; async function getSavedObjectAttributesFromRepo( - savedObjectsRepository: SavedObjectsRepository, + savedObjectsRepository: ISavedObjectsRepository, docType: string, docID: string ) { @@ -35,9 +38,9 @@ async function getSavedObjectAttributesFromRepo( } } -async function getDeprecationLoggingStatusValue(callCluster: any): Promise { +async function getDeprecationLoggingStatusValue(callAsCurrentUser: APICaller): Promise { try { - const loggerDeprecationCallResult = await callCluster('cluster.getSettings', { + const loggerDeprecationCallResult = await callAsCurrentUser('cluster.getSettings', { includeDefaults: true, }); @@ -48,17 +51,17 @@ async function getDeprecationLoggingStatusValue(callCluster: any): Promise { - const { getSavedObjectsRepository } = server.savedObjects; - const savedObjectsRepository = getSavedObjectsRepository(callCluster); + const savedObjectsRepository = savedObjects.createInternalRepository(); const upgradeAssistantSOAttributes = await getSavedObjectAttributesFromRepo( savedObjectsRepository, UPGRADE_ASSISTANT_TYPE, UPGRADE_ASSISTANT_DOC_ID ); - const deprecationLoggingStatusValue = await getDeprecationLoggingStatusValue(callCluster); + const callAsInternalUser = adminClient.callAsInternalUser.bind(adminClient); + const deprecationLoggingStatusValue = await getDeprecationLoggingStatusValue(callAsInternalUser); const getTelemetrySavedObject = ( upgradeAssistantTelemetrySavedObjectAttrs: UpgradeAssistantTelemetrySavedObjectAttributes | null @@ -103,14 +106,21 @@ export async function fetchUpgradeAssistantMetrics( }; } -export function registerUpgradeAssistantUsageCollector( - usageCollection: UsageCollectionSetup, - server: ServerShim -) { +interface Dependencies { + elasticsearch: ElasticsearchServiceSetup; + savedObjects: SavedObjectsServiceStart; + usageCollection: UsageCollectionSetup; +} + +export function registerUpgradeAssistantUsageCollector({ + elasticsearch, + usageCollection, + savedObjects, +}: Dependencies) { const upgradeAssistantUsageCollector = usageCollection.makeUsageCollector({ type: UPGRADE_ASSISTANT_TYPE, isReady: () => true, - fetch: async (callCluster: any) => fetchUpgradeAssistantMetrics(callCluster, server), + fetch: async () => fetchUpgradeAssistantMetrics(elasticsearch, savedObjects), }); usageCollection.registerCollector(upgradeAssistantUsageCollector); diff --git a/x-pack/plugins/upgrade_assistant/server/plugin.ts b/x-pack/plugins/upgrade_assistant/server/plugin.ts new file mode 100644 index 0000000000000..6ccd073a9e020 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/plugin.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 { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; + +import { + Plugin, + CoreSetup, + CoreStart, + PluginInitializerContext, + Logger, + ElasticsearchServiceSetup, + SavedObjectsClient, + SavedObjectsServiceStart, +} from '../../../../src/core/server'; + +import { CloudSetup } from '../../cloud/server'; +import { LicensingPluginSetup } from '../../licensing/server'; + +import { CredentialStore, credentialStoreFactory } from './lib/reindexing/credential_store'; +import { ReindexWorker } from './lib/reindexing'; +import { registerUpgradeAssistantUsageCollector } from './lib/telemetry'; +import { registerClusterCheckupRoutes } from './routes/cluster_checkup'; +import { registerDeprecationLoggingRoutes } from './routes/deprecation_logging'; +import { registerReindexIndicesRoutes, createReindexWorker } from './routes/reindex_indices'; +import { registerTelemetryRoutes } from './routes/telemetry'; +import { RouteDependencies } from './types'; + +interface PluginsSetup { + usageCollection: UsageCollectionSetup; + licensing: LicensingPluginSetup; + cloud?: CloudSetup; +} + +export class UpgradeAssistantServerPlugin implements Plugin { + private readonly logger: Logger; + private readonly credentialStore: CredentialStore; + + // Properties set at setup + private licensing?: LicensingPluginSetup; + private elasticSearchService?: ElasticsearchServiceSetup; + + // Properties set at start + private savedObjectsServiceStart?: SavedObjectsServiceStart; + private worker?: ReindexWorker; + + constructor({ logger }: PluginInitializerContext) { + this.logger = logger.get(); + this.credentialStore = credentialStoreFactory(); + } + + private getWorker() { + if (!this.worker) { + throw new Error('Worker unavailable'); + } + return this.worker; + } + + setup( + { http, elasticsearch, getStartServices, capabilities }: CoreSetup, + { usageCollection, cloud, licensing }: PluginsSetup + ) { + this.elasticSearchService = elasticsearch; + this.licensing = licensing; + + const router = http.createRouter(); + + const dependencies: RouteDependencies = { + cloud, + router, + credentialStore: this.credentialStore, + log: this.logger, + getSavedObjectsService: () => { + if (!this.savedObjectsServiceStart) { + throw new Error('Saved Objects Start service not available'); + } + return this.savedObjectsServiceStart; + }, + licensing, + }; + + registerClusterCheckupRoutes(dependencies); + registerDeprecationLoggingRoutes(dependencies); + registerReindexIndicesRoutes(dependencies, this.getWorker.bind(this)); + // Bootstrap the needed routes and the collector for the telemetry + registerTelemetryRoutes(dependencies); + + if (usageCollection) { + getStartServices().then(([{ savedObjects }]) => { + registerUpgradeAssistantUsageCollector({ elasticsearch, usageCollection, savedObjects }); + }); + } + } + + start({ savedObjects }: CoreStart) { + this.savedObjectsServiceStart = savedObjects; + + // The ReindexWorker uses a map of request headers that contain the authentication credentials + // for a given reindex. We cannot currently store these in an the .kibana index b/c we do not + // want to expose these credentials to any unauthenticated users. We also want to avoid any need + // to add a user for a special index just for upgrading. This in-memory cache allows us to + // process jobs without the browser staying on the page, but will require that jobs go into + // a paused state if no Kibana nodes have the required credentials. + + this.worker = createReindexWorker({ + credentialStore: this.credentialStore, + licensing: this.licensing!, + elasticsearchService: this.elasticSearchService!, + logger: this.logger, + savedObjects: new SavedObjectsClient( + this.savedObjectsServiceStart.createInternalRepository() + ), + }); + + this.worker.start(); + } + + stop(): void { + if (this.worker) { + this.worker.stop(); + } + } +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/request.mock.ts similarity index 92% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts rename to x-pack/plugins/upgrade_assistant/server/routes/__mocks__/request.mock.ts index d09a66dbb4326..fb68e188bb255 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/request.mock.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/request.mock.ts @@ -6,7 +6,7 @@ export const createRequestMock = (opts?: { headers?: any; params?: Record; - payload?: Record; + body?: Record; }) => { return Object.assign({ headers: {} }, opts || {}); }; diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/routes.mock.ts similarity index 72% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts rename to x-pack/plugins/upgrade_assistant/server/routes/__mocks__/routes.mock.ts index 3769bc389123e..a8be171dccd98 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/__mocks__/routes.mock.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/__mocks__/routes.mock.ts @@ -3,7 +3,21 @@ * 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 { RequestHandler, RequestHandlerContext } from 'src/core/server'; +import { + elasticsearchServiceMock, + savedObjectsClientMock, +} from '../../../../../../src/core/server/mocks'; + +export const routeHandlerContextMock = ({ + core: { + elasticsearch: { + adminClient: elasticsearchServiceMock.createScopedClusterClient(), + dataClient: elasticsearchServiceMock.createScopedClusterClient(), + }, + savedObjects: { client: savedObjectsClientMock.create() }, + }, +} as unknown) as RequestHandlerContext; /** * Creates a very crude mock of the new platform router implementation. This enables use to test diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts similarity index 73% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts rename to x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts index 3fe2e1797182b..16f8001f8e1de 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/cluster_checkup.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { kibanaResponseFactory } from 'src/core/server'; -import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; jest.mock('../lib/es_version_precheck', () => ({ @@ -24,32 +24,22 @@ import { registerClusterCheckupRoutes } from './cluster_checkup'; * more thoroughly in the es_migration_apis test. */ describe('cluster checkup API', () => { - afterEach(() => jest.clearAllMocks()); - let mockRouter: MockRouter; - let serverShim: any; - let ctxMock: any; - let mockPluginsSetup: any; + let routeDependencies: any; beforeEach(() => { mockRouter = createMockRouter(); - mockPluginsSetup = { + routeDependencies = { cloud: { isCloudEnabled: true, }, - }; - ctxMock = { - core: {}, - }; - serverShim = { router: mockRouter, - plugins: { - elasticsearch: { - getCluster: () => ({ callWithRequest: jest.fn() } as any), - } as any, - }, }; - registerClusterCheckupRoutes(serverShim, mockPluginsSetup); + registerClusterCheckupRoutes(routeDependencies); + }); + + afterEach(() => { + jest.resetAllMocks(); }); describe('with cloud enabled', () => { @@ -62,11 +52,11 @@ describe('cluster checkup API', () => { nodes: [], }); - await serverShim.router.getHandler({ + await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/status', - })(ctxMock, createRequestMock(), kibanaResponseFactory); - expect(spy.mock.calls[0][2]).toBe(true); + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + expect(spy.mock.calls[0][1]).toBe(true); }); }); @@ -77,10 +67,10 @@ describe('cluster checkup API', () => { indices: [], nodes: [], }); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/status', - })(ctxMock, createRequestMock(), kibanaResponseFactory); + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); expect(resp.status).toEqual(200); expect(JSON.stringify(resp.payload)).toMatchInlineSnapshot( @@ -93,10 +83,10 @@ describe('cluster checkup API', () => { e.status = 403; MigrationApis.getUpgradeAssistantStatus.mockRejectedValue(e); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/status', - })(ctxMock, createRequestMock(), kibanaResponseFactory); + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); expect(resp.status).toEqual(403); }); @@ -104,10 +94,10 @@ describe('cluster checkup API', () => { it('returns an 500 error if it throws', async () => { MigrationApis.getUpgradeAssistantStatus.mockRejectedValue(new Error(`scary error!`)); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/status', - })(ctxMock, createRequestMock(), kibanaResponseFactory); + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); expect(resp.status).toEqual(500); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts new file mode 100644 index 0000000000000..22a121ab78683 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/cluster_checkup.ts @@ -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. + */ + +import { getUpgradeAssistantStatus } from '../lib/es_migration_apis'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { RouteDependencies } from '../types'; + +export function registerClusterCheckupRoutes({ cloud, router }: RouteDependencies) { + const isCloudEnabled = Boolean(cloud?.isCloudEnabled); + + router.get( + { + path: '/api/upgrade_assistant/status', + validate: false, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { dataClient }, + }, + }, + request, + response + ) => { + try { + return response.ok({ + body: await getUpgradeAssistantStatus(dataClient, isCloudEnabled), + }); + } catch (e) { + if (e.status === 403) { + return response.forbidden(e.message); + } + + return response.internalError({ body: e }); + } + } + ) + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts similarity index 56% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts rename to x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts index d663361956374..845a0238f7918 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/deprecation_logging.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.test.ts @@ -5,7 +5,7 @@ */ import { kibanaResponseFactory } from 'src/core/server'; -import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; jest.mock('../lib/es_version_precheck', () => ({ @@ -21,42 +21,42 @@ import { registerDeprecationLoggingRoutes } from './deprecation_logging'; */ describe('deprecation logging API', () => { let mockRouter: MockRouter; - let serverShim: any; - let callWithRequest: any; - const ctxMock: any = {}; + let routeDependencies: any; beforeEach(() => { mockRouter = createMockRouter(); - callWithRequest = jest.fn(); - serverShim = { + routeDependencies = { router: mockRouter, - plugins: { - elasticsearch: { - getCluster: () => ({ callWithRequest } as any), - } as any, - }, }; - registerDeprecationLoggingRoutes(serverShim); + registerDeprecationLoggingRoutes(routeDependencies); + }); + + afterEach(() => { + jest.resetAllMocks(); }); describe('GET /api/upgrade_assistant/deprecation_logging', () => { it('returns isEnabled', async () => { - callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'WARN' } } }); - const resp = await serverShim.router.getHandler({ + (routeHandlerContextMock.core.elasticsearch.dataClient + .callAsCurrentUser as jest.Mock).mockResolvedValue({ + default: { logger: { deprecation: 'WARN' } }, + }); + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/deprecation_logging', - })(ctxMock, createRequestMock(), kibanaResponseFactory); + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); expect(resp.status).toEqual(200); expect(resp.payload).toEqual({ isEnabled: true }); }); it('returns an error if it throws', async () => { - callWithRequest.mockRejectedValue(new Error(`scary error!`)); - const resp = await serverShim.router.getHandler({ + (routeHandlerContextMock.core.elasticsearch.dataClient + .callAsCurrentUser as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/deprecation_logging', - })(ctxMock, createRequestMock(), kibanaResponseFactory); + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); expect(resp.status).toEqual(500); }); @@ -64,21 +64,25 @@ describe('deprecation logging API', () => { describe('PUT /api/upgrade_assistant/deprecation_logging', () => { it('returns isEnabled', async () => { - callWithRequest.mockResolvedValue({ default: { logger: { deprecation: 'ERROR' } } }); - const resp = await serverShim.router.getHandler({ + (routeHandlerContextMock.core.elasticsearch.dataClient + .callAsCurrentUser as jest.Mock).mockResolvedValue({ + default: { logger: { deprecation: 'ERROR' } }, + }); + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/deprecation_logging', - })(ctxMock, createRequestMock(), kibanaResponseFactory); + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); expect(resp.payload).toEqual({ isEnabled: false }); }); it('returns an error if it throws', async () => { - callWithRequest.mockRejectedValue(new Error(`scary error!`)); - const resp = await serverShim.router.getHandler({ + (routeHandlerContextMock.core.elasticsearch.dataClient + .callAsCurrentUser as jest.Mock).mockRejectedValue(new Error(`scary error!`)); + const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/deprecation_logging', - })(ctxMock, { body: { isEnabled: false } }, kibanaResponseFactory); + })(routeHandlerContextMock, { body: { isEnabled: false } }, kibanaResponseFactory); expect(resp.status).toEqual(500); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts new file mode 100644 index 0000000000000..739a789c95ce0 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/deprecation_logging.ts @@ -0,0 +1,72 @@ +/* + * 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 } from '@kbn/config-schema'; + +import { + getDeprecationLoggingStatus, + setDeprecationLogging, +} from '../lib/es_deprecation_logging_apis'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { RouteDependencies } from '../types'; + +export function registerDeprecationLoggingRoutes({ router }: RouteDependencies) { + router.get( + { + path: '/api/upgrade_assistant/deprecation_logging', + validate: false, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { dataClient }, + }, + }, + request, + response + ) => { + try { + const result = await getDeprecationLoggingStatus(dataClient); + return response.ok({ body: result }); + } catch (e) { + return response.internalError({ body: e }); + } + } + ) + ); + + router.put( + { + path: '/api/upgrade_assistant/deprecation_logging', + validate: { + body: schema.object({ + isEnabled: schema.boolean(), + }), + }, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + elasticsearch: { dataClient }, + }, + }, + request, + response + ) => { + try { + const { isEnabled } = request.body as { isEnabled: boolean }; + return response.ok({ + body: await setDeprecationLogging(dataClient, isEnabled), + }); + } catch (e) { + return response.internalError({ body: e }); + } + } + ) + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts similarity index 80% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts rename to x-pack/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts index d520324239656..695bb6304cfdf 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/reindex_indices.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices.test.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { savedObjectsClientMock } from 'src/core/server/mocks'; import { kibanaResponseFactory } from 'src/core/server'; -import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { licensingMock } from '../../../licensing/server/mocks'; +import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; const mockReindexService = { @@ -31,12 +31,7 @@ jest.mock('../lib/reindexing', () => { }; }); -import { - IndexGroup, - ReindexSavedObject, - ReindexStatus, - ReindexWarning, -} from '../../../common/types'; +import { IndexGroup, ReindexSavedObject, ReindexStatus, ReindexWarning } from '../../common/types'; import { credentialStoreFactory } from '../lib/reindexing/credential_store'; import { registerReindexIndicesRoutes } from './reindex_indices'; @@ -46,9 +41,8 @@ import { registerReindexIndicesRoutes } from './reindex_indices'; * more thoroughly in the es_migration_apis test. */ describe('reindex API', () => { - let serverShim: any; + let routeDependencies: any; let mockRouter: MockRouter; - let ctxMock: any; const credentialStore = credentialStoreFactory(); const worker = { @@ -57,24 +51,13 @@ describe('reindex API', () => { } as any; beforeEach(() => { - ctxMock = { - core: { - savedObjects: savedObjectsClientMock.create(), - }, - }; mockRouter = createMockRouter(); - serverShim = { + routeDependencies = { + credentialStore, router: mockRouter, - plugins: { - xpack_main: { - info: jest.fn(), - }, - elasticsearch: { - getCluster: () => ({ callWithRequest: jest.fn() } as any), - } as any, - }, + licensing: licensingMock.createSetup(), }; - registerReindexIndicesRoutes(serverShim, worker, credentialStore); + registerReindexIndicesRoutes(routeDependencies, () => worker); mockReindexService.hasRequiredPrivileges.mockResolvedValue(true); mockReindexService.detectReindexWarnings.mockReset(); @@ -92,7 +75,9 @@ describe('reindex API', () => { credentialStore.clear(); }); - afterEach(() => jest.clearAllMocks()); + afterEach(() => { + jest.resetAllMocks(); + }); describe('GET /api/upgrade_assistant/reindex/{indexName}', () => { it('returns the attributes of the reindex operation and reindex warnings', async () => { @@ -101,10 +86,14 @@ describe('reindex API', () => { }); mockReindexService.detectReindexWarnings.mockResolvedValueOnce([ReindexWarning.allField]); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', - })(ctxMock, createRequestMock({ params: { indexName: 'wowIndex' } }), kibanaResponseFactory); + })( + routeHandlerContextMock, + createRequestMock({ params: { indexName: 'wowIndex' } }), + kibanaResponseFactory + ); // It called into the service correctly expect(mockReindexService.findReindexOperation).toHaveBeenCalledWith('wowIndex'); @@ -121,10 +110,14 @@ describe('reindex API', () => { mockReindexService.findReindexOperation.mockResolvedValueOnce(null); mockReindexService.detectReindexWarnings.mockResolvedValueOnce(null); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', - })(ctxMock, createRequestMock({ params: { indexName: 'anIndex' } }), kibanaResponseFactory); + })( + routeHandlerContextMock, + createRequestMock({ params: { indexName: 'anIndex' } }), + kibanaResponseFactory + ); expect(resp.status).toEqual(200); const data = resp.payload; @@ -137,10 +130,14 @@ describe('reindex API', () => { mockReindexService.detectReindexWarnings.mockResolvedValueOnce([]); mockReindexService.getIndexGroup.mockReturnValue(IndexGroup.ml); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'get', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', - })(ctxMock, createRequestMock({ params: { indexName: 'anIndex' } }), kibanaResponseFactory); + })( + routeHandlerContextMock, + createRequestMock({ params: { indexName: 'anIndex' } }), + kibanaResponseFactory + ); expect(resp.status).toEqual(200); const data = resp.payload; @@ -154,10 +151,14 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex' }, }); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'post', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', - })(ctxMock, createRequestMock({ params: { indexName: 'theIndex' } }), kibanaResponseFactory); + })( + routeHandlerContextMock, + createRequestMock({ params: { indexName: 'theIndex' } }), + kibanaResponseFactory + ); // It called create correctly expect(mockReindexService.createReindexOperation).toHaveBeenCalledWith('theIndex'); @@ -173,10 +174,14 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex' }, }); - await serverShim.router.getHandler({ + await routeDependencies.router.getHandler({ method: 'post', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', - })(ctxMock, createRequestMock({ params: { indexName: 'theIndex' } }), kibanaResponseFactory); + })( + routeHandlerContextMock, + createRequestMock({ params: { indexName: 'theIndex' } }), + kibanaResponseFactory + ); expect(worker.forceRefresh).toHaveBeenCalled(); }); @@ -187,11 +192,11 @@ describe('reindex API', () => { } as ReindexSavedObject; mockReindexService.createReindexOperation.mockResolvedValueOnce(reindexOp); - await serverShim.router.getHandler({ + await routeDependencies.router.getHandler({ method: 'post', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ headers: { 'kbn-auth-x': 'HERE!', @@ -212,11 +217,11 @@ describe('reindex API', () => { attributes: { indexName: 'theIndex', status: ReindexStatus.inProgress }, }); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'post', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ params: { indexName: 'theIndex' }, }), @@ -235,11 +240,11 @@ describe('reindex API', () => { it('returns a 403 if required privileges fails', async () => { mockReindexService.hasRequiredPrivileges.mockResolvedValueOnce(false); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'post', pathPattern: '/api/upgrade_assistant/reindex/{indexName}', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ params: { indexName: 'theIndex' }, }), @@ -254,11 +259,11 @@ describe('reindex API', () => { it('returns a 501', async () => { mockReindexService.cancelReindexing.mockResolvedValueOnce({}); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'post', pathPattern: '/api/upgrade_assistant/reindex/{indexName}/cancel', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ params: { indexName: 'cancelMe' }, }), diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices.ts new file mode 100644 index 0000000000000..a910145474061 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices.ts @@ -0,0 +1,217 @@ +/* + * 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 } from '@kbn/config-schema'; +import { Logger, ElasticsearchServiceSetup, SavedObjectsClient } from 'src/core/server'; +import { ReindexStatus } from '../../common/types'; +import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; +import { reindexServiceFactory, ReindexWorker } from '../lib/reindexing'; +import { CredentialStore } from '../lib/reindexing/credential_store'; +import { reindexActionsFactory } from '../lib/reindexing/reindex_actions'; +import { RouteDependencies } from '../types'; +import { LicensingPluginSetup } from '../../../licensing/server'; + +interface CreateReindexWorker { + logger: Logger; + elasticsearchService: ElasticsearchServiceSetup; + credentialStore: CredentialStore; + savedObjects: SavedObjectsClient; + licensing: LicensingPluginSetup; +} + +export function createReindexWorker({ + logger, + elasticsearchService, + credentialStore, + savedObjects, + licensing, +}: CreateReindexWorker) { + const { adminClient } = elasticsearchService; + return new ReindexWorker(savedObjects, credentialStore, adminClient, logger, licensing); +} + +export function registerReindexIndicesRoutes( + { credentialStore, router, licensing, log }: RouteDependencies, + getWorker: () => ReindexWorker +) { + const BASE_PATH = '/api/upgrade_assistant/reindex'; + + // Start reindex for an index + router.post( + { + path: `${BASE_PATH}/{indexName}`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + savedObjects, + elasticsearch: { dataClient }, + }, + }, + request, + response + ) => { + const { indexName } = request.params as any; + const { client } = savedObjects; + const callAsCurrentUser = dataClient.callAsCurrentUser.bind(dataClient); + const reindexActions = reindexActionsFactory(client, callAsCurrentUser); + const reindexService = reindexServiceFactory( + callAsCurrentUser, + reindexActions, + log, + licensing + ); + + try { + if (!(await reindexService.hasRequiredPrivileges(indexName))) { + return response.forbidden({ + body: `You do not have adequate privileges to reindex this index.`, + }); + } + + const existingOp = await reindexService.findReindexOperation(indexName); + + // If the reindexOp already exists and it's paused, resume it. Otherwise create a new one. + const reindexOp = + existingOp && existingOp.attributes.status === ReindexStatus.paused + ? await reindexService.resumeReindexOperation(indexName) + : await reindexService.createReindexOperation(indexName); + + // Add users credentials for the worker to use + credentialStore.set(reindexOp, request.headers); + + // Kick the worker on this node to immediately pickup the new reindex operation. + getWorker().forceRefresh(); + + return response.ok({ body: reindexOp.attributes }); + } catch (e) { + return response.internalError({ body: e }); + } + } + ) + ); + + // Get status + router.get( + { + path: `${BASE_PATH}/{indexName}`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + savedObjects, + elasticsearch: { dataClient }, + }, + }, + request, + response + ) => { + const { client } = savedObjects; + const { indexName } = request.params as any; + const callAsCurrentUser = dataClient.callAsCurrentUser.bind(dataClient); + const reindexActions = reindexActionsFactory(client, callAsCurrentUser); + const reindexService = reindexServiceFactory( + callAsCurrentUser, + reindexActions, + log, + licensing + ); + + try { + const hasRequiredPrivileges = await reindexService.hasRequiredPrivileges(indexName); + const reindexOp = await reindexService.findReindexOperation(indexName); + // If the user doesn't have privileges than querying for warnings is going to fail. + const warnings = hasRequiredPrivileges + ? await reindexService.detectReindexWarnings(indexName) + : []; + const indexGroup = reindexService.getIndexGroup(indexName); + + return response.ok({ + body: { + reindexOp: reindexOp ? reindexOp.attributes : null, + warnings, + indexGroup, + hasRequiredPrivileges, + }, + }); + } catch (e) { + if (!e.isBoom) { + return response.internalError({ body: e }); + } + return response.customError({ + body: { + message: e.message, + }, + statusCode: e.statusCode, + }); + } + } + ) + ); + + // Cancel reindex + router.post( + { + path: `${BASE_PATH}/{indexName}/cancel`, + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, + }, + versionCheckHandlerWrapper( + async ( + { + core: { + savedObjects, + elasticsearch: { dataClient }, + }, + }, + request, + response + ) => { + const { indexName } = request.params as any; + const { client } = savedObjects; + const callAsCurrentUser = dataClient.callAsCurrentUser.bind(dataClient); + const reindexActions = reindexActionsFactory(client, callAsCurrentUser); + const reindexService = reindexServiceFactory( + callAsCurrentUser, + reindexActions, + log, + licensing + ); + + try { + await reindexService.cancelReindexing(indexName); + + return response.ok({ body: { acknowledged: true } }); + } catch (e) { + if (!e.isBoom) { + return response.internalError({ body: e }); + } + return response.customError({ + body: { + message: e.message, + }, + statusCode: e.statusCode, + }); + } + } + ) + ); +} diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts similarity index 79% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts rename to x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts index 582c75e3701b6..b2b8ccf1ca57a 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.test.ts @@ -5,7 +5,8 @@ */ import { kibanaResponseFactory } from 'src/core/server'; -import { createMockRouter, MockRouter } from './__mocks__/routes.mock'; +import { savedObjectsServiceMock } from 'src/core/server/saved_objects/saved_objects_service.mock'; +import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; jest.mock('../lib/telemetry/es_ui_open_apis', () => ({ @@ -26,24 +27,15 @@ import { registerTelemetryRoutes } from './telemetry'; * more thoroughly in the lib/telemetry tests. */ describe('Upgrade Assistant Telemetry API', () => { - let serverShim: any; + let routeDependencies: any; let mockRouter: MockRouter; - let ctxMock: any; beforeEach(() => { - ctxMock = {}; mockRouter = createMockRouter(); - serverShim = { + routeDependencies = { + getSavedObjectsService: () => savedObjectsServiceMock.create(), router: mockRouter, - plugins: { - xpack_main: { - info: jest.fn(), - }, - elasticsearch: { - getCluster: () => ({ callWithRequest: jest.fn() } as any), - } as any, - }, }; - registerTelemetryRoutes(serverShim); + registerTelemetryRoutes(routeDependencies); }); afterEach(() => jest.clearAllMocks()); @@ -57,10 +49,14 @@ describe('Upgrade Assistant Telemetry API', () => { (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/telemetry/ui_open', - })(ctxMock, createRequestMock(), kibanaResponseFactory); + })( + routeHandlerContextMock, + createRequestMock({ body: returnPayload }), + kibanaResponseFactory + ); expect(resp.payload).toEqual(returnPayload); }); @@ -74,13 +70,13 @@ describe('Upgrade Assistant Telemetry API', () => { (upsertUIOpenOption as jest.Mock).mockResolvedValue(returnPayload); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/telemetry/ui_open', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ - payload: { + body: { overview: true, cluster: true, indices: true, @@ -95,13 +91,13 @@ describe('Upgrade Assistant Telemetry API', () => { it('returns an error if it throws', async () => { (upsertUIOpenOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/telemetry/ui_open', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ - payload: { + body: { overview: false, }, }), @@ -123,13 +119,13 @@ describe('Upgrade Assistant Telemetry API', () => { (upsertUIReindexOption as jest.Mock).mockRejectedValue(returnPayload); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ - payload: { + body: { overview: false, }, }), @@ -149,13 +145,13 @@ describe('Upgrade Assistant Telemetry API', () => { (upsertUIReindexOption as jest.Mock).mockRejectedValue(returnPayload); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ - payload: { + body: { close: true, open: true, start: true, @@ -171,13 +167,13 @@ describe('Upgrade Assistant Telemetry API', () => { it('returns an error if it throws', async () => { (upsertUIReindexOption as jest.Mock).mockRejectedValue(new Error(`scary error!`)); - const resp = await serverShim.router.getHandler({ + const resp = await routeDependencies.router.getHandler({ method: 'put', pathPattern: '/api/upgrade_assistant/telemetry/ui_reindex', })( - ctxMock, + routeHandlerContextMock, createRequestMock({ - payload: { + body: { start: false, }, }), diff --git a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts similarity index 66% rename from x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts rename to x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts index f08c49809033d..900a5e64c55c3 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/server/np_ready/routes/telemetry.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/telemetry.ts @@ -7,11 +7,10 @@ import { schema } from '@kbn/config-schema'; import { upsertUIOpenOption } from '../lib/telemetry/es_ui_open_apis'; import { upsertUIReindexOption } from '../lib/telemetry/es_ui_reindex_apis'; -import { ServerShimWithRouter } from '../types'; -import { createRequestShim } from './create_request_shim'; +import { RouteDependencies } from '../types'; -export function registerTelemetryRoutes(server: ServerShimWithRouter) { - server.router.put( +export function registerTelemetryRoutes({ router, getSavedObjectsService }: RouteDependencies) { + router.put( { path: '/api/upgrade_assistant/telemetry/ui_open', validate: { @@ -23,16 +22,23 @@ export function registerTelemetryRoutes(server: ServerShimWithRouter) { }, }, async (ctx, request, response) => { - const reqShim = createRequestShim(request); + const { cluster, indices, overview } = request.body; try { - return response.ok({ body: await upsertUIOpenOption(server, reqShim) }); + return response.ok({ + body: await upsertUIOpenOption({ + savedObjects: getSavedObjectsService(), + cluster, + indices, + overview, + }), + }); } catch (e) { return response.internalError({ body: e }); } } ); - server.router.put( + router.put( { path: '/api/upgrade_assistant/telemetry/ui_reindex', validate: { @@ -45,9 +51,17 @@ export function registerTelemetryRoutes(server: ServerShimWithRouter) { }, }, async (ctx, request, response) => { - const reqShim = createRequestShim(request); + const { close, open, start, stop } = request.body; try { - return response.ok({ body: await upsertUIReindexOption(server, reqShim) }); + return response.ok({ + body: await upsertUIReindexOption({ + savedObjects: getSavedObjectsService(), + close, + open, + start, + stop, + }), + }); } catch (e) { return response.internalError({ body: e }); } diff --git a/x-pack/plugins/upgrade_assistant/server/types.ts b/x-pack/plugins/upgrade_assistant/server/types.ts new file mode 100644 index 0000000000000..3f3beadd2f333 --- /dev/null +++ b/x-pack/plugins/upgrade_assistant/server/types.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IRouter, Logger, SavedObjectsServiceStart } from 'src/core/server'; +import { CloudSetup } from '../../cloud/server'; +import { CredentialStore } from './lib/reindexing/credential_store'; +import { LicensingPluginSetup } from '../../licensing/server'; + +export interface RouteDependencies { + router: IRouter; + credentialStore: CredentialStore; + log: Logger; + getSavedObjectsService: () => SavedObjectsServiceStart; + licensing: LicensingPluginSetup; + cloud?: CloudSetup; +} diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js index 9fc8078162847..38fc1f0c6356f 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js @@ -6,10 +6,7 @@ import expect from '@kbn/expect'; -import { - ReindexStatus, - REINDEX_OP_TYPE, -} from '../../../legacy/plugins/upgrade_assistant/common/types'; +import { ReindexStatus, REINDEX_OP_TYPE } from '../../../plugins/upgrade_assistant/common/types'; export default function({ getService }) { const supertest = getService('supertest'); From 10bf90f9f57112c078db973b196974277404f745 Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Tue, 25 Feb 2020 09:34:53 -0500 Subject: [PATCH 11/11] [SIEM] [Detection Engine] Increase unit test coverage (#58274) * updates read privileges route tests * fixes test for 404 when alertsClient is not present, adds new test for catching errors at the route level for prepackaged rules route * fixes test for happy path on create rules bulk route (missing mock resulted in 200, but was still throwing an error), adds tests for covering case where a rule with a matching rule id is found to have already existed, adds a test covering the case where createRules throws an error and that error is caught in the catch block, and appears in the response * adds more jest functions to beforeEach to ensure mockImplementation state used by spyOn is not carried over between tests, increases test coverage for create rules route * updates unit test coverage for delete rules route and bulk delete * increase unit test coverage for find_rules_route * add test case to get_prepackaged_rules where findRules throws an error * adds unit test for missing alertsClient in patch_rules_bulk route * adds unit test coverage for transform error and pathRules throwing an error on patch rules route * adds unit test coverage for rule not found, transform error, and readRules throws an error on read_rules_route * adds unit test coverage for update rules (bulk) routes * increases unit test coverage for open close signals route * updates coverage for signals query route * adds unit tests for rules status route, updates utils test coverage. Removed unreachable code. * updates test coverage, removes usage of pipes from ndjson to stream conversion and returns arrays of tranformers to be used in createPromiseFromStreams so that unhandled promise rejections can be handled appropriately. * fixes type errors * fix bug on transform when rulestatus saved objects array is empty because we are no longer passing in the current status, we are passing in the whole saved object. * adds unit test for when readRules throws an error inside of get export by object ids * adds unit tests for catching errors on read rules and fixes property undefined bug in catch block * removes unused function from utils * adds the 'else' clause back to the getTupleDuplicateErrorsAndUniqueRules function and adds a test case for when an attempt to import rules with missing ruleIds is made, and the expected outcome. --- .../routes/__mocks__/request_responses.ts | 43 ++- .../routes/__mocks__/utils.ts | 37 ++ .../privileges/read_privileges_route.test.ts | 12 + .../rules/add_prepackaged_rules_route.test.ts | 23 +- .../rules/create_rules_bulk_route.test.ts | 49 ++- .../routes/rules/create_rules_route.test.ts | 48 ++- .../rules/delete_rules_bulk_route.test.ts | 10 + .../routes/rules/delete_rules_bulk_route.ts | 2 +- .../routes/rules/delete_rules_route.test.ts | 33 ++ .../routes/rules/find_rules_route.test.ts | 49 ++- .../rules/find_rules_status_route.test.ts | 96 +++++ .../routes/rules/find_rules_status_route.ts | 77 ++-- ...get_prepackaged_rules_status_route.test.ts | 17 + .../routes/rules/import_rules_route.test.ts | 38 +- .../routes/rules/import_rules_route.ts | 332 +++++++++--------- .../routes/rules/patch_rules_bulk.test.ts | 9 + .../routes/rules/patch_rules_route.test.ts | 34 ++ .../routes/rules/read_rules_route.test.ts | 41 ++- .../routes/rules/update_rules_bulk.test.ts | 4 +- .../routes/rules/update_rules_route.test.ts | 30 ++ .../routes/rules/utils.test.ts | 44 ++- .../detection_engine/routes/rules/utils.ts | 6 +- .../routes/signals/open_close_signals.test.ts | 14 + .../signals/open_close_signals_route.ts | 16 +- .../signals/query_signals_route.test.ts | 13 + .../routes/signals/query_signals_route.ts | 16 +- .../lib/detection_engine/routes/utils.test.ts | 12 + .../lib/detection_engine/routes/utils.ts | 9 + .../create_rules_stream_from_ndjson.test.ts | 64 +++- .../rules/create_rules_stream_from_ndjson.ts | 22 +- .../rules/get_export_by_object_ids.test.ts | 23 ++ .../detection_engine/rules/read_rules.test.ts | 73 ++++ .../lib/detection_engine/rules/read_rules.ts | 2 +- .../lib/detection_engine/rules/types.ts | 4 - .../security_and_spaces/tests/import_rules.ts | 11 + 35 files changed, 1038 insertions(+), 275 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts index 1578c71dddc6a..2b50011cf4dff 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -427,13 +427,54 @@ export const getMockPrivileges = () => ({ has_encryption_key: true, }); -export const getFindResultStatus = (): SavedObjectsFindResponse => ({ +export const getFindResultStatusEmpty = (): SavedObjectsFindResponse => ({ page: 1, per_page: 1, total: 0, saved_objects: [], }); +export const getFindResultStatus = (): SavedObjectsFindResponse => ({ + page: 1, + per_page: 6, + total: 2, + saved_objects: [ + { + type: 'my-type', + id: 'e0b86950-4e9f-11ea-bdbd-07b56aa159b3', + attributes: { + alertId: '1ea5a820-4da1-4e82-92a1-2b43a7bece08', + statusDate: '2020-02-18T15:26:49.783Z', + status: 'succeeded', + lastFailureAt: null, + lastSuccessAt: '2020-02-18T15:26:49.783Z', + lastFailureMessage: null, + lastSuccessMessage: 'succeeded', + }, + references: [], + updated_at: '2020-02-18T15:26:51.333Z', + version: 'WzQ2LDFd', + }, + { + type: 'my-type', + id: '91246bd0-5261-11ea-9650-33b954270f67', + attributes: { + alertId: '1ea5a820-4da1-4e82-92a1-2b43a7bece08', + statusDate: '2020-02-18T15:15:58.806Z', + status: 'failed', + lastFailureAt: '2020-02-18T15:15:58.806Z', + lastSuccessAt: '2020-02-13T20:31:59.855Z', + lastFailureMessage: + 'Signal rule name: "Query with a rule id Number 1", id: "1ea5a820-4da1-4e82-92a1-2b43a7bece08", rule_id: "query-rule-id-1" has a time gap of 5 days (412682928ms), and could be missing signals within that time. Consider increasing your look behind time or adding more Kibana instances.', + lastSuccessMessage: 'succeeded', + }, + references: [], + updated_at: '2020-02-18T15:15:58.860Z', + version: 'WzMyLDFd', + }, + ], +}); + export const getIndexName = () => 'index-name'; export const getEmptyIndex = (): { _shards: Partial } => ({ _shards: { total: 0 }, diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts index f8c8e1f231ffa..32226e38a1f7f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/__mocks__/utils.ts @@ -26,6 +26,20 @@ export const getSimpleRule = (ruleId = 'rule-1'): Partial = query: 'user.name: root or user.name: admin', }); +/** + * This is a typical simple rule for testing that is easy for most basic testing + * @param ruleId + */ +export const getSimpleRuleWithId = (id = 'rule-1'): Partial => ({ + name: 'Simple Rule Query', + description: 'Simple Rule Query', + risk_score: 1, + id, + severity: 'high', + type: 'query', + query: 'user.name: root or user.name: admin', +}); + /** * Given an array of rule_id strings this will return a ndjson buffer which is useful * for testing uploads. @@ -51,3 +65,26 @@ export const getSimpleRuleAsMultipartContent = (ruleIds: string[], isNdjson = tr return Buffer.from(resultingPayload); }; + +/** + * Given an array of rule_id strings this will return a ndjson buffer which is useful + * for testing uploads. + * @param count Number of rules to generate + * @param isNdjson Boolean to determine file extension + */ +export const getSimpleRuleAsMultipartContentNoRuleId = (count: number, isNdjson = true): Buffer => { + const arrayOfRules = Array(count).fill(JSON.stringify(getSimpleRuleWithId())); + const stringOfRules = arrayOfRules.join('\r\n'); + + const resultingPayload = + `--${TEST_BOUNDARY}\r\n` + + `Content-Disposition: form-data; name="file"; filename="rules.${ + isNdjson ? 'ndjson' : 'json' + }\r\n` + + 'Content-Type: application/octet-stream\r\n' + + '\r\n' + + `${stringOfRules}\r\n` + + `--${TEST_BOUNDARY}--\r\n`; + + return Buffer.from(resultingPayload); +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts index 308ee95a77e20..3c31658c61d6e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts @@ -5,6 +5,7 @@ */ import { readPrivilegesRoute } from './read_privileges_route'; +import * as readPrivileges from '../../privileges/read_privileges'; import { createMockServer, createMockConfig, clientsServiceMock } from '../__mocks__'; import { getPrivilegeRequest, getMockPrivileges } from '../__mocks__/request_responses'; @@ -38,5 +39,16 @@ describe('read_privileges', () => { const { payload } = await inject(getPrivilegeRequest()); expect(JSON.parse(payload)).toEqual(getMockPrivileges()); }); + + test('returns 500 when bad response from readPrivileges', async () => { + jest.spyOn(readPrivileges, 'readPrivileges').mockImplementation(() => { + throw new Error('Test error'); + }); + const { payload } = await inject(getPrivilegeRequest()); + expect(JSON.parse(payload)).toEqual({ + message: 'Test error', + status_code: 500, + }); + }); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts index e018ed4cc22ff..e6a93fdadcfca 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts @@ -6,7 +6,6 @@ import { omit } from 'lodash/fp'; -import { createRulesRoute } from './create_rules_route'; import { getFindResult, getResult, @@ -17,6 +16,7 @@ import { getNonEmptyIndex, } from '../__mocks__/request_responses'; import { createMockServer, createMockConfig, clientsServiceMock } from '../__mocks__'; +import * as updatePrepackagedRules from '../../rules/update_prepacked_rules'; jest.mock('../../rules/get_prepackaged_rules', () => { return { @@ -54,7 +54,8 @@ describe('add_prepackaged_rules_route', () => { beforeEach(() => { jest.resetAllMocks(); - + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); config = createMockConfig(); getClients = clientsServiceMock.createGetScoped(); @@ -78,9 +79,7 @@ describe('add_prepackaged_rules_route', () => { test('returns 404 if alertClient is not available on the route', async () => { getClients.mockResolvedValue(omit('alertsClient', clients)); - const { inject, route } = createMockServer(); - createRulesRoute(route, config, getClients); - const { statusCode } = await inject(addPrepackagedRulesRequest()); + const { statusCode } = await server.inject(addPrepackagedRulesRequest()); expect(statusCode).toBe(404); }); }); @@ -126,5 +125,19 @@ describe('add_prepackaged_rules_route', () => { rules_updated: 1, }); }); + test('catches errors if payloads cause errors to be thrown', async () => { + jest.spyOn(updatePrepackagedRules, 'updatePrepackagedRules').mockImplementation(() => { + throw new Error('Test error'); + }); + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.actionsClient.create.mockResolvedValue(createActionResult()); + clients.alertsClient.create.mockResolvedValue(getResult()); + const { payload } = await server.inject(addPrepackagedRulesRequest()); + expect(JSON.parse(payload)).toEqual({ + message: 'Test error', + status_code: 500, + }); + }); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index 664d27a7572ad..931623ea6652c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -14,12 +14,15 @@ import { typicalPayload, getReadBulkRequest, getEmptyIndex, + getNonEmptyIndex, } from '../__mocks__/request_responses'; import { createMockServer, createMockConfig, clientsServiceMock } from '../__mocks__'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { createRulesBulkRoute } from './create_rules_bulk_route'; import { BulkError } from '../utils'; import { OutputRuleAlertRest } from '../../types'; +import * as createRules from '../../rules/create_rules'; +import * as readRules from '../../rules/read_rules'; describe('create_rules_bulk', () => { let server = createMockServer(); @@ -29,10 +32,14 @@ describe('create_rules_bulk', () => { beforeEach(() => { jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); config = createMockConfig(); getClients = clientsServiceMock.createGetScoped(); clients = clientsServiceMock.createClients(); + clients.clusterClient.callAsCurrentUser.mockResolvedValue(getNonEmptyIndex()); + getClients.mockResolvedValue(clients); createRulesBulkRoute(server.route, config, getClients); @@ -44,8 +51,12 @@ describe('create_rules_bulk', () => { clients.alertsClient.get.mockResolvedValue(getResult()); clients.actionsClient.create.mockResolvedValue(createActionResult()); clients.alertsClient.create.mockResolvedValue(getResult()); - const { statusCode } = await server.inject(getReadBulkRequest()); + jest.spyOn(createRules, 'createRules').mockImplementation(async () => { + return getResult(); + }); + const { payload, statusCode } = await server.inject(getReadBulkRequest()); expect(statusCode).toBe(200); + expect(JSON.parse(payload).error).toBeUndefined(); }); test('returns 404 if alertClient is not available on the route', async () => { @@ -149,6 +160,24 @@ describe('create_rules_bulk', () => { expect(output.some(item => item.error?.status_code === 409)).toBeTruthy(); }); + test('returns 409 if duplicate rule_ids found in rule saved objects', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResult()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.actionsClient.create.mockResolvedValue(createActionResult()); + clients.alertsClient.create.mockResolvedValue(getResult()); + jest.spyOn(readRules, 'readRules').mockImplementation(async () => { + return getResult(); + }); + const request: ServerInjectOptions = { + method: 'POST', + url: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + payload: [typicalPayload()], + }; + const { payload } = await server.inject(request); + const output: Array> = JSON.parse(payload); + expect(output.some(item => item.error?.status_code === 409)).toBeTruthy(); + }); + test('returns one error object in response when duplicate rule_ids found in request payload', async () => { clients.alertsClient.find.mockResolvedValue(getFindResult()); clients.alertsClient.get.mockResolvedValue(getResult()); @@ -163,4 +192,22 @@ describe('create_rules_bulk', () => { const output: Array> = JSON.parse(payload); expect(output.length).toBe(1); }); + + test('catches error if createRules throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResult()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.actionsClient.create.mockResolvedValue(createActionResult()); + clients.alertsClient.create.mockResolvedValue(getResult()); + jest.spyOn(createRules, 'createRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const request: ServerInjectOptions = { + method: 'POST', + url: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, + payload: [typicalPayload()], + }; + const { payload } = await server.inject(request); + const output: Array> = JSON.parse(payload); + expect(output[0].error.message).toBe('Test error'); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts index 4f28771db8ed7..5ad43e70f2651 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/create_rules_route.test.ts @@ -9,6 +9,9 @@ import { omit } from 'lodash/fp'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { createRulesRoute } from './create_rules_route'; +import * as createRules from '../../rules/create_rules'; +import * as readRules from '../../rules/read_rules'; +import * as utils from './utils'; import { getFindResult, @@ -29,8 +32,12 @@ describe('create_rules', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); - + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); config = createMockConfig(); getClients = clientsServiceMock.createGetScoped(); @@ -130,5 +137,44 @@ describe('create_rules', () => { const { statusCode } = await server.inject(request); expect(statusCode).toBe(400); }); + + test('catches error if createRules throws error', async () => { + clients.actionsClient.create.mockResolvedValue(createActionResult()); + clients.alertsClient.find.mockResolvedValue(getFindResult()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.alertsClient.create.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(createRules, 'createRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getCreateRequest()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); + + test('catches error if transform returns null', async () => { + clients.actionsClient.create.mockResolvedValue(createActionResult()); + clients.alertsClient.find.mockResolvedValue(getFindResult()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.alertsClient.create.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(utils, 'transform').mockReturnValue(null); + const { payload, statusCode } = await server.inject(getCreateRequest()); + expect(JSON.parse(payload).message).toBe('Internal error transforming rules'); + expect(statusCode).toBe(500); + }); + + test('returns 409 if duplicate rule_ids found in rule saved objects', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResult()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.actionsClient.create.mockResolvedValue(createActionResult()); + clients.alertsClient.create.mockResolvedValue(getResult()); + jest.spyOn(readRules, 'readRules').mockImplementation(async () => { + return getResult(); + }); + const { payload } = await server.inject(getCreateRequest()); + const output = JSON.parse(payload); + expect(output.status_code).toEqual(409); + }); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts index 855bf7f634c26..fb44f96d76859 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts @@ -48,6 +48,16 @@ describe('delete_rules', () => { expect(statusCode).toBe(200); }); + test('resturns 200 when deleting a single rule and related rule status', async () => { + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + clients.savedObjectsClient.delete.mockResolvedValue(true); + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.alertsClient.delete.mockResolvedValue({}); + const { statusCode } = await server.inject(getDeleteBulkRequest()); + expect(statusCode).toBe(200); + }); + test('returns 200 when deleting a single rule with a valid actionClient and alertClient by alertId using POST', async () => { clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); clients.alertsClient.get.mockResolvedValue(getResult()); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts index 6438318cb43db..aabf3e513bfea 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.ts @@ -58,7 +58,7 @@ export const createDeleteRulesBulkRoute = (getClients: GetScopedClients): Hapi.S ruleStatuses.saved_objects.forEach(async obj => savedObjectsClient.delete(ruleStatusSavedObjectType, obj.id) ); - return transformOrBulkError(idOrRuleIdOrUnknown, rule); + return transformOrBulkError(idOrRuleIdOrUnknown, rule, ruleStatuses); } else { return getIdBulkError({ id, ruleId }); } diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts index a0a6f61223279..57c7c85976619 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts @@ -7,6 +7,8 @@ import { ServerInjectOptions } from 'hapi'; import { omit } from 'lodash/fp'; import { deleteRulesRoute } from './delete_rules_route'; +import * as utils from './utils'; +import * as deleteRules from '../../rules/delete_rules'; import { getFindResult, @@ -25,7 +27,12 @@ describe('delete_rules', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); getClients = clientsServiceMock.createGetScoped(); clients = clientsServiceMock.createClients(); @@ -73,6 +80,32 @@ describe('delete_rules', () => { const { statusCode } = await inject(getDeleteRequest()); expect(statusCode).toBe(404); }); + + test('returns 500 when transform fails', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.alertsClient.delete.mockResolvedValue({}); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + clients.savedObjectsClient.delete.mockResolvedValue({}); + jest.spyOn(utils, 'transform').mockReturnValue(null); + const { payload, statusCode } = await server.inject(getDeleteRequest()); + expect(JSON.parse(payload).message).toBe('Internal error transforming rules'); + expect(statusCode).toBe(500); + }); + + test('catches error if deleteRules throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.alertsClient.delete.mockResolvedValue({}); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + clients.savedObjectsClient.delete.mockResolvedValue({}); + jest.spyOn(deleteRules, 'deleteRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getDeleteRequestById()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts index 5b75f17164acf..019424ea2420a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_route.test.ts @@ -6,13 +6,22 @@ import { omit } from 'lodash/fp'; +import { + getFindResult, + getResult, + getFindResultWithSingleHit, + getFindResultStatus, + getFindRequest, +} from '../__mocks__/request_responses'; import { createMockServer } from '../__mocks__'; import { clientsServiceMock } from '../__mocks__/clients_service_mock'; +import * as utils from './utils'; +import * as findRules from '../../rules/find_rules'; + import { findRulesRoute } from './find_rules_route'; import { ServerInjectOptions } from 'hapi'; -import { getFindResult, getResult, getFindRequest } from '../__mocks__/request_responses'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; describe('find_rules', () => { @@ -21,7 +30,12 @@ describe('find_rules', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); getClients = clientsServiceMock.createGetScoped(); @@ -33,15 +47,10 @@ describe('find_rules', () => { }); describe('status codes with actionClient and alertClient', () => { - test('returns 200 when finding a single rule with a valid actionClient and alertClient', async () => { - clients.alertsClient.find.mockResolvedValue(getFindResult()); - clients.actionsClient.find.mockResolvedValue({ - page: 1, - perPage: 1, - total: 0, - data: [], - }); + test('returns 200 when finding a single rule with a valid alertsClient', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); const { statusCode } = await server.inject(getFindRequest()); expect(statusCode).toBe(200); }); @@ -53,6 +62,28 @@ describe('find_rules', () => { const { statusCode } = await inject(getFindRequest()); expect(statusCode).toBe(404); }); + + test('catches error when transformation fails', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(utils, 'transformFindAlerts').mockReturnValue(null); + const { payload, statusCode } = await server.inject(getFindRequest()); + expect(statusCode).toBe(500); + expect(JSON.parse(payload).message).toBe('unknown data type, error transforming alert'); + }); + + test('catch error when findRules function throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(findRules, 'findRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getFindRequest()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts new file mode 100644 index 0000000000000..00411c550fa2e --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts @@ -0,0 +1,96 @@ +/* + * 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 { omit } from 'lodash/fp'; + +import { getFindResultStatus } from '../__mocks__/request_responses'; +import { createMockServer } from '../__mocks__'; +import { clientsServiceMock } from '../__mocks__/clients_service_mock'; + +import { findRulesStatusesRoute } from './find_rules_status_route'; +import { ServerInjectOptions } from 'hapi'; + +import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; + +describe('find_statuses', () => { + let server = createMockServer(); + let getClients = clientsServiceMock.createGetScoped(); + let clients = clientsServiceMock.createClients(); + + beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 + jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); + + server = createMockServer(); + getClients = clientsServiceMock.createGetScoped(); + clients = clientsServiceMock.createClients(); + + getClients.mockResolvedValue(clients); + + findRulesStatusesRoute(server.route, getClients); + }); + + describe('status codes with actionClient and alertClient', () => { + test('returns 200 when finding a single rule status with a valid alertsClient', async () => { + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + const request: ServerInjectOptions = { + method: 'GET', + url: `${DETECTION_ENGINE_RULES_URL}/_find_statuses?ids=["someid"]`, + }; + const { statusCode } = await server.inject(request); + expect(statusCode).toBe(200); + }); + + test('returns 404 if alertClient is not available on the route', async () => { + getClients.mockResolvedValue(omit('alertsClient', clients)); + const request: ServerInjectOptions = { + method: 'GET', + url: `${DETECTION_ENGINE_RULES_URL}/_find_statuses?ids=["someid"]`, + }; + const { statusCode } = await server.inject(request); + expect(statusCode).toBe(404); + }); + + test('catch error when savedObjectsClient find function throws error', async () => { + clients.savedObjectsClient.find.mockImplementation(async () => { + throw new Error('Test error'); + }); + const request: ServerInjectOptions = { + method: 'GET', + url: `${DETECTION_ENGINE_RULES_URL}/_find_statuses?ids=["someid"]`, + }; + const { payload, statusCode } = await server.inject(request); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); + }); + + describe('validation', () => { + test('returns 400 if id is given instead of ids', async () => { + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + const request: ServerInjectOptions = { + method: 'GET', + url: `${DETECTION_ENGINE_RULES_URL}/_find_statuses?id=["someid"]`, + }; + const { statusCode } = await server.inject(request); + expect(statusCode).toBe(400); + }); + + test('returns 200 if the set of optional query parameters are given', async () => { + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + const request: ServerInjectOptions = { + method: 'GET', + url: `${DETECTION_ENGINE_RULES_URL}/_find_statuses?ids=["someid"]`, + }; + const { statusCode } = await server.inject(request); + expect(statusCode).toBe(200); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts index fe8742ff0b60c..c496c7b7ce59c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/find_rules_status_route.ts @@ -5,7 +5,6 @@ */ import Hapi from 'hapi'; -import { snakeCase } from 'lodash/fp'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { LegacyServices, LegacyRequest } from '../../../../types'; @@ -18,17 +17,7 @@ import { IRuleStatusAttributes, } from '../../rules/types'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const convertToSnakeCase = >(obj: T): Partial | null => { - if (!obj) { - return null; - } - return Object.keys(obj).reduce((acc, item) => { - const newKey = snakeCase(item); - return { ...acc, [newKey]: obj[item] }; - }, {}); -}; +import { transformError, convertToSnakeCase } from '../utils'; export const createFindRulesStatusRoute = (getClients: GetScopedClients): Hapi.ServerRoute => ({ method: 'GET', @@ -57,33 +46,43 @@ export const createFindRulesStatusRoute = (getClients: GetScopedClients): Hapi.S "anotherAlertId": ... } */ - const statuses = await query.ids.reduce>(async (acc, id) => { - const lastFiveErrorsForId = await savedObjectsClient.find< - IRuleSavedAttributesSavedObjectAttributes - >({ - type: ruleStatusSavedObjectType, - perPage: 6, - sortField: 'statusDate', - sortOrder: 'desc', - search: id, - searchFields: ['alertId'], - }); - const accumulated = await acc; - const currentStatus = convertToSnakeCase( - lastFiveErrorsForId.saved_objects[0]?.attributes - ); - const failures = lastFiveErrorsForId.saved_objects - .slice(1) - .map(errorItem => convertToSnakeCase(errorItem.attributes)); - return { - ...accumulated, - [id]: { - current_status: currentStatus, - failures, - }, - }; - }, Promise.resolve({})); - return statuses; + try { + const statuses = await query.ids.reduce>(async (acc, id) => { + const lastFiveErrorsForId = await savedObjectsClient.find< + IRuleSavedAttributesSavedObjectAttributes + >({ + type: ruleStatusSavedObjectType, + perPage: 6, + sortField: 'statusDate', + sortOrder: 'desc', + search: id, + searchFields: ['alertId'], + }); + const accumulated = await acc; + const currentStatus = convertToSnakeCase( + lastFiveErrorsForId.saved_objects[0]?.attributes + ); + const failures = lastFiveErrorsForId.saved_objects + .slice(1) + .map(errorItem => convertToSnakeCase(errorItem.attributes)); + return { + ...accumulated, + [id]: { + current_status: currentStatus, + failures, + }, + }; + }, Promise.resolve({})); + return statuses; + } catch (err) { + const error = transformError(err); + return headers + .response({ + message: error.message, + status_code: error.statusCode, + }) + .code(error.statusCode); + } }, }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts index 8f27910a7e5e2..99157b4d15360 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts @@ -7,6 +7,7 @@ import { omit } from 'lodash/fp'; import { getPrepackagedRulesStatusRoute } from './get_prepackaged_rules_status_route'; +import * as findRules from '../../rules/find_rules'; import { getFindResult, @@ -47,7 +48,12 @@ describe('get_prepackaged_rule_status_route', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); getClients = clientsServiceMock.createGetScoped(); @@ -76,6 +82,17 @@ describe('get_prepackaged_rule_status_route', () => { const { statusCode } = await inject(getPrepackagedRulesStatusRequest()); expect(statusCode).toBe(404); }); + + test('catch error when findRules function throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + jest.spyOn(findRules, 'findRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getPrepackagedRulesStatusRequest()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('payload', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts index b1dd08f8ca371..c8b77e505b5d7 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.test.ts @@ -8,6 +8,7 @@ import { omit } from 'lodash/fp'; import { getSimpleRuleAsMultipartContent, + getSimpleRuleAsMultipartContentNoRuleId, TEST_BOUNDARY, UNPARSABLE_LINE, getSimpleRule, @@ -25,6 +26,7 @@ import { import { createMockServer, createMockConfig, clientsServiceMock } from '../__mocks__'; import { importRulesRoute } from './import_rules_route'; import { DEFAULT_SIGNALS_INDEX } from '../../../../../common/constants'; +import * as createRulesStreamFromNdJson from '../../rules/create_rules_stream_from_ndjson'; describe('import_rules_route', () => { let server = createMockServer(); @@ -33,8 +35,12 @@ describe('import_rules_route', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); - + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); config = createMockConfig(); config = () => ({ @@ -94,6 +100,21 @@ describe('import_rules_route', () => { const { statusCode } = await inject(getImportRulesRequest(requestPayload)); expect(statusCode).toEqual(404); }); + + test('returns error if createPromiseFromStreams throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResult()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.alertsClient.create.mockResolvedValue(getResult()); + jest + .spyOn(createRulesStreamFromNdJson, 'createRulesStreamFromNdJson') + .mockImplementation(() => { + throw new Error('Test error'); + }); + const requestPayload = getSimpleRuleAsMultipartContent(['rule-1']); + const { payload, statusCode } = await server.inject(getImportRulesRequest(requestPayload)); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('validation', () => { @@ -306,6 +327,21 @@ describe('import_rules_route', () => { expect(statusCode).toEqual(200); }); + test('returns 200 with errors if all rules are missing rule_ids and import fails on validation', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResult()); + + const requestPayload = getSimpleRuleAsMultipartContentNoRuleId(2); + const { statusCode, payload } = await server.inject(getImportRulesRequest(requestPayload)); + const parsed: ImportSuccessError = JSON.parse(payload); + + expect(parsed.success).toEqual(false); + expect(parsed.errors[0].error.message).toEqual( + 'child "rule_id" fails because ["rule_id" is required]' + ); + expect(parsed.errors[0].error.status_code).toEqual(400); + expect(statusCode).toEqual(200); + }); + test('returns 200 with reported conflict if error parsing rule', async () => { const multipartPayload = `--${TEST_BOUNDARY}\r\n` + diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts index f438e0120f96a..a9358a47f25fc 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/import_rules_route.ts @@ -7,6 +7,7 @@ import Hapi from 'hapi'; import { chunk, isEmpty } from 'lodash/fp'; import { extname } from 'path'; +import { Readable } from 'stream'; import { createPromiseFromStreams } from '../../../../../../../../../src/legacy/utils/streams'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; @@ -15,7 +16,7 @@ import { createRules } from '../../rules/create_rules'; import { ImportRulesRequest } from '../../rules/types'; import { readRules } from '../../rules/read_rules'; import { getIndexExists } from '../../index/get_index_exists'; -import { getIndex, createBulkErrorObject, ImportRuleResponse } from '../utils'; +import { getIndex, transformError, createBulkErrorObject, ImportRuleResponse } from '../utils'; import { createRulesStreamFromNdJson } from '../../rules/create_rules_stream_from_ndjson'; import { ImportRuleAlertRest } from '../../types'; import { patchRules } from '../../rules/patch_rules'; @@ -74,179 +75,192 @@ export const createImportRulesRoute = ( } const objectLimit = config().get('savedObjects.maxImportExportSize'); - const readStream = createRulesStreamFromNdJson(request.payload.file, objectLimit); - const parsedObjects = await createPromiseFromStreams([readStream]); - const [duplicateIdErrors, uniqueParsedObjects] = getTupleDuplicateErrorsAndUniqueRules( - parsedObjects, - request.query.overwrite - ); + try { + const readStream = createRulesStreamFromNdJson(objectLimit); + const parsedObjects = await createPromiseFromStreams([ + request.payload.file as Readable, + ...readStream, + ]); + const [duplicateIdErrors, uniqueParsedObjects] = getTupleDuplicateErrorsAndUniqueRules( + parsedObjects, + request.query.overwrite + ); - const chunkParseObjects = chunk(CHUNK_PARSED_OBJECT_SIZE, uniqueParsedObjects); - let importRuleResponse: ImportRuleResponse[] = []; + const chunkParseObjects = chunk(CHUNK_PARSED_OBJECT_SIZE, uniqueParsedObjects); + let importRuleResponse: ImportRuleResponse[] = []; - while (chunkParseObjects.length) { - const batchParseObjects = chunkParseObjects.shift() ?? []; - const newImportRuleResponse = await Promise.all( - batchParseObjects.reduce>>((accum, parsedRule) => { - const importsWorkerPromise = new Promise( - async (resolve, reject) => { - if (parsedRule instanceof Error) { - // If the JSON object had a validation or parse error then we return - // early with the error and an (unknown) for the ruleId - resolve( - createBulkErrorObject({ - statusCode: 400, - message: parsedRule.message, - }) - ); - return null; - } - const { - description, - enabled, - false_positives: falsePositives, - from, - immutable, - query, - language, - output_index: outputIndex, - saved_id: savedId, - meta, - filters, - rule_id: ruleId, - index, - interval, - max_signals: maxSignals, - risk_score: riskScore, - name, - severity, - tags, - threat, - to, - type, - references, - timeline_id: timelineId, - timeline_title: timelineTitle, - version, - } = parsedRule; - try { - const finalIndex = getIndex(spacesClient.getSpaceId, config); - const indexExists = await getIndexExists( - clusterClient.callAsCurrentUser, - finalIndex - ); - if (!indexExists) { + while (chunkParseObjects.length) { + const batchParseObjects = chunkParseObjects.shift() ?? []; + const newImportRuleResponse = await Promise.all( + batchParseObjects.reduce>>((accum, parsedRule) => { + const importsWorkerPromise = new Promise( + async (resolve, reject) => { + if (parsedRule instanceof Error) { + // If the JSON object had a validation or parse error then we return + // early with the error and an (unknown) for the ruleId resolve( createBulkErrorObject({ - ruleId, - statusCode: 409, - message: `To create a rule, the index must exist first. Index ${finalIndex} does not exist`, + statusCode: 400, + message: parsedRule.message, }) ); + return null; } - const rule = await readRules({ alertsClient, ruleId }); - if (rule == null) { - await createRules({ - alertsClient, - actionsClient, - description, - enabled, - falsePositives, - from, - immutable, - query, - language, - outputIndex: finalIndex, - savedId, - timelineId, - timelineTitle, - meta, - filters, - ruleId, - index, - interval, - maxSignals, - riskScore, - name, - severity, - tags, - to, - type, - threat, - references, - version, - }); - resolve({ rule_id: ruleId, status_code: 200 }); - } else if (rule != null && request.query.overwrite) { - await patchRules({ - alertsClient, - actionsClient, - savedObjectsClient, - description, - enabled, - falsePositives, - from, - immutable, - query, - language, - outputIndex, - savedId, - timelineId, - timelineTitle, - meta, - filters, - id: undefined, - ruleId, - index, - interval, - maxSignals, - riskScore, - name, - severity, - tags, - to, - type, - threat, - references, - version, - }); - resolve({ rule_id: ruleId, status_code: 200 }); - } else if (rule != null) { + const { + description, + enabled, + false_positives: falsePositives, + from, + immutable, + query, + language, + output_index: outputIndex, + saved_id: savedId, + meta, + filters, + rule_id: ruleId, + index, + interval, + max_signals: maxSignals, + risk_score: riskScore, + name, + severity, + tags, + threat, + to, + type, + references, + timeline_id: timelineId, + timeline_title: timelineTitle, + version, + } = parsedRule; + try { + const finalIndex = getIndex(spacesClient.getSpaceId, config); + const indexExists = await getIndexExists( + clusterClient.callAsCurrentUser, + finalIndex + ); + if (!indexExists) { + resolve( + createBulkErrorObject({ + ruleId, + statusCode: 409, + message: `To create a rule, the index must exist first. Index ${finalIndex} does not exist`, + }) + ); + } + const rule = await readRules({ alertsClient, ruleId }); + if (rule == null) { + await createRules({ + alertsClient, + actionsClient, + description, + enabled, + falsePositives, + from, + immutable, + query, + language, + outputIndex: finalIndex, + savedId, + timelineId, + timelineTitle, + meta, + filters, + ruleId, + index, + interval, + maxSignals, + riskScore, + name, + severity, + tags, + to, + type, + threat, + references, + version, + }); + resolve({ rule_id: ruleId, status_code: 200 }); + } else if (rule != null && request.query.overwrite) { + await patchRules({ + alertsClient, + actionsClient, + savedObjectsClient, + description, + enabled, + falsePositives, + from, + immutable, + query, + language, + outputIndex, + savedId, + timelineId, + timelineTitle, + meta, + filters, + id: undefined, + ruleId, + index, + interval, + maxSignals, + riskScore, + name, + severity, + tags, + to, + type, + threat, + references, + version, + }); + resolve({ rule_id: ruleId, status_code: 200 }); + } else if (rule != null) { + resolve( + createBulkErrorObject({ + ruleId, + statusCode: 409, + message: `rule_id: "${ruleId}" already exists`, + }) + ); + } + } catch (err) { resolve( createBulkErrorObject({ ruleId, - statusCode: 409, - message: `rule_id: "${ruleId}" already exists`, + statusCode: 400, + message: err.message, }) ); } - } catch (err) { - resolve( - createBulkErrorObject({ - ruleId, - statusCode: 400, - message: err.message, - }) - ); } - } - ); - return [...accum, importsWorkerPromise]; - }, []) - ); - importRuleResponse = [ - ...duplicateIdErrors, - ...importRuleResponse, - ...newImportRuleResponse, - ]; - } + ); + return [...accum, importsWorkerPromise]; + }, []) + ); + importRuleResponse = [ + ...duplicateIdErrors, + ...importRuleResponse, + ...newImportRuleResponse, + ]; + } - const errorsResp = importRuleResponse.filter(resp => !isEmpty(resp.error)); - return { - success: errorsResp.length === 0, - success_count: importRuleResponse.filter(resp => resp.status_code === 200).length, - errors: errorsResp, - }; + const errorsResp = importRuleResponse.filter(resp => !isEmpty(resp.error)); + return { + success: errorsResp.length === 0, + success_count: importRuleResponse.filter(resp => resp.status_code === 200).length, + errors: errorsResp, + }; + } catch (exc) { + const error = transformError(exc); + return headers + .response({ + message: error.message, + status_code: error.statusCode, + }) + .code(error.statusCode); + } }, }; }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk.test.ts index 02af4135b534f..1cfb4ae81ab85 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_bulk.test.ts @@ -15,6 +15,7 @@ import { typicalPayload, getFindResultWithSingleHit, getPatchBulkRequest, + getFindResultStatus, } from '../__mocks__/request_responses'; import { createMockServer, clientsServiceMock } from '../__mocks__'; import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; @@ -43,6 +44,7 @@ describe('patch_rules_bulk', () => { clients.alertsClient.get.mockResolvedValue(getResult()); clients.actionsClient.update.mockResolvedValue(updateActionResult()); clients.alertsClient.update.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); const { statusCode } = await server.inject(getPatchBulkRequest()); expect(statusCode).toBe(200); }); @@ -56,6 +58,13 @@ describe('patch_rules_bulk', () => { expect(statusCode).toBe(200); }); + test('returns 404 as a response when missing alertsClient', async () => { + getClients.mockResolvedValue(omit('alertsClient', clients)); + clients.actionsClient.update.mockResolvedValue(updateActionResult()); + const { statusCode } = await server.inject(getPatchBulkRequest()); + expect(statusCode).toBe(404); + }); + test('returns 404 within the payload when updating a single rule that does not exist', async () => { clients.alertsClient.find.mockResolvedValue(getFindResult()); clients.alertsClient.get.mockResolvedValue(getResult()); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts index cc84b08fdef11..04cd3a026562f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts @@ -7,6 +7,8 @@ import { ServerInjectOptions } from 'hapi'; import { omit } from 'lodash/fp'; import { patchRulesRoute } from './patch_rules_route'; +import * as utils from './utils'; +import * as patchRules from '../../rules/patch_rules'; import { getFindResult, @@ -26,7 +28,13 @@ describe('patch_rules', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); + server = createMockServer(); getClients = clientsServiceMock.createGetScoped(); clients = clientsServiceMock.createClients(); @@ -63,6 +71,32 @@ describe('patch_rules', () => { const { statusCode } = await inject(getPatchRequest()); expect(statusCode).toBe(404); }); + + test('returns 500 when transform fails', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.actionsClient.update.mockResolvedValue(updateActionResult()); + clients.alertsClient.update.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(utils, 'transform').mockReturnValue(null); + const { payload, statusCode } = await server.inject(getPatchRequest()); + expect(JSON.parse(payload).message).toBe('Internal error transforming rules'); + expect(statusCode).toBe(500); + }); + + test('catches error if patchRules throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.actionsClient.update.mockResolvedValue(updateActionResult()); + clients.alertsClient.update.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(patchRules, 'patchRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getPatchRequest()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts index 7c4653af97f21..0366d3648e1ea 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/read_rules_route.test.ts @@ -7,6 +7,9 @@ import { ServerInjectOptions } from 'hapi'; import { omit } from 'lodash/fp'; +import * as utils from './utils'; +import * as readRules from '../../rules/read_rules'; + import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { readRulesRoute } from './read_rules_route'; import { @@ -24,8 +27,12 @@ describe('read_signals', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); - + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); getClients = clientsServiceMock.createGetScoped(); clients = clientsServiceMock.createClients(); @@ -50,6 +57,38 @@ describe('read_signals', () => { const { statusCode } = await inject(getReadRequest()); expect(statusCode).toBe(404); }); + + test('returns error if readRules returns null', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(readRules, 'readRules').mockResolvedValue(null); + const { payload, statusCode } = await server.inject(getReadRequest()); + expect(JSON.parse(payload).message).toBe('rule_id: "rule-1" not found'); + expect(statusCode).toBe(404); + }); + + test('returns 500 when transform fails', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(utils, 'transform').mockReturnValue(null); + const { payload, statusCode } = await server.inject(getReadRequest()); + expect(JSON.parse(payload).message).toBe('Internal error transforming rules'); + expect(statusCode).toBe(500); + }); + + test('catches error if readRules throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(readRules, 'readRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getReadRequest()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts index 9ff7ebc37aab1..32a633799ad44 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_bulk.test.ts @@ -75,9 +75,9 @@ describe('update_rules_bulk', () => { test('returns 404 if alertClient is not available on the route', async () => { getClients.mockResolvedValue(omit('alertsClient', clients)); - const { route, inject } = createMockServer(); + const { route } = createMockServer(); updateRulesRoute(route, config, getClients); - const { statusCode } = await inject(getUpdateBulkRequest()); + const { statusCode } = await server.inject(getUpdateBulkRequest()); expect(statusCode).toBe(404); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index 7cadfa94467a7..c3a92ed9a61ae 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -7,6 +7,9 @@ import { ServerInjectOptions } from 'hapi'; import { omit } from 'lodash/fp'; +import * as utils from './utils'; +import * as updateRules from '../../rules/update_rules'; + import { updateRulesRoute } from './update_rules_route'; import { getFindResult, @@ -27,7 +30,12 @@ describe('update_rules', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); server = createMockServer(); config = createMockConfig(); @@ -66,6 +74,28 @@ describe('update_rules', () => { const { statusCode } = await inject(getUpdateRequest()); expect(statusCode).toBe(404); }); + + test('returns 500 when transform fails', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(utils, 'transform').mockReturnValue(null); + const { payload, statusCode } = await server.inject(getUpdateRequest()); + expect(JSON.parse(payload).message).toBe('Internal error transforming rules'); + expect(statusCode).toBe(500); + }); + + test('catches error if readRules throws error', async () => { + clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + clients.alertsClient.get.mockResolvedValue(getResult()); + clients.savedObjectsClient.find.mockResolvedValue(getFindResultStatus()); + jest.spyOn(updateRules, 'updateRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getUpdateRequest()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts index 593c55bcae9f2..b5b687c284b25 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.test.ts @@ -1251,9 +1251,10 @@ describe('utils', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); const parsedObjects = await createPromiseFromStreams([ - rulesObjectsStream, + ndJsonStream, + ...rulesObjectsStream, ]); const [errors, output] = getTupleDuplicateErrorsAndUniqueRules(parsedObjects, false); const isInstanceOfError = output[0] instanceof Error; @@ -1272,9 +1273,10 @@ describe('utils', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); const parsedObjects = await createPromiseFromStreams([ - rulesObjectsStream, + ndJsonStream, + ...rulesObjectsStream, ]); const [errors, output] = getTupleDuplicateErrorsAndUniqueRules(parsedObjects, false); @@ -1290,6 +1292,30 @@ describe('utils', () => { ]); }); + test('returns tuple of duplicate conflict error and single rule when rules with matching ids passed in and `overwrite` is false', async () => { + const rule = getSimpleRule('rule-1'); + delete rule.rule_id; + const rule2 = getSimpleRule('rule-1'); + delete rule2.rule_id; + const ndJsonStream = new Readable({ + read() { + this.push(`${JSON.stringify(rule)}\n`); + this.push(`${JSON.stringify(rule2)}\n`); + this.push(null); + }, + }); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); + const parsedObjects = await createPromiseFromStreams([ + ndJsonStream, + ...rulesObjectsStream, + ]); + const [errors, output] = getTupleDuplicateErrorsAndUniqueRules(parsedObjects, false); + const isInstanceOfError = output[0] instanceof Error; + + expect(isInstanceOfError).toEqual(true); + expect(errors).toEqual([]); + }); + test('returns tuple of empty duplicate errors array and single rule when rules with matching rule-ids passed in and `overwrite` is true', async () => { const rule = getSimpleRule('rule-1'); const rule2 = getSimpleRule('rule-1'); @@ -1300,9 +1326,10 @@ describe('utils', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); const parsedObjects = await createPromiseFromStreams([ - rulesObjectsStream, + ndJsonStream, + ...rulesObjectsStream, ]); const [errors, output] = getTupleDuplicateErrorsAndUniqueRules(parsedObjects, true); @@ -1320,9 +1347,10 @@ describe('utils', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); const parsedObjects = await createPromiseFromStreams([ - rulesObjectsStream, + ndJsonStream, + ...rulesObjectsStream, ]); const [errors, output] = getTupleDuplicateErrorsAndUniqueRules(parsedObjects, false); const isInstanceOfError = output[0] instanceof Error; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts index 198cdbfb9771d..ab80e1570c31c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/rules/utils.ts @@ -180,9 +180,7 @@ export const transform = ( if (!ruleStatus && isAlertType(alert)) { return transformAlertToRule(alert); } - if (isAlertType(alert) && isRuleStatusFindType(ruleStatus)) { - return transformAlertToRule(alert, ruleStatus.saved_objects[0]); - } else if (isAlertType(alert) && isRuleStatusSavedObjectType(ruleStatus)) { + if (isAlertType(alert) && isRuleStatusSavedObjectType(ruleStatus)) { return transformAlertToRule(alert, ruleStatus); } else { return null; @@ -195,7 +193,7 @@ export const transformOrBulkError = ( ruleStatus?: unknown ): Partial | BulkError => { if (isAlertType(alert)) { - if (isRuleStatusFindType(ruleStatus)) { + if (isRuleStatusFindType(ruleStatus) && ruleStatus?.saved_objects.length > 0) { return transformAlertToRule(alert, ruleStatus?.saved_objects[0] ?? ruleStatus); } else { return transformAlertToRule(alert); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals.test.ts index 3e7ed4de6d8c6..7086c62f81711 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals.test.ts @@ -25,7 +25,12 @@ describe('set signal status', () => { let clients = clientsServiceMock.createClients(); beforeEach(() => { + // jest carries state between mocked implementations when using + // spyOn. So now we're doing all three of these. + // https://github.com/facebook/jest/issues/7136#issuecomment-565976599 jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); jest.spyOn(myUtils, 'getIndex').mockReturnValue('fakeindex'); server = createMockServer(); @@ -50,6 +55,15 @@ describe('set signal status', () => { const { statusCode } = await server.inject(getSetSignalStatusByQueryRequest()); expect(statusCode).toBe(200); }); + + test('catches error if callAsCurrentUser throws error', async () => { + clients.clusterClient.callAsCurrentUser.mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(getSetSignalStatusByQueryRequest()); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); describe('validation', () => { diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts index dd3b8d3c99e0c..ee3fd349a26ee 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/open_close_signals_route.ts @@ -28,7 +28,7 @@ export const setSignalsStatusRouteDef = ( payload: setSignalsStatusSchema, }, }, - async handler(request: SignalsStatusRequest) { + async handler(request: SignalsStatusRequest, headers) { const { signal_ids: signalIds, query, status } = request.payload; const { clusterClient, spacesClient } = await getClients(request); const index = getIndex(spacesClient.getSpaceId, config); @@ -45,7 +45,7 @@ export const setSignalsStatusRouteDef = ( }; } try { - return clusterClient.callAsCurrentUser('updateByQuery', { + const updateByQueryResponse = await clusterClient.callAsCurrentUser('updateByQuery', { index, body: { script: { @@ -56,9 +56,15 @@ export const setSignalsStatusRouteDef = ( }, ignoreUnavailable: true, }); - } catch (exc) { - // error while getting or updating signal with id: id in signal index .siem-signals - return transformError(exc); + return updateByQueryResponse; + } catch (err) { + const error = transformError(err); + return headers + .response({ + message: error.message, + status_code: error.statusCode, + }) + .code(error.statusCode); } }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.test.ts index 9439adfcec3cb..210ac9f3d7b01 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.test.ts @@ -127,5 +127,18 @@ describe('query for signal', () => { const { statusCode } = await server.inject(request); expect(statusCode).toBe(400); }); + test('catches error if deleteRules throws error', async () => { + const request: ServerInjectOptions = { + method: 'POST', + url: DETECTION_ENGINE_QUERY_SIGNALS_URL, + payload: { ...typicalSignalsQueryAggs(), ...typicalSignalsQuery() }, + }; + clients.clusterClient.callAsCurrentUser.mockImplementation(async () => { + throw new Error('Test error'); + }); + const { payload, statusCode } = await server.inject(request); + expect(JSON.parse(payload).message).toBe('Test error'); + expect(statusCode).toBe(500); + }); }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts index adb6e5f32921a..7636329ecc306 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/signals/query_signals_route.ts @@ -28,21 +28,27 @@ export const querySignalsRouteDef = ( payload: querySignalsSchema, }, }, - async handler(request: SignalsQueryRequest) { + async handler(request: SignalsQueryRequest, headers) { const { query, aggs, _source, track_total_hits, size } = request.payload; const { clusterClient, spacesClient } = await getClients(request); const index = getIndex(spacesClient.getSpaceId, config); try { - return clusterClient.callAsCurrentUser('search', { + const searchSignalsIndexResult = await clusterClient.callAsCurrentUser('search', { index, body: { query, aggs, _source, track_total_hits, size }, ignoreUnavailable: true, }); - } catch (exc) { - // error while getting or updating signal with id: id in signal index .siem-signals - return transformError(exc); + return searchSignalsIndexResult; + } catch (err) { + const error = transformError(err); + return headers + .response({ + message: error.message, + status_code: error.statusCode, + }) + .code(error.statusCode); } }, }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts index 957ddd4ee6caa..3148083b4db26 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.test.ts @@ -15,6 +15,7 @@ import { ImportSuccessError, createImportErrorObject, transformImportError, + convertToSnakeCase, } from './utils'; import { createMockConfig } from './__mocks__'; @@ -312,4 +313,15 @@ describe('utils', () => { expect(index).toEqual('mockSignalsIndex-myspace'); }); }); + + describe('convertToSnakeCase', () => { + it('converts camelCase to snakeCase', () => { + const values = { myTestCamelCaseKey: 'something' }; + expect(convertToSnakeCase(values)).toEqual({ my_test_camel_case_key: 'something' }); + }); + it('returns empty object when object is empty', () => { + const values = {}; + expect(convertToSnakeCase(values)).toEqual({}); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts index 55832ab67dc6b..36e1a814d8ec2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/routes/utils.ts @@ -5,6 +5,7 @@ */ import Boom from 'boom'; +import { snakeCase } from 'lodash/fp'; import { APP_ID, SIGNALS_INDEX_KEY } from '../../../../common/constants'; import { LegacyServices } from '../../../types'; @@ -211,3 +212,11 @@ export const getIndex = (getSpaceId: () => string, config: LegacyServices['confi return `${signalsIndex}-${spaceId}`; }; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const convertToSnakeCase = >(obj: T): Partial | null => { + return Object.keys(obj).reduce((acc, item) => { + const newKey = snakeCase(item); + return { ...acc, [newKey]: obj[item] }; + }, {}); +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts index d4b7c252e3e38..b1dc62f6fc90f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.test.ts @@ -5,12 +5,10 @@ */ import { Readable } from 'stream'; import { createRulesStreamFromNdJson } from './create_rules_stream_from_ndjson'; -import { createPromiseFromStreams, createConcatStream } from 'src/legacy/utils/streams'; +import { createPromiseFromStreams } from 'src/legacy/utils/streams'; import { ImportRuleAlertRest } from '../types'; -const readStreamToCompletion = (stream: Readable) => { - return createPromiseFromStreams([stream, createConcatStream([])]); -}; +type PromiseFromStreams = ImportRuleAlertRest | Error; export const getOutputSample = (): Partial => ({ rule_id: 'rule-1', @@ -43,8 +41,11 @@ describe('create_rules_stream_from_ndjson', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); - const result = await readStreamToCompletion(rulesObjectsStream); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); + const result = await createPromiseFromStreams([ + ndJsonStream, + ...rulesObjectsStream, + ]); expect(result).toEqual([ { rule_id: 'rule-1', @@ -95,6 +96,22 @@ describe('create_rules_stream_from_ndjson', () => { ]); }); + test('returns error when ndjson stream is larger than limit', async () => { + const sample1 = getOutputSample(); + const sample2 = getOutputSample(); + sample2.rule_id = 'rule-2'; + const ndJsonStream = new Readable({ + read() { + this.push(getSampleAsNdjson(sample1)); + this.push(getSampleAsNdjson(sample2)); + }, + }); + const rulesObjectsStream = createRulesStreamFromNdJson(1); + await expect( + createPromiseFromStreams([ndJsonStream, ...rulesObjectsStream]) + ).rejects.toThrowError("Can't import more than 1 rules"); + }); + test('skips empty lines', async () => { const sample1 = getOutputSample(); const sample2 = getOutputSample(); @@ -108,8 +125,11 @@ describe('create_rules_stream_from_ndjson', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); - const result = await readStreamToCompletion(rulesObjectsStream); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); + const result = await createPromiseFromStreams([ + ndJsonStream, + ...rulesObjectsStream, + ]); expect(result).toEqual([ { rule_id: 'rule-1', @@ -172,8 +192,11 @@ describe('create_rules_stream_from_ndjson', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); - const result = await readStreamToCompletion(rulesObjectsStream); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); + const result = await createPromiseFromStreams([ + ndJsonStream, + ...rulesObjectsStream, + ]); expect(result).toEqual([ { rule_id: 'rule-1', @@ -236,8 +259,11 @@ describe('create_rules_stream_from_ndjson', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); - const result = await readStreamToCompletion(rulesObjectsStream); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); + const result = await createPromiseFromStreams([ + ndJsonStream, + ...rulesObjectsStream, + ]); const resultOrError = result as Error[]; expect(resultOrError[0]).toEqual({ rule_id: 'rule-1', @@ -300,8 +326,11 @@ describe('create_rules_stream_from_ndjson', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); - const result = await readStreamToCompletion(rulesObjectsStream); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); + const result = await createPromiseFromStreams([ + ndJsonStream, + ...rulesObjectsStream, + ]); const resultOrError = result as TypeError[]; expect(resultOrError[0]).toEqual({ rule_id: 'rule-1', @@ -366,8 +395,11 @@ describe('create_rules_stream_from_ndjson', () => { this.push(null); }, }); - const rulesObjectsStream = createRulesStreamFromNdJson(ndJsonStream, 1000); - const result = await readStreamToCompletion(rulesObjectsStream); + const rulesObjectsStream = createRulesStreamFromNdJson(1000); + const result = await createPromiseFromStreams([ + ndJsonStream, + ...rulesObjectsStream, + ]); const resultOrError = result as TypeError[]; expect(resultOrError[1] instanceof TypeError).toEqual(true); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.ts index 6d58171a3245d..ae0dfa20852aa 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.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 { Readable, Transform } from 'stream'; +import { Transform } from 'stream'; import { has, isString } from 'lodash/fp'; import { ImportRuleAlertRest } from '../types'; import { @@ -74,15 +74,13 @@ export const createLimitStream = (limit: number): Transform => { * Inspiration and the pattern of code followed is from: * saved_objects/lib/create_saved_objects_stream_from_ndjson.ts */ -export const createRulesStreamFromNdJson = ( - ndJsonStream: Readable, - ruleLimit: number -): Transform => { - return ndJsonStream - .pipe(createSplitStream('\n')) - .pipe(parseNdjsonStrings()) - .pipe(filterExportedCounts()) - .pipe(validateRules()) - .pipe(createLimitStream(ruleLimit)) - .pipe(createConcatStream([])); +export const createRulesStreamFromNdJson = (ruleLimit: number) => { + return [ + createSplitStream('\n'), + parseNdjsonStrings(), + filterExportedCounts(), + validateRules(), + createLimitStream(ruleLimit), + createConcatStream([]), + ]; }; diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts index 98f5df4852530..44d3013263c65 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts @@ -10,9 +10,15 @@ import { getFindResultWithSingleHit, FindHit, } from '../routes/__mocks__/request_responses'; +import * as readRules from './read_rules'; import { alertsClientMock } from '../../../../../../../plugins/alerting/server/mocks'; describe('get_export_by_object_ids', () => { + beforeEach(() => { + jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); + }); describe('getExportByObjectIds', () => { test('it exports object ids into an expected string with new line characters', async () => { const alertsClient = alertsClientMock.create(); @@ -119,6 +125,23 @@ describe('get_export_by_object_ids', () => { expect(exports).toEqual(expected); }); + test('it returns error when readRules throws error', async () => { + const alertsClient = alertsClientMock.create(); + alertsClient.get.mockResolvedValue(getResult()); + alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); + jest.spyOn(readRules, 'readRules').mockImplementation(async () => { + throw new Error('Test error'); + }); + const objects = [{ rule_id: 'rule-1' }]; + const exports = await getRulesFromObjects(alertsClient, objects); + const expected: RulesErrors = { + exportedCount: 0, + missingRules: [{ rule_id: objects[0].rule_id }], + rules: [], + }; + expect(exports).toEqual(expected); + }); + test('it does not transform the rule if the rule is an immutable rule and designates it as a missing rule', async () => { const alertsClient = alertsClientMock.create(); const result = getResult(); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts index 45507a69f50c2..aa1cce6f15238 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.test.ts @@ -8,7 +8,23 @@ import { readRules } from './read_rules'; import { alertsClientMock } from '../../../../../../../plugins/alerting/server/mocks'; import { getResult, getFindResultWithSingleHit } from '../routes/__mocks__/request_responses'; +class TestError extends Error { + constructor() { + // Pass remaining arguments (including vendor specific ones) to parent constructor + super(); + + this.name = 'CustomError'; + this.output = { statusCode: 404 }; + } + public output: { statusCode: number }; +} + describe('read_rules', () => { + beforeEach(() => { + jest.resetAllMocks(); + jest.restoreAllMocks(); + jest.clearAllMocks(); + }); describe('readRules', () => { test('should return the output from alertsClient if id is set but ruleId is undefined', async () => { const alertsClient = alertsClientMock.create(); @@ -21,6 +37,49 @@ describe('read_rules', () => { }); expect(rule).toEqual(getResult()); }); + test('should return null if saved object found by alerts client given id is not alert type', async () => { + const alertsClient = alertsClientMock.create(); + const { alertTypeId, ...rest } = getResult(); + // @ts-ignore + alertsClient.get.mockImplementation(() => rest); + + const rule = await readRules({ + alertsClient, + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + ruleId: undefined, + }); + expect(rule).toEqual(null); + }); + + test('should return error if alerts client throws 404 error on get', async () => { + const alertsClient = alertsClientMock.create(); + alertsClient.get.mockImplementation(() => { + throw new TestError(); + }); + + const rule = await readRules({ + alertsClient, + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + ruleId: undefined, + }); + expect(rule).toEqual(null); + }); + + test('should return error if alerts client throws error on get', async () => { + const alertsClient = alertsClientMock.create(); + alertsClient.get.mockImplementation(() => { + throw new Error('Test error'); + }); + try { + await readRules({ + alertsClient, + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + ruleId: undefined, + }); + } catch (exc) { + expect(exc.message).toEqual('Test error'); + } + }); test('should return the output from alertsClient if id is set but ruleId is null', async () => { const alertsClient = alertsClientMock.create(); @@ -47,6 +106,20 @@ describe('read_rules', () => { expect(rule).toEqual(getResult()); }); + test('should return null if the output from alertsClient with ruleId set is empty', async () => { + const alertsClient = alertsClientMock.create(); + alertsClient.get.mockResolvedValue(getResult()); + // @ts-ignore + alertsClient.find.mockResolvedValue({ data: [] }); + + const rule = await readRules({ + alertsClient, + id: undefined, + ruleId: 'rule-1', + }); + expect(rule).toEqual(null); + }); + test('should return the output from alertsClient if id is null but ruleId is set', async () => { const alertsClient = alertsClientMock.create(); alertsClient.get.mockResolvedValue(getResult()); diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts index cbe6dbda8449f..94e4e6357a4a0 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/read_rules.ts @@ -31,7 +31,7 @@ export const readRules = async ({ return null; } } catch (err) { - if (err.output.statusCode === 404) { + if (err?.output?.statusCode === 404) { return null; } else { // throw non-404 as they would be 500 or other internal errors diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts index fa22765c143e1..3d95e9868a1d6 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/types.ts @@ -197,10 +197,6 @@ export const isAlertType = (obj: unknown): obj is RuleAlertType => { return get('alertTypeId', obj) === SIGNALS_ID; }; -export const isRuleStatusAttributes = (obj: unknown): obj is IRuleStatusAttributes => { - return get('lastSuccessMessage', obj) != null; -}; - export const isRuleStatusSavedObjectType = ( obj: unknown ): obj is SavedObject => { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts index 79a1e667e5458..a1cb60483c332 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts @@ -74,6 +74,17 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('should report that it failed to import a thousand and one (10001) simple rules', async () => { + const { body } = await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', getSimpleRuleAsNdjson(new Array(10001).fill('rule-1')), 'rules.ndjson') + .query() + .expect(500); + + expect(body).to.eql({ message: "Can't import more than 10000 rules", status_code: 500 }); + }); + it('should be able to read an imported rule back out correctly', async () => { await supertest .post(`${DETECTION_ENGINE_RULES_URL}/_import`)