From 91e4fd46f46e6fc2df229bb51ad9e7cf432ea0c4 Mon Sep 17 00:00:00 2001 From: Clint Andrew Hall Date: Tue, 9 Jun 2020 11:54:37 -0500 Subject: [PATCH 01/53] Enable exhaustive-deps; correct any lint warnings (#68453) Co-authored-by: Elastic Machine --- .eslintrc.js | 1 - .../workpad/workpad_app/workpad_telemetry.tsx | 16 +++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c33f4de15b919..3cac46e7d2605 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -91,7 +91,6 @@ module.exports = { { files: ['x-pack/plugins/canvas/**/*.{js,ts,tsx}'], rules: { - 'react-hooks/exhaustive-deps': 'off', 'jsx-a11y/click-events-have-key-events': 'off', }, }, diff --git a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx index 47b461f22ad65..3014369d94857 100644 --- a/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx +++ b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx @@ -69,6 +69,7 @@ export const withUnconnectedElementsLoadedTelemetry =

( ) => function ElementsLoadedTelemetry(props: ElementsLoadedTelemetryProps) { const { telemetryElementCounts, workpad, telemetryResolvedArgs, ...other } = props; + const { error, pending } = telemetryElementCounts; const [currentWorkpadId, setWorkpadId] = useState(undefined); const [hasReported, setHasReported] = useState(false); @@ -87,27 +88,20 @@ export const withUnconnectedElementsLoadedTelemetry =

( 0 ); - if ( - workpadElementCount === 0 || - (resolvedArgsAreForWorkpad && telemetryElementCounts.pending === 0) - ) { + if (workpadElementCount === 0 || (resolvedArgsAreForWorkpad && pending === 0)) { setHasReported(true); } else { setHasReported(false); } - } else if ( - !hasReported && - telemetryElementCounts.pending === 0 && - resolvedArgsAreForWorkpad - ) { - if (telemetryElementCounts.error > 0) { + } else if (!hasReported && pending === 0 && resolvedArgsAreForWorkpad) { + if (error > 0) { trackMetric(METRIC_TYPE.LOADED, [WorkpadLoadedMetric, WorkpadLoadedWithErrorsMetric]); } else { trackMetric(METRIC_TYPE.LOADED, WorkpadLoadedMetric); } setHasReported(true); } - }); + }, [currentWorkpadId, hasReported, error, pending, telemetryResolvedArgs, workpad]); return ; }; From 45c81ce1ab778488d839000ade4e1eae8181c342 Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 9 Jun 2020 10:41:41 -0700 Subject: [PATCH 02/53] run page_load_metrics tests in visual regresssion jobs (#68570) Co-authored-by: spalger --- test/scripts/jenkins_visual_regression.sh | 3 +-- test/scripts/jenkins_xpack_visual_regression.sh | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/scripts/jenkins_visual_regression.sh b/test/scripts/jenkins_visual_regression.sh index c6fefd45b005d..a32782deec65b 100755 --- a/test/scripts/jenkins_visual_regression.sh +++ b/test/scripts/jenkins_visual_regression.sh @@ -11,8 +11,7 @@ mkdir -p "$installDir" tar -xzf "$linuxBuild" -C "$installDir" --strip=1 echo " -> running visual regression tests from kibana directory" -checks-reporter-with-killswitch "X-Pack visual regression tests" \ - yarn percy exec -t 500 -- -- \ +yarn percy exec -t 500 -- -- \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$installDir" \ diff --git a/test/scripts/jenkins_xpack_visual_regression.sh b/test/scripts/jenkins_xpack_visual_regression.sh index 96521ccc8f787..e406bb3e6106f 100755 --- a/test/scripts/jenkins_xpack_visual_regression.sh +++ b/test/scripts/jenkins_xpack_visual_regression.sh @@ -13,9 +13,11 @@ tar -xzf "$linuxBuild" -C "$installDir" --strip=1 echo " -> running visual regression tests from x-pack directory" cd "$XPACK_DIR" -checks-reporter-with-killswitch "X-Pack visual regression tests" \ - yarn percy exec -t 500 -- -- \ +yarn percy exec -t 500 -- -- \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$installDir" \ --config test/visual_regression/config.ts; + +cd "$KIBANA_DIR" +source "test/scripts/jenkins_xpack_page_load_metrics.sh" From 14410e0c79bdced1e402c3a303729f7328207efb Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Tue, 9 Jun 2020 13:47:00 -0400 Subject: [PATCH 03/53] [Endpoint] Re-enable Functional test case for Endpoint related pages (#68445) * Improve Policy test service provider - Added `getFullAgentConfig()` to Endpoint Policy Test data provider service * enable Policy List functional tests * Added Policy Details Tests * Add test ids to policy detail Max and Linux forms * Added page objects utilities and moved `clickOnEuiCheckbox` there --- .../pages/policy/view/policy_details.tsx | 14 +- .../view/policy_forms/events/checkbox.tsx | 17 +- .../policy/view/policy_forms/events/linux.tsx | 1 + .../policy/view/policy_forms/events/mac.tsx | 1 + .../view/policy_forms/events/windows.tsx | 1 + x-pack/scripts/functional_tests.js | 1 + .../{host_list.ts => endpoint_list.ts} | 43 ++-- .../feature_controls/endpoint_spaces.ts | 76 ------ .../apps/endpoint/feature_controls/index.ts | 13 - .../apps/endpoint/header_nav.ts | 55 ----- .../apps/endpoint/index.ts | 11 +- .../apps/endpoint/landing_page.ts | 29 --- .../apps/endpoint/policy_details.ts | 225 ++++++++++++++++++ .../apps/endpoint/policy_list.ts | 46 ++-- .../page_objects/endpoint_page.ts | 17 +- .../functional_endpoint/page_objects/index.ts | 4 + .../page_objects/page_utils.ts | 30 +++ .../page_objects/policy_page.ts | 59 +++++ .../services/endpoint_policy.ts | 163 +++++++++---- 19 files changed, 522 insertions(+), 284 deletions(-) rename x-pack/test/functional_endpoint/apps/endpoint/{host_list.ts => endpoint_list.ts} (84%) delete mode 100644 x-pack/test/functional_endpoint/apps/endpoint/feature_controls/endpoint_spaces.ts delete mode 100644 x-pack/test/functional_endpoint/apps/endpoint/feature_controls/index.ts delete mode 100644 x-pack/test/functional_endpoint/apps/endpoint/header_nav.ts delete mode 100644 x-pack/test/functional_endpoint/apps/endpoint/landing_page.ts create mode 100644 x-pack/test/functional_endpoint/apps/endpoint/policy_details.ts create mode 100644 x-pack/test/functional_endpoint/page_objects/page_utils.ts create mode 100644 x-pack/test/functional_endpoint/page_objects/policy_page.ts diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx index f4c4b36ce153f..d1f7da91bd6fa 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_details.tsx @@ -68,11 +68,13 @@ export const PolicyDetails = React.memo(() => { } ), body: ( - + + + ), }); } else { @@ -116,7 +118,7 @@ export const PolicyDetails = React.memo(() => { ) : policyApiError ? ( - {policyApiError?.message} + {policyApiError?.message} ) : null} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx index e5f3b2c7e8b7e..9ceade5d0264c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/checkbox.tsx @@ -5,23 +5,25 @@ */ import React, { useCallback, useMemo } from 'react'; -import { EuiCheckbox, htmlIdGenerator } from '@elastic/eui'; +import { EuiCheckbox, EuiCheckboxProps, htmlIdGenerator } from '@elastic/eui'; import { useDispatch } from 'react-redux'; - import { usePolicyDetailsSelector } from '../../policy_hooks'; import { policyConfig } from '../../../store/policy_details/selectors'; import { PolicyDetailsAction } from '../../../store/policy_details'; import { UIPolicyConfig } from '../../../../../../../common/endpoint/types'; +type EventsCheckboxProps = Omit & { + name: string; + setter: (config: UIPolicyConfig, checked: boolean) => UIPolicyConfig; + getter: (config: UIPolicyConfig) => boolean; +}; + export const EventsCheckbox = React.memo(function ({ name, setter, getter, -}: { - name: string; - setter: (config: UIPolicyConfig, checked: boolean) => UIPolicyConfig; - getter: (config: UIPolicyConfig) => boolean; -}) { + ...otherProps +}: EventsCheckboxProps) { const policyDetailsConfig = usePolicyDetailsSelector(policyConfig); const selected = getter(policyDetailsConfig); const dispatch = useDispatch<(action: PolicyDetailsAction) => void>(); @@ -44,6 +46,7 @@ export const EventsCheckbox = React.memo(function ({ label={name} checked={selected} onChange={handleCheckboxChange} + {...otherProps} /> ); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx index d0ddd5cb6fe2f..d7bae0d2e6bad 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx @@ -73,6 +73,7 @@ export const LinuxEvents = React.memo(() => { setIn(config)(item.os)('events')(item.protectionField)(checked) } diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/mac.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/mac.tsx index e2d6b70d33415..37709ff608857 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/mac.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/mac.tsx @@ -73,6 +73,7 @@ export const MacEvents = React.memo(() => { setIn(config)(item.os)('events')(item.protectionField)(checked) } diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/windows.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/windows.tsx index 23f33cb6fd86f..3c7ecae0d9b4e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/windows.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/windows.tsx @@ -113,6 +113,7 @@ export const WindowsEvents = React.memo(() => { setIn(config)(item.os)('events')(item.protectionField)(checked) } diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index 4392299a78e72..c120e1f780761 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -6,6 +6,7 @@ const alwaysImportedTests = [ require.resolve('../test/functional/config.js'), + require.resolve('../test/functional_endpoint/config.ts'), require.resolve('../test/functional_with_es_ssl/config.ts'), require.resolve('../test/functional/config_security_basic.ts'), require.resolve('../test/functional/config_security_trial.ts'), diff --git a/x-pack/test/functional_endpoint/apps/endpoint/host_list.ts b/x-pack/test/functional_endpoint/apps/endpoint/endpoint_list.ts similarity index 84% rename from x-pack/test/functional_endpoint/apps/endpoint/host_list.ts rename to x-pack/test/functional_endpoint/apps/endpoint/endpoint_list.ts index 029953f113a9c..c5338e2a35765 100644 --- a/x-pack/test/functional_endpoint/apps/endpoint/host_list.ts +++ b/x-pack/test/functional_endpoint/apps/endpoint/endpoint_list.ts @@ -13,68 +13,71 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const testSubjects = getService('testSubjects'); // FLAKY: https://github.com/elastic/kibana/issues/63621 - describe.skip('host list', function () { + describe.skip('endpoint list', function () { this.tags('ciGroup7'); const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms)); before(async () => { await esArchiver.load('endpoint/metadata/api_feature'); - await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/hosts'); - await pageObjects.header.waitUntilLoadingHasFinished(); + await pageObjects.endpoint.navigateToEndpointList(); }); it('finds title', async () => { - const title = await testSubjects.getVisibleText('hostListTitle'); - expect(title).to.equal('Hosts'); + const title = await testSubjects.getVisibleText('pageViewHeaderLeftTitle'); + expect(title).to.equal('Endpoints'); }); it('displays table data', async () => { const expectedData = [ [ 'Hostname', + 'Host Status', 'Policy', 'Policy Status', 'Alerts', 'Operating System', 'IP Address', - 'Sensor Version', + 'Version', 'Last Active', ], [ 'cadmann-4.example.com', + 'Error', 'Policy Name', 'Policy Status', '0', 'windows 10.0', '10.192.213.130, 10.70.28.129', - 'version', - 'xxxx', + '6.6.1', + 'Jan 24, 2020 @ 16:06:09.541', ], [ 'thurlow-9.example.com', + 'Error', 'Policy Name', 'Policy Status', '0', 'windows 10.0', '10.46.229.234', - 'version', - 'xxxx', + '6.0.0', + 'Jan 24, 2020 @ 16:06:09.541', ], [ 'rezzani-7.example.com', + 'Error', 'Policy Name', 'Policy Status', '0', 'windows 10.0', '10.101.149.26, 2606:a000:ffc0:39:11ef:37b9:3371:578c', - 'version', - 'xxxx', + '6.8.0', + 'Jan 24, 2020 @ 16:06:09.541', ], ]; const tableData = await pageObjects.endpoint.getEndpointAppTableData('hostListTable'); expect(tableData).to.eql(expectedData); }); - it('no details flyout when host page displayed', async () => { + it('no details flyout when endpoint page displayed', async () => { await testSubjects.missingOrFail('hostDetailsFlyout'); }); @@ -108,22 +111,21 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await (await testSubjects.findAll('hostnameCellLink'))[1].click(); await sleep(500); // give page time to refresh and verify it did not change const hostDetailTitleNew = await testSubjects.getVisibleText('hostDetailsFlyoutTitle'); - expect(hostDetailTitleNew).to.eql(hostDetailTitleInitial); + expect(hostDetailTitleNew).to.equal(hostDetailTitleInitial); }); describe('no data', () => { before(async () => { // clear out the data and reload the page await esArchiver.unload('endpoint/metadata/api_feature'); - await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/hosts'); - await pageObjects.header.waitUntilLoadingHasFinished(); + await pageObjects.endpoint.navigateToEndpointList(); }); after(async () => { // reload the data so the other tests continue to pass await esArchiver.load('endpoint/metadata/api_feature'); }); it('displays no items found when empty', async () => { - // get the host list table data and verify message + // get the endpoint list table data and verify message const [, [noItemsFoundMessage]] = await pageObjects.endpoint.getEndpointAppTableData( 'hostListTable' ); @@ -133,12 +135,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('has a url with a host id', () => { before(async () => { - await pageObjects.common.navigateToUrlWithBrowserHistory( - 'endpoint', - '/hosts', + await pageObjects.endpoint.navigateToEndpointList( 'selected_host=fc0ff548-feba-41b6-8367-65e8790d0eaf' ); - await pageObjects.header.waitUntilLoadingHasFinished(); }); it('shows a flyout', async () => { @@ -168,7 +167,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { '', '0', '00000000-0000-0000-0000-000000000000', - 'Successful', + 'Unknown', '10.101.149.262606:a000:ffc0:39:11ef:37b9:3371:578c', 'rezzani-7.example.com', '6.8.0', diff --git a/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/endpoint_spaces.ts b/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/endpoint_spaces.ts deleted file mode 100644 index 27fabb515757a..0000000000000 --- a/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/endpoint_spaces.ts +++ /dev/null @@ -1,76 +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 expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getPageObjects, getService }: FtrProviderContext) { - const pageObjects = getPageObjects(['common']); - const spacesService = getService('spaces'); - const testSubjects = getService('testSubjects'); - const appsMenu = getService('appsMenu'); - - describe('spaces', () => { - describe('space with no features disabled', () => { - before(async () => { - await spacesService.create({ - id: 'custom_space', - name: 'custom_space', - disabledFeatures: [], - }); - }); - - after(async () => { - await spacesService.delete('custom_space'); - }); - - it('shows endpoint navlink', async () => { - await pageObjects.common.navigateToApp('home', { - basePath: '/s/custom_space', - }); - const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.contain('Endpoint'); - }); - - it(`endpoint app shows 'Hello World'`, async () => { - await pageObjects.common.navigateToApp('endpoint', { - basePath: '/s/custom_space', - }); - await testSubjects.existOrFail('welcomeTitle'); - }); - - it(`endpoint hosts shows hosts lists page`, async () => { - await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/hosts', undefined, { - basePath: '/s/custom_space', - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - }); - await testSubjects.existOrFail('hostPage'); - }); - }); - - describe('space with endpoint disabled', () => { - before(async () => { - await spacesService.create({ - id: 'custom_space', - name: 'custom_space', - disabledFeatures: ['endpoint'], - }); - }); - - after(async () => { - await spacesService.delete('custom_space'); - }); - - it(`doesn't show endpoint navlink`, async () => { - await pageObjects.common.navigateToApp('home', { - basePath: '/s/custom_space', - }); - const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).not.to.contain('Endpoint'); - }); - }); - }); -} diff --git a/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/index.ts b/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/index.ts deleted file mode 100644 index da0919d7c39f3..0000000000000 --- a/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/index.ts +++ /dev/null @@ -1,13 +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 { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('feature controls', function () { - this.tags('skipFirefox'); - loadTestFile(require.resolve('./endpoint_spaces')); - }); -} diff --git a/x-pack/test/functional_endpoint/apps/endpoint/header_nav.ts b/x-pack/test/functional_endpoint/apps/endpoint/header_nav.ts deleted file mode 100644 index 48cdd6aec5b1a..0000000000000 --- a/x-pack/test/functional_endpoint/apps/endpoint/header_nav.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default ({ getPageObjects, getService }: FtrProviderContext) => { - const pageObjects = getPageObjects(['common', 'endpoint']); - const testSubjects = getService('testSubjects'); - - describe('Header nav', function () { - this.tags('ciGroup7'); - before(async () => { - await pageObjects.common.navigateToApp('endpoint'); - }); - - it('renders the tabs when the app loads', async () => { - const homeTabText = await testSubjects.getVisibleText('homeEndpointTab'); - const hostsTabText = await testSubjects.getVisibleText('hostsEndpointTab'); - const alertsTabText = await testSubjects.getVisibleText('alertsEndpointTab'); - const policiesTabText = await testSubjects.getVisibleText('policiesEndpointTab'); - - expect(homeTabText.trim()).to.be('Home'); - expect(hostsTabText.trim()).to.be('Hosts'); - expect(alertsTabText.trim()).to.be('Alerts'); - expect(policiesTabText.trim()).to.be('Policies'); - }); - - it('renders the hosts page when the Hosts tab is selected', async () => { - await (await testSubjects.find('hostsEndpointTab')).click(); - await testSubjects.existOrFail('hostPage'); - }); - - it('renders the alerts page when the Alerts tab is selected', async () => { - await (await testSubjects.find('alertsEndpointTab')).click(); - await testSubjects.existOrFail('alertListPage'); - }); - - it('renders the policy page when Policy tab is selected', async () => { - await (await testSubjects.find('policiesEndpointTab')).click(); - await testSubjects.existOrFail('policyListPage'); - }); - - it('renders the home page when Home tab is selected after selecting another tab', async () => { - await (await testSubjects.find('hostsEndpointTab')).click(); - await testSubjects.existOrFail('hostPage'); - - await (await testSubjects.find('homeEndpointTab')).click(); - await testSubjects.existOrFail('welcomeTitle'); - }); - }); -}; diff --git a/x-pack/test/functional_endpoint/apps/endpoint/index.ts b/x-pack/test/functional_endpoint/apps/endpoint/index.ts index 296ee45ff181c..199d138d1c450 100644 --- a/x-pack/test/functional_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/functional_endpoint/apps/endpoint/index.ts @@ -9,12 +9,11 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('endpoint', function () { this.tags('ciGroup7'); - loadTestFile(require.resolve('./feature_controls')); - loadTestFile(require.resolve('./landing_page')); - loadTestFile(require.resolve('./header_nav')); - loadTestFile(require.resolve('./host_list')); + loadTestFile(require.resolve('./endpoint_list')); loadTestFile(require.resolve('./policy_list')); - loadTestFile(require.resolve('./alerts')); - loadTestFile(require.resolve('./resolver')); + loadTestFile(require.resolve('./policy_details')); + + // loadTestFile(require.resolve('./alerts')); + // loadTestFile(require.resolve('./resolver')); }); } diff --git a/x-pack/test/functional_endpoint/apps/endpoint/landing_page.ts b/x-pack/test/functional_endpoint/apps/endpoint/landing_page.ts deleted file mode 100644 index f2a55df56421a..0000000000000 --- a/x-pack/test/functional_endpoint/apps/endpoint/landing_page.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 expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default ({ getPageObjects, getService }: FtrProviderContext) => { - const pageObjects = getPageObjects(['common', 'endpoint']); - const testSubjects = getService('testSubjects'); - - describe('Endpoint landing page', function () { - this.tags('ciGroup7'); - before(async () => { - await pageObjects.common.navigateToApp('endpoint'); - }); - - it('Loads the endpoint app', async () => { - const welcomeEndpointMessage = await pageObjects.endpoint.welcomeEndpointTitle(); - expect(welcomeEndpointMessage).to.be('Hello World'); - }); - - it('Does not display a toast indicating that the ingest manager failed to initialize', async () => { - await testSubjects.missingOrFail('euiToastHeader'); - }); - }); -}; diff --git a/x-pack/test/functional_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/functional_endpoint/apps/endpoint/policy_details.ts new file mode 100644 index 0000000000000..25fb477b5a99a --- /dev/null +++ b/x-pack/test/functional_endpoint/apps/endpoint/policy_details.ts @@ -0,0 +1,225 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { PolicyTestResourceInfo } from '../../services/endpoint_policy'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const pageObjects = getPageObjects(['common', 'endpoint', 'policy', 'endpointPageUtils']); + const testSubjects = getService('testSubjects'); + const policyTestResources = getService('policyTestResources'); + + describe('When on the Endpoint Policy Details Page', function () { + this.tags(['ciGroup7']); + + describe('with an invalid policy id', () => { + it('should display an error', async () => { + await pageObjects.policy.navigateToPolicyDetails('invalid-id'); + await testSubjects.existOrFail('policyDetailsIdNotFoundMessage'); + expect(await testSubjects.getVisibleText('policyDetailsIdNotFoundMessage')).to.equal( + 'Saved object [ingest-datasources/invalid-id] not found' + ); + }); + }); + + describe('with a valid policy id', () => { + let policyInfo: PolicyTestResourceInfo; + + before(async () => { + policyInfo = await policyTestResources.createPolicy(); + await pageObjects.policy.navigateToPolicyDetails(policyInfo.datasource.id); + }); + + after(async () => { + if (policyInfo) { + await policyInfo.cleanup(); + } + }); + + it('should display policy view', async () => { + expect(await testSubjects.getVisibleText('pageViewHeaderLeftTitle')).to.equal( + policyInfo.datasource.name + ); + }); + }); + + describe('and the save button is clicked', () => { + let policyInfo: PolicyTestResourceInfo; + + beforeEach(async () => { + policyInfo = await policyTestResources.createPolicy(); + await pageObjects.policy.navigateToPolicyDetails(policyInfo.datasource.id); + }); + + afterEach(async () => { + if (policyInfo) { + await policyInfo.cleanup(); + } + }); + + it('should display success toast on successful save', async () => { + await pageObjects.endpointPageUtils.clickOnEuiCheckbox('policyWindowsEvent_dns'); + await pageObjects.policy.confirmAndSave(); + + await testSubjects.existOrFail('policyDetailsSuccessMessage'); + expect(await testSubjects.getVisibleText('policyDetailsSuccessMessage')).to.equal( + `Policy ${policyInfo.datasource.name} has been updated.` + ); + }); + it('should persist update on the screen', async () => { + await pageObjects.endpointPageUtils.clickOnEuiCheckbox('policyWindowsEvent_process'); + await pageObjects.policy.confirmAndSave(); + + await testSubjects.existOrFail('policyDetailsSuccessMessage'); + await pageObjects.policy.navigateToPolicyList(); + await pageObjects.policy.navigateToPolicyDetails(policyInfo.datasource.id); + + expect(await (await testSubjects.find('policyWindowsEvent_process')).isSelected()).to.equal( + false + ); + }); + it('should have updated policy data in overall agent configuration', async () => { + // This test ensures that updates made to the Endpoint Policy are carried all the way through + // to the generated Agent Configuration that is dispatch down to the Elastic Agent. + + await Promise.all([ + pageObjects.endpointPageUtils.clickOnEuiCheckbox('policyWindowsEvent_file'), + pageObjects.endpointPageUtils.clickOnEuiCheckbox('policyLinuxEvent_file'), + pageObjects.endpointPageUtils.clickOnEuiCheckbox('policyMacEvent_file'), + ]); + await pageObjects.policy.confirmAndSave(); + await testSubjects.existOrFail('policyDetailsSuccessMessage'); + + const agentFullConfig = await policyTestResources.getFullAgentConfig( + policyInfo.agentConfig.id + ); + + expect(agentFullConfig).to.eql({ + datasources: [ + { + enabled: true, + id: policyInfo.datasource.id, + inputs: [ + { + enabled: true, + policy: { + linux: { + advanced: { + elasticsearch: { + indices: { + control: 'control-index', + event: 'event-index', + logging: 'logging-index', + }, + kernel: { + connect: true, + process: true, + }, + }, + }, + events: { + file: false, + network: true, + process: true, + }, + logging: { + file: 'info', + stdout: 'debug', + }, + }, + mac: { + advanced: { + elasticsearch: { + indices: { + control: 'control-index', + event: 'event-index', + logging: 'logging-index', + }, + kernel: { + connect: true, + process: true, + }, + }, + }, + events: { + file: false, + network: true, + process: true, + }, + logging: { + file: 'info', + stdout: 'debug', + }, + malware: { + mode: 'detect', + }, + }, + windows: { + advanced: { + elasticsearch: { + indices: { + control: 'control-index', + event: 'event-index', + logging: 'logging-index', + }, + kernel: { + connect: true, + process: true, + }, + }, + }, + events: { + dll_and_driver_load: true, + dns: true, + file: false, + network: true, + process: true, + registry: true, + security: true, + }, + logging: { + file: 'info', + stdout: 'debug', + }, + malware: { + mode: 'prevent', + }, + }, + }, + streams: [], + type: 'endpoint', + }, + ], + name: 'Protect East Coast', + namespace: 'default', + package: { + name: 'endpoint', + version: policyInfo.packageInfo.version, + }, + use_output: 'default', + }, + ], + id: policyInfo.agentConfig.id, + outputs: { + default: { + hosts: ['http://localhost:9200'], + type: 'elasticsearch', + }, + }, + revision: 3, + settings: { + monitoring: { + enabled: false, + logs: false, + metrics: false, + }, + }, + }); + }); + }); + }); +} diff --git a/x-pack/test/functional_endpoint/apps/endpoint/policy_list.ts b/x-pack/test/functional_endpoint/apps/endpoint/policy_list.ts index 11b1b8e718ff7..9f87f884b327e 100644 --- a/x-pack/test/functional_endpoint/apps/endpoint/policy_list.ts +++ b/x-pack/test/functional_endpoint/apps/endpoint/policy_list.ts @@ -8,15 +8,15 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { PolicyTestResourceInfo } from '../../services/endpoint_policy'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const pageObjects = getPageObjects(['common', 'endpoint']); + const pageObjects = getPageObjects(['common', 'endpoint', 'policy']); const testSubjects = getService('testSubjects'); const policyTestResources = getService('policyTestResources'); + const RELATIVE_DATE_FORMAT = /\d (?:seconds|minutes) ago/i; - // FLAKY: https://github.com/elastic/kibana/issues/66579 - describe.skip('When on the Endpoint Policy List', function () { + describe('When on the Endpoint Policy List', function () { this.tags(['ciGroup7']); before(async () => { - await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/policy'); + await pageObjects.policy.navigateToPolicyList(); }); it('loads the Policy List Page', async () => { @@ -34,10 +34,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const allHeaderCells = await pageObjects.endpoint.tableHeaderVisibleText('policyTable'); expect(allHeaderCells).to.eql([ 'Policy Name', - 'Revision', + 'Created By', + 'Created Date', + 'Last Updated By', + 'Last Updated', 'Version', - 'Description', - 'Agent Configuration', + 'Actions', ]); }); it('should show empty table results message', async () => { @@ -47,13 +49,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(noItemsFoundMessage).to.equal('No items found'); }); - xdescribe('and policies exists', () => { + describe('and policies exists', () => { let policyInfo: PolicyTestResourceInfo; before(async () => { // load/create a policy and then navigate back to the policy view so that the list is refreshed policyInfo = await policyTestResources.createPolicy(); - await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/policy'); + await pageObjects.policy.navigateToPolicyList(); await pageObjects.endpoint.waitForTableToHaveData('policyTable'); }); after(async () => { @@ -64,26 +66,24 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should show policy on the list', async () => { const [, policyRow] = await pageObjects.endpoint.getEndpointAppTableData('policyTable'); - expect(policyRow).to.eql([ - 'Protect East Coast', - '1', - 'Elastic Endpoint v1.0.0', - 'Protect the worlds data - but in the East Coast', - policyInfo.agentConfig.id, + // Validate row data with the exception of the Date columns - since those are initially + // shown as relative. + expect([policyRow[0], policyRow[1], policyRow[3], policyRow[5], policyRow[6]]).to.eql([ + 'Protect East Coastrev. 1', + 'elastic', + 'elastic', + `${policyInfo.datasource.package?.title} v${policyInfo.datasource.package?.version}`, + '', ]); + [policyRow[2], policyRow[4]].forEach((relativeDate) => { + expect(relativeDate).to.match(RELATIVE_DATE_FORMAT); + }); }); it('should show policy name as link', async () => { const policyNameLink = await testSubjects.find('policyNameLink'); expect(await policyNameLink.getTagName()).to.equal('a'); expect(await policyNameLink.getAttribute('href')).to.match( - new RegExp(`\/endpoint\/policy\/${policyInfo.datasource.id}$`) - ); - }); - it('should show agent configuration as link', async () => { - const agentConfigLink = await testSubjects.find('agentConfigLink'); - expect(await agentConfigLink.getTagName()).to.equal('a'); - expect(await agentConfigLink.getAttribute('href')).to.match( - new RegExp(`\/app\/ingestManager\#\/configs\/${policyInfo.datasource.config_id}$`) + new RegExp(`\/management\/policy\/${policyInfo.datasource.id}$`) ); }); }); diff --git a/x-pack/test/functional_endpoint/page_objects/endpoint_page.ts b/x-pack/test/functional_endpoint/page_objects/endpoint_page.ts index 7f78bd6b804f7..3234169e7265e 100644 --- a/x-pack/test/functional_endpoint/page_objects/endpoint_page.ts +++ b/x-pack/test/functional_endpoint/page_objects/endpoint_page.ts @@ -7,11 +7,22 @@ import { WebElementWrapper } from 'test/functional/services/lib/web_element_wrapper'; import { FtrProviderContext } from '../ftr_provider_context'; -export function EndpointPageProvider({ getService }: FtrProviderContext) { +export function EndpointPageProvider({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects(['common', 'header']); const retry = getService('retry'); return { + /** + * Navigate to the Endpoints list page + */ + async navigateToEndpointList(searchParams?: string) { + await pageObjects.common.navigateToApp('securitySolution', { + hash: `/management/endpoints${searchParams ? `?${searchParams}` : ''}`, + }); + await pageObjects.header.waitUntilLoadingHasFinished(); + }, + /** * Finds the Table with the given `selector` (test subject) and returns * back an array containing the table's header column text @@ -31,10 +42,6 @@ export function EndpointPageProvider({ getService }: FtrProviderContext) { ); }, - async welcomeEndpointTitle() { - return await testSubjects.getVisibleText('welcomeTitle'); - }, - /** * Finds a table and returns the data in a nested array with row 0 is the headers if they exist. * It uses euiTableCellContent to avoid poluting the array data with the euiTableRowCell__mobileHeader data. diff --git a/x-pack/test/functional_endpoint/page_objects/index.ts b/x-pack/test/functional_endpoint/page_objects/index.ts index 8138ce2eeccb3..5b550bea5b55d 100644 --- a/x-pack/test/functional_endpoint/page_objects/index.ts +++ b/x-pack/test/functional_endpoint/page_objects/index.ts @@ -7,9 +7,13 @@ import { pageObjects as xpackFunctionalPageObjects } from '../../functional/page_objects'; import { EndpointPageProvider } from './endpoint_page'; import { EndpointAlertsPageProvider } from './endpoint_alerts_page'; +import { EndpointPolicyPageProvider } from './policy_page'; +import { EndpointPageUtils } from './page_utils'; export const pageObjects = { ...xpackFunctionalPageObjects, endpoint: EndpointPageProvider, + policy: EndpointPolicyPageProvider, + endpointPageUtils: EndpointPageUtils, endpointAlerts: EndpointAlertsPageProvider, }; diff --git a/x-pack/test/functional_endpoint/page_objects/page_utils.ts b/x-pack/test/functional_endpoint/page_objects/page_utils.ts new file mode 100644 index 0000000000000..daf66464f7e1e --- /dev/null +++ b/x-pack/test/functional_endpoint/page_objects/page_utils.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +export function EndpointPageUtils({ getService }: FtrProviderContext) { + const find = getService('find'); + + return { + /** + * Finds a given EuiCheckbox by test subject and clicks on it + * + * @param euiCheckBoxTestId + */ + async clickOnEuiCheckbox(euiCheckBoxTestId: string) { + // This utility is needed because EuiCheckbox forwards the test subject on to + // the actual `` which is not actually visible/accessible on the page. + // In order to actually cause the state of the checkbox to change, the `

@@ -19,7 +24,16 @@ exports[`CertStatus renders expected elements for valid props 1`] = ` class="euiFlexItem euiFlexItem--flexGrowZero" > - OK + OK +
+
+ for 4 months +
+
diff --git a/x-pack/plugins/uptime/public/components/certificates/cert_status.tsx b/x-pack/plugins/uptime/public/components/certificates/cert_status.tsx index e7a86ce98fa3c..ea0a49a4a6c5b 100644 --- a/x-pack/plugins/uptime/public/components/certificates/cert_status.tsx +++ b/x-pack/plugins/uptime/public/components/certificates/cert_status.tsx @@ -5,45 +5,95 @@ */ import React from 'react'; -import { EuiHealth } from '@elastic/eui'; +import moment from 'moment'; +import styled from 'styled-components'; +import { EuiHealth, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { useSelector } from 'react-redux'; import { Cert } from '../../../common/runtime_types'; import { useCertStatus } from '../../hooks'; import * as labels from './translations'; import { CERT_STATUS } from '../../../common/constants'; +import { selectDynamicSettings } from '../../state/selectors'; interface Props { cert: Cert; } +const DateText = styled(EuiText)` + display: inline-block; + margin-left: 5px; +`; + export const CertStatus: React.FC = ({ cert }) => { const certStatus = useCertStatus(cert?.not_after, cert?.not_before); + const dss = useSelector(selectDynamicSettings); + + const relativeDate = moment(cert?.not_after).fromNow(); + if (certStatus === CERT_STATUS.EXPIRING_SOON) { return ( - {labels.EXPIRES_SOON} + + {labels.EXPIRES_SOON} + {' '} + + {relativeDate} + + ); } if (certStatus === CERT_STATUS.EXPIRED) { return ( - {labels.EXPIRED} + + {labels.EXPIRED} + {' '} + + {relativeDate} + + ); } if (certStatus === CERT_STATUS.TOO_OLD) { + const ageThreshold = dss.settings?.certAgeThreshold; + + const oldRelativeDate = moment(cert?.not_before).add(ageThreshold, 'days').fromNow(); + return ( - {labels.TOO_OLD} + + {labels.TOO_OLD} + + {oldRelativeDate} + + ); } + const okRelativeDate = moment(cert?.not_after).fromNow(true); + return ( - {labels.OK} + + {labels.OK} + {' '} + + + + ); }; From ee5284e7fd6c04d24416fc04f8362c2bc0046982 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 9 Jun 2020 14:24:47 -0400 Subject: [PATCH 05/53] [Component templates] Table view (#68031) --- .../plugins/index_management/common/index.ts | 2 +- .../component_template_serialization.test.ts | 94 ++++++++ .../lib/component_template_serialization.ts | 86 ++++++++ .../index_management/common/lib/index.ts | 5 + .../common/types/component_templates.ts | 39 ++++ .../index_management/common/types/index.ts | 2 + .../common/types/templates.ts | 5 + .../public/application/app.tsx | 6 +- .../component_template_list.test.ts | 174 +++++++++++++++ .../component_template_list.helpers.ts | 95 ++++++++ .../helpers/http_requests.ts | 52 +++++ .../client_integration/helpers/index.ts | 15 ++ .../helpers/setup_environment.tsx | 45 ++++ .../component_template_list.tsx | 75 +++++++ .../component_template_list/delete_modal.tsx | 128 +++++++++++ .../component_template_list/empty_prompt.tsx | 43 ++++ .../component_template_list/error.tsx | 38 ++++ .../component_template_list/index.ts | 7 + .../component_template_list/table.tsx | 205 ++++++++++++++++++ .../component_templates_context.tsx | 63 ++++++ .../component_templates/constants.ts | 10 + .../components/component_templates/index.ts | 11 + .../components/component_templates/lib/api.ts | 44 ++++ .../component_templates/lib/documentation.ts | 16 ++ .../component_templates/lib/index.ts | 11 + .../component_templates/lib/request.ts | 31 +++ .../component_templates/shared_imports.ts | 15 ++ .../components/component_templates/types.ts | 17 ++ .../public/application/components/index.ts | 1 + .../public/application/index.tsx | 18 +- .../public/application/sections/home/home.tsx | 29 ++- .../public/application/sections/home/index.ts | 2 +- .../server/client/elasticsearch.ts | 11 + .../routes/api/component_templates/get.ts | 34 ++- .../index_management/component_templates.ts | 10 +- .../apps/index_management/home_page.ts | 17 ++ .../page_objects/index_management_page.ts | 2 +- 37 files changed, 1436 insertions(+), 22 deletions(-) create mode 100644 x-pack/plugins/index_management/common/lib/component_template_serialization.test.ts create mode 100644 x-pack/plugins/index_management/common/lib/component_template_serialization.ts create mode 100644 x-pack/plugins/index_management/common/types/component_templates.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/component_template_list.test.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/component_template_list.helpers.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/http_requests.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/delete_modal.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/error.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/index.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/constants.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/index.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/lib/index.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/lib/request.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/types.ts diff --git a/x-pack/plugins/index_management/common/index.ts b/x-pack/plugins/index_management/common/index.ts index 3792e322ae40b..4ad428744deab 100644 --- a/x-pack/plugins/index_management/common/index.ts +++ b/x-pack/plugins/index_management/common/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { PLUGIN, API_BASE_PATH, CREATE_LEGACY_TEMPLATE_BY_DEFAULT } from './constants'; +export { PLUGIN, API_BASE_PATH, CREATE_LEGACY_TEMPLATE_BY_DEFAULT, BASE_PATH } from './constants'; export { getTemplateParameter } from './lib'; diff --git a/x-pack/plugins/index_management/common/lib/component_template_serialization.test.ts b/x-pack/plugins/index_management/common/lib/component_template_serialization.test.ts new file mode 100644 index 0000000000000..eaa7f24017a2f --- /dev/null +++ b/x-pack/plugins/index_management/common/lib/component_template_serialization.test.ts @@ -0,0 +1,94 @@ +/* + * 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 { deserializeComponentTemplate } from './component_template_serialization'; + +describe('deserializeComponentTemplate', () => { + test('deserializes a component template', () => { + expect( + deserializeComponentTemplate( + { + name: 'my_component_template', + component_template: { + version: 1, + _meta: { + serialization: { + id: 10, + class: 'MyComponentTemplate', + }, + description: 'set number of shards to one', + }, + template: { + settings: { + number_of_shards: 1, + }, + mappings: { + _source: { + enabled: false, + }, + properties: { + host_name: { + type: 'keyword', + }, + created_at: { + type: 'date', + format: 'EEE MMM dd HH:mm:ss Z yyyy', + }, + }, + }, + }, + }, + }, + [ + { + name: 'my_index_template', + index_template: { + index_patterns: ['foo'], + template: { + settings: { + number_of_replicas: 2, + }, + }, + composed_of: ['my_component_template'], + }, + }, + ] + ) + ).toEqual({ + name: 'my_component_template', + version: 1, + _meta: { + serialization: { + id: 10, + class: 'MyComponentTemplate', + }, + description: 'set number of shards to one', + }, + template: { + settings: { + number_of_shards: 1, + }, + mappings: { + _source: { + enabled: false, + }, + properties: { + host_name: { + type: 'keyword', + }, + created_at: { + type: 'date', + format: 'EEE MMM dd HH:mm:ss Z yyyy', + }, + }, + }, + }, + _kbnMeta: { + usedBy: ['my_index_template'], + }, + }); + }); +}); diff --git a/x-pack/plugins/index_management/common/lib/component_template_serialization.ts b/x-pack/plugins/index_management/common/lib/component_template_serialization.ts new file mode 100644 index 0000000000000..0db81bf81d300 --- /dev/null +++ b/x-pack/plugins/index_management/common/lib/component_template_serialization.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { + TemplateFromEs, + ComponentTemplateFromEs, + ComponentTemplateDeserialized, + ComponentTemplateListItem, +} from '../types'; + +const hasEntries = (data: object = {}) => Object.entries(data).length > 0; + +/** + * Normalize a list of component templates to a map where each key + * is a component template name, and the value is an array of index templates name using it + * + * @example + * + { + "comp-1": [ + "template-1", + "template-2" + ], + "comp2": [ + "template-1", + "template-2" + ] + } + * + * @param indexTemplatesEs List of component templates + */ + +const getIndexTemplatesToUsedBy = (indexTemplatesEs: TemplateFromEs[]) => { + return indexTemplatesEs.reduce((acc, item) => { + if (item.index_template.composed_of) { + item.index_template.composed_of.forEach((component) => { + acc[component] = acc[component] ? [...acc[component], item.name] : [item.name]; + }); + } + return acc; + }, {} as { [key: string]: string[] }); +}; + +export function deserializeComponentTemplate( + componentTemplateEs: ComponentTemplateFromEs, + indexTemplatesEs: TemplateFromEs[] +) { + const { name, component_template: componentTemplate } = componentTemplateEs; + const { template, _meta, version } = componentTemplate; + + const indexTemplatesToUsedBy = getIndexTemplatesToUsedBy(indexTemplatesEs); + + const deserializedComponentTemplate: ComponentTemplateDeserialized = { + name, + template, + version, + _meta, + _kbnMeta: { + usedBy: indexTemplatesToUsedBy[name] || [], + }, + }; + + return deserializedComponentTemplate; +} + +export function deserializeComponenTemplateList( + componentTemplateEs: ComponentTemplateFromEs, + indexTemplatesEs: TemplateFromEs[] +) { + const { name, component_template: componentTemplate } = componentTemplateEs; + const { template } = componentTemplate; + + const indexTemplatesToUsedBy = getIndexTemplatesToUsedBy(indexTemplatesEs); + + const componentTemplateListItem: ComponentTemplateListItem = { + name, + usedBy: indexTemplatesToUsedBy[name] || [], + hasSettings: hasEntries(template.settings), + hasMappings: hasEntries(template.mappings), + hasAliases: hasEntries(template.aliases), + }; + + return componentTemplateListItem; +} diff --git a/x-pack/plugins/index_management/common/lib/index.ts b/x-pack/plugins/index_management/common/lib/index.ts index 16eb544c56a08..c67d28da2c24b 100644 --- a/x-pack/plugins/index_management/common/lib/index.ts +++ b/x-pack/plugins/index_management/common/lib/index.ts @@ -11,3 +11,8 @@ export { } from './template_serialization'; export { getTemplateParameter } from './utils'; + +export { + deserializeComponentTemplate, + deserializeComponenTemplateList, +} from './component_template_serialization'; diff --git a/x-pack/plugins/index_management/common/types/component_templates.ts b/x-pack/plugins/index_management/common/types/component_templates.ts new file mode 100644 index 0000000000000..bc7ebdc2753dd --- /dev/null +++ b/x-pack/plugins/index_management/common/types/component_templates.ts @@ -0,0 +1,39 @@ +/* + * 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 { IndexSettings } from './indices'; +import { Aliases } from './aliases'; +import { Mappings } from './mappings'; + +export interface ComponentTemplateSerialized { + template: { + settings?: IndexSettings; + aliases?: Aliases; + mappings?: Mappings; + }; + version?: number; + _meta?: { [key: string]: any }; +} + +export interface ComponentTemplateDeserialized extends ComponentTemplateSerialized { + name: string; + _kbnMeta: { + usedBy: string[]; + }; +} + +export interface ComponentTemplateFromEs { + name: string; + component_template: ComponentTemplateSerialized; +} + +export interface ComponentTemplateListItem { + name: string; + usedBy: string[]; + hasMappings: boolean; + hasAliases: boolean; + hasSettings: boolean; +} diff --git a/x-pack/plugins/index_management/common/types/index.ts b/x-pack/plugins/index_management/common/types/index.ts index b467f020978a5..81a06156dd291 100644 --- a/x-pack/plugins/index_management/common/types/index.ts +++ b/x-pack/plugins/index_management/common/types/index.ts @@ -11,3 +11,5 @@ export * from './indices'; export * from './mappings'; export * from './templates'; + +export * from './component_templates'; diff --git a/x-pack/plugins/index_management/common/types/templates.ts b/x-pack/plugins/index_management/common/types/templates.ts index f113aa44d058f..006a2d9dea8f2 100644 --- a/x-pack/plugins/index_management/common/types/templates.ts +++ b/x-pack/plugins/index_management/common/types/templates.ts @@ -49,6 +49,11 @@ export interface TemplateDeserialized { }; } +export interface TemplateFromEs { + name: string; + index_template: TemplateSerialized; +} + /** * Interface for the template list in our UI table * we don't include the mappings, settings and aliases diff --git a/x-pack/plugins/index_management/public/application/app.tsx b/x-pack/plugins/index_management/public/application/app.tsx index 10bbe3ced64da..bfd99de6949e5 100644 --- a/x-pack/plugins/index_management/public/application/app.tsx +++ b/x-pack/plugins/index_management/public/application/app.tsx @@ -5,10 +5,12 @@ */ import React, { useEffect } from 'react'; + import { Router, Switch, Route, Redirect } from 'react-router-dom'; import { ScopedHistory } from 'kibana/public'; + import { UIM_APP_LOAD } from '../../common/constants'; -import { IndexManagementHome } from './sections/home'; +import { IndexManagementHome, homeSections } from './sections/home'; import { TemplateCreate } from './sections/template_create'; import { TemplateClone } from './sections/template_clone'; import { TemplateEdit } from './sections/template_edit'; @@ -32,7 +34,7 @@ export const AppWithoutRouter = () => ( - + ); diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/component_template_list.test.ts b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/component_template_list.test.ts new file mode 100644 index 0000000000000..830cc0ee6a980 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/component_template_list.test.ts @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { act } from 'react-dom/test-utils'; + +import { setupEnvironment, pageHelpers } from './helpers'; +import { ComponentTemplateListTestBed } from './helpers/component_template_list.helpers'; +import { API_BASE_PATH } from '../../../../../../common/constants'; +import { ComponentTemplateListItem } from '../../types'; + +const { setup } = pageHelpers.componentTemplateList; + +jest.mock('ui/i18n', () => { + const I18nContext = ({ children }: any) => children; + return { I18nContext }; +}); + +describe('', () => { + const { server, httpRequestsMockHelpers } = setupEnvironment(); + let testBed: ComponentTemplateListTestBed; + + afterAll(() => { + server.restore(); + }); + + beforeEach(async () => { + await act(async () => { + testBed = await setup(); + }); + + testBed.component.update(); + }); + + describe('With component templates', () => { + const componentTemplate1: ComponentTemplateListItem = { + name: 'test_component_template_1', + hasMappings: true, + hasAliases: true, + hasSettings: true, + usedBy: [], + }; + + const componentTemplate2: ComponentTemplateListItem = { + name: 'test_component_template_2', + hasMappings: true, + hasAliases: true, + hasSettings: true, + usedBy: ['test_index_template_1'], + }; + + const componentTemplates = [componentTemplate1, componentTemplate2]; + + httpRequestsMockHelpers.setLoadComponentTemplatesResponse(componentTemplates); + + test('should render the list view', async () => { + const { table } = testBed; + + // Verify table content + const { tableCellsValues } = table.getMetaData('componentTemplatesTable'); + tableCellsValues.forEach((row, i) => { + const { name, usedBy } = componentTemplates[i]; + const usedByText = usedBy.length === 0 ? 'Not in use' : usedBy.length.toString(); + + expect(row).toEqual(['', name, usedByText, '', '', '', '']); + }); + }); + + test('should reload the component templates data', async () => { + const { component, actions } = testBed; + const totalRequests = server.requests.length; + + await act(async () => { + actions.clickReloadButton(); + }); + + component.update(); + + expect(server.requests.length).toBe(totalRequests + 1); + expect(server.requests[server.requests.length - 1].url).toBe( + `${API_BASE_PATH}/component_templates` + ); + }); + + test('should delete a component template', async () => { + const { actions, component } = testBed; + const { name: componentTemplateName } = componentTemplate1; + + await act(async () => { + actions.clickDeleteActionAt(0); + }); + + // We need to read the document "body" as the modal is added there and not inside + // the component DOM tree. + const modal = document.body.querySelector( + '[data-test-subj="deleteComponentTemplatesConfirmation"]' + ); + const confirmButton: HTMLButtonElement | null = modal!.querySelector( + '[data-test-subj="confirmModalConfirmButton"]' + ); + + expect(modal).not.toBe(null); + expect(modal!.textContent).toContain('Delete component template'); + + httpRequestsMockHelpers.setDeleteComponentTemplateResponse({ + itemsDeleted: [componentTemplateName], + errors: [], + }); + + await act(async () => { + confirmButton!.click(); + }); + + component.update(); + + const deleteRequest = server.requests[server.requests.length - 2]; + + expect(deleteRequest.method).toBe('DELETE'); + expect(deleteRequest.url).toBe( + `${API_BASE_PATH}/component_templates/${componentTemplateName}` + ); + expect(deleteRequest.status).toEqual(200); + }); + }); + + describe('No component templates', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadComponentTemplatesResponse([]); + + await act(async () => { + testBed = await setup(); + }); + + testBed.component.update(); + }); + + test('should display an empty prompt', async () => { + const { exists, find } = testBed; + + expect(exists('sectionLoading')).toBe(false); + expect(exists('emptyList')).toBe(true); + expect(find('emptyList.title').text()).toEqual('Start by creating a component template'); + }); + }); + + describe('Error handling', () => { + beforeEach(async () => { + const error = { + status: 500, + error: 'Internal server error', + message: 'Internal server error', + }; + + httpRequestsMockHelpers.setLoadComponentTemplatesResponse(undefined, { body: error }); + + await act(async () => { + testBed = await setup(); + }); + + testBed.component.update(); + }); + + test('should render an error message if error fetching component templates', async () => { + const { exists, find } = testBed; + + expect(exists('componentTemplatesLoadError')).toBe(true); + expect(find('componentTemplatesLoadError').text()).toContain( + 'Unable to load component templates. Try again.' + ); + }); + }); +}); diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/component_template_list.helpers.ts b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/component_template_list.helpers.ts new file mode 100644 index 0000000000000..8fb4dcff0bcea --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/component_template_list.helpers.ts @@ -0,0 +1,95 @@ +/* + * 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 { act } from 'react-dom/test-utils'; + +import { BASE_PATH } from '../../../../../../../common'; +import { + registerTestBed, + TestBed, + TestBedConfig, + findTestSubject, + nextTick, +} from '../../../../../../../../../test_utils'; +import { WithAppDependencies } from './setup_environment'; +import { ComponentTemplateList } from '../../../component_template_list'; + +const testBedConfig: TestBedConfig = { + memoryRouter: { + initialEntries: [`${BASE_PATH}component_templates`], + componentRoutePath: `${BASE_PATH}component_templates`, + }, + doMountAsync: true, +}; + +const initTestBed = registerTestBed(WithAppDependencies(ComponentTemplateList), testBedConfig); + +export type ComponentTemplateListTestBed = TestBed & { + actions: ReturnType; +}; + +const createActions = (testBed: TestBed) => { + const { find } = testBed; + + /** + * User Actions + */ + const clickReloadButton = () => { + find('reloadButton').simulate('click'); + }; + + const clickComponentTemplateAt = async (index: number) => { + const { component, table, router } = testBed; + const { rows } = table.getMetaData('componentTemplatesTable'); + const componentTemplateLink = findTestSubject( + rows[index].reactWrapper, + 'componentTemplateDetailsLink' + ); + + await act(async () => { + const { href } = componentTemplateLink.props(); + router.navigateTo(href!); + await nextTick(); + component.update(); + }); + }; + + const clickDeleteActionAt = (index: number) => { + const { table } = testBed; + + const { rows } = table.getMetaData('componentTemplatesTable'); + const deleteButton = findTestSubject(rows[index].reactWrapper, 'deleteComponentTemplateButton'); + + deleteButton.simulate('click'); + }; + + return { + clickReloadButton, + clickComponentTemplateAt, + clickDeleteActionAt, + }; +}; + +export const setup = async (): Promise => { + const testBed = await initTestBed(); + + return { + ...testBed, + actions: createActions(testBed), + }; +}; + +export type ComponentTemplateTestSubjects = + | 'componentTemplatesTable' + | 'componentTemplateDetails' + | 'componentTemplateDetails.title' + | 'deleteComponentTemplatesConfirmation' + | 'emptyList' + | 'emptyList.title' + | 'sectionLoading' + | 'componentTemplatesLoadError' + | 'deleteComponentTemplateButton' + | 'reloadButton'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/http_requests.ts new file mode 100644 index 0000000000000..8473041ee0af3 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/http_requests.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import sinon, { SinonFakeServer } from 'sinon'; +import { API_BASE_PATH } from '../../../../../../../common'; + +// Register helpers to mock HTTP Requests +const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { + const setLoadComponentTemplatesResponse = (response?: any[], error?: any) => { + const status = error ? error.status || 400 : 200; + const body = error ? error.body : response; + + server.respondWith('GET', `${API_BASE_PATH}/component_templates`, [ + status, + { 'Content-Type': 'application/json' }, + JSON.stringify(body), + ]); + }; + + const setDeleteComponentTemplateResponse = (response?: object) => { + server.respondWith('DELETE', `${API_BASE_PATH}/component_templates/:name`, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(response), + ]); + }; + + return { + setLoadComponentTemplatesResponse, + setDeleteComponentTemplateResponse, + }; +}; + +export const init = () => { + const server = sinon.fakeServer.create(); + server.respondImmediately = true; + + // Define default response for unhandled requests. + // We make requests to APIs which don't impact the component under test, e.g. UI metric telemetry, + // and we can mock them all with a 200 instead of mocking each one individually. + server.respondWith([200, {}, 'DefaultMockedResponse']); + + const httpRequestsMockHelpers = registerHttpRequestMockHelpers(server); + + return { + server, + httpRequestsMockHelpers, + }; +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts new file mode 100644 index 0000000000000..c1d75b3c2dd9b --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { setup as componentTemplatesListSetup } from './component_template_list.helpers'; + +export { nextTick, getRandomString, findTestSubject } from '../../../../../../../../../test_utils'; + +export { setupEnvironment } from './setup_environment'; + +export const pageHelpers = { + componentTemplateList: { setup: componentTemplatesListSetup }, +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx new file mode 100644 index 0000000000000..c0aeb70166b5b --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/__jest__/client_integration/helpers/setup_environment.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @kbn/eslint/no-restricted-paths */ +import React from 'react'; +import axios from 'axios'; +import axiosXhrAdapter from 'axios/lib/adapters/xhr'; + +import { HttpSetup } from 'kibana/public'; +import { BASE_PATH, API_BASE_PATH } from '../../../../../../../common/constants'; +import { + notificationServiceMock, + docLinksServiceMock, +} from '../../../../../../../../../../src/core/public/mocks'; + +import { init as initHttpRequests } from './http_requests'; +import { ComponentTemplatesProvider } from '../../../component_templates_context'; + +const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); + +const appDependencies = { + httpClient: (mockHttpClient as unknown) as HttpSetup, + apiBasePath: API_BASE_PATH, + appBasePath: BASE_PATH, + trackMetric: () => {}, + docLinks: docLinksServiceMock.createStartContract(), + toasts: notificationServiceMock.createSetupContract().toasts, +}; + +export const setupEnvironment = () => { + const { server, httpRequestsMockHelpers } = initHttpRequests(); + + return { + server, + httpRequestsMockHelpers, + }; +}; + +export const WithAppDependencies = (Comp: any) => (props: any) => ( + + + +); diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx new file mode 100644 index 0000000000000..41fa608ef538b --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useEffect } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { SectionLoading } from '../shared_imports'; +import { useComponentTemplatesContext } from '../component_templates_context'; +import { UIM_COMPONENT_TEMPLATE_LIST_LOAD } from '../constants'; + +import { EmptyPrompt } from './empty_prompt'; +import { ComponentTable } from './table'; +import { LoadError } from './error'; +import { ComponentTemplatesDeleteModal } from './delete_modal'; + +export const ComponentTemplateList: React.FunctionComponent = () => { + const { api, trackMetric } = useComponentTemplatesContext(); + + const { data, isLoading, error, sendRequest } = api.useLoadComponentTemplates(); + + const [componentTemplatesToDelete, setComponentTemplatesToDelete] = useState([]); + + // Track component loaded + useEffect(() => { + trackMetric('loaded', UIM_COMPONENT_TEMPLATE_LIST_LOAD); + }, [trackMetric]); + + if (data && data.length === 0) { + return ; + } + + let content: React.ReactNode; + + if (isLoading) { + content = ( + + + + ); + } else if (data?.length) { + content = ( + + ); + } else if (error) { + content = ; + } + + return ( +
+ {content} + {componentTemplatesToDelete?.length > 0 ? ( + { + if (deleteResponse?.hasDeletedComponentTemplates) { + // refetch the component templates + sendRequest(); + } + setComponentTemplatesToDelete([]); + }} + componentTemplatesToDelete={componentTemplatesToDelete} + /> + ) : null} +
+ ); +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/delete_modal.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/delete_modal.tsx new file mode 100644 index 0000000000000..bf621065842b5 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/delete_modal.tsx @@ -0,0 +1,128 @@ +/* + * 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 { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { useComponentTemplatesContext } from '../component_templates_context'; + +export const ComponentTemplatesDeleteModal = ({ + componentTemplatesToDelete, + callback, +}: { + componentTemplatesToDelete: string[]; + callback: (data?: { hasDeletedComponentTemplates: boolean }) => void; +}) => { + const { toasts, api } = useComponentTemplatesContext(); + const numComponentTemplatesToDelete = componentTemplatesToDelete.length; + + const handleDeleteComponentTemplates = () => { + api + .deleteComponentTemplates(componentTemplatesToDelete) + .then(({ data: { itemsDeleted, errors }, error }) => { + const hasDeletedComponentTemplates = itemsDeleted && itemsDeleted.length; + + if (hasDeletedComponentTemplates) { + const successMessage = + itemsDeleted.length === 1 + ? i18n.translate( + 'xpack.idxMgmt.home.componentTemplates.deleteModal.successDeleteSingleNotificationMessageText', + { + defaultMessage: "Deleted component template '{componentTemplateName}'", + values: { componentTemplateName: componentTemplatesToDelete[0] }, + } + ) + : i18n.translate( + 'xpack.idxMgmt.home.componentTemplates.deleteModal.successDeleteMultipleNotificationMessageText', + { + defaultMessage: + 'Deleted {numSuccesses, plural, one {# component template} other {# component templates}}', + values: { numSuccesses: itemsDeleted.length }, + } + ); + + callback({ hasDeletedComponentTemplates }); + toasts.addSuccess(successMessage); + } + + if (error || errors?.length) { + const hasMultipleErrors = + errors?.length > 1 || (error && componentTemplatesToDelete.length > 1); + const errorMessage = hasMultipleErrors + ? i18n.translate( + 'xpack.idxMgmt.home.componentTemplates.deleteModal.multipleErrorsNotificationMessageText', + { + defaultMessage: 'Error deleting {count} component templates', + values: { + count: errors?.length || componentTemplatesToDelete.length, + }, + } + ) + : i18n.translate( + 'xpack.idxMgmt.home.componentTemplates.deleteModal.errorNotificationMessageText', + { + defaultMessage: "Error deleting component template '{name}'", + values: { name: (errors && errors[0].name) || componentTemplatesToDelete[0] }, + } + ); + toasts.addDanger(errorMessage); + } + }); + }; + + const handleOnCancel = () => { + callback(); + }; + + return ( + + + } + onCancel={handleOnCancel} + onConfirm={handleDeleteComponentTemplates} + cancelButtonText={ + + } + confirmButtonText={ + + } + > + <> +

+ +

+ +
    + {componentTemplatesToDelete.map((name) => ( +
  • {name}
  • + ))} +
+ +
+
+ ); +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx new file mode 100644 index 0000000000000..edd9f77cbf635 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiEmptyPrompt, EuiLink } from '@elastic/eui'; + +import { useComponentTemplatesContext } from '../component_templates_context'; + +export const EmptyPrompt: FunctionComponent = () => { + const { documentation } = useComponentTemplatesContext(); + + return ( + + {i18n.translate('xpack.idxMgmt.home.componentTemplates.emptyPromptTitle', { + defaultMessage: 'Start by creating a component template', + })} + + } + body={ +

+ +
+ + {i18n.translate('xpack.idxMgmt.home.componentTemplates.emptyPromptDocumentionLink', { + defaultMessage: 'Learn more', + })} + +

+ } + /> + ); +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/error.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/error.tsx new file mode 100644 index 0000000000000..aa37b9ce5767c --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/error.tsx @@ -0,0 +1,38 @@ +/* + * 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, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiLink, EuiCallOut } from '@elastic/eui'; + +export interface Props { + onReloadClick: () => void; +} + +export const LoadError: FunctionComponent = ({ onReloadClick }) => { + return ( + + + + ), + }} + /> + } + /> + ); +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/index.ts new file mode 100644 index 0000000000000..84ee48d14bb8c --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/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 { ComponentTemplateList } from './component_template_list'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx new file mode 100644 index 0000000000000..2d9557e64e6e7 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx @@ -0,0 +1,205 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { FunctionComponent, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiInMemoryTable, + EuiButton, + EuiInMemoryTableProps, + EuiTextColor, + EuiIcon, +} from '@elastic/eui'; + +import { ComponentTemplateListItem } from '../types'; + +export interface Props { + componentTemplates: ComponentTemplateListItem[]; + onReloadClick: () => void; + onDeleteClick: (componentTemplateName: string[]) => void; +} + +export const ComponentTable: FunctionComponent = ({ + componentTemplates, + onReloadClick, + onDeleteClick, +}) => { + const [selection, setSelection] = useState([]); + + const tableProps: EuiInMemoryTableProps = { + itemId: 'name', + isSelectable: true, + 'data-test-subj': 'componentTemplatesTable', + sorting: { sort: { field: 'name', direction: 'asc' } }, + selection: { + onSelectionChange: setSelection, + selectable: ({ usedBy }) => usedBy.length === 0, + selectableMessage: (selectable) => + selectable + ? i18n.translate('xpack.idxMgmt.componentTemplatesList.table.selectionLabel', { + defaultMessage: 'Select this component template', + }) + : i18n.translate('xpack.idxMgmt.componentTemplatesList.table.disabledSelectionLabel', { + defaultMessage: 'Component template is in use and cannot be deleted', + }), + }, + rowProps: () => ({ + 'data-test-subj': 'componentTemplateTableRow', + }), + search: { + toolsLeft: + selection.length > 0 ? ( + onDeleteClick(selection.map(({ name }) => name))} + color="danger" + > + + + ) : undefined, + toolsRight: [ + + {i18n.translate('xpack.idxMgmt.componentTemplatesList.table.reloadButtonLabel', { + defaultMessage: 'Reload', + })} + , + ], + box: { + incremental: true, + }, + filters: [ + { + type: 'field_value_toggle_group', + field: 'usedBy.length', + items: [ + { + value: 1, + name: i18n.translate( + 'xpack.idxMgmt.componentTemplatesList.table.inUseFilterOptionLabel', + { + defaultMessage: 'In use', + } + ), + operator: 'gte', + }, + { + value: 0, + name: i18n.translate( + 'xpack.idxMgmt.componentTemplatesList.table.notInUseFilterOptionLabel', + { + defaultMessage: 'Not in use', + } + ), + operator: 'eq', + }, + ], + }, + ], + }, + pagination: { + initialPageSize: 10, + pageSizeOptions: [10, 20, 50], + }, + columns: [ + { + field: 'name', + name: i18n.translate('xpack.idxMgmt.componentTemplatesList.table.nameColumnTitle', { + defaultMessage: 'Name', + }), + sortable: true, + }, + { + field: 'usedBy', + name: i18n.translate('xpack.idxMgmt.componentTemplatesList.table.isInUseColumnTitle', { + defaultMessage: 'Index templates', + }), + sortable: true, + render: (usedBy: string[]) => { + if (usedBy.length) { + return usedBy.length; + } + + return ( + + + + + + ); + }, + }, + { + field: 'hasMappings', + name: i18n.translate('xpack.idxMgmt.componentTemplatesList.table.mappingsColumnTitle', { + defaultMessage: 'Mappings', + }), + truncateText: true, + sortable: true, + render: (hasMappings: boolean) => (hasMappings ? : null), + }, + { + field: 'hasSettings', + name: i18n.translate('xpack.idxMgmt.componentTemplatesList.table.settingsColumnTitle', { + defaultMessage: 'Settings', + }), + truncateText: true, + sortable: true, + render: (hasSettings: boolean) => (hasSettings ? : null), + }, + { + field: 'hasAliases', + name: i18n.translate('xpack.idxMgmt.componentTemplatesList.table.aliasesColumnTitle', { + defaultMessage: 'Aliases', + }), + truncateText: true, + sortable: true, + render: (hasAliases: boolean) => (hasAliases ? : null), + }, + { + name: ( + + ), + actions: [ + { + 'data-test-subj': 'deleteComponentTemplateButton', + isPrimary: true, + name: i18n.translate('xpack.idxMgmt.componentTemplatesList.table.deleteActionLabel', { + defaultMessage: 'Delete', + }), + description: i18n.translate( + 'xpack.idxMgmt.componentTemplatesList.table.deleteActionDescription', + { defaultMessage: 'Delete this component template' } + ), + type: 'icon', + icon: 'trash', + color: 'danger', + onClick: ({ name }) => onDeleteClick([name]), + enabled: ({ usedBy }) => usedBy.length === 0, + }, + ], + }, + ], + items: componentTemplates ?? [], + }; + + return ; +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx new file mode 100644 index 0000000000000..6f5f5bdebd6d0 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx @@ -0,0 +1,63 @@ +/* + * 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, { createContext, useContext } from 'react'; +import { HttpSetup, DocLinksSetup, NotificationsSetup } from 'src/core/public'; + +import { getApi, getUseRequest, getSendRequest, getDocumentation } from './lib'; + +const ComponentTemplatesContext = createContext(undefined); + +interface Props { + httpClient: HttpSetup; + apiBasePath: string; + appBasePath: string; + trackMetric: (type: 'loaded' | 'click' | 'count', eventName: string) => void; + docLinks: DocLinksSetup; + toasts: NotificationsSetup['toasts']; +} + +interface Context { + api: ReturnType; + documentation: ReturnType; + trackMetric: (type: 'loaded' | 'click' | 'count', eventName: string) => void; + toasts: NotificationsSetup['toasts']; + appBasePath: string; +} + +export const ComponentTemplatesProvider = ({ + children, + value, +}: { + value: Props; + children: React.ReactNode; +}) => { + const { httpClient, apiBasePath, trackMetric, docLinks, toasts, appBasePath } = value; + + const useRequest = getUseRequest(httpClient); + const sendRequest = getSendRequest(httpClient); + + const api = getApi(useRequest, sendRequest, apiBasePath, trackMetric); + const documentation = getDocumentation(docLinks); + + return ( + + {children} + + ); +}; + +export const useComponentTemplatesContext = () => { + const ctx = useContext(ComponentTemplatesContext); + if (!ctx) { + throw new Error( + '"useComponentTemplatesContext" can only be called inside of ComponentTemplatesProvider!' + ); + } + return ctx; +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/constants.ts b/x-pack/plugins/index_management/public/application/components/component_templates/constants.ts new file mode 100644 index 0000000000000..3e763119fa9fb --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/constants.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +// ui metric constants +export const UIM_COMPONENT_TEMPLATE_LIST_LOAD = 'component_template_list_load'; +export const UIM_COMPONENT_TEMPLATE_DELETE = 'component_template_delete'; +export const UIM_COMPONENT_TEMPLATE_DELETE_MANY = 'component_template_delete_many'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/index.ts new file mode 100644 index 0000000000000..e0219ec71787f --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { ComponentTemplatesProvider } from './component_templates_context'; + +export { ComponentTemplateList } from './component_template_list'; + +export * from './types'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts b/x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts new file mode 100644 index 0000000000000..351e83c6c0cb5 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts @@ -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 { ComponentTemplateListItem } from '../types'; +import { UseRequestHook, SendRequestHook } from './request'; +import { UIM_COMPONENT_TEMPLATE_DELETE_MANY, UIM_COMPONENT_TEMPLATE_DELETE } from '../constants'; + +export const getApi = ( + useRequest: UseRequestHook, + sendRequest: SendRequestHook, + apiBasePath: string, + trackMetric: (type: 'loaded' | 'click' | 'count', eventName: string) => void +) => { + function useLoadComponentTemplates() { + return useRequest({ + path: `${apiBasePath}/component_templates`, + method: 'get', + }); + } + + function deleteComponentTemplates(names: string[]) { + const result = sendRequest({ + path: `${apiBasePath}/component_templates/${names + .map((name) => encodeURIComponent(name)) + .join(',')}`, + method: 'delete', + }); + + trackMetric( + 'count', + names.length > 1 ? UIM_COMPONENT_TEMPLATE_DELETE_MANY : UIM_COMPONENT_TEMPLATE_DELETE + ); + + return result; + } + + return { + useLoadComponentTemplates, + deleteComponentTemplates, + }; +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts b/x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts new file mode 100644 index 0000000000000..dc27dadf0b807 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DocLinksSetup } from 'src/core/public'; + +export const getDocumentation = ({ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }: DocLinksSetup) => { + const docsBase = `${ELASTIC_WEBSITE_URL}guide/en`; + const esDocsBase = `${docsBase}/elasticsearch/reference/${DOC_LINK_VERSION}`; + + return { + componentTemplates: `${esDocsBase}/indices-component-template.html`, + }; +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/lib/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/lib/index.ts new file mode 100644 index 0000000000000..9a91312f83294 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/lib/index.ts @@ -0,0 +1,11 @@ +/* + * 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 './api'; + +export * from './request'; + +export * from './documentation'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/lib/request.ts b/x-pack/plugins/index_management/public/application/components/component_templates/lib/request.ts new file mode 100644 index 0000000000000..97ffa4d875ecb --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/lib/request.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. + */ + +import { HttpSetup } from 'src/core/public'; + +import { + UseRequestConfig, + UseRequestResponse, + SendRequestConfig, + SendRequestResponse, + sendRequest as _sendRequest, + useRequest as _useRequest, +} from '../shared_imports'; + +export type UseRequestHook = (config: UseRequestConfig) => UseRequestResponse; +export type SendRequestHook = (config: SendRequestConfig) => Promise; + +export const getUseRequest = (httpClient: HttpSetup): UseRequestHook => ( + config: UseRequestConfig +) => { + return _useRequest(httpClient, config); +}; + +export const getSendRequest = (httpClient: HttpSetup): SendRequestHook => ( + config: SendRequestConfig +) => { + return _sendRequest(httpClient, config); +}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts b/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts new file mode 100644 index 0000000000000..863b00b353c49 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { + UseRequestConfig, + UseRequestResponse, + SendRequestConfig, + SendRequestResponse, + sendRequest, + useRequest, + SectionLoading, +} from '../../../../../../../src/plugins/es_ui_shared/public'; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/types.ts b/x-pack/plugins/index_management/public/application/components/component_templates/types.ts new file mode 100644 index 0000000000000..0aab3b6b0a94a --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/component_templates/types.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. + */ + +// Ideally, we shouldn't depend on anything in index management that is +// outside of the components_templates directory +// We could consider creating shared types or duplicating the types here if +// the component_templates app were to move outside of index management +import { + ComponentTemplateSerialized, + ComponentTemplateDeserialized, + ComponentTemplateListItem, +} from '../../../../common'; + +export { ComponentTemplateSerialized, ComponentTemplateDeserialized, ComponentTemplateListItem }; diff --git a/x-pack/plugins/index_management/public/application/components/index.ts b/x-pack/plugins/index_management/public/application/components/index.ts index e6d836c0d0501..7ec25ed5583b7 100644 --- a/x-pack/plugins/index_management/public/application/components/index.ts +++ b/x-pack/plugins/index_management/public/application/components/index.ts @@ -11,3 +11,4 @@ export { PageErrorForbidden } from './page_error'; export { TemplateDeleteModal } from './template_delete_modal'; export { TemplateForm } from './template_form'; export * from './mappings_editor'; +export * from './component_templates'; diff --git a/x-pack/plugins/index_management/public/application/index.tsx b/x-pack/plugins/index_management/public/application/index.tsx index 8da556cc81fcc..5d1096c9ee24e 100644 --- a/x-pack/plugins/index_management/public/application/index.tsx +++ b/x-pack/plugins/index_management/public/application/index.tsx @@ -10,9 +10,12 @@ import { render, unmountComponentAtNode } from 'react-dom'; import { CoreStart } from '../../../../../src/core/public'; +import { API_BASE_PATH, BASE_PATH } from '../../common'; + import { AppContextProvider, AppDependencies } from './app_context'; import { App } from './app'; import { indexManagementStore } from './store'; +import { ComponentTemplatesProvider } from './components'; export const renderApp = ( elem: HTMLElement | null, @@ -22,15 +25,26 @@ export const renderApp = ( return () => undefined; } - const { i18n } = core; + const { i18n, docLinks, notifications } = core; const { Context: I18nContext } = i18n; const { services, history } = dependencies; + const componentTemplateProviderValues = { + httpClient: services.httpService.httpClient, + apiBasePath: API_BASE_PATH, + appBasePath: BASE_PATH, + trackMetric: services.uiMetricService.trackMetric.bind(services.uiMetricService), + docLinks, + toasts: notifications.toasts, + }; + render( - + + + , diff --git a/x-pack/plugins/index_management/public/application/sections/home/home.tsx b/x-pack/plugins/index_management/public/application/sections/home/home.tsx index 9d4331d742a25..0ddf4fefce466 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/home.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/home.tsx @@ -21,9 +21,16 @@ import { import { documentationService } from '../../services/documentation'; import { IndexList } from './index_list'; import { TemplateList } from './template_list'; +import { ComponentTemplateList } from '../../components/component_templates'; import { breadcrumbService } from '../../services/breadcrumbs'; -type Section = 'indices' | 'templates'; +export enum Section { + Indices = 'indices', + IndexTemplates = 'templates', + ComponentTemplates = 'component_templates', +} + +export const homeSections = [Section.Indices, Section.IndexTemplates, Section.ComponentTemplates]; interface MatchParams { section: Section; @@ -37,11 +44,11 @@ export const IndexManagementHome: React.FunctionComponent { const tabs = [ { - id: 'indices' as Section, + id: Section.Indices, name: , }, { - id: 'templates' as Section, + id: Section.IndexTemplates, name: ( ), }, + { + id: Section.ComponentTemplates, + name: ( + + ), + }, ]; const onSectionChange = (newSection: Section) => { @@ -106,13 +122,14 @@ export const IndexManagementHome: React.FunctionComponent - - + + + diff --git a/x-pack/plugins/index_management/public/application/sections/home/index.ts b/x-pack/plugins/index_management/public/application/sections/home/index.ts index 3a29ef4e58555..b53910748aedb 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index.ts +++ b/x-pack/plugins/index_management/public/application/sections/home/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { IndexManagementHome } from './home'; +export { IndexManagementHome, Section, homeSections } from './home'; diff --git a/x-pack/plugins/index_management/server/client/elasticsearch.ts b/x-pack/plugins/index_management/server/client/elasticsearch.ts index 65bd5411a249b..b51f7d924dba7 100644 --- a/x-pack/plugins/index_management/server/client/elasticsearch.ts +++ b/x-pack/plugins/index_management/server/client/elasticsearch.ts @@ -10,6 +10,7 @@ export const elasticsearchJsPlugin = (Client: any, config: any, components: any) Client.prototype.dataManagement = components.clientAction.namespaceFactory(); const dataManagement = Client.prototype.dataManagement.prototype; + // Component templates dataManagement.getComponentTemplates = ca({ urls: [ { @@ -60,4 +61,14 @@ export const elasticsearchJsPlugin = (Client: any, config: any, components: any) ], method: 'DELETE', }); + + // Composable index templates + dataManagement.getComposableIndexTemplates = ca({ + urls: [ + { + fmt: '/_index_template', + }, + ], + method: 'GET', + }); }; diff --git a/x-pack/plugins/index_management/server/routes/api/component_templates/get.ts b/x-pack/plugins/index_management/server/routes/api/component_templates/get.ts index 87aa64421624e..f6f8e7d63d370 100644 --- a/x-pack/plugins/index_management/server/routes/api/component_templates/get.ts +++ b/x-pack/plugins/index_management/server/routes/api/component_templates/get.ts @@ -5,6 +5,11 @@ */ import { schema } from '@kbn/config-schema'; +import { + deserializeComponentTemplate, + deserializeComponenTemplateList, +} from '../../../../common/lib'; +import { ComponentTemplateFromEs } from '../../../../common'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../index'; @@ -20,9 +25,25 @@ export function registerGetAllRoute({ router, license, lib: { isEsError } }: Rou const { callAsCurrentUser } = ctx.dataManagement!.client; try { - const response = await callAsCurrentUser('dataManagement.getComponentTemplates'); + const { + component_templates: componentTemplates, + }: { component_templates: ComponentTemplateFromEs[] } = await callAsCurrentUser( + 'dataManagement.getComponentTemplates' + ); + + const { index_templates: indexTemplates } = await callAsCurrentUser( + 'dataManagement.getComposableIndexTemplates' + ); + + const body = componentTemplates.map((componentTemplate) => { + const deserializedComponentTemplateListItem = deserializeComponenTemplateList( + componentTemplate, + indexTemplates + ); + return deserializedComponentTemplateListItem; + }); - return res.ok({ body: response.component_templates }); + return res.ok({ body }); } catch (error) { if (isEsError(error)) { return res.customError({ @@ -56,11 +77,12 @@ export function registerGetAllRoute({ router, license, lib: { isEsError } }: Rou } ); + const { index_templates: indexTemplates } = await callAsCurrentUser( + 'dataManagement.getComposableIndexTemplates' + ); + return res.ok({ - body: { - ...componentTemplates[0], - name, - }, + body: deserializeComponentTemplate(componentTemplates[0], indexTemplates), }); } catch (error) { if (isEsError(error)) { diff --git a/x-pack/test/api_integration/apis/management/index_management/component_templates.ts b/x-pack/test/api_integration/apis/management/index_management/component_templates.ts index a33e82ad9f79d..64bf03a043b55 100644 --- a/x-pack/test/api_integration/apis/management/index_management/component_templates.ts +++ b/x-pack/test/api_integration/apis/management/index_management/component_templates.ts @@ -61,7 +61,10 @@ export default function ({ getService }: FtrProviderContext) { expect(testComponentTemplate).to.eql({ name: COMPONENT_NAME, - component_template: COMPONENT, + usedBy: [], + hasSettings: true, + hasMappings: true, + hasAliases: false, }); }); }); @@ -74,8 +77,9 @@ export default function ({ getService }: FtrProviderContext) { expect(body).to.eql({ name: COMPONENT_NAME, - component_template: { - ...COMPONENT, + ...COMPONENT, + _kbnMeta: { + usedBy: [], }, }); }); diff --git a/x-pack/test/functional/apps/index_management/home_page.ts b/x-pack/test/functional/apps/index_management/home_page.ts index e985e338122e7..cca0a5d1ad1bd 100644 --- a/x-pack/test/functional/apps/index_management/home_page.ts +++ b/x-pack/test/functional/apps/index_management/home_page.ts @@ -47,5 +47,22 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(templateList).to.be(true); }); }); + + describe('Component templates', () => { + it('renders the component templates tab', async () => { + // Navigate to the component templates tab + await pageObjects.indexManagement.changeTabs('component_templatesTab'); + + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Verify url + const url = await browser.getCurrentUrl(); + expect(url).to.contain(`/component_templates`); + + // There should be no component templates by default, so we verify the empty prompt displays + const componentTemplateEmptyPrompt = await testSubjects.exists('emptyList'); + expect(componentTemplateEmptyPrompt).to.be(true); + }); + }); }); }; diff --git a/x-pack/test/functional/page_objects/index_management_page.ts b/x-pack/test/functional/page_objects/index_management_page.ts index d12186f2e2189..9bfcd79671b4d 100644 --- a/x-pack/test/functional/page_objects/index_management_page.ts +++ b/x-pack/test/functional/page_objects/index_management_page.ts @@ -44,7 +44,7 @@ export function IndexManagementPageProvider({ getService }: FtrProviderContext) }; }); }, - async changeTabs(tab: 'indicesTab' | 'templatesTab') { + async changeTabs(tab: 'indicesTab' | 'templatesTab' | 'component_templatesTab') { await testSubjects.click(tab); }, }; From 5d8de7a162a28dd987804e15dd33eac185df2070 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 9 Jun 2020 21:40:05 +0300 Subject: [PATCH 06/53] Use Search API in Vega (#68257) * Use Search API in Vega * fix PR comments * fix PR comments --- ...-data-public.getsearchparamsfromrequest.md | 44 ++++++++++++ .../kibana-plugin-plugins-data-public.md | 1 + .../vis_type_vega/vega_visualization.js | 44 ++++++++++-- src/plugins/data/public/index.ts | 1 + src/plugins/data/public/public.api.md | 46 ++++++++---- .../public/search/fetch/get_search_params.ts | 18 ++++- src/plugins/data/public/search/fetch/index.ts | 1 + src/plugins/data/public/search/index.ts | 1 + .../search/search_source/search_source.ts | 15 ++-- .../public/__mocks__/services.ts | 10 +-- .../public/data_model/es_query_parser.js | 41 ++++------- .../public/data_model/es_query_parser.test.js | 26 ++++--- .../public/data_model/search_api.ts | 60 ++++++++++++++++ .../public/data_model/search_cache.js | 48 ------------- .../public/data_model/search_cache.test.js | 71 ------------------- .../public/data_model/vega_parser.js | 4 +- .../public/data_model/vega_parser.test.js | 18 ++++- src/plugins/vis_type_vega/public/plugin.ts | 2 + src/plugins/vis_type_vega/public/services.ts | 14 +++- src/plugins/vis_type_vega/public/vega_fn.ts | 4 +- .../public/vega_request_handler.ts | 33 +++++---- 21 files changed, 289 insertions(+), 213 deletions(-) create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md create mode 100644 src/plugins/vis_type_vega/public/data_model/search_api.ts delete mode 100644 src/plugins/vis_type_vega/public/data_model/search_cache.js delete mode 100644 src/plugins/vis_type_vega/public/data_model/search_cache.test.js diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md new file mode 100644 index 0000000000000..1923f0e2e4ea1 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md @@ -0,0 +1,44 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [getSearchParamsFromRequest](./kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md) + +## getSearchParamsFromRequest() function + +Signature: + +```typescript +export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { + injectedMetadata: CoreStart['injectedMetadata']; + uiSettings: IUiSettingsClient; +}): { + rest_total_hits_as_int: boolean; + ignore_unavailable: boolean; + ignore_throttled: boolean; + max_concurrent_shard_requests: any; + preference: any; + timeout: string | undefined; + index: any; + body: any; +}; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| searchRequest | SearchRequest | | +| dependencies | {
injectedMetadata: CoreStart['injectedMetadata'];
uiSettings: IUiSettingsClient;
} | | + +Returns: + +`{ + rest_total_hits_as_int: boolean; + ignore_unavailable: boolean; + ignore_throttled: boolean; + max_concurrent_shard_requests: any; + preference: any; + timeout: string | undefined; + index: any; + body: any; +}` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index e818fb009fb19..bc1eb9100e85c 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -40,6 +40,7 @@ | [getEsPreference(uiSettings, sessionId)](./kibana-plugin-plugins-data-public.getespreference.md) | | | [getQueryLog(uiSettings, storage, appName, language)](./kibana-plugin-plugins-data-public.getquerylog.md) | | | [getSearchErrorType({ message })](./kibana-plugin-plugins-data-public.getsearcherrortype.md) | | +| [getSearchParamsFromRequest(searchRequest, dependencies)](./kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-public.gettime.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-public.plugin.md) | | diff --git a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_vega/vega_visualization.js b/src/legacy/core_plugins/kibana/public/__tests__/vis_type_vega/vega_visualization.js index 6d6eb69e66792..485390dc50a79 100644 --- a/src/legacy/core_plugins/kibana/public/__tests__/vis_type_vega/vega_visualization.js +++ b/src/legacy/core_plugins/kibana/public/__tests__/vis_type_vega/vega_visualization.js @@ -44,7 +44,7 @@ import vegaMapImage256 from './vega_map_image_256.png'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { VegaParser } from '../../../../../../plugins/vis_type_vega/public/data_model/vega_parser'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { SearchCache } from '../../../../../../plugins/vis_type_vega/public/data_model/search_cache'; +import { SearchAPI } from '../../../../../../plugins/vis_type_vega/public/data_model/search_api'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { createVegaTypeDefinition } from '../../../../../../plugins/vis_type_vega/public/vega_type'; @@ -205,7 +205,14 @@ describe('VegaVisualizations', () => { try { vegaVis = new VegaVisualization(domNode, vis); - const vegaParser = new VegaParser(vegaliteGraph, new SearchCache()); + const vegaParser = new VegaParser( + vegaliteGraph, + new SearchAPI({ + search: npStart.plugins.data.search, + uiSettings: npStart.core.uiSettings, + injectedMetadata: npStart.core.injectedMetadata, + }) + ); await vegaParser.parseAsync(); await vegaVis.render(vegaParser, vis.params, { data: true }); @@ -227,7 +234,14 @@ describe('VegaVisualizations', () => { let vegaVis; try { vegaVis = new VegaVisualization(domNode, vis); - const vegaParser = new VegaParser(vegaGraph, new SearchCache()); + const vegaParser = new VegaParser( + vegaGraph, + new SearchAPI({ + search: npStart.plugins.data.search, + uiSettings: npStart.core.uiSettings, + injectedMetadata: npStart.core.injectedMetadata, + }) + ); await vegaParser.parseAsync(); await vegaVis.render(vegaParser, vis.params, { data: true }); @@ -243,7 +257,14 @@ describe('VegaVisualizations', () => { let vegaVis; try { vegaVis = new VegaVisualization(domNode, vis); - const vegaParser = new VegaParser(vegaTooltipGraph, new SearchCache()); + const vegaParser = new VegaParser( + vegaTooltipGraph, + new SearchAPI({ + search: npStart.plugins.data.search, + uiSettings: npStart.core.uiSettings, + injectedMetadata: npStart.core.injectedMetadata, + }) + ); await vegaParser.parseAsync(); await vegaVis.render(vegaParser, vis.params, { data: true }); @@ -285,7 +306,14 @@ describe('VegaVisualizations', () => { let vegaVis; try { vegaVis = new VegaVisualization(domNode, vis); - const vegaParser = new VegaParser(vegaMapGraph, new SearchCache()); + const vegaParser = new VegaParser( + vegaMapGraph, + new SearchAPI({ + search: npStart.plugins.data.search, + uiSettings: npStart.core.uiSettings, + injectedMetadata: npStart.core.injectedMetadata, + }) + ); await vegaParser.parseAsync(); domNode.style.width = '256px'; @@ -324,7 +352,11 @@ describe('VegaVisualizations', () => { } ] }`, - new SearchCache() + new SearchAPI({ + search: npStart.plugins.data.search, + uiSettings: npStart.core.uiSettings, + injectedMetadata: npStart.core.injectedMetadata, + }) ); await vegaParser.parseAsync(); diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index eb3f937a4168b..301ff8d3f67d8 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -358,6 +358,7 @@ export { ISearchSource, parseSearchSourceJSON, injectSearchSourceReferences, + getSearchParamsFromRequest, extractSearchSourceReferences, SearchSourceFields, EsQuerySortValue, diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 7054575e8ef9e..bd3ec0d3f2294 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -30,6 +30,7 @@ import { IconType } from '@elastic/eui'; import { InjectedIntl } from '@kbn/i18n/react'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { IUiSettingsClient } from 'src/core/public'; +import { IUiSettingsClient as IUiSettingsClient_3 } from 'kibana/public'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { MaybePromise } from '@kbn/utility-types'; @@ -641,6 +642,23 @@ export function getQueryLog(uiSettings: IUiSettingsClient, storage: IStorageWrap // @public (undocumented) export function getSearchErrorType({ message }: Pick): "UNSUPPORTED_QUERY" | undefined; +// Warning: (ae-missing-release-tag) "getSearchParamsFromRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { + injectedMetadata: CoreStart['injectedMetadata']; + uiSettings: IUiSettingsClient_3; +}): { + rest_total_hits_as_int: boolean; + ignore_unavailable: boolean; + ignore_throttled: boolean; + max_concurrent_shard_requests: any; + preference: any; + timeout: string | undefined; + index: any; + body: any; +}; + // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1851,20 +1869,20 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:375:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:375:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:375:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:375:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:377:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:378:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:387:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:393:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:397:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:376:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:376:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:376:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:376:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:378:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:379:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:394:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:395:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts // src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 60bdc9ed6473a..f2ad243ce72d0 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -17,8 +17,9 @@ * under the License. */ -import { IUiSettingsClient } from 'kibana/public'; +import { IUiSettingsClient, CoreStart } from 'kibana/public'; import { UI_SETTINGS } from '../../../common'; +import { SearchRequest } from './types'; const sessionId = Date.now(); @@ -53,3 +54,18 @@ export function getPreference(config: IUiSettingsClient) { export function getTimeout(esShardTimeout: number) { return esShardTimeout > 0 ? `${esShardTimeout}ms` : undefined; } + +export function getSearchParamsFromRequest( + searchRequest: SearchRequest, + dependencies: { injectedMetadata: CoreStart['injectedMetadata']; uiSettings: IUiSettingsClient } +) { + const { injectedMetadata, uiSettings } = dependencies; + const esShardTimeout = injectedMetadata.getInjectedVar('esShardTimeout') as number; + const searchParams = getSearchParams(uiSettings, esShardTimeout); + + return { + index: searchRequest.index.title || searchRequest.index, + body: searchRequest.body, + ...searchParams, + }; +} diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts index 39845ec31bfaa..ab856d681ba12 100644 --- a/src/plugins/data/public/search/fetch/index.ts +++ b/src/plugins/data/public/search/fetch/index.ts @@ -20,6 +20,7 @@ export * from './types'; export { getSearchParams, + getSearchParamsFromRequest, getPreference, getTimeout, getIgnoreThrottled, diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index 53686f9be9b4d..1b5395e1071c5 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -44,6 +44,7 @@ export { SearchRequest, SearchResponse, getSearchErrorType, + getSearchParamsFromRequest, } from './fetch'; export { diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index b926739112e0e..a33cda964bd1d 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -77,7 +77,7 @@ import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/public'; import { IIndexPattern, ISearchGeneric, SearchRequest } from '../..'; import { SearchSourceOptions, SearchSourceFields } from './types'; -import { FetchOptions, RequestFailure, getSearchParams, handleResponse } from '../fetch'; +import { FetchOptions, RequestFailure, handleResponse, getSearchParamsFromRequest } from '../fetch'; import { getEsQueryConfig, buildEsQuery, Filter, UI_SETTINGS } from '../../../common'; import { getHighlightRequest } from '../../../common/field_formats'; @@ -204,13 +204,12 @@ export class SearchSource { */ private fetch$(searchRequest: SearchRequest, signal?: AbortSignal) { const { search, injectedMetadata, uiSettings } = this.dependencies; - const esShardTimeout = injectedMetadata.getInjectedVar('esShardTimeout') as number; - const searchParams = getSearchParams(uiSettings, esShardTimeout); - const params = { - index: searchRequest.index.title || searchRequest.index, - body: searchRequest.body, - ...searchParams, - }; + + const params = getSearchParamsFromRequest(searchRequest, { + injectedMetadata, + uiSettings, + }); + return search({ params, indexType: searchRequest.indexType }, { signal }).pipe( map(({ rawResponse }) => handleResponse(searchRequest, rawResponse)) ); diff --git a/src/plugins/vis_type_vega/public/__mocks__/services.ts b/src/plugins/vis_type_vega/public/__mocks__/services.ts index 1bf051232e4c9..4775241a66d50 100644 --- a/src/plugins/vis_type_vega/public/__mocks__/services.ts +++ b/src/plugins/vis_type_vega/public/__mocks__/services.ts @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ +import { CoreStart, IUiSettingsClient, NotificationsStart, SavedObjectsStart } from 'kibana/public'; import { createGetterSetter } from '../../../kibana_utils/public'; import { DataPublicPluginStart } from '../../../data/public'; -import { IUiSettingsClient, NotificationsStart, SavedObjectsStart } from 'kibana/public'; import { dataPluginMock } from '../../../data/public/mocks'; import { coreMock } from '../../../../core/public/mocks'; @@ -34,22 +34,24 @@ setNotifications(coreMock.createStart().notifications); export const [getUISettings, setUISettings] = createGetterSetter('UISettings'); setUISettings(coreMock.createStart().uiSettings); +export const [getInjectedMetadata, setInjectedMetadata] = createGetterSetter< + CoreStart['injectedMetadata'] +>('InjectedMetadata'); +setInjectedMetadata(coreMock.createStart().injectedMetadata); + export const [getSavedObjects, setSavedObjects] = createGetterSetter( 'SavedObjects' ); setSavedObjects(coreMock.createStart().savedObjects); export const [getInjectedVars, setInjectedVars] = createGetterSetter<{ - esShardTimeout: number; enableExternalUrls: boolean; emsTileLayerId: unknown; }>('InjectedVars'); setInjectedVars({ emsTileLayerId: {}, enableExternalUrls: true, - esShardTimeout: 10000, }); -export const getEsShardTimeout = () => getInjectedVars().esShardTimeout; export const getEnableExternalUrls = () => getInjectedVars().enableExternalUrls; export const getEmsTileLayerId = () => getInjectedVars().emsTileLayerId; diff --git a/src/plugins/vis_type_vega/public/data_model/es_query_parser.js b/src/plugins/vis_type_vega/public/data_model/es_query_parser.js index 066c9f06fc109..387301c2c7de9 100644 --- a/src/plugins/vis_type_vega/public/data_model/es_query_parser.js +++ b/src/plugins/vis_type_vega/public/data_model/es_query_parser.js @@ -17,11 +17,9 @@ * under the License. */ -import _ from 'lodash'; import moment from 'moment'; import { i18n } from '@kbn/i18n'; - -import { getEsShardTimeout } from '../services'; +import { isPlainObject, cloneDeep } from 'lodash'; const TIMEFILTER = '%timefilter%'; const AUTOINTERVAL = '%autointerval%'; @@ -37,12 +35,11 @@ const TIMEFIELD = '%timefield%'; * This class parses ES requests specified in the data.url objects. */ export class EsQueryParser { - constructor(timeCache, searchCache, filters, onWarning) { + constructor(timeCache, searchAPI, filters, onWarning) { this._timeCache = timeCache; - this._searchCache = searchCache; + this._searchAPI = searchAPI; this._filters = filters; this._onWarning = onWarning; - this._esShardTimeout = getEsShardTimeout(); } // noinspection JSMethodCanBeStatic @@ -59,7 +56,7 @@ export class EsQueryParser { if (body === undefined) { url.body = body = {}; - } else if (!_.isPlainObject(body)) { + } else if (!isPlainObject(body)) { throw new Error( i18n.translate('visTypeVega.esQueryParser.urlBodyValueTypeErrorMessage', { defaultMessage: '{configName} must be an object', @@ -167,7 +164,7 @@ export class EsQueryParser { if (context) { // Use dashboard context - const newQuery = _.cloneDeep(this._filters); + const newQuery = cloneDeep(this._filters); if (timefield) { newQuery.bool.must.push(body.query); } @@ -179,34 +176,20 @@ export class EsQueryParser { return { dataObject, url }; } - mapRequest = (request) => { - const esRequest = request.url; - if (this._esShardTimeout) { - // remove possible timeout query param to prevent two conflicting timeout parameters - const { body = {}, timeout, ...rest } = esRequest; //eslint-disable-line no-unused-vars - body.timeout = `${this._esShardTimeout}ms`; - return { - body, - ...rest, - }; - } else { - return esRequest; - } - }; - /** * Process items generated by parseUrl() * @param {object[]} requests each object is generated by parseUrl() * @returns {Promise} */ async populateData(requests) { - const esSearches = requests.map(this.mapRequest); + const esSearches = requests.map((r) => r.url); + const data$ = this._searchAPI.search(esSearches); - const results = await this._searchCache.search(esSearches); + const results = await data$.toPromise(); - for (let i = 0; i < requests.length; i++) { - requests[i].dataObject.values = results[i]; - } + results.forEach((data) => { + requests[data.id].dataObject.values = data.rawResponse; + }); } /** @@ -222,7 +205,7 @@ export class EsQueryParser { const item = obj[pos]; if (isQuery && (item === MUST_CLAUSE || item === MUST_NOT_CLAUSE)) { const ctxTag = item === MUST_CLAUSE ? 'must' : 'must_not'; - const ctx = _.cloneDeep(this._filters); + const ctx = cloneDeep(this._filters); if (ctx && ctx.bool && ctx.bool[ctxTag]) { if (Array.isArray(ctx.bool[ctxTag])) { // replace one value with an array of values diff --git a/src/plugins/vis_type_vega/public/data_model/es_query_parser.test.js b/src/plugins/vis_type_vega/public/data_model/es_query_parser.test.js index c519da33ab1c9..fd474bef73b8c 100644 --- a/src/plugins/vis_type_vega/public/data_model/es_query_parser.test.js +++ b/src/plugins/vis_type_vega/public/data_model/es_query_parser.test.js @@ -94,28 +94,36 @@ describe(`EsQueryParser time`, () => { }); describe('EsQueryParser.populateData', () => { - let searchStub; + let searchApiStub; + let data; let parser; beforeEach(() => { - searchStub = jest.fn(() => Promise.resolve([{}, {}])); - parser = new EsQueryParser({}, { search: searchStub }, undefined, undefined); + searchApiStub = { + search: jest.fn(() => ({ + toPromise: jest.fn(() => Promise.resolve(data)), + })), + }; + parser = new EsQueryParser({}, searchApiStub, undefined, undefined); }); test('should set the timeout for each request', async () => { + data = [ + { id: 0, rawResponse: {} }, + { id: 1, rawResponse: {} }, + ]; await parser.populateData([ { url: { body: {} }, dataObject: {} }, { url: { body: {} }, dataObject: {} }, ]); - expect(searchStub.mock.calls[0][0][0].body.timeout).toBe.defined; + + expect(searchApiStub.search.mock.calls[0][0][0].body).toBeDefined(); }); test('should remove possible timeout parameters on a request', async () => { - await parser.populateData([ - { url: { timeout: '500h', body: { timeout: '500h' } }, dataObject: {} }, - ]); - expect(searchStub.mock.calls[0][0][0].body.timeout).toBe.defined; - expect(searchStub.mock.calls[0][0][0].timeout).toBe(undefined); + data = [{ id: 0, rawResponse: {} }]; + await parser.populateData([{ url: { body: { timeout: '500h' } }, dataObject: {} }]); + expect(searchApiStub.search.mock.calls[0][0][0].body.timeout).toBeDefined(); }); }); diff --git a/src/plugins/vis_type_vega/public/data_model/search_api.ts b/src/plugins/vis_type_vega/public/data_model/search_api.ts new file mode 100644 index 0000000000000..c2eecf13c2d51 --- /dev/null +++ b/src/plugins/vis_type_vega/public/data_model/search_api.ts @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { combineLatest } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { CoreStart, IUiSettingsClient } from 'kibana/public'; +import { + getSearchParamsFromRequest, + SearchRequest, + DataPublicPluginStart, +} from '../../../data/public'; + +export interface SearchAPIDependencies { + uiSettings: IUiSettingsClient; + injectedMetadata: CoreStart['injectedMetadata']; + search: DataPublicPluginStart['search']; +} + +export class SearchAPI { + constructor( + private readonly dependencies: SearchAPIDependencies, + private readonly abortSignal?: AbortSignal + ) {} + + search(searchRequests: SearchRequest[]) { + const { search } = this.dependencies.search; + + return combineLatest( + searchRequests.map((request, index) => { + const params = getSearchParamsFromRequest(request, { + uiSettings: this.dependencies.uiSettings, + injectedMetadata: this.dependencies.injectedMetadata, + }); + + return search({ params }, { signal: this.abortSignal }).pipe( + map((data) => ({ + id: index, + rawResponse: data.rawResponse, + })) + ); + }) + ); + } +} diff --git a/src/plugins/vis_type_vega/public/data_model/search_cache.js b/src/plugins/vis_type_vega/public/data_model/search_cache.js deleted file mode 100644 index 41e4c67c3b2ad..0000000000000 --- a/src/plugins/vis_type_vega/public/data_model/search_cache.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import LruCache from 'lru-cache'; - -export class SearchCache { - constructor(es, cacheOpts) { - this._es = es; - this._cache = new LruCache(cacheOpts); - } - - /** - * Execute multiple searches, possibly combining the results of the cached searches - * with the new ones already in cache - * @param {object[]} requests array of search requests - */ - search(requests) { - const promises = []; - - for (const request of requests) { - const key = JSON.stringify(request); - let pending = this._cache.get(key); - if (pending === undefined) { - pending = this._es.search(request); - this._cache.set(key, pending); - } - promises.push(pending); - } - - return Promise.all(promises); - } -} diff --git a/src/plugins/vis_type_vega/public/data_model/search_cache.test.js b/src/plugins/vis_type_vega/public/data_model/search_cache.test.js deleted file mode 100644 index 92f80545ce1b5..0000000000000 --- a/src/plugins/vis_type_vega/public/data_model/search_cache.test.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SearchCache } from './search_cache'; -jest.mock('../services'); - -describe(`SearchCache`, () => { - class FauxEs { - constructor() { - // contains all request batches, separated by 0 - this.searches = []; - } - - async search(request) { - this.searches.push(request); - return { req: request }; - } - } - - const request1 = { body: 'b1' }; - const expected1 = { req: { body: 'b1' } }; - const request2 = { body: 'b2' }; - const expected2 = { req: { body: 'b2' } }; - const request3 = { body: 'b3' }; - const expected3 = { req: { body: 'b3' } }; - - it(`sequence`, async () => { - const sc = new SearchCache(new FauxEs()); - - // empty request - let res = await sc.search([]); - expect(res).toEqual([]); - expect(sc._es.searches).toEqual([]); - - // single request - res = await sc.search([request1]); - expect(res).toEqual([expected1]); - expect(sc._es.searches).toEqual([request1]); - - // repeat the same search, use array notation - res = await sc.search([request1]); - expect(res).toEqual([expected1]); - expect(sc._es.searches).toEqual([request1]); // no new entries - - // new single search - res = await sc.search([request2]); - expect(res).toEqual([expected2]); - expect(sc._es.searches).toEqual([request1, request2]); - - // multiple search, some new, some old - res = await sc.search([request1, request3, request2]); - expect(res).toEqual([expected1, expected3, expected2]); - expect(sc._es.searches).toEqual([request1, request2, request3]); - }); -}); diff --git a/src/plugins/vis_type_vega/public/data_model/vega_parser.js b/src/plugins/vis_type_vega/public/data_model/vega_parser.js index f541b9f104adc..cbfe2a6ede4f2 100644 --- a/src/plugins/vis_type_vega/public/data_model/vega_parser.js +++ b/src/plugins/vis_type_vega/public/data_model/vega_parser.js @@ -46,7 +46,7 @@ const locToDirMap = { const DEFAULT_PARSER = 'elasticsearch'; export class VegaParser { - constructor(spec, searchCache, timeCache, filters, serviceSettings) { + constructor(spec, searchAPI, timeCache, filters, serviceSettings) { this.spec = spec; this.hideWarnings = false; this.error = undefined; @@ -54,7 +54,7 @@ export class VegaParser { const onWarn = this._onWarning.bind(this); this._urlParsers = { - elasticsearch: new EsQueryParser(timeCache, searchCache, filters, onWarn), + elasticsearch: new EsQueryParser(timeCache, searchAPI, filters, onWarn), emsfile: new EmsFileParser(serviceSettings), url: new UrlParser(onWarn), }; diff --git a/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js b/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js index 1bd26b8713044..a40ef31260b6f 100644 --- a/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js +++ b/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js @@ -78,9 +78,25 @@ describe(`VegaParser._setDefaultColors`, () => { }); describe('VegaParser._resolveEsQueries', () => { + let searchApiStub; + const data = [ + { + id: 0, + rawResponse: [42], + }, + ]; + + beforeEach(() => { + searchApiStub = { + search: jest.fn(() => ({ + toPromise: jest.fn(() => Promise.resolve(data)), + })), + }; + }); + function check(spec, expected, warnCount) { return async () => { - const vp = new VegaParser(spec, { search: async () => [[42]] }, 0, 0, { + const vp = new VegaParser(spec, searchApiStub, 0, 0, { getFileLayers: async () => [{ name: 'file1', url: 'url1' }], getUrlForRegionLayer: async (layer) => { return layer.url; diff --git a/src/plugins/vis_type_vega/public/plugin.ts b/src/plugins/vis_type_vega/public/plugin.ts index 1bce7ac92e564..b3e35dac3711f 100644 --- a/src/plugins/vis_type_vega/public/plugin.ts +++ b/src/plugins/vis_type_vega/public/plugin.ts @@ -28,6 +28,7 @@ import { setUISettings, setKibanaMapFactory, setMapsLegacyConfig, + setInjectedMetadata, } from './services'; import { createVegaFn } from './vega_fn'; @@ -96,5 +97,6 @@ export class VegaPlugin implements Plugin, void> { setNotifications(core.notifications); setSavedObjects(core.savedObjects); setData(data); + setInjectedMetadata(core.injectedMetadata); } } diff --git a/src/plugins/vis_type_vega/public/services.ts b/src/plugins/vis_type_vega/public/services.ts index f2fddb41cf72b..7d988d464b52b 100644 --- a/src/plugins/vis_type_vega/public/services.ts +++ b/src/plugins/vis_type_vega/public/services.ts @@ -17,8 +17,13 @@ * under the License. */ -import { SavedObjectsStart } from 'kibana/public'; -import { NotificationsStart, IUiSettingsClient } from 'src/core/public'; +import { + CoreStart, + SavedObjectsStart, + NotificationsStart, + IUiSettingsClient, +} from 'src/core/public'; + import { DataPublicPluginStart } from '../../data/public'; import { createGetterSetter } from '../../kibana_utils/public'; import { MapsLegacyConfigType } from '../../maps_legacy/public'; @@ -34,6 +39,10 @@ export const [getKibanaMapFactory, setKibanaMapFactory] = createGetterSetter('UISettings'); +export const [getInjectedMetadata, setInjectedMetadata] = createGetterSetter< + CoreStart['injectedMetadata'] +>('InjectedMetadata'); + export const [getSavedObjects, setSavedObjects] = createGetterSetter( 'SavedObjects' ); @@ -48,6 +57,5 @@ export const [getMapsLegacyConfig, setMapsLegacyConfig] = createGetterSetter getInjectedVars().esShardTimeout; export const getEnableExternalUrls = () => getInjectedVars().enableExternalUrls; export const getEmsTileLayerId = () => getMapsLegacyConfig().emsTileLayerId; diff --git a/src/plugins/vis_type_vega/public/vega_fn.ts b/src/plugins/vis_type_vega/public/vega_fn.ts index 6d45e043f7cee..a9c915fcfb636 100644 --- a/src/plugins/vis_type_vega/public/vega_fn.ts +++ b/src/plugins/vis_type_vega/public/vega_fn.ts @@ -54,8 +54,8 @@ export const createVegaFn = ( help: '', }, }, - async fn(input, args) { - const vegaRequestHandler = createVegaRequestHandler(dependencies); + async fn(input, args, context) { + const vegaRequestHandler = createVegaRequestHandler(dependencies, context.abortSignal); const response = await vegaRequestHandler({ timeRange: get(input, 'timeRange'), diff --git a/src/plugins/vis_type_vega/public/vega_request_handler.ts b/src/plugins/vis_type_vega/public/vega_request_handler.ts index efc02e368efa8..ac28f0b3782b2 100644 --- a/src/plugins/vis_type_vega/public/vega_request_handler.ts +++ b/src/plugins/vis_type_vega/public/vega_request_handler.ts @@ -19,14 +19,14 @@ import { Filter, esQuery, TimeRange, Query } from '../../data/public'; -// @ts-ignore -import { SearchCache } from './data_model/search_cache'; +import { SearchAPI } from './data_model/search_api'; + // @ts-ignore import { TimeCache } from './data_model/time_cache'; import { VegaVisualizationDependencies } from './plugin'; import { VisParams } from './vega_fn'; -import { getData } from './services'; +import { getData, getInjectedMetadata } from './services'; interface VegaRequestHandlerParams { query: Query; @@ -35,12 +35,11 @@ interface VegaRequestHandlerParams { visParams: VisParams; } -export function createVegaRequestHandler({ - plugins: { data }, - core: { uiSettings }, - serviceSettings, -}: VegaVisualizationDependencies) { - let searchCache: SearchCache | undefined; +export function createVegaRequestHandler( + { plugins: { data }, core: { uiSettings }, serviceSettings }: VegaVisualizationDependencies, + abortSignal?: AbortSignal +) { + let searchAPI: SearchAPI; const { timefilter } = data.query.timefilter; const timeCache = new TimeCache(timefilter, 3 * 1000); @@ -50,11 +49,15 @@ export function createVegaRequestHandler({ query, visParams, }: VegaRequestHandlerParams) { - if (!searchCache) { - searchCache = new SearchCache(getData().search.__LEGACY.esClient, { - max: 10, - maxAge: 4 * 1000, - }); + if (!searchAPI) { + searchAPI = new SearchAPI( + { + uiSettings, + search: getData().search, + injectedMetadata: getInjectedMetadata(), + }, + abortSignal + ); } timeCache.setTimeRange(timeRange); @@ -63,7 +66,7 @@ export function createVegaRequestHandler({ const filtersDsl = esQuery.buildEsQuery(undefined, query, filters, esQueryConfigs); // @ts-ignore const { VegaParser } = await import('./data_model/vega_parser'); - const vp = new VegaParser(visParams.spec, searchCache, timeCache, filtersDsl, serviceSettings); + const vp = new VegaParser(visParams.spec, searchAPI, timeCache, filtersDsl, serviceSettings); return await vp.parseAsync(); }; From 5260c32706316c80982cde3e5921187e6a24e3d0 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 9 Jun 2020 12:50:33 -0600 Subject: [PATCH 07/53] [Security] [Cases] Attach timeline to existing case (#68580) --- .../cases/components/add_comment/index.tsx | 32 + .../cases/components/all_cases/columns.tsx | 274 +++---- .../cases/components/all_cases/index.test.tsx | 16 +- .../cases/components/all_cases/index.tsx | 694 +++++++++--------- .../components/all_cases_modal/index.test.tsx | 140 ++++ .../components/all_cases_modal/index.tsx | 56 ++ .../all_cases_modal/translations.ts | 10 + .../public/cases/pages/case_details.tsx | 2 - .../public/common/mock/global_state.ts | 1 + .../public/common/mock/index.ts | 1 + .../components/flyout/header/index.tsx | 8 +- .../header_with_close_button/index.test.tsx | 30 +- .../__snapshots__/timeline.test.tsx.snap | 51 +- .../components/timeline/index.test.tsx | 14 +- .../insert_timeline_popover/index.test.tsx | 30 +- .../insert_timeline_popover/index.tsx | 35 +- .../use_insert_timeline.tsx | 2 +- .../timeline/properties/helpers.tsx | 51 +- .../timeline/properties/index.test.tsx | 477 ++++-------- .../components/timeline/properties/index.tsx | 39 + .../properties/properties_right.test.tsx | 4 +- .../timeline/properties/properties_right.tsx | 69 +- .../timeline/properties/translations.ts | 7 + .../components/timeline/timeline.test.tsx | 24 + .../timelines/store/timeline/actions.ts | 3 + .../timelines/store/timeline/helpers.ts | 1 + .../timelines/store/timeline/reducer.ts | 22 +- .../timelines/store/timeline/selectors.ts | 5 +- .../public/timelines/store/timeline/types.ts | 7 + 29 files changed, 1166 insertions(+), 939 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.tsx create mode 100644 x-pack/plugins/security_solution/public/cases/components/all_cases_modal/translations.ts diff --git a/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx b/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx index a57fae8081bea..a830b299d655b 100644 --- a/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/add_comment/index.tsx @@ -8,6 +8,7 @@ import { EuiButton, EuiLoadingSpinner } from '@elastic/eui'; import React, { useCallback, useEffect } from 'react'; import styled from 'styled-components'; +import { useDispatch } from 'react-redux'; import { CommentRequest } from '../../../../../case/common/api'; import { usePostComment } from '../../containers/use_post_comment'; import { Case } from '../../containers/types'; @@ -18,6 +19,12 @@ import { Form, useForm, UseField } from '../../../shared_imports'; import * as i18n from './translations'; import { schema } from './schema'; +import { + dispatchUpdateTimeline, + queryTimelineById, +} from '../../../timelines/components/open_timeline/helpers'; +import { updateIsLoading as dispatchUpdateIsLoading } from '../../../timelines/store/timeline/actions'; +import { useApolloClient } from '../../../common/utils/apollo_context'; const MySpinner = styled(EuiLoadingSpinner)` position: absolute; @@ -46,6 +53,8 @@ export const AddComment = React.memo( options: { stripEmptyFields: false }, schema, }); + const dispatch = useDispatch(); + const apolloClient = useApolloClient(); const { handleCursorChange, handleOnTimelineChange } = useInsertTimeline( form, 'comment' @@ -62,6 +71,28 @@ export const AddComment = React.memo( // eslint-disable-next-line react-hooks/exhaustive-deps }, [insertQuote]); + const handleTimelineClick = useCallback( + (timelineId: string) => { + queryTimelineById({ + apolloClient, + timelineId, + updateIsLoading: ({ + id: currentTimelineId, + isLoading: isLoadingTimeline, + }: { + id: string; + isLoading: boolean; + }) => + dispatch( + dispatchUpdateIsLoading({ id: currentTimelineId, isLoading: isLoadingTimeline }) + ), + updateTimeline: dispatchUpdateTimeline(dispatch), + }); + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [apolloClient] + ); + const onSubmit = useCallback(async () => { const { isValid, data } = await form.submit(); if (isValid) { @@ -86,6 +117,7 @@ export const AddComment = React.memo( dataTestSubj: 'add-comment', placeholder: i18n.ADD_COMMENT_HELP_TEXT, onCursorPositionUpdate: handleCursorChange, + onClickTimeline: handleTimelineClick, bottomRightContent: ( export const getCasesColumns = ( actions: Array>, - filterStatus: string -): CasesColumns[] => [ - { - name: i18n.NAME, - render: (theCase: Case) => { - if (theCase.id != null && theCase.title != null) { - const caseDetailsLinkComponent = ( - - {theCase.title} - - ); - return theCase.status === 'open' ? ( - caseDetailsLinkComponent - ) : ( - <> - + filterStatus: string, + isModal: boolean +): CasesColumns[] => { + const columns = [ + { + name: i18n.NAME, + render: (theCase: Case) => { + if (theCase.id != null && theCase.title != null) { + const caseDetailsLinkComponent = !isModal ? ( + + {theCase.title} + + ) : ( + {theCase.title} + ); + return theCase.status === 'open' ? ( + caseDetailsLinkComponent + ) : ( + <> {caseDetailsLinkComponent} - {i18n.CLOSED} - - - ); - } - return getEmptyTagValue(); + + {i18n.CLOSED} + + + ); + } + return getEmptyTagValue(); + }, }, - }, - { - field: 'createdBy', - name: i18n.REPORTER, - render: (createdBy: Case['createdBy']) => { - if (createdBy != null) { - return ( - <> - - - {createdBy.fullName ? createdBy.fullName : createdBy.username ?? ''} - - - ); - } - return getEmptyTagValue(); + { + field: 'createdBy', + name: i18n.REPORTER, + render: (createdBy: Case['createdBy']) => { + if (createdBy != null) { + return ( + <> + + + {createdBy.fullName ? createdBy.fullName : createdBy.username ?? ''} + + + ); + } + return getEmptyTagValue(); + }, + }, + { + field: 'tags', + name: i18n.TAGS, + render: (tags: Case['tags']) => { + if (tags != null && tags.length > 0) { + return ( + + {tags.map((tag: string, i: number) => ( + + {tag} + + ))} + + ); + } + return getEmptyTagValue(); + }, + truncateText: true, }, - }, - { - field: 'tags', - name: i18n.TAGS, - render: (tags: Case['tags']) => { - if (tags != null && tags.length > 0) { - return ( - - {tags.map((tag: string, i: number) => ( - - {tag} - - ))} - - ); - } - return getEmptyTagValue(); + { + align: 'right' as HorizontalAlignment, + field: 'totalComment', + name: i18n.COMMENTS, + sortable: true, + render: (totalComment: Case['totalComment']) => + totalComment != null + ? renderStringField(`${totalComment}`, `case-table-column-commentCount`) + : getEmptyTagValue(), }, - truncateText: true, - }, - { - align: 'right', - field: 'totalComment', - name: i18n.COMMENTS, - sortable: true, - render: (totalComment: Case['totalComment']) => - totalComment != null - ? renderStringField(`${totalComment}`, `case-table-column-commentCount`) - : getEmptyTagValue(), - }, - filterStatus === 'open' - ? { - field: 'createdAt', - name: i18n.OPENED_ON, - sortable: true, - render: (createdAt: Case['createdAt']) => { - if (createdAt != null) { - return ( - - - - ); - } - return getEmptyTagValue(); - }, - } - : { - field: 'closedAt', - name: i18n.CLOSED_ON, - sortable: true, - render: (closedAt: Case['closedAt']) => { - if (closedAt != null) { - return ( - - - - ); - } - return getEmptyTagValue(); + filterStatus === 'open' + ? { + field: 'createdAt', + name: i18n.OPENED_ON, + sortable: true, + render: (createdAt: Case['createdAt']) => { + if (createdAt != null) { + return ( + + + + ); + } + return getEmptyTagValue(); + }, + } + : { + field: 'closedAt', + name: i18n.CLOSED_ON, + sortable: true, + render: (closedAt: Case['closedAt']) => { + if (closedAt != null) { + return ( + + + + ); + } + return getEmptyTagValue(); + }, }, + { + name: i18n.EXTERNAL_INCIDENT, + render: (theCase: Case) => { + if (theCase.id != null) { + return ; + } + return getEmptyTagValue(); }, - { - name: i18n.EXTERNAL_INCIDENT, - render: (theCase: Case) => { - if (theCase.id != null) { - return ; - } - return getEmptyTagValue(); }, - }, - { - name: i18n.INCIDENT_MANAGEMENT_SYSTEM, - render: (theCase: Case) => { - if (theCase.externalService != null) { - return renderStringField( - `${theCase.externalService.connectorName}`, - `case-table-column-connector` - ); - } - return getEmptyTagValue(); + { + name: i18n.INCIDENT_MANAGEMENT_SYSTEM, + render: (theCase: Case) => { + if (theCase.externalService != null) { + return renderStringField( + `${theCase.externalService.connectorName}`, + `case-table-column-connector` + ); + } + return getEmptyTagValue(); + }, + }, + { + name: i18n.ACTIONS, + actions, }, - }, - { - name: i18n.ACTIONS, - actions, - }, -]; + ]; + if (isModal) { + columns.pop(); // remove actions if in modal + } + return columns; +}; interface Props { theCase: Case; diff --git a/x-pack/plugins/security_solution/public/cases/components/all_cases/index.test.tsx b/x-pack/plugins/security_solution/public/cases/components/all_cases/index.test.tsx index e3f4fee15ce68..bbb96f433d3c8 100644 --- a/x-pack/plugins/security_solution/public/cases/components/all_cases/index.test.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/all_cases/index.test.tsx @@ -151,8 +151,22 @@ describe('AllCases', () => { expect(column.find('.euiTableRowCell--hideForDesktop').text()).toEqual(columnName); expect(column.find('span').text()).toEqual(emptyTag); }; - getCasesColumns([], 'open').map((i, key) => i.name != null && checkIt(`${i.name}`, key)); + getCasesColumns([], 'open', false).map((i, key) => i.name != null && checkIt(`${i.name}`, key)); }); + + it('should not render case link or actions on modal=true', () => { + const wrapper = mount( + + + + ); + const checkIt = (columnName: string) => { + expect(columnName).not.toEqual(i18n.ACTIONS); + }; + getCasesColumns([], 'open', true).map((i, key) => i.name != null && checkIt(`${i.name}`)); + expect(wrapper.find(`a[data-test-subj="case-details-link"]`).exists()).toBeFalsy(); + }); + it('should tableHeaderSortButton AllCases', () => { const wrapper = mount( diff --git a/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx b/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx index 32a7c4078071e..d27f383fb94e3 100644 --- a/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/all_cases/index.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +/* eslint-disable react-hooks/exhaustive-deps */ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { EuiBasicTable, @@ -72,7 +72,6 @@ const ProgressLoader = styled(EuiProgress)` z-index: ${theme.eui.euiZHeader}; `} `; - const getSortField = (field: string): SortFieldCase => { if (field === SortFieldCase.createdAt) { return SortFieldCase.createdAt; @@ -83,368 +82,373 @@ const getSortField = (field: string): SortFieldCase => { }; interface AllCasesProps { + onRowClick?: (id: string) => void; + isModal?: boolean; userCanCrud: boolean; } -export const AllCases = React.memo(({ userCanCrud }) => { - const urlSearch = useGetUrlSearch(navTabs.case); - const { actionLicense } = useGetActionLicense(); - const { - countClosedCases, - countOpenCases, - isLoading: isCasesStatusLoading, - fetchCasesStatus, - } = useGetCasesStatus(); - const { - data, - dispatchUpdateCaseProperty, - filterOptions, - loading, - queryParams, - selectedCases, - refetchCases, - setFilters, - setQueryParams, - setSelectedCases, - } = useGetCases(); +export const AllCases = React.memo( + ({ onRowClick = () => {}, isModal = false, userCanCrud }) => { + const urlSearch = useGetUrlSearch(navTabs.case); + const { actionLicense } = useGetActionLicense(); + const { + countClosedCases, + countOpenCases, + isLoading: isCasesStatusLoading, + fetchCasesStatus, + } = useGetCasesStatus(); + const { + data, + dispatchUpdateCaseProperty, + filterOptions, + loading, + queryParams, + selectedCases, + refetchCases, + setFilters, + setQueryParams, + setSelectedCases, + } = useGetCases(); - // Delete case - const { - dispatchResetIsDeleted, - handleOnDeleteConfirm, - handleToggleModal, - isLoading: isDeleting, - isDeleted, - isDisplayConfirmDeleteModal, - } = useDeleteCases(); - - // Update case - const { - dispatchResetIsUpdated, - isLoading: isUpdating, - isUpdated, - updateBulkStatus, - } = useUpdateCases(); - const [deleteThisCase, setDeleteThisCase] = useState({ - title: '', - id: '', - }); - const [deleteBulk, setDeleteBulk] = useState([]); - const filterRefetch = useRef<() => void>(); - const setFilterRefetch = useCallback( - (refetchFilter: () => void) => { - filterRefetch.current = refetchFilter; - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [filterRefetch.current] - ); - const refreshCases = useCallback( - (dataRefresh = true) => { - if (dataRefresh) refetchCases(); - fetchCasesStatus(); - setSelectedCases([]); - setDeleteBulk([]); - if (filterRefetch.current != null) { - filterRefetch.current(); - } - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [filterOptions, queryParams, filterRefetch.current] - ); + // Delete case + const { + dispatchResetIsDeleted, + handleOnDeleteConfirm, + handleToggleModal, + isLoading: isDeleting, + isDeleted, + isDisplayConfirmDeleteModal, + } = useDeleteCases(); - useEffect(() => { - if (isDeleted) { - refreshCases(); - dispatchResetIsDeleted(); - } - if (isUpdated) { - refreshCases(); - dispatchResetIsUpdated(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isDeleted, isUpdated]); - const confirmDeleteModal = useMemo( - () => ( - 0} - onCancel={handleToggleModal} - onConfirm={handleOnDeleteConfirm.bind( - null, - deleteBulk.length > 0 ? deleteBulk : [deleteThisCase] - )} - /> - ), - // eslint-disable-next-line react-hooks/exhaustive-deps - [deleteBulk, deleteThisCase, isDisplayConfirmDeleteModal] - ); + // Update case + const { + dispatchResetIsUpdated, + isLoading: isUpdating, + isUpdated, + updateBulkStatus, + } = useUpdateCases(); + const [deleteThisCase, setDeleteThisCase] = useState({ + title: '', + id: '', + }); + const [deleteBulk, setDeleteBulk] = useState([]); + const filterRefetch = useRef<() => void>(); + const setFilterRefetch = useCallback( + (refetchFilter: () => void) => { + filterRefetch.current = refetchFilter; + }, + [filterRefetch.current] + ); + const refreshCases = useCallback( + (dataRefresh = true) => { + if (dataRefresh) refetchCases(); + fetchCasesStatus(); + setSelectedCases([]); + setDeleteBulk([]); + if (filterRefetch.current != null) { + filterRefetch.current(); + } + }, + [filterOptions, queryParams, filterRefetch.current] + ); - const toggleDeleteModal = useCallback((deleteCase: Case) => { - handleToggleModal(); - setDeleteThisCase(deleteCase); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + useEffect(() => { + if (isDeleted) { + refreshCases(); + dispatchResetIsDeleted(); + } + if (isUpdated) { + refreshCases(); + dispatchResetIsUpdated(); + } + }, [isDeleted, isUpdated]); + const confirmDeleteModal = useMemo( + () => ( + 0} + onCancel={handleToggleModal} + onConfirm={handleOnDeleteConfirm.bind( + null, + deleteBulk.length > 0 ? deleteBulk : [deleteThisCase] + )} + /> + ), + [deleteBulk, deleteThisCase, isDisplayConfirmDeleteModal] + ); - const toggleBulkDeleteModal = useCallback( - (caseIds: string[]) => { + const toggleDeleteModal = useCallback((deleteCase: Case) => { handleToggleModal(); - if (caseIds.length === 1) { - const singleCase = selectedCases.find((theCase) => theCase.id === caseIds[0]); - if (singleCase) { - return setDeleteThisCase({ id: singleCase.id, title: singleCase.title }); + setDeleteThisCase(deleteCase); + }, []); + + const toggleBulkDeleteModal = useCallback( + (caseIds: string[]) => { + handleToggleModal(); + if (caseIds.length === 1) { + const singleCase = selectedCases.find((theCase) => theCase.id === caseIds[0]); + if (singleCase) { + return setDeleteThisCase({ id: singleCase.id, title: singleCase.title }); + } } - } - const convertToDeleteCases: DeleteCase[] = caseIds.map((id) => ({ id })); - setDeleteBulk(convertToDeleteCases); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [selectedCases] - ); + const convertToDeleteCases: DeleteCase[] = caseIds.map((id) => ({ id })); + setDeleteBulk(convertToDeleteCases); + }, + [selectedCases] + ); - const handleUpdateCaseStatus = useCallback( - (status: string) => { - updateBulkStatus(selectedCases, status); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [selectedCases] - ); + const handleUpdateCaseStatus = useCallback( + (status: string) => { + updateBulkStatus(selectedCases, status); + }, + [selectedCases] + ); - const selectedCaseIds = useMemo( - (): string[] => selectedCases.map((caseObj: Case) => caseObj.id), - [selectedCases] - ); + const selectedCaseIds = useMemo( + (): string[] => selectedCases.map((caseObj: Case) => caseObj.id), + [selectedCases] + ); - const getBulkItemsPopoverContent = useCallback( - (closePopover: () => void) => ( - - ), - // eslint-disable-next-line react-hooks/exhaustive-deps - [selectedCaseIds, filterOptions.status, toggleBulkDeleteModal] - ); - const handleDispatchUpdate = useCallback( - (args: Omit) => { - dispatchUpdateCaseProperty({ ...args, refetchCasesStatus: fetchCasesStatus }); - }, - [dispatchUpdateCaseProperty, fetchCasesStatus] - ); + const getBulkItemsPopoverContent = useCallback( + (closePopover: () => void) => ( + + ), + [selectedCaseIds, filterOptions.status, toggleBulkDeleteModal] + ); + const handleDispatchUpdate = useCallback( + (args: Omit) => { + dispatchUpdateCaseProperty({ ...args, refetchCasesStatus: fetchCasesStatus }); + }, + [dispatchUpdateCaseProperty, fetchCasesStatus] + ); - const actions = useMemo( - () => - getActions({ - caseStatus: filterOptions.status, - deleteCaseOnClick: toggleDeleteModal, - dispatchUpdate: handleDispatchUpdate, - }), - [filterOptions.status, toggleDeleteModal, handleDispatchUpdate] - ); + const actions = useMemo( + () => + getActions({ + caseStatus: filterOptions.status, + deleteCaseOnClick: toggleDeleteModal, + dispatchUpdate: handleDispatchUpdate, + }), + [filterOptions.status, toggleDeleteModal, handleDispatchUpdate] + ); - const actionsErrors = useMemo(() => getActionLicenseError(actionLicense), [actionLicense]); + const actionsErrors = useMemo(() => getActionLicenseError(actionLicense), [actionLicense]); - const tableOnChangeCallback = useCallback( - ({ page, sort }: EuiBasicTableOnChange) => { - let newQueryParams = queryParams; - if (sort) { - newQueryParams = { - ...newQueryParams, - sortField: getSortField(sort.field), - sortOrder: sort.direction, - }; - } - if (page) { - newQueryParams = { - ...newQueryParams, - page: page.index + 1, - perPage: page.size, - }; - } - setQueryParams(newQueryParams); - refreshCases(false); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [queryParams] - ); + const tableOnChangeCallback = useCallback( + ({ page, sort }: EuiBasicTableOnChange) => { + let newQueryParams = queryParams; + if (sort) { + newQueryParams = { + ...newQueryParams, + sortField: getSortField(sort.field), + sortOrder: sort.direction, + }; + } + if (page) { + newQueryParams = { + ...newQueryParams, + page: page.index + 1, + perPage: page.size, + }; + } + setQueryParams(newQueryParams); + refreshCases(false); + }, + [queryParams] + ); - const onFilterChangedCallback = useCallback( - (newFilterOptions: Partial) => { - if (newFilterOptions.status && newFilterOptions.status === 'closed') { - setQueryParams({ sortField: SortFieldCase.closedAt }); - } else if (newFilterOptions.status && newFilterOptions.status === 'open') { - setQueryParams({ sortField: SortFieldCase.createdAt }); - } - setFilters(newFilterOptions); - refreshCases(false); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [filterOptions, queryParams] - ); + const onFilterChangedCallback = useCallback( + (newFilterOptions: Partial) => { + if (newFilterOptions.status && newFilterOptions.status === 'closed') { + setQueryParams({ sortField: SortFieldCase.closedAt }); + } else if (newFilterOptions.status && newFilterOptions.status === 'open') { + setQueryParams({ sortField: SortFieldCase.createdAt }); + } + setFilters(newFilterOptions); + refreshCases(false); + }, + [filterOptions, queryParams] + ); - const memoizedGetCasesColumns = useMemo( - () => getCasesColumns(userCanCrud ? actions : [], filterOptions.status), - [actions, filterOptions.status, userCanCrud] - ); - const memoizedPagination = useMemo( - () => ({ - pageIndex: queryParams.page - 1, - pageSize: queryParams.perPage, - totalItemCount: data.total, - pageSizeOptions: [5, 10, 15, 20, 25], - }), - [data, queryParams] - ); + const memoizedGetCasesColumns = useMemo( + () => getCasesColumns(userCanCrud ? actions : [], filterOptions.status, isModal), + [actions, filterOptions.status, userCanCrud, isModal] + ); + const memoizedPagination = useMemo( + () => ({ + pageIndex: queryParams.page - 1, + pageSize: queryParams.perPage, + totalItemCount: data.total, + pageSizeOptions: [5, 10, 15, 20, 25], + }), + [data, queryParams] + ); - const sorting: EuiTableSortingType = { - sort: { field: queryParams.sortField, direction: queryParams.sortOrder }, - }; - const euiBasicTableSelectionProps = useMemo>( - () => ({ onSelectionChange: setSelectedCases }), - // eslint-disable-next-line react-hooks/exhaustive-deps - [selectedCases] - ); - const isCasesLoading = useMemo( - () => loading.indexOf('cases') > -1 || loading.indexOf('caseUpdate') > -1, - [loading] - ); - const isDataEmpty = useMemo(() => data.total === 0, [data]); + const sorting: EuiTableSortingType = { + sort: { field: queryParams.sortField, direction: queryParams.sortOrder }, + }; + const euiBasicTableSelectionProps = useMemo>( + () => ({ onSelectionChange: setSelectedCases }), + [selectedCases] + ); + const isCasesLoading = useMemo( + () => loading.indexOf('cases') > -1 || loading.indexOf('caseUpdate') > -1, + [loading] + ); + const isDataEmpty = useMemo(() => data.total === 0, [data]); - return ( - <> - {!isEmpty(actionsErrors) && ( - - )} - - - - - - - - - - } - titleTooltip={!isEmpty(actionsErrors) ? actionsErrors[0].title : ''} - urlSearch={urlSearch} - /> - - - - {i18n.CREATE_TITLE} - - - - - {(isCasesLoading || isDeleting || isUpdating) && !isDataEmpty && ( - - )} - - - {isCasesLoading && isDataEmpty ? ( -
- -
- ) : ( -
- - - - - {i18n.SHOWING_CASES(data.total ?? 0)} - - - - - {i18n.SHOWING_SELECTED_CASES(selectedCases.length)} - - {userCanCrud && ( - - {i18n.BULK_ACTIONS} - - )} - - {i18n.REFRESH} - - - - - {i18n.NO_CASES}} - titleSize="xs" - body={i18n.NO_CASES_BODY} - actions={ - - {i18n.ADD_NEW_CASE} - - } + const TableWrap = useMemo(() => (isModal ? 'span' : Panel), [isModal]); + return ( + <> + {!isEmpty(actionsErrors) && ( + + )} + {!isModal && ( + + + + + + + - } - onChange={tableOnChangeCallback} - pagination={memoizedPagination} - selection={userCanCrud ? euiBasicTableSelectionProps : {}} - sorting={sorting} - /> -
+ + + } + titleTooltip={!isEmpty(actionsErrors) ? actionsErrors[0].title : ''} + urlSearch={urlSearch} + /> + + + + {i18n.CREATE_TITLE} + + + + + )} + {(isCasesLoading || isDeleting || isUpdating) && !isDataEmpty && ( + )} -
- {confirmDeleteModal} - - ); -}); + + + {isCasesLoading && isDataEmpty ? ( +
+ +
+ ) : ( +
+ + + + + {i18n.SHOWING_CASES(data.total ?? 0)} + + + {!isModal && ( + + + {i18n.SHOWING_SELECTED_CASES(selectedCases.length)} + + {userCanCrud && ( + + {i18n.BULK_ACTIONS} + + )} + + {i18n.REFRESH} + + + )} + + + {i18n.NO_CASES}} + titleSize="xs" + body={i18n.NO_CASES_BODY} + actions={ + + {i18n.ADD_NEW_CASE} + + } + /> + } + onChange={tableOnChangeCallback} + pagination={memoizedPagination} + rowProps={(item) => + isModal + ? { + onClick: () => onRowClick(item.id), + } + : {} + } + selection={userCanCrud && !isModal ? euiBasicTableSelectionProps : undefined} + sorting={sorting} + /> +
+ )} +
+ {confirmDeleteModal} + + ); + } +); AllCases.displayName = 'AllCases'; diff --git a/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.test.tsx b/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.test.tsx new file mode 100644 index 0000000000000..a24cb6a87de74 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.test.tsx @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { mount } from 'enzyme'; +import React from 'react'; +import { AllCasesModal } from '.'; +import { TestProviders } from '../../../common/mock'; + +import { useGetCasesMockState, basicCaseId } from '../../containers/mock'; +import { useDeleteCases } from '../../containers/use_delete_cases'; +import { useGetCases } from '../../containers/use_get_cases'; +import { useGetCasesStatus } from '../../containers/use_get_cases_status'; +import { useUpdateCases } from '../../containers/use_bulk_update_case'; +import { EuiTableRow } from '@elastic/eui'; + +jest.mock('../../containers/use_bulk_update_case'); +jest.mock('../../containers/use_delete_cases'); +jest.mock('../../containers/use_get_cases'); +jest.mock('../../containers/use_get_cases_status'); + +const useDeleteCasesMock = useDeleteCases as jest.Mock; +const useGetCasesMock = useGetCases as jest.Mock; +const useGetCasesStatusMock = useGetCasesStatus as jest.Mock; +const useUpdateCasesMock = useUpdateCases as jest.Mock; +jest.mock('../../../common/lib/kibana', () => { + const originalModule = jest.requireActual('../../../common/lib/kibana'); + return { + ...originalModule, + useGetUserSavedObjectPermissions: jest.fn(), + }; +}); + +const onCloseCaseModal = jest.fn(); +const onRowClick = jest.fn(); +const defaultProps = { + onCloseCaseModal, + onRowClick, + showCaseModal: true, +}; +describe('AllCasesModal', () => { + const dispatchResetIsDeleted = jest.fn(); + const dispatchResetIsUpdated = jest.fn(); + const dispatchUpdateCaseProperty = jest.fn(); + const handleOnDeleteConfirm = jest.fn(); + const handleToggleModal = jest.fn(); + const refetchCases = jest.fn(); + const setFilters = jest.fn(); + const setQueryParams = jest.fn(); + const setSelectedCases = jest.fn(); + const updateBulkStatus = jest.fn(); + const fetchCasesStatus = jest.fn(); + + const defaultGetCases = { + ...useGetCasesMockState, + dispatchUpdateCaseProperty, + refetchCases, + setFilters, + setQueryParams, + setSelectedCases, + }; + const defaultDeleteCases = { + dispatchResetIsDeleted, + handleOnDeleteConfirm, + handleToggleModal, + isDeleted: false, + isDisplayConfirmDeleteModal: false, + isLoading: false, + }; + const defaultCasesStatus = { + countClosedCases: 0, + countOpenCases: 5, + fetchCasesStatus, + isError: false, + isLoading: true, + }; + const defaultUpdateCases = { + isUpdated: false, + isLoading: false, + isError: false, + dispatchResetIsUpdated, + updateBulkStatus, + }; + /* eslint-disable no-console */ + // Silence until enzyme fixed to use ReactTestUtils.act() + const originalError = console.error; + beforeAll(() => { + console.error = jest.fn(); + }); + afterAll(() => { + console.error = originalError; + }); + /* eslint-enable no-console */ + beforeEach(() => { + jest.resetAllMocks(); + useUpdateCasesMock.mockImplementation(() => defaultUpdateCases); + useGetCasesMock.mockImplementation(() => defaultGetCases); + useDeleteCasesMock.mockImplementation(() => defaultDeleteCases); + useGetCasesStatusMock.mockImplementation(() => defaultCasesStatus); + }); + + it('renders with unselectable rows', () => { + const wrapper = mount( + + + + ); + expect(wrapper.find(`[data-test-subj='all-cases-modal']`).exists()).toBeTruthy(); + expect(wrapper.find(EuiTableRow).first().prop('isSelectable')).toBeFalsy(); + }); + it('does not render modal if showCaseModal: false', () => { + const wrapper = mount( + + + + ); + expect(wrapper.find(`[data-test-subj='all-cases-modal']`).exists()).toBeFalsy(); + }); + it('onRowClick called when row is clicked', () => { + const wrapper = mount( + + + + ); + const firstRow = wrapper.find(EuiTableRow).first(); + firstRow.simulate('click'); + expect(onRowClick.mock.calls[0][0]).toEqual(basicCaseId); + }); + it('Closing modal calls onCloseCaseModal', () => { + const wrapper = mount( + + + + ); + const modalClose = wrapper.find('.euiModal__closeIcon').first(); + modalClose.simulate('click'); + expect(onCloseCaseModal).toBeCalled(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.tsx b/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.tsx new file mode 100644 index 0000000000000..d2ca0f0cd02ee --- /dev/null +++ b/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/index.tsx @@ -0,0 +1,56 @@ +/* + * 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 { + EuiModal, + EuiModalBody, + EuiModalHeader, + EuiModalHeaderTitle, + EuiOverlayMask, +} from '@elastic/eui'; +import { useGetUserSavedObjectPermissions } from '../../../common/lib/kibana'; +import { AllCases } from '../all_cases'; +import * as i18n from './translations'; + +interface AllCasesModalProps { + onCloseCaseModal: () => void; + showCaseModal: boolean; + onRowClick: (id: string) => void; +} + +export const AllCasesModalComponent = ({ + onCloseCaseModal, + onRowClick, + showCaseModal, +}: AllCasesModalProps) => { + const userPermissions = useGetUserSavedObjectPermissions(); + let modal; + if (showCaseModal) { + modal = ( + + + + {i18n.SELECT_CASE_TITLE} + + + + + + + ); + } + + return <>{modal}; +}; + +export const AllCasesModal = React.memo(AllCasesModalComponent); + +AllCasesModal.displayName = 'AllCasesModal'; diff --git a/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/translations.ts b/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/translations.ts new file mode 100644 index 0000000000000..e0f84d8541424 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cases/components/all_cases_modal/translations.ts @@ -0,0 +1,10 @@ +/* + * 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'; +export const SELECT_CASE_TITLE = i18n.translate('xpack.securitySolution.case.caseModal.title', { + defaultMessage: 'Select case to attach timeline', +}); diff --git a/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx b/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx index 5dfe12179b990..780de303c02d3 100644 --- a/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx +++ b/x-pack/plugins/security_solution/public/cases/pages/case_details.tsx @@ -10,7 +10,6 @@ import { useParams, Redirect } from 'react-router-dom'; import { WrapperPage } from '../../common/components/wrapper_page'; import { useGetUrlSearch } from '../../common/components/navigation/use_get_url_search'; import { useGetUserSavedObjectPermissions } from '../../common/lib/kibana'; -import { SpyRoute } from '../../common/utils/route/spy_routes'; import { getCaseUrl } from '../../common/components/link_to'; import { navTabs } from '../../app/home/home_navigations'; import { CaseView } from '../components/case_view'; @@ -36,7 +35,6 @@ export const CaseDetailsPage = React.memo(() => { )} - ) : null; }); diff --git a/x-pack/plugins/security_solution/public/common/mock/global_state.ts b/x-pack/plugins/security_solution/public/common/mock/global_state.ts index 4af39ade70d25..3e84e4035e15e 100644 --- a/x-pack/plugins/security_solution/public/common/mock/global_state.ts +++ b/x-pack/plugins/security_solution/public/common/mock/global_state.ts @@ -229,6 +229,7 @@ export const mockGlobalState: State = { status: TimelineStatus.active, }, }, + insertTimeline: null, }, /** * These state's are wrapped in `Immutable`, but for compatibility with the overall app architecture, diff --git a/x-pack/plugins/security_solution/public/common/mock/index.ts b/x-pack/plugins/security_solution/public/common/mock/index.ts index bdad0ab1712ab..30eb4c63f40b8 100644 --- a/x-pack/plugins/security_solution/public/common/mock/index.ts +++ b/x-pack/plugins/security_solution/public/common/mock/index.ts @@ -15,3 +15,4 @@ export * from './test_providers'; export * from './utils'; export * from './mock_ecs'; export * from './timeline_results'; +export * from './kibana_react'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx index ab8a24889e9bf..8ad32d6e2cad0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx @@ -33,14 +33,14 @@ const StatefulFlyoutHeader = React.memo( associateNote, createTimeline, description, - isFavorite, isDataInTimeline, isDatepickerLocked, - title, + isFavorite, noteIds, notesById, status, timelineId, + title, toggleLock, updateDescription, updateIsFavorite, @@ -61,15 +61,15 @@ const StatefulFlyoutHeader = React.memo( isDataInTimeline={isDataInTimeline} isDatepickerLocked={isDatepickerLocked} isFavorite={isFavorite} - title={title} noteIds={noteIds} status={status} timelineId={timelineId} + title={title} toggleLock={toggleLock} updateDescription={updateDescription} updateIsFavorite={updateIsFavorite} - updateTitle={updateTitle} updateNote={updateNote} + updateTitle={updateTitle} usersViewing={usersViewing} /> ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/header_with_close_button/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/header_with_close_button/index.test.tsx index 34a20e7215906..e5fc8b68b1cb7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/header_with_close_button/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/header_with_close_button/index.test.tsx @@ -10,22 +10,26 @@ import React from 'react'; import { TestProviders } from '../../../../common/mock'; import { FlyoutHeaderWithCloseButton } from '.'; -jest.mock('../../../../common/lib/kibana', () => { - return { - useKibana: jest.fn().mockReturnValue({ - services: { - application: { - capabilities: { - securitySolution: { - crud: true, - }, +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: jest.fn(), +})); +jest.mock('../../../../common/lib/kibana', () => ({ + ...jest.requireActual('../../../../common/lib/kibana'), + useKibana: jest.fn().mockReturnValue({ + services: { + application: { + capabilities: { + securitySolution: { + crud: true, }, }, }, - }), - useUiSetting$: jest.fn().mockReturnValue([]), - }; -}); + }, + }), + useUiSetting$: jest.fn().mockReturnValue([]), + useGetUserSavedObjectPermissions: jest.fn(), +})); describe('FlyoutHeaderWithCloseButton', () => { test('renders correctly against snapshot', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap index 4ed0b52fc0f14..4e6cce618880b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/__snapshots__/timeline.test.tsx.snap @@ -606,19 +606,40 @@ exports[`Timeline rendering renders correctly against snapshot 1`] = ` }, "filters": Array [], "uiSettings": Object { - "get": [Function], - "get$": [MockFunction], - "getAll": [MockFunction], - "getSaved$": [MockFunction], - "getUpdate$": [MockFunction], - "getUpdateErrors$": [MockFunction], - "isCustom": [MockFunction], - "isDeclared": [MockFunction], - "isDefault": [MockFunction], - "isOverridden": [MockFunction], - "overrideLocalDefault": [MockFunction], - "remove": [MockFunction], - "set": [MockFunction], + "get": [MockFunction] { + "calls": Array [ + Array [ + "query:allowLeadingWildcards", + ], + Array [ + "query:queryString:options", + ], + Array [ + "courier:ignoreFilterIfFieldNotInIndex", + ], + Array [ + "dateFormat:tz", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + ], + }, }, "updated$": Subject { "_isScalar": false, @@ -826,7 +847,7 @@ exports[`Timeline rendering renders correctly against snapshot 1`] = ` } inputId="timeline" /> - - + `; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx index 931623d080198..3110129867628 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx @@ -26,15 +26,25 @@ import { mockDataProviders } from './data_providers/mock/mock_data_providers'; import { StatefulTimeline, Props as StatefulTimelineProps } from './index'; import { Timeline } from './timeline'; -jest.mock('../../../common/lib/kibana'); +jest.mock('../../../common/lib/kibana', () => { + const originalModule = jest.requireActual('../../../common/lib/kibana'); + return { + ...originalModule, + useGetUserSavedObjectPermissions: jest.fn(), + }; +}); + const mockUseResizeObserver: jest.Mock = useResizeObserver as jest.Mock; jest.mock('use-resize-observer/polyfilled'); mockUseResizeObserver.mockImplementation(() => ({})); const mockUseSignalIndex: jest.Mock = useSignalIndex as jest.Mock; jest.mock('../../../alerts/containers/detection_engine/alerts/use_signal_index'); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: jest.fn(), +})); jest.mock('../flyout/header_with_close_button'); - describe('StatefulTimeline', () => { let props = {} as StatefulTimelineProps; const sort: Sort = { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.test.tsx index 0a70413b7ea29..2ffbae1f7eb5c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.test.tsx @@ -17,6 +17,14 @@ jest.mock('react-redux', () => { return { ...reactRedux, useDispatch: () => mockDispatch, + useSelector: jest + .fn() + .mockReturnValueOnce({ + timelineId: 'timeline-id', + timelineSavedObjectId: '34578-3497-5893-47589-34759', + timelineTitle: 'Timeline title', + }) + .mockReturnValue(null), }; }); const mockLocation = { @@ -25,17 +33,6 @@ const mockLocation = { search: '', state: '', }; -const mockLocationWithState = { - ...mockLocation, - state: { - insertTimeline: { - timelineId: 'timeline-id', - timelineSavedObjectId: '34578-3497-5893-47589-34759', - timelineTitle: 'Timeline title', - }, - }, -}; - const onTimelineChange = jest.fn(); const defaultProps = { isDisabled: false, @@ -43,18 +40,21 @@ const defaultProps = { }; describe('Insert timeline popover ', () => { - beforeEach(() => { - jest.resetAllMocks(); + afterEach(() => { + jest.clearAllMocks(); }); it('should insert a timeline when passed in the router state', () => { - jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocationWithState); mount(); - expect(mockDispatch).toBeCalledWith({ + expect(mockDispatch.mock.calls[0][0]).toEqual({ payload: { id: 'timeline-id', show: false }, type: 'x-pack/security_solution/local/timeline/SHOW_TIMELINE', }); expect(onTimelineChange).toBeCalledWith('Timeline title', '34578-3497-5893-47589-34759'); + expect(mockDispatch.mock.calls[1][0]).toEqual({ + payload: null, + type: 'x-pack/security_solution/local/timeline/SET_INSERT_TIMELINE', + }); }); it('should do nothing when router state', () => { jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx index ed4d742bb8b4d..de199d9a1cc2e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/index.tsx @@ -6,14 +6,15 @@ import { EuiButtonIcon, EuiPopover, EuiSelectableOption, EuiToolTip } from '@elastic/eui'; import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; -import { useLocation } from 'react-router-dom'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { OpenTimelineResult } from '../../open_timeline/types'; import { SelectableTimeline } from '../selectable_timeline'; import * as i18n from '../translations'; -import { timelineActions } from '../../../../timelines/store/timeline'; +import { timelineActions, timelineSelectors } from '../../../../timelines/store/timeline'; import { TimelineType } from '../../../../../common/types/timeline'; +import { State } from '../../../../common/store'; +import { setInsertTimeline } from '../../../store/timeline/actions'; interface InsertTimelinePopoverProps { isDisabled: boolean; @@ -21,14 +22,6 @@ interface InsertTimelinePopoverProps { onTimelineChange: (timelineTitle: string, timelineId: string | null) => void; } -interface RouterState { - insertTimeline: { - timelineId: string; - timelineSavedObjectId: string; - timelineTitle: string; - }; -} - type Props = InsertTimelinePopoverProps; export const InsertTimelinePopoverComponent: React.FC = ({ @@ -38,22 +31,18 @@ export const InsertTimelinePopoverComponent: React.FC = ({ }) => { const dispatch = useDispatch(); const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const { state } = useLocation(); - const [routerState, setRouterState] = useState(state ?? null); + const insertTimeline = useSelector((state: State) => { + return timelineSelectors.selectInsertTimeline(state); + }); useEffect(() => { - if (routerState && routerState.insertTimeline) { - dispatch( - timelineActions.showTimeline({ id: routerState.insertTimeline.timelineId, show: false }) - ); - onTimelineChange( - routerState.insertTimeline.timelineTitle, - routerState.insertTimeline.timelineSavedObjectId - ); - setRouterState(null); + if (insertTimeline != null) { + dispatch(timelineActions.showTimeline({ id: insertTimeline.timelineId, show: false })); + onTimelineChange(insertTimeline.timelineTitle, insertTimeline.timelineSavedObjectId); + dispatch(setInsertTimeline(null)); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [routerState]); + }, [insertTimeline, dispatch]); const handleClosePopover = useCallback(() => { setIsPopoverOpen(false); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx index 0f9e64082a603..6269bc1b4a1a3 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/insert_timeline_popover/use_insert_timeline.tsx @@ -17,7 +17,7 @@ export const useInsertTimeline = (form: FormHook, fieldNa }); const handleOnTimelineChange = useCallback( (title: string, id: string | null) => { - const builtLink = `${basePath}/app/siem#/timelines?timeline=(id:'${id}',isOpen:!t)`; + const builtLink = `${basePath}/app/security#/timelines?timeline=(id:'${id}',isOpen:!t)`; const currentValue = form.getFormData()[fieldName]; const newValue: string = [ currentValue.slice(0, cursorPosition.start), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx index 9e74298f3aca9..00a0e57324841 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/helpers.tsx @@ -21,7 +21,7 @@ import React, { useCallback } from 'react'; import uuid from 'uuid'; import styled from 'styled-components'; import { useHistory } from 'react-router-dom'; -import { useSelector } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { TimelineTypeLiteral, @@ -41,6 +41,7 @@ import { AssociateNote, UpdateNote } from '../../notes/helpers'; import { NOTES_PANEL_WIDTH } from './notes_size'; import { ButtonContainer, DescriptionContainer, LabelText, NameField, StyledStar } from './styles'; import * as i18n from './translations'; +import { setInsertTimeline } from '../../../store/timeline/actions'; import { useCreateTimelineButton } from './use_create_timeline'; export const historyToolTip = 'The chronological history of actions related to this timeline'; @@ -144,23 +145,25 @@ interface NewCaseProps { export const NewCase = React.memo( ({ onClosePopover, timelineId, timelineStatus, timelineTitle }) => { const history = useHistory(); + const dispatch = useDispatch(); const { savedObjectId } = useSelector((state: State) => timelineSelectors.selectTimeline(state, timelineId) ); + const handleClick = useCallback(() => { onClosePopover(); history.push({ pathname: `/${SiemPageName.case}/create`, - state: { - insertTimeline: { - timelineId, - timelineSavedObjectId: savedObjectId, - timelineTitle: timelineTitle.length > 0 ? timelineTitle : i18n.UNTITLED_TIMELINE, - }, - }, }); + dispatch( + setInsertTimeline({ + timelineId, + timelineSavedObjectId: savedObjectId, + timelineTitle: timelineTitle.length > 0 ? timelineTitle : i18n.UNTITLED_TIMELINE, + }) + ); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [onClosePopover, history, timelineId, timelineTitle]); + }, [dispatch, onClosePopover, history, timelineId, timelineTitle]); return ( ( ); NewCase.displayName = 'NewCase'; +interface ExistingCaseProps { + onClosePopover: () => void; + onOpenCaseModal: () => void; + timelineStatus: TimelineStatus; +} +export const ExistingCase = React.memo( + ({ onClosePopover, onOpenCaseModal, timelineStatus }) => { + const handleClick = useCallback(() => { + onClosePopover(); + onOpenCaseModal(); + }, [onOpenCaseModal, onClosePopover]); + + return ( + <> + + {i18n.ATTACH_TIMELINE_TO_EXISTING_CASE} + + + ); + } +); +ExistingCase.displayName = 'ExistingCase'; + export interface NewTimelineProps { createTimeline?: CreateTimeline; closeGearMenu?: () => void; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.test.tsx index 952a7c104e19e..505d0b8cba854 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.test.tsx @@ -6,33 +6,43 @@ import { mount } from 'enzyme'; import React from 'react'; -import { Provider as ReduxStoreProvider } from 'react-redux'; - import { TimelineStatus } from '../../../../../common/types/timeline'; import { mockGlobalState, apolloClientObservable, SUB_PLUGINS_REDUCER, + TestProviders, } from '../../../../common/mock'; import { createStore, State } from '../../../../common/store'; import { useThrottledResizeObserver } from '../../../../common/components/utils'; import { Properties, showDescriptionThreshold, showNotesThreshold } from '.'; +import { SiemPageName } from '../../../../app/types'; +import { setInsertTimeline } from '../../../store/timeline/actions'; +export { nextTick } from '../../../../../../../test_utils'; + +import { act } from 'react-dom/test-utils'; -jest.mock('../../../../common/lib/kibana', () => ({ - useKibana: jest.fn().mockReturnValue({ - services: { - application: { - capabilities: { - securitySolution: { - crud: true, +jest.mock('../../../../common/lib/kibana', () => { + const originalModule = jest.requireActual('../../../../common/lib/kibana'); + return { + ...originalModule, + useKibana: jest.fn().mockReturnValue({ + services: { + application: { + capabilities: { + securitySolution: { + crud: true, + }, }, }, }, - }, - }), - useUiSetting$: jest.fn().mockReturnValue([]), -})); + }), + useUiSetting$: jest.fn().mockReturnValue([]), + useGetUserSavedObjectPermissions: jest.fn(), + }; +}); +const mockDispatch = jest.fn(); jest.mock('../../../../common/components/utils', () => { return { useThrottledResizeObserver: jest.fn(), @@ -48,21 +58,44 @@ jest.mock('react-redux', () => { }; }); -jest.mock('react-router-dom', () => { - const originalModule = jest.requireActual('react-router-dom'); +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useDispatch: () => mockDispatch, + useSelector: jest.fn().mockReturnValue({ savedObjectId: '1', urlState: {} }), +})); +const mockHistoryPush = jest.fn(); - return { - ...originalModule, - useHistory: jest.fn(), - }; -}); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: () => ({ + push: mockHistoryPush, + }), +})); jest.mock('./use_create_timeline', () => ({ useCreateTimelineButton: jest.fn().mockReturnValue({ getButton: jest.fn() }), })); - +const usersViewing = ['elastic']; +const defaultProps = { + associateNote: jest.fn(), + createTimeline: jest.fn(), + isDataInTimeline: false, + isDatepickerLocked: false, + isFavorite: false, + title: '', + description: '', + getNotesByIds: jest.fn(), + noteIds: [], + status: TimelineStatus.active, + timelineId: 'abc', + toggleLock: jest.fn(), + updateDescription: jest.fn(), + updateIsFavorite: jest.fn(), + updateTitle: jest.fn(), + updateNote: jest.fn(), + usersViewing, +}; describe('Properties', () => { - const usersViewing = ['elastic']; const state: State = mockGlobalState; let mockedWidth = 1000; let store = createStore(state, SUB_PLUGINS_REDUCER, apolloClientObservable); @@ -75,27 +108,9 @@ describe('Properties', () => { test('renders correctly', () => { const wrapper = mount( - - - + + + ); wrapper.find('[data-test-subj="settings-gear"]').at(0).simulate('click'); @@ -104,31 +119,16 @@ describe('Properties', () => { expect(wrapper.find('button[data-test-subj="attach-timeline-case"]').prop('disabled')).toEqual( false ); + expect( + wrapper.find('button[data-test-subj="attach-timeline-existing-case"]').prop('disabled') + ).toEqual(false); }); test('renders correctly draft timeline', () => { const wrapper = mount( - - - + + + ); wrapper.find('[data-test-subj="settings-gear"]').at(0).simulate('click'); @@ -136,31 +136,16 @@ describe('Properties', () => { expect(wrapper.find('button[data-test-subj="attach-timeline-case"]').prop('disabled')).toEqual( true ); + expect( + wrapper.find('button[data-test-subj="attach-timeline-existing-case"]').prop('disabled') + ).toEqual(true); }); test('it renders an empty star icon when it is NOT a favorite', () => { const wrapper = mount( - - - + + + ); expect(wrapper.find('[data-test-subj="timeline-favorite-empty-star"]').exists()).toEqual(true); @@ -168,27 +153,9 @@ describe('Properties', () => { test('it renders a filled star icon when it is a favorite', () => { const wrapper = mount( - - - + + + ); expect(wrapper.find('[data-test-subj="timeline-favorite-filled-star"]').exists()).toEqual(true); @@ -198,27 +165,9 @@ describe('Properties', () => { const title = 'foozle'; const wrapper = mount( - - - + + + ); expect(wrapper.find('[data-test-subj="timeline-title"]').first().props().value).toEqual(title); @@ -226,27 +175,9 @@ describe('Properties', () => { test('it renders the date picker with the lock icon', () => { const wrapper = mount( - - - + + + ); expect( @@ -259,27 +190,9 @@ describe('Properties', () => { test('it renders the lock icon when isDatepickerLocked is true', () => { const wrapper = mount( - - - + + + ); expect( wrapper @@ -291,27 +204,9 @@ describe('Properties', () => { test('it renders the unlock icon when isDatepickerLocked is false', () => { const wrapper = mount( - - - + + + ); expect( wrapper @@ -328,27 +223,9 @@ describe('Properties', () => { (useThrottledResizeObserver as jest.Mock).mockReturnValue({ width: showDescriptionThreshold }); const wrapper = mount( - - - + + + ); expect( @@ -369,27 +246,9 @@ describe('Properties', () => { }); const wrapper = mount( - - - + + + ); expect( @@ -404,27 +263,9 @@ describe('Properties', () => { mockedWidth = showNotesThreshold; const wrapper = mount( - - - + + + ); expect( @@ -442,27 +283,9 @@ describe('Properties', () => { }); const wrapper = mount( - - - + + + ); expect( @@ -475,27 +298,9 @@ describe('Properties', () => { test('it renders a settings icon', () => { const wrapper = mount( - - - + + + ); expect(wrapper.find('[data-test-subj="settings-gear"]').exists()).toEqual(true); @@ -505,27 +310,9 @@ describe('Properties', () => { const title = 'port scan'; const wrapper = mount( - - - + + + ); expect(wrapper.find('[data-test-subj="avatar"]').exists()).toEqual(true); @@ -533,29 +320,45 @@ describe('Properties', () => { test('it does NOT render an avatar for the current user viewing the timeline when it does NOT have a title', () => { const wrapper = mount( - - - + + + ); expect(wrapper.find('[data-test-subj="avatar"]').exists()).toEqual(false); }); + + test('insert timeline - new case', () => { + const wrapper = mount( + + + + ); + wrapper.find('[data-test-subj="settings-gear"]').at(0).simulate('click'); + wrapper.find('[data-test-subj="attach-timeline-case"]').first().simulate('click'); + + expect(mockHistoryPush).toBeCalledWith({ pathname: `/${SiemPageName.case}/create` }); + expect(mockDispatch).toBeCalledWith( + setInsertTimeline({ + timelineId: defaultProps.timelineId, + timelineSavedObjectId: '1', + timelineTitle: 'coolness', + }) + ); + }); + + test('insert timeline - existing case', async () => { + const wrapper = mount( + + + + ); + wrapper.find('[data-test-subj="settings-gear"]').at(0).simulate('click'); + wrapper.find('[data-test-subj="attach-timeline-existing-case"]').first().simulate('click'); + + await act(async () => { + await Promise.resolve({}); + }); + expect(wrapper.find('[data-test-subj="all-cases-modal"]').exists()).toBeTruthy(); + }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx index d4c43c9929f0e..be79c0773bf88 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/index.tsx @@ -6,6 +6,8 @@ import React, { useState, useCallback, useMemo } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; import { TimelineStatus, TimelineTypeLiteral } from '../../../../../common/types/timeline'; import { useThrottledResizeObserver } from '../../../../common/components/utils'; import { Note } from '../../../../common/lib/note'; @@ -16,6 +18,12 @@ import { AssociateNote, UpdateNote } from '../../notes/helpers'; import { TimelineProperties } from './styles'; import { PropertiesRight } from './properties_right'; import { PropertiesLeft } from './properties_left'; +import { AllCasesModal } from '../../../../cases/components/all_cases_modal'; +import { SiemPageName } from '../../../../app/types'; +import * as i18n from './translations'; +import { State } from '../../../../common/store'; +import { timelineSelectors } from '../../../store/timeline'; +import { setInsertTimeline } from '../../../store/timeline/actions'; type CreateTimeline = ({ id, @@ -87,6 +95,7 @@ export const Properties = React.memo( const [showActions, setShowActions] = useState(false); const [showNotes, setShowNotes] = useState(false); const [showTimelineModal, setShowTimelineModal] = useState(false); + const dispatch = useDispatch(); const onButtonClick = useCallback(() => setShowActions(!showActions), [showActions]); const onToggleShowNotes = useCallback(() => setShowNotes(!showNotes), [showNotes]); @@ -98,6 +107,30 @@ export const Properties = React.memo( setShowTimelineModal(true); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const [showCaseModal, setShowCaseModal] = useState(false); + const onCloseCaseModal = useCallback(() => setShowCaseModal(false), []); + const onOpenCaseModal = useCallback(() => setShowCaseModal(true), []); + const history = useHistory(); + const currentTimeline = useSelector((state: State) => + timelineSelectors.selectTimeline(state, timelineId) + ); + + const onRowClick = useCallback( + (id: string) => { + onCloseCaseModal(); + history.push({ + pathname: `/${SiemPageName.case}/${id}`, + }); + dispatch( + setInsertTimeline({ + timelineId, + timelineSavedObjectId: currentTimeline.savedObjectId, + timelineTitle: title.length > 0 ? title : i18n.UNTITLED_TIMELINE, + }) + ); + }, + [onCloseCaseModal, currentTimeline, dispatch, history, timelineId, title] + ); const datePickerWidth = useMemo( () => @@ -144,6 +177,7 @@ export const Properties = React.memo( onButtonClick={onButtonClick} onClosePopover={onClosePopover} onCloseTimelineModal={onCloseTimelineModal} + onOpenCaseModal={onOpenCaseModal} onOpenTimelineModal={onOpenTimelineModal} onToggleShowNotes={onToggleShowNotes} showActions={showActions} @@ -159,6 +193,11 @@ export const Properties = React.memo( updateNote={updateNote} usersViewing={usersViewing} /> + ); } diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.test.tsx index 58927e7b236e7..e297a3cc595d6 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.test.tsx @@ -28,9 +28,10 @@ jest.mock('./new_template_timeline', () => { jest.mock('./helpers', () => { return { Description: jest.fn().mockReturnValue(
), - NotesButton: jest.fn().mockReturnValue(
), + ExistingCase: jest.fn().mockReturnValue(
), NewCase: jest.fn().mockReturnValue(
), NewTimeline: jest.fn().mockReturnValue(
), + NotesButton: jest.fn().mockReturnValue(
), }; }); @@ -62,6 +63,7 @@ describe('Properties Right', () => { noteIds: [], onToggleShowNotes: jest.fn(), onCloseTimelineModal: jest.fn(), + onOpenCaseModal: jest.fn(), onOpenTimelineModal: jest.fn(), status: TimelineStatus.active, showTimelineModal: false, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx index f9ab7fb2e69ae..a9baf73676ffb 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/properties/properties_right.tsx @@ -14,6 +14,7 @@ import { EuiToolTip, EuiAvatar, } from '@elastic/eui'; +import { NewTimeline, Description, NotesButton, NewCase, ExistingCase } from './helpers'; import { disableTemplate } from '../../../../../common/constants'; import { TimelineStatus } from '../../../../../common/types/timeline'; @@ -27,7 +28,6 @@ import { OpenTimelineModalButton } from '../../open_timeline/open_timeline_modal import { OpenTimelineModal } from '../../open_timeline/open_timeline_modal'; import * as i18n from './translations'; -import { Description, NotesButton, NewCase, NewTimeline } from './helpers'; import { NewTemplateTimeline } from './new_template_timeline'; export const PropertiesRightStyle = styled(EuiFlexGroup)` @@ -64,54 +64,56 @@ Avatar.displayName = 'Avatar'; type UpdateDescription = ({ id, description }: { id: string; description: string }) => void; export type UpdateNote = (note: Note) => void; -export interface PropertiesRightComponentProps { - onButtonClick: () => void; - onClosePopover: () => void; - showActions: boolean; - timelineId: string; - isDataInTimeline: boolean; - showNotes: boolean; - showNotesFromWidth: boolean; - showDescription: boolean; - showUsersView: boolean; - usersViewing: string[]; - description: string; - updateDescription: UpdateDescription; +interface PropertiesRightComponentProps { associateNote: AssociateNote; + description: string; getNotesByIds: (noteIds: string[]) => Note[]; + isDataInTimeline: boolean; noteIds: string[]; - onToggleShowNotes: () => void; + onButtonClick: () => void; + onClosePopover: () => void; onCloseTimelineModal: () => void; + onOpenCaseModal: () => void; onOpenTimelineModal: () => void; + onToggleShowNotes: () => void; + showActions: boolean; + showDescription: boolean; + showNotes: boolean; + showNotesFromWidth: boolean; showTimelineModal: boolean; + showUsersView: boolean; status: TimelineStatus; + timelineId: string; title: string; + updateDescription: UpdateDescription; updateNote: UpdateNote; + usersViewing: string[]; } const PropertiesRightComponent: React.FC = ({ - onButtonClick, - showActions, - onClosePopover, - timelineId, - isDataInTimeline, - showNotesFromWidth, - showNotes, - showDescription, - showUsersView, - usersViewing, - description, - updateDescription, associateNote, + description, getNotesByIds, + isDataInTimeline, noteIds, + onButtonClick, + onClosePopover, + onCloseTimelineModal, + onOpenCaseModal, + onOpenTimelineModal, onToggleShowNotes, - updateNote, + showActions, + showDescription, + showNotes, + showNotesFromWidth, showTimelineModal, + showUsersView, status, - onCloseTimelineModal, - onOpenTimelineModal, + timelineId, title, + updateDescription, + updateNote, + usersViewing, }) => { const uiCapabilities = useKibana().services.application.capabilities; const capabilitiesCanUserCRUD: boolean = !!uiCapabilities.securitySolution.crud; @@ -170,6 +172,13 @@ const PropertiesRightComponent: React.FC = ({ timelineStatus={status} /> + + + ({})); +jest.mock('react-router-dom', () => { + const originalModule = jest.requireActual('react-router-dom'); + return { + ...originalModule, + useHistory: jest.fn(), + }; +}); +jest.mock('../../../common/lib/kibana', () => { + const originalModule = jest.requireActual('../../../common/lib/kibana'); + return { + ...originalModule, + useKibana: jest.fn().mockReturnValue({ + services: { + uiSettings: { + get: jest.fn(), + }, + savedObjects: { + client: {}, + }, + }, + }), + useGetUserSavedObjectPermissions: jest.fn(), + }; +}); describe('Timeline', () => { let props = {} as TimelineComponentProps; const sort: Sort = { diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts index e8b5ba68eecdf..c5df017604b0c 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts @@ -17,6 +17,7 @@ import { KueryFilterQuery, SerializedFilterQuery } from '../../../common/store/t import { EventType, KqlMode, TimelineModel, ColumnHeaderOptions } from './model'; import { TimelineNonEcsData } from '../../../graphql/types'; import { TimelineTypeLiteral } from '../../../../common/types/timeline'; +import { InsertTimeline } from './types'; const actionCreator = actionCreatorFactory('x-pack/security_solution/local/timeline'); @@ -98,6 +99,8 @@ export const addTimeline = actionCreator<{ timeline: TimelineModel; }>('ADD_TIMELINE'); +export const setInsertTimeline = actionCreator('SET_INSERT_TIMELINE'); + export const startTimelineSaving = actionCreator<{ id: string; }>('START_TIMELINE_SAVING'); diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts index 97ac423cee653..03e9ca176ee82 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/helpers.ts @@ -36,6 +36,7 @@ export const initialTimelineState: TimelineState = { newTimelineModel: null, }, showCallOutUnauthorizedMsg: false, + insertTimeline: null, }; interface AddTimelineHistoryParams { diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts index 3666968e8ab92..5e314f1597451 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.ts @@ -6,14 +6,17 @@ import { reducerWithInitialState } from 'typescript-fsa-reducers'; import { - addTimeline, addHistory, addNote, addNoteToEvent, addProvider, + addTimeline, applyDeltaToColumnWidth, applyDeltaToWidth, applyKqlFilterQuery, + clearEventsDeleted, + clearEventsLoading, + clearSelected, createTimeline, dataProviderEdited, endTimelineSaving, @@ -21,12 +24,12 @@ import { removeColumn, removeProvider, setEventsDeleted, - clearEventsDeleted, setEventsLoading, - clearEventsLoading, + setFilters, + setInsertTimeline, setKqlFilterQueryDraft, + setSavedQueryId, setSelected, - clearSelected, showCallOutUnauthorizedMsg, showTimeline, startTimelineSaving, @@ -37,9 +40,11 @@ import { updateDataProviderExcluded, updateDataProviderKqlQuery, updateDescription, + updateEventType, updateHighlightedDropAndProviderId, updateIsFavorite, updateIsLive, + updateIsLoading, updateItemsPerPage, updateItemsPerPageOptions, updateKqlMode, @@ -50,10 +55,6 @@ import { updateTimeline, updateTitle, upsertColumn, - updateIsLoading, - setSavedQueryId, - setFilters, - updateEventType, } from './actions'; import { addNewTimeline, @@ -107,6 +108,7 @@ export const initialTimelineState: TimelineState = { newTimelineModel: null, }, showCallOutUnauthorizedMsg: false, + insertTimeline: null, }; /** The reducer for all timeline actions */ @@ -486,4 +488,8 @@ export const timelineReducer = reducerWithInitialState(initialTimelineState) timelineById: state.timelineById, }), })) + .case(setInsertTimeline, (state, insertTimeline) => ({ + ...state, + insertTimeline, + })) .build(); diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/selectors.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/selectors.ts index af7ac075468c3..a80a28660e28b 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/selectors.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/selectors.ts @@ -10,7 +10,7 @@ import { isFromKueryExpressionValid } from '../../../common/lib/keury'; import { State } from '../../../common/store/types'; import { TimelineModel } from './model'; -import { AutoSavedWarningMsg, TimelineById } from './types'; +import { AutoSavedWarningMsg, InsertTimeline, TimelineById } from './types'; const selectTimelineById = (state: State): TimelineById => state.timeline.timelineById; @@ -22,6 +22,9 @@ const selectCallOutUnauthorizedMsg = (state: State): boolean => export const selectTimeline = (state: State, timelineId: string): TimelineModel => state.timeline.timelineById[timelineId]; +export const selectInsertTimeline = (state: State): InsertTimeline | null => + state.timeline.insertTimeline; + export const autoSaveMsgSelector = createSelector(selectAutoSaveMsg, (autoSaveMsg) => autoSaveMsg); export const timelineByIdSelector = createSelector( diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/types.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/types.ts index 1cc4517d2c964..aa6c308614287 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/types.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/types.ts @@ -16,6 +16,12 @@ export interface TimelineById { [id: string]: TimelineModel; } +export interface InsertTimeline { + timelineId: string; + timelineSavedObjectId: string | null; + timelineTitle: string; +} + export const EMPTY_TIMELINE_BY_ID: TimelineById = {}; // stable reference /** The state of all timelines is stored here */ @@ -23,6 +29,7 @@ export interface TimelineState { timelineById: TimelineById; autoSavedWarningMsg: AutoSavedWarningMsg; showCallOutUnauthorizedMsg: boolean; + insertTimeline: InsertTimeline | null; } export interface ActionTimeline extends Action { From f4cfa491d8a2acbcd0365952cb6a893bd534c55f Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 9 Jun 2020 12:11:53 -0700 Subject: [PATCH 08/53] Prefer using npm_execpath when spawning Yarn (#68673) Prevents instances where an incorrect version of Yarn is used from a parent directory containing node_modules. Signed-off-by: Tyler Smalley --- packages/kbn-pm/dist/index.js | 9 +++++---- packages/kbn-pm/src/utils/scripts.ts | 10 ++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 93152ef1b71dc..ef2b7e7c06a25 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -55242,6 +55242,7 @@ __webpack_require__.r(__webpack_exports__); * under the License. */ +const YARN_EXEC = process.env.npm_execpath || 'yarn'; /** * Install all dependencies in the given directory @@ -55250,7 +55251,7 @@ async function installInDir(directory, extraArgs = []) { const options = ['install', '--non-interactive', ...extraArgs]; // We pass the mutex flag to ensure only one instance of yarn runs at any // given time (e.g. to avoid conflicts). - await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', options, { + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])(YARN_EXEC, options, { cwd: directory }); } @@ -55262,7 +55263,7 @@ async function runScriptInPackage(script, args, pkg) { const execOpts = { cwd: pkg.path }; - await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['run', script, ...args], execOpts); + await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])(YARN_EXEC, ['run', script, ...args], execOpts); } /** * Run script in the given directory @@ -55277,7 +55278,7 @@ function runScriptInPackageStreaming({ const execOpts = { cwd: pkg.path }; - return Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawnStreaming"])('yarn', ['run', script, ...args], execOpts, { + return Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawnStreaming"])(YARN_EXEC, ['run', script, ...args], execOpts, { prefix: pkg.name, debug }); @@ -55285,7 +55286,7 @@ function runScriptInPackageStreaming({ async function yarnWorkspacesInfo(directory) { const { stdout - } = await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])('yarn', ['--json', 'workspaces', 'info'], { + } = await Object(_child_process__WEBPACK_IMPORTED_MODULE_0__["spawn"])(YARN_EXEC, ['--json', 'workspaces', 'info'], { cwd: directory, stdio: 'pipe' }); diff --git a/packages/kbn-pm/src/utils/scripts.ts b/packages/kbn-pm/src/utils/scripts.ts index 728ac4287b1ce..6b1dc729906f2 100644 --- a/packages/kbn-pm/src/utils/scripts.ts +++ b/packages/kbn-pm/src/utils/scripts.ts @@ -20,6 +20,8 @@ import { spawn, spawnStreaming } from './child_process'; import { Project } from './project'; +const YARN_EXEC = process.env.npm_execpath || 'yarn'; + interface WorkspaceInfo { location: string; workspaceDependencies: string[]; @@ -37,7 +39,7 @@ export async function installInDir(directory: string, extraArgs: string[] = []) // We pass the mutex flag to ensure only one instance of yarn runs at any // given time (e.g. to avoid conflicts). - await spawn('yarn', options, { + await spawn(YARN_EXEC, options, { cwd: directory, }); } @@ -50,7 +52,7 @@ export async function runScriptInPackage(script: string, args: string[], pkg: Pr cwd: pkg.path, }; - await spawn('yarn', ['run', script, ...args], execOpts); + await spawn(YARN_EXEC, ['run', script, ...args], execOpts); } /** @@ -71,14 +73,14 @@ export function runScriptInPackageStreaming({ cwd: pkg.path, }; - return spawnStreaming('yarn', ['run', script, ...args], execOpts, { + return spawnStreaming(YARN_EXEC, ['run', script, ...args], execOpts, { prefix: pkg.name, debug, }); } export async function yarnWorkspacesInfo(directory: string): Promise { - const { stdout } = await spawn('yarn', ['--json', 'workspaces', 'info'], { + const { stdout } = await spawn(YARN_EXEC, ['--json', 'workspaces', 'info'], { cwd: directory, stdio: 'pipe', }); From ccb607303b4f5d76c13f941703611854f40188c8 Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Tue, 9 Jun 2020 15:16:14 -0500 Subject: [PATCH 09/53] [Uptime] Fix race on overview page query (#67843) Fixes https://github.com/elastic/kibana/issues/67842 by requerying during the refine phase to see if a newer matching doc has come in. --- .../refine_potential_matches.test.ts | 112 ++++++++++++++++++ .../server/lib/requests/search/fetch_chunk.ts | 4 +- .../requests/search/find_potential_matches.ts | 44 +------ .../search/refine_potential_matches.ts | 90 +++++++++----- 4 files changed, 174 insertions(+), 76 deletions(-) create mode 100644 x-pack/plugins/uptime/server/lib/requests/search/__tests__/refine_potential_matches.test.ts diff --git a/x-pack/plugins/uptime/server/lib/requests/search/__tests__/refine_potential_matches.test.ts b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/refine_potential_matches.test.ts new file mode 100644 index 0000000000000..283f5fb8909f6 --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/requests/search/__tests__/refine_potential_matches.test.ts @@ -0,0 +1,112 @@ +/* + * 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 { fullyMatchingIds } from '../refine_potential_matches'; +import { MonitorLocCheckGroup } from '..'; + +const mockQueryResult = (opts: { latestSummary: any; latestMatching: any }) => { + return { + aggregations: { + monitor: { + buckets: [ + { + key: 'my-monitor', + location: { + buckets: [ + { + key: 'my-location', + summaries: { + latest: { + hits: { + hits: [ + { + _source: opts.latestSummary, + }, + ], + }, + }, + }, + latest_matching: { + top: { + hits: { + hits: [ + { + _source: opts.latestMatching, + }, + ], + }, + }, + }, + }, + ], + }, + }, + ], + }, + }, + }; +}; + +describe('fully matching IDs', () => { + it('should exclude items whose latest result does not match', () => { + const queryRes = mockQueryResult({ + latestSummary: { + '@timestamp': '2020-06-04T12:39:54.698-0500', + monitor: { + check_group: 'latest-summary-check-group', + }, + summary: { + up: 1, + down: 0, + }, + }, + latestMatching: { + '@timestamp': '2019-06-04T12:39:54.698-0500', + summary: { + up: 1, + down: 0, + }, + }, + }); + const res = fullyMatchingIds(queryRes, undefined); + const expected = new Map(); + expect(res).toEqual(expected); + }); + + it('should include items whose latest result does match', () => { + const queryRes = mockQueryResult({ + latestSummary: { + '@timestamp': '2020-06-04T12:39:54.698-0500', + monitor: { + check_group: 'latest-summary-check-group', + }, + summary: { + up: 1, + down: 0, + }, + }, + latestMatching: { + '@timestamp': '2020-06-04T12:39:54.698-0500', + summary: { + up: 1, + down: 0, + }, + }, + }); + const res = fullyMatchingIds(queryRes, undefined); + const expected = new Map(); + expected.set('my-monitor', [ + { + checkGroup: 'latest-summary-check-group', + location: 'my-location', + monitorId: 'my-monitor', + status: 'up', + summaryTimestamp: new Date('2020-06-04T12:39:54.698-0500'), + }, + ]); + expect(res).toEqual(expected); + }); +}); diff --git a/x-pack/plugins/uptime/server/lib/requests/search/fetch_chunk.ts b/x-pack/plugins/uptime/server/lib/requests/search/fetch_chunk.ts index 77676ac9a6373..2a5f1f1261cb3 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/fetch_chunk.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/fetch_chunk.ts @@ -26,12 +26,12 @@ export const fetchChunk: ChunkFetcher = async ( searchAfter: any, size: number ): Promise => { - const { monitorIds, checkGroups, searchAfter: foundSearchAfter } = await findPotentialMatches( + const { monitorIds, searchAfter: foundSearchAfter } = await findPotentialMatches( queryContext, searchAfter, size ); - const matching = await refinePotentialMatches(queryContext, monitorIds, checkGroups); + const matching = await refinePotentialMatches(queryContext, monitorIds); return { monitorGroups: matching, diff --git a/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts index a3e7324086073..ac4ff91230b95 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/find_potential_matches.ts @@ -8,12 +8,8 @@ import { get, set } from 'lodash'; import { CursorDirection } from '../../../../common/runtime_types'; 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. -// Note that these check groups may not be the most recent groups for the matching monitor ID! We'll filter those /** - * This is the first phase of the query. In it, we find the most recent check groups that matched the given query. - * Note that these check groups may not be the most recent groups for the matching monitor ID. They'll be filtered - * out in the next phase. + * This is the first phase of the query. In it, we find all monitor IDs that have ever matched the given filters. * @param queryContext the data and resources needed to perform the query * @param searchAfter indicates where Elasticsearch should continue querying on subsequent requests, if at all * @param size the minimum size of the matches to chunk @@ -24,29 +20,14 @@ export const findPotentialMatches = async ( size: number ) => { const queryResult = await query(queryContext, searchAfter, size); - const checkGroups = new Set(); const monitorIds: string[] = []; get(queryResult, 'aggregations.monitors.buckets', []).forEach((b: any) => { const monitorId = b.key.monitor_id; monitorIds.push(monitorId); - - // Doc count can be zero if status filter optimization does not match - if (b.doc_count > 0) { - // Here we grab the most recent 2 check groups per location and add them to the list. - // Why 2? Because the most recent one may be a partial result from mode: all, and hence not match a summary doc. - b.locations.buckets.forEach((lb: any) => { - lb.ips.buckets.forEach((ib: any) => { - ib.top.hits.hits.forEach((h: any) => { - checkGroups.add(h._source.monitor.check_group); - }); - }); - }); - } }); return { monitorIds, - checkGroups, searchAfter: queryResult.aggregations?.monitors?.after_key, }; }; @@ -89,29 +70,6 @@ const queryBody = async (queryContext: QueryContext, searchAfter: any, size: num }, ], }, - aggs: { - // Here we grab the most recent 2 check groups per location. - // Why 2? Because the most recent one may not be for a summary, it may be incomplete. - locations: { - terms: { field: 'observer.geo.name', missing: '__missing__' }, - aggs: { - ips: { - terms: { field: 'monitor.ip', missing: '0.0.0.0' }, - aggs: { - top: { - top_hits: { - sort: [{ '@timestamp': 'desc' }], - _source: { - includes: ['monitor.check_group', '@timestamp'], - }, - size: 2, - }, - }, - }, - }, - }, - }, - }, }, }, }; diff --git a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts index e5e3de322cbc7..2f54f3f6dd689 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts @@ -18,18 +18,14 @@ import { MonitorGroups, MonitorLocCheckGroup } from './fetch_page'; // check groups for their associated monitor IDs. If not, it discards the result. export const refinePotentialMatches = async ( queryContext: QueryContext, - potentialMatchMonitorIDs: string[], - potentialMatchCheckGroups: Set + potentialMatchMonitorIDs: string[] ): Promise => { if (potentialMatchMonitorIDs.length === 0) { return []; } - const recentGroupsMatchingStatus = await fullyMatchingIds( - queryContext, - potentialMatchMonitorIDs, - potentialMatchCheckGroups - ); + const queryResult = await query(queryContext, potentialMatchMonitorIDs); + const recentGroupsMatchingStatus = await fullyMatchingIds(queryResult, queryContext.statusFilter); // Return the monitor groups filtering out potential matches that weren't current const matches: MonitorGroups[] = potentialMatchMonitorIDs @@ -49,27 +45,35 @@ export const refinePotentialMatches = async ( return matches; }; -const fullyMatchingIds = async ( - queryContext: QueryContext, - potentialMatchMonitorIDs: string[], - potentialMatchCheckGroups: Set -) => { - const mostRecentQueryResult = await mostRecentCheckGroups(queryContext, potentialMatchMonitorIDs); - +export const fullyMatchingIds = (queryResult: any, statusFilter?: string) => { const matching = new Map(); - MonitorLoop: for (const monBucket of mostRecentQueryResult.aggregations.monitor.buckets) { + MonitorLoop: for (const monBucket of queryResult.aggregations.monitor.buckets) { const monitorId: string = monBucket.key; const groups: MonitorLocCheckGroup[] = []; + // Did at least one location match? + let matched = false; for (const locBucket of monBucket.location.buckets) { const location = locBucket.key; - const topSource = locBucket.top.hits.hits[0]._source; - const checkGroup = topSource.monitor.check_group; - const status = topSource.summary.down > 0 ? 'down' : 'up'; + const latestSource = locBucket.summaries.latest.hits.hits[0]._source; + const latestStillMatchingSource = locBucket.latest_matching.top.hits.hits[0]?._source; + // If the most recent document still matches the most recent document matching the current filters + // we can include this in the result + // + // We just check if the timestamp is greater. Note this may match an incomplete check group + // that has not yet sent a summary doc + if ( + latestStillMatchingSource && + latestStillMatchingSource['@timestamp'] >= latestSource['@timestamp'] + ) { + matched = true; + } + const checkGroup = latestSource.monitor.check_group; + const status = latestSource.summary.down > 0 ? 'down' : 'up'; // This monitor doesn't match, so just skip ahead and don't add it to the output // Only skip in case of up statusFilter, for a monitor to be up, all checks should be up - if (queryContext?.statusFilter === 'up' && queryContext.statusFilter !== status) { + if (statusFilter === 'up' && statusFilter !== status) { continue MonitorLoop; } @@ -78,12 +82,12 @@ const fullyMatchingIds = async ( location, checkGroup, status, - summaryTimestamp: topSource['@timestamp'], + summaryTimestamp: new Date(latestSource['@timestamp']), }); } - // We only truly match the monitor if one of the most recent check groups was found in the potential matches phase - if (groups.some((g) => potentialMatchCheckGroups.has(g.checkGroup))) { + // If one location matched, include data from all locations in the result set + if (matched) { matching.set(monitorId, groups); } } @@ -91,7 +95,7 @@ const fullyMatchingIds = async ( return matching; }; -export const mostRecentCheckGroups = async ( +export const query = async ( queryContext: QueryContext, potentialMatchMonitorIDs: string[] ): Promise => { @@ -104,8 +108,6 @@ export const mostRecentCheckGroups = async ( filter: [ await queryContext.dateRangeFilter(), { terms: { 'monitor.id': potentialMatchMonitorIDs } }, - // only match summary docs because we only want the latest *complete* check group. - { exists: { field: 'summary' } }, ], }, }, @@ -116,13 +118,39 @@ export const mostRecentCheckGroups = async ( location: { terms: { field: 'observer.geo.name', missing: 'N/A', size: 100 }, aggs: { - top: { - top_hits: { - sort: [{ '@timestamp': 'desc' }], - _source: { - includes: ['monitor.check_group', '@timestamp', 'summary.up', 'summary.down'], + summaries: { + // only match summary docs because we only want the latest *complete* check group. + filter: { exists: { field: 'summary' } }, + aggs: { + latest: { + top_hits: { + sort: [{ '@timestamp': 'desc' }], + _source: { + includes: [ + 'monitor.check_group', + '@timestamp', + 'summary.up', + 'summary.down', + ], + }, + size: 1, + }, + }, + }, + }, + // We want to find the latest check group, even if it's not part of a summary + latest_matching: { + filter: queryContext.filterClause || { match_all: {} }, + aggs: { + top: { + top_hits: { + sort: [{ '@timestamp': 'desc' }], + _source: { + includes: ['monitor.check_group', '@timestamp'], + }, + size: 1, + }, }, - size: 1, }, }, }, From 696d71e13a436b536b518a3e3ff097c33596417c Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 9 Jun 2020 16:37:03 -0400 Subject: [PATCH 10/53] [ML] DF Analytics: Creation wizard part 2 (#68462) * Add ability to clone job * remove deprecated creation form code * ensure excludes cloned correctly and update clone action jest test * remove unused translations * update helper function name --- .../data_frame_analytics/_index.scss | 2 - .../analysis_fields_table.tsx | 2 +- .../configuration_step_form.tsx | 38 +- .../form_options_validation.ts | 2 +- .../supported_fields_message.tsx | 5 +- .../create_analytics_advanced_editor.tsx | 7 +- .../create_analytics_advanced_editor/index.ts | 0 .../components/create_step/create_step.tsx | 13 +- .../components/shared}/index.ts | 2 +- .../components/shared}/messages.tsx | 2 +- .../pages/analytics_creation/page.tsx | 54 +- .../analytics_list/action_clone.test.ts | 38 +- .../analytics_list/action_clone.tsx | 74 +- .../components/analytics_list/actions.tsx | 14 +- .../analytics_list/analytics_list.tsx | 7 - .../_create_analytics_flyout.scss | 3 - .../create_analytics_flyout/_index.scss | 1 - .../create_analytics_flyout.test.tsx | 42 - .../create_analytics_flyout.tsx | 108 --- .../create_analytics_flyout/index.ts | 7 - .../create_analytics_flyout_wrapper.tsx | 28 - .../create_analytics_flyout_wrapper/index.ts | 7 - .../_create_analytics_form.scss | 31 - .../create_analytics_form/_index.scss | 1 - .../create_analytics_form.test.tsx | 69 -- .../create_analytics_form.tsx | 850 ------------------ .../create_analytics_form/job_description.tsx | 37 - .../create_analytics_form/job_type.tsx | 80 -- .../use_create_analytics_form/actions.ts | 7 - .../use_create_analytics_form/reducer.test.ts | 15 - .../use_create_analytics_form/reducer.ts | 12 - .../use_create_analytics_form/state.test.ts | 54 +- .../hooks/use_create_analytics_form/state.ts | 27 +- .../use_create_analytics_form.test.tsx | 28 +- .../use_create_analytics_form.ts | 21 - .../analytics_job_creation.tsx | 7 +- .../translations/translations/ja-JP.json | 17 - .../translations/translations/zh-CN.json | 17 - 38 files changed, 236 insertions(+), 1493 deletions(-) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/{analytics_management/components/create_analytics_form => analytics_creation/components/configuration_step}/form_options_validation.ts (93%) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/{analytics_management => analytics_creation}/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx (95%) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/{analytics_management => analytics_creation}/components/create_analytics_advanced_editor/index.ts (100%) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/{analytics_management/components/create_analytics_form => analytics_creation/components/shared}/index.ts (79%) rename x-pack/plugins/ml/public/application/data_frame_analytics/pages/{analytics_management/components/create_analytics_form => analytics_creation/components/shared}/messages.tsx (92%) delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_create_analytics_flyout.scss delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.test.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/index.ts delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/create_analytics_flyout_wrapper.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/index.ts delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_create_analytics_form.scss delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_description.tsx delete mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss index 5508c021d3313..140593cb17f6e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/_index.scss @@ -1,5 +1,3 @@ @import 'pages/analytics_exploration/components/regression_exploration/index'; @import 'pages/analytics_management/components/analytics_list/index'; -@import 'pages/analytics_management/components/create_analytics_form/index'; -@import 'pages/analytics_management/components/create_analytics_flyout/index'; @import 'pages/analytics_management/components/create_analytics_button/index'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx index ad540285e49f0..09aea596d81e9 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/analysis_fields_table.tsx @@ -85,7 +85,7 @@ export const MemoizedAnalysisFieldsTable: FC<{ if (excludes.length > 0) { setCurrentSelection(excludes); } - }, []); + }, [tableItems]); // Only set form state on unmount to prevent re-renders due to props changing if exludes was updated on each selection useEffect(() => { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx index 9446dfd4ed525..e63756686a4ba 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx @@ -20,13 +20,13 @@ import { TRAINING_PERCENT_MAX, } from '../../../../common/analytics'; import { CreateAnalyticsStepProps } from '../../../analytics_management/hooks/use_create_analytics_form'; -import { Messages } from '../../../analytics_management/components/create_analytics_form/messages'; +import { Messages } from '../shared'; import { DEFAULT_MODEL_MEMORY_LIMIT, getJobConfigFromFormState, State, } from '../../../analytics_management/hooks/use_create_analytics_form/state'; -import { shouldAddAsDepVarOption } from '../../../analytics_management/components/create_analytics_form/form_options_validation'; +import { shouldAddAsDepVarOption } from './form_options_validation'; import { ml } from '../../../../../services/ml_api_service'; import { getToastNotifications } from '../../../../../util/dependency_cache'; @@ -56,7 +56,7 @@ export const ConfigurationStepForm: FC = ({ const { currentSavedSearch, currentIndexPattern } = mlContext; const { savedSearchQuery, savedSearchQueryStr } = useSavedSearch(); - const { initiateWizard, setEstimatedModelMemoryLimit, setFormState } = actions; + const { setEstimatedModelMemoryLimit, setFormState } = actions; const { estimatedModelMemoryLimit, form, isJobCreated, requestMessages } = state; const firstUpdate = useRef(true); const { @@ -75,9 +75,12 @@ export const ConfigurationStepForm: FC = ({ modelMemoryLimit, previousJobType, requiredFieldsError, + sourceIndex, trainingPercent, } = form; + const toastNotifications = getToastNotifications(); + const setJobConfigQuery = ({ query, queryString }: { query: any; queryString: string }) => { setFormState({ jobConfigQuery: query, jobConfigQueryString: queryString }); }; @@ -90,7 +93,7 @@ export const ConfigurationStepForm: FC = ({ const indexPreviewProps = { ...indexData, dataTestSubj: 'mlAnalyticsCreationDataGrid', - toastNotifications: getToastNotifications(), + toastNotifications, }; const isJobTypeWithDepVar = @@ -209,7 +212,8 @@ export const ConfigurationStepForm: FC = ({ }); } } catch (e) { - let errorMessage; + let maxDistinctValuesErrorMessage; + if ( jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION && e.body && @@ -218,7 +222,23 @@ export const ConfigurationStepForm: FC = ({ (e.body.message.includes('must have at most') || e.body.message.includes('must have at least')) ) { - errorMessage = e.body.message; + maxDistinctValuesErrorMessage = e.body.message; + } + + if ( + e.body && + e.body.message !== undefined && + e.body.message.includes('status_exception') && + e.body.message.includes('Unable to estimate memory usage as no documents') + ) { + toastNotifications.addWarning( + i18n.translate('xpack.ml.dataframe.analytics.create.allDocsMissingFieldsErrorMessage', { + defaultMessage: `Unable to estimate memory usage. There are mapped fields for source index [{index}] that do not exist in any indexed documents. You will have to switch to the JSON editor for explicit field selection and include only fields that exist in indexed documents.`, + values: { + index: sourceIndex, + }, + }) + ); } const fallbackModelMemoryLimit = jobType !== undefined @@ -227,17 +247,13 @@ export const ConfigurationStepForm: FC = ({ setEstimatedModelMemoryLimit(fallbackModelMemoryLimit); setFormState({ fieldOptionsFetchFail: true, - maxDistinctValuesError: errorMessage, + maxDistinctValuesError: maxDistinctValuesErrorMessage, loadingFieldOptions: false, ...(shouldUpdateModelMemoryLimit ? { modelMemoryLimit: fallbackModelMemoryLimit } : {}), }); } }, 300); - useEffect(() => { - initiateWizard(); - }, []); - useEffect(() => { setFormState({ sourceIndex: currentIndexPattern.title }); }, []); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/form_options_validation.ts similarity index 93% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/form_options_validation.ts index 0579283c97d61..bf3ab01549139 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/form_options_validation.ts @@ -7,7 +7,7 @@ import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public'; import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../common/types/fields'; import { ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics'; -import { AnalyticsJobType } from '../../hooks/use_create_analytics_form/state'; +import { AnalyticsJobType } from '../../../analytics_management/hooks/use_create_analytics_form/state'; import { BASIC_NUMERICAL_TYPES, EXTENDED_NUMERICAL_TYPES } from '../../../../common/fields'; export const CATEGORICAL_TYPES = new Set(['ip', 'keyword']); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/supported_fields_message.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/supported_fields_message.tsx index fe13cc1d6edfc..0a4ba67831818 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/supported_fields_message.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/supported_fields_message.tsx @@ -12,10 +12,7 @@ import { AnalyticsJobType } from '../../../analytics_management/hooks/use_create import { ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics'; import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../common/types/fields'; import { BASIC_NUMERICAL_TYPES, EXTENDED_NUMERICAL_TYPES } from '../../../../common/fields'; -import { - OMIT_FIELDS, - CATEGORICAL_TYPES, -} from '../../../analytics_management/components/create_analytics_form/form_options_validation'; +import { OMIT_FIELDS, CATEGORICAL_TYPES } from './form_options_validation'; import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public'; import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx similarity index 95% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx index 17b905cab135b..a35a314bec985 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx @@ -22,9 +22,9 @@ import { XJsonMode } from '../../../../../../../shared_imports'; const xJsonMode = new XJsonMode(); -import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; -import { CreateStep } from '../../../analytics_creation/components/create_step'; -import { ANALYTICS_STEPS } from '../../../analytics_creation/page'; +import { CreateAnalyticsFormProps } from '../../../analytics_management/hooks/use_create_analytics_form'; +import { CreateStep } from '../create_step'; +import { ANALYTICS_STEPS } from '../../page'; export const CreateAnalyticsAdvancedEditor: FC = (props) => { const { actions, state } = props; @@ -125,7 +125,6 @@ export const CreateAnalyticsAdvancedEditor: FC = (prop onChange={onChange} setOptions={{ fontSize: '12px', - maxLines: 20, }} theme="textmate" aria-label={i18n.translate( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_analytics_advanced_editor/index.ts similarity index 100% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/index.ts rename to x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_analytics_advanced_editor/index.ts diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx index 2dda5f5d819b7..8d51848a25f50 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/create_step/create_step.tsx @@ -16,7 +16,7 @@ import { import { i18n } from '@kbn/i18n'; import { CreateAnalyticsFormProps } from '../../../analytics_management/hooks/use_create_analytics_form'; -import { Messages } from '../../../analytics_management/components/create_analytics_form/messages'; +import { Messages } from '../shared'; import { ANALYTICS_STEPS } from '../../page'; import { BackToListPanel } from '../back_to_list_panel'; @@ -26,14 +26,7 @@ interface Props extends CreateAnalyticsFormProps { export const CreateStep: FC = ({ actions, state, step }) => { const { createAnalyticsJob, startAnalyticsJob } = actions; - const { - isAdvancedEditorValidJson, - isJobCreated, - isJobStarted, - isModalButtonDisabled, - isValid, - requestMessages, - } = state; + const { isAdvancedEditorValidJson, isJobCreated, isJobStarted, isValid, requestMessages } = state; const [checked, setChecked] = useState(true); @@ -75,7 +68,7 @@ export const CreateStep: FC = ({ actions, state, step }) => { { +interface Props { + jobId?: DataFrameAnalyticsId; +} + +export const Page: FC = ({ jobId }) => { const [currentStep, setCurrentStep] = useState(ANALYTICS_STEPS.CONFIGURATION); const [activatedSteps, setActivatedSteps] = useState([true, false, false, false]); @@ -44,23 +50,36 @@ export const Page: FC = () => { const createAnalyticsForm = useCreateAnalyticsForm(); const { isAdvancedEditorEnabled } = createAnalyticsForm.state; const { jobType } = createAnalyticsForm.state.form; - const { switchToAdvancedEditor } = createAnalyticsForm.actions; + const { initiateWizard, setJobClone, switchToAdvancedEditor } = createAnalyticsForm.actions; useEffect(() => { - if (activatedSteps[currentStep] === false) { - activatedSteps.splice(currentStep, 1, true); - setActivatedSteps(activatedSteps); - } - }, [currentStep]); + initiateWizard(); - useEffect(() => { if (currentIndexPattern) { (async function () { await newJobCapsService.initializeFromIndexPattern(currentIndexPattern, false, false); + + if (jobId !== undefined) { + const analyticsConfigs = await ml.dataFrameAnalytics.getDataFrameAnalytics(jobId); + if ( + Array.isArray(analyticsConfigs.data_frame_analytics) && + analyticsConfigs.data_frame_analytics.length > 0 + ) { + const clonedJobConfig: any = analyticsConfigs.data_frame_analytics[0]; + await setJobClone(clonedJobConfig); + } + } })(); } }, []); + useEffect(() => { + if (activatedSteps[currentStep] === false) { + activatedSteps.splice(currentStep, 1, true); + setActivatedSteps(activatedSteps); + } + }, [currentStep]); + const analyticsWizardSteps = [ { title: i18n.translate('xpack.ml.dataframe.analytics.creation.configurationStepTitle', { @@ -127,10 +146,19 @@ export const Page: FC = () => {

- + {jobId === undefined && ( + + )} + {jobId !== undefined && ( + + )}

diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.test.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.test.ts index 9221f8c500326..01d92d8e192c1 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.test.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.test.ts @@ -140,8 +140,8 @@ describe('Analytics job clone action', () => { expect(isAdvancedConfig(advancedClassificationJob)).toBe(true); }); - test('should detect advanced outlier_detection job', () => { - const advancedOutlierDetectionJob = { + test('should detect advanced regression job', () => { + const advancedRegressionJob = { description: "Outlier detection job with 'glass' dataset", source: { index: ['glass_withoutdupl_norm'], @@ -155,10 +155,8 @@ describe('Analytics job clone action', () => { results_field: 'ml', }, analysis: { - outlier_detection: { - compute_feature_influence: false, - outlier_fraction: 0.05, - standardization_enabled: true, + regression: { + loss_function: 'msle', }, }, analyzed_fields: { @@ -168,7 +166,7 @@ describe('Analytics job clone action', () => { model_memory_limit: '1mb', allow_lazy_start: false, }; - expect(isAdvancedConfig(advancedOutlierDetectionJob)).toBe(true); + expect(isAdvancedConfig(advancedRegressionJob)).toBe(true); }); test('should detect a custom query', () => { @@ -207,32 +205,6 @@ describe('Analytics job clone action', () => { expect(isAdvancedConfig(advancedRegressionJob)).toBe(true); }); - test('should detect custom analysis settings', () => { - const config = { - description: "Classification clone with 'bank-marketing' dataset", - source: { - index: 'bank-marketing', - }, - dest: { - index: 'bank_classification4', - }, - analyzed_fields: { - excludes: [], - }, - analysis: { - classification: { - dependent_variable: 'y', - training_percent: 71, - max_trees: 1500, - num_top_feature_importance_values: 4, - }, - }, - model_memory_limit: '400mb', - }; - - expect(isAdvancedConfig(config)).toBe(true); - }); - test('should detect as advanced if the prop is unknown', () => { const config = { description: "Classification clone with 'bank-marketing' dataset", diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx index cfb11856670c4..a1f0448b819d1 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_clone.tsx @@ -8,10 +8,12 @@ import { EuiButtonEmpty } from '@elastic/eui'; import React, { FC } from 'react'; import { isEqual, cloneDeep } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { IIndexPattern } from 'src/plugins/data/common'; import { DeepReadonly } from '../../../../../../../common/types/common'; import { DataFrameAnalyticsConfig, isOutlierAnalysis } from '../../../../common'; import { isClassificationAnalysis, isRegressionAnalysis } from '../../../../common/analytics'; import { DEFAULT_RESULTS_FIELD } from '../../../../common/constants'; +import { useMlKibana } from '../../../../../contexts/kibana'; import { CreateAnalyticsFormProps, DEFAULT_NUM_TOP_FEATURE_IMPORTANCE_VALUES, @@ -19,6 +21,7 @@ import { import { State } from '../../hooks/use_create_analytics_form/state'; import { DataFrameAnalyticsListRow } from './common'; import { checkPermission } from '../../../../../capabilities/check_capabilities'; +import { extractErrorMessage } from '../../../../../util/error_utils'; interface PropDefinition { /** @@ -74,31 +77,39 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo }, eta: { optional: true, + formKey: 'eta', }, feature_bag_fraction: { optional: true, + formKey: 'featureBagFraction', }, max_trees: { optional: true, + formKey: 'maxTrees', }, gamma: { optional: true, + formKey: 'gamma', }, lambda: { optional: true, + formKey: 'lambda', }, num_top_classes: { optional: true, defaultValue: 2, + formKey: 'numTopClasses', }, prediction_field_name: { optional: true, defaultValue: `${config.analysis.classification.dependent_variable}_prediction`, + formKey: 'predictionFieldName', }, randomize_seed: { optional: true, // By default it is randomly generated ignore: true, + formKey: 'randomizeSeed', }, num_top_feature_importance_values: { optional: true, @@ -118,23 +129,29 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo standardization_enabled: { defaultValue: true, optional: true, + formKey: 'standardizationEnabled', }, compute_feature_influence: { defaultValue: true, optional: true, + formKey: 'computeFeatureInfluence', }, outlier_fraction: { defaultValue: 0.05, optional: true, + formKey: 'outlierFraction', }, feature_influence_threshold: { optional: true, + formKey: 'featureInfluenceThreshold', }, method: { optional: true, + formKey: 'method', }, n_neighbors: { optional: true, + formKey: 'nNeighbors', }, }, } @@ -152,22 +169,28 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo }, eta: { optional: true, + formKey: 'eta', }, feature_bag_fraction: { optional: true, + formKey: 'featureBagFraction', }, max_trees: { optional: true, + formKey: 'maxTrees', }, gamma: { optional: true, + formKey: 'gamma', }, lambda: { optional: true, + formKey: 'lambda', }, prediction_field_name: { optional: true, defaultValue: `${config.analysis.regression.dependent_variable}_prediction`, + formKey: 'predictionFieldName', }, num_top_feature_importance_values: { optional: true, @@ -178,11 +201,15 @@ const getAnalyticsJobMeta = (config: CloneDataFrameAnalyticsConfig): AnalyticsJo optional: true, // By default it is randomly generated ignore: true, + formKey: 'randomizeSeed', }, loss_function: { optional: true, defaultValue: 'mse', }, + loss_function_parameter: { + optional: true, + }, }, } : {}), @@ -332,9 +359,52 @@ export const CloneAction: FC = ({ createAnalyticsForm, item }) const buttonText = i18n.translate('xpack.ml.dataframe.analyticsList.cloneJobButtonLabel', { defaultMessage: 'Clone job', }); - const { actions } = createAnalyticsForm; + + const { notifications, savedObjects } = useMlKibana().services; + const savedObjectsClient = savedObjects.client; + const onClick = async () => { - await actions.setJobClone(item.config); + const sourceIndex = Array.isArray(item.config.source.index) + ? item.config.source.index[0] + : item.config.source.index; + let sourceIndexId; + + try { + const response = await savedObjectsClient.find({ + type: 'index-pattern', + perPage: 10, + search: `"${sourceIndex}"`, + searchFields: ['title'], + fields: ['title'], + }); + + const ip = response.savedObjects.find( + (obj) => obj.attributes.title.toLowerCase() === sourceIndex.toLowerCase() + ); + if (ip !== undefined) { + sourceIndexId = ip.id; + } + } catch (e) { + const { toasts } = notifications; + const error = extractErrorMessage(e); + + toasts.addDanger( + i18n.translate( + 'xpack.ml.dataframe.analyticsList.fetchSourceIndexPatternForCloneErrorMessage', + { + defaultMessage: + 'An error occurred checking if index pattern {indexPattern} exists: {error}', + values: { indexPattern: sourceIndex, error }, + } + ) + ); + } + + if (sourceIndexId) { + window.location.href = `ml#/data_frame_analytics/new_job?index=${encodeURIComponent( + sourceIndexId + )}&jobId=${item.config.id}`; + } }; return ( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx index 295a3988e1b58..72514c91ff58b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/actions.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; -// import { DeepReadonly } from '../../../../../../../common/types/common'; +import { DeepReadonly } from '../../../../../../../common/types/common'; import { checkPermission, @@ -21,7 +21,7 @@ import { isClassificationAnalysis, } from '../../../../common/analytics'; import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; -// import { CloneAction } from './action_clone'; +import { CloneAction } from './action_clone'; import { getResultsUrl, isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common'; import { stopAnalytics } from '../../services/analytics_service'; @@ -106,10 +106,10 @@ export const getActions = (createAnalyticsForm: CreateAnalyticsFormProps) => { return ; }, }, - // { - // render: (item: DeepReadonly) => { - // return ; - // }, - // }, + { + render: (item: DeepReadonly) => { + return ; + }, + }, ]; }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx index bb012a2190859..25e3a2808fc61 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/analytics_list.tsx @@ -51,7 +51,6 @@ import { AnalyticStatsBarStats, StatsBar } from '../../../../../components/stats import { RefreshAnalyticsListButton } from '../refresh_analytics_list_button'; import { CreateAnalyticsButton } from '../create_analytics_button'; import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; -import { CreateAnalyticsFlyoutWrapper } from '../create_analytics_flyout_wrapper'; import { getSelectedJobIdFromUrl } from '../../../../../jobs/jobs_list/components/utils'; import { SourceSelection } from '../source_selection'; @@ -286,9 +285,6 @@ export const DataFrameAnalyticsList: FC = ({ } data-test-subj="mlNoDataFrameAnalyticsFound" /> - {!isManagementTable && createAnalyticsForm && ( - - )} {isSourceIndexModalVisible === true && ( setIsSourceIndexModalVisible(false)} /> )} @@ -440,9 +436,6 @@ export const DataFrameAnalyticsList: FC = ({ />
- {!isManagementTable && createAnalyticsForm?.state.isModalVisible && ( - - )} {isSourceIndexModalVisible === true && ( setIsSourceIndexModalVisible(false)} /> )} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_create_analytics_flyout.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_create_analytics_flyout.scss deleted file mode 100644 index e6c6ffafc446a..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_create_analytics_flyout.scss +++ /dev/null @@ -1,3 +0,0 @@ -.mlAnalyticsCreateFlyout__footerButton { - float: right; -} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_index.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_index.scss deleted file mode 100644 index 668b35f8370d2..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'create_analytics_flyout'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.test.tsx deleted file mode 100644 index dc91c955184b0..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.test.tsx +++ /dev/null @@ -1,42 +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 { mount } from 'enzyme'; -import React from 'react'; -import { mountHook } from 'test_utils/enzyme_helpers'; - -import { CreateAnalyticsFlyout } from './create_analytics_flyout'; - -import { MlContext } from '../../../../../contexts/ml'; -import { kibanaContextValueMock } from '../../../../../contexts/ml/__mocks__/kibana_context_value'; - -import { useCreateAnalyticsForm } from '../../hooks/use_create_analytics_form'; - -const getMountedHook = () => - mountHook( - () => useCreateAnalyticsForm(), - ({ children }) => ( - {children} - ) - ); - -// workaround to make React.memo() work with enzyme -jest.mock('react', () => { - const r = jest.requireActual('react'); - return { ...r, memo: (x: any) => x }; -}); - -describe('Data Frame Analytics: ', () => { - test('Minimal initialization', () => { - const { getLastHookValue } = getMountedHook(); - const props = getLastHookValue(); - const wrapper = mount(); - - expect(wrapper.find('[data-test-subj="mlDataFrameAnalyticsFlyoutHeaderTitle"]').text()).toBe( - 'Create analytics job' - ); - }); -}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.tsx deleted file mode 100644 index b0f13e398cc50..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/create_analytics_flyout.tsx +++ /dev/null @@ -1,108 +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, { FC } from 'react'; - -import { - EuiButton, - EuiButtonEmpty, - EuiFlyout, - EuiFlyoutBody, - EuiFlyoutHeader, - EuiFlyoutFooter, - EuiTitle, -} from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; - -import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; - -export const CreateAnalyticsFlyout: FC = ({ - actions, - children, - state, -}) => { - const { closeModal, createAnalyticsJob, startAnalyticsJob } = actions; - const { - isJobCreated, - isJobStarted, - isModalButtonDisabled, - isValid, - isAdvancedEditorValidJson, - cloneJob, - } = state; - - const headerText = !!cloneJob - ? i18n.translate('xpack.ml.dataframe.analytics.clone.flyoutHeaderTitle', { - defaultMessage: 'Clone job from {job_id}', - values: { job_id: cloneJob.id }, - }) - : i18n.translate('xpack.ml.dataframe.analytics.create.flyoutHeaderTitle', { - defaultMessage: 'Create analytics job', - }); - - return ( - - - -

{headerText}

-
-
- {children} - - {(!isJobCreated || !isJobStarted) && ( - - {isJobCreated === true - ? i18n.translate('xpack.ml.dataframe.analytics.create.flyoutCloseButton', { - defaultMessage: 'Close', - }) - : i18n.translate('xpack.ml.dataframe.analytics.create.flyoutCancelButton', { - defaultMessage: 'Cancel', - })} - - )} - - {!isJobCreated && !isJobStarted && ( - - {i18n.translate('xpack.ml.dataframe.analytics.create.flyoutCreateButton', { - defaultMessage: 'Create', - })} - - )} - {isJobCreated && !isJobStarted && ( - - {i18n.translate('xpack.ml.dataframe.analytics.create.flyoutStartButton', { - defaultMessage: 'Start', - })} - - )} - {isJobCreated && isJobStarted && ( - - {i18n.translate('xpack.ml.dataframe.analytics.create.flyoutCloseButton', { - defaultMessage: 'Close', - })} - - )} - -
- ); -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/index.ts deleted file mode 100644 index 3a25359373aa6..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout/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 { CreateAnalyticsFlyout } from './create_analytics_flyout'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/create_analytics_flyout_wrapper.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/create_analytics_flyout_wrapper.tsx deleted file mode 100644 index 2f3c38b6ffe4e..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/create_analytics_flyout_wrapper.tsx +++ /dev/null @@ -1,28 +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, { FC } from 'react'; - -import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; - -import { CreateAnalyticsAdvancedEditor } from '../create_analytics_advanced_editor'; -import { CreateAnalyticsForm } from '../create_analytics_form'; -import { CreateAnalyticsFlyout } from '../create_analytics_flyout'; - -export const CreateAnalyticsFlyoutWrapper: FC = (props) => { - const { isAdvancedEditorEnabled, isModalVisible } = props.state; - - if (isModalVisible === false) { - return null; - } - - return ( - - {isAdvancedEditorEnabled === false && } - {isAdvancedEditorEnabled === true && } - - ); -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/index.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/index.ts deleted file mode 100644 index c8e7a958f6d42..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_flyout_wrapper/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 { CreateAnalyticsFlyoutWrapper } from './create_analytics_flyout_wrapper'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_create_analytics_form.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_create_analytics_form.scss deleted file mode 100644 index 9b4559f9e2cb2..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_create_analytics_form.scss +++ /dev/null @@ -1,31 +0,0 @@ -/* - The job creation form displayed in the modal adapts its height dynamically - if the content changes. If a form element changes to show/hide error messages, - this results in a changing height of the modal. If you type quickly e.g. - in the job ID input field and type chars which are invalid only for example - at the end of the string, this will result in an unwanted height toggling - effect. The following CSS avoids this by 1) delaying the visilibity of the - error message by 500ms and 2) animating the height and opacity to create - a fade-in effect after that so the modal grows smoothly and doesn't - toggle its height. - */ - -@keyframes mlDelayedShow { - 0%, 50% { - max-height: 0; - opacity: 0; - padding: 0; - visibility: hidden; - } - 100% { - max-height: 300px; - opacity: 1; - padding-top: $euiSizeS; - } -} - -.mlDataFrameAnalyticsCreateForm { - .euiFormErrorText { - animation: mlDelayedShow 1s; - } -} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_index.scss b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_index.scss deleted file mode 100644 index 66fa2c02e60f5..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'create_analytics_form'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx deleted file mode 100644 index 85cd70912b41f..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.test.tsx +++ /dev/null @@ -1,69 +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 { mount } from 'enzyme'; -import React from 'react'; -import { mountHook } from 'test_utils/enzyme_helpers'; - -import { CreateAnalyticsForm } from './create_analytics_form'; - -import { MlContext } from '../../../../../contexts/ml'; -import { kibanaContextValueMock } from '../../../../../contexts/ml/__mocks__/kibana_context_value'; - -import { useCreateAnalyticsForm } from '../../hooks/use_create_analytics_form'; - -const getMountedHook = () => - mountHook( - () => useCreateAnalyticsForm(), - ({ children }) => ( - {children} - ) - ); - -// workaround to make React.memo() work with enzyme -jest.mock('react', () => { - const r = jest.requireActual('react'); - return { ...r, memo: (x: any) => x }; -}); - -jest.mock('../../../../../contexts/kibana', () => ({ - useMlKibana: () => { - return { - services: { - docLinks: () => ({ - ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', - DOC_LINK_VERSION: 'jest-metadata-mock-branch', - }), - }, - }; - }, -})); - -describe('Data Frame Analytics: ', () => { - test('Minimal initialization', () => { - const { getLastHookValue } = getMountedHook(); - const props = getLastHookValue(); - const wrapper = mount( - - - - ); - - const euiFormRows = wrapper.find('EuiFormRow'); - expect(euiFormRows.length).toBe(10); - - const row1 = euiFormRows.at(0); - expect(row1.find('label').text()).toBe('Job type'); - - const options = row1.find('option'); - expect(options.at(0).props().value).toBe(''); - expect(options.at(1).props().value).toBe('outlier_detection'); - expect(options.at(2).props().value).toBe('regression'); - - const row2 = euiFormRows.at(1); - expect(row2.find('EuiSwitch').text()).toBe('Enable advanced editor'); - }); -}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx deleted file mode 100644 index 64fe736e67b17..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx +++ /dev/null @@ -1,850 +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, { Fragment, FC, useEffect, useMemo, useRef } from 'react'; - -import { - EuiComboBox, - EuiComboBoxOptionOption, - EuiForm, - EuiFieldNumber, - EuiFieldText, - EuiFormRow, - EuiLink, - EuiRange, - EuiSwitch, -} from '@elastic/eui'; -import { debounce } from 'lodash'; - -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { useMlKibana } from '../../../../../contexts/kibana'; -import { ml } from '../../../../../services/ml_api_service'; -import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; -import { useMlContext } from '../../../../../contexts/ml'; -import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; -import { - DEFAULT_MODEL_MEMORY_LIMIT, - getJobConfigFromFormState, - State, -} from '../../hooks/use_create_analytics_form/state'; -import { JOB_ID_MAX_LENGTH } from '../../../../../../../common/constants/validation'; -import { Messages } from './messages'; -import { JobType } from './job_type'; -import { JobDescriptionInput } from './job_description'; -import { getModelMemoryLimitErrors } from '../../hooks/use_create_analytics_form/reducer'; -import { IndexPattern, indexPatterns } from '../../../../../../../../../../src/plugins/data/public'; -import { - ANALYSIS_CONFIG_TYPE, - DfAnalyticsExplainResponse, - FieldSelectionItem, - NUM_TOP_FEATURE_IMPORTANCE_VALUES_MIN, - TRAINING_PERCENT_MIN, - TRAINING_PERCENT_MAX, -} from '../../../../common/analytics'; -import { shouldAddAsDepVarOption, OMIT_FIELDS } from './form_options_validation'; - -const requiredFieldsErrorText = i18n.translate( - 'xpack.ml.dataframe.analytics.create.requiredFieldsErrorMessage', - { - defaultMessage: 'At least one field must be included in the analysis.', - } -); - -export const CreateAnalyticsForm: FC = ({ actions, state }) => { - const { - services: { docLinks }, - } = useMlKibana(); - const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; - const { setFormState, setEstimatedModelMemoryLimit } = actions; - const mlContext = useMlContext(); - const { - estimatedModelMemoryLimit, - form, - indexPatternsMap, - isAdvancedEditorEnabled, - isJobCreated, - requestMessages, - } = state; - - const forceInput = useRef(null); - const firstUpdate = useRef(true); - - const { - createIndexPattern, - dependentVariable, - dependentVariableFetchFail, - dependentVariableOptions, - description, - destinationIndex, - destinationIndexNameEmpty, - destinationIndexNameExists, - destinationIndexNameValid, - destinationIndexPatternTitleExists, - excludes, - excludesOptions, - fieldOptionsFetchFail, - jobId, - jobIdEmpty, - jobIdExists, - jobIdValid, - jobIdInvalidMaxLength, - jobType, - loadingDepVarOptions, - loadingFieldOptions, - maxDistinctValuesError, - modelMemoryLimit, - modelMemoryLimitValidationResult, - numTopFeatureImportanceValues, - numTopFeatureImportanceValuesValid, - previousJobType, - previousSourceIndex, - requiredFieldsError, - sourceIndex, - sourceIndexNameEmpty, - sourceIndexNameValid, - sourceIndexContainsNumericalFields, - sourceIndexFieldsCheckFailed, - trainingPercent, - } = form; - const characterList = indexPatterns.ILLEGAL_CHARACTERS_VISIBLE.join(', '); - - const mmlErrors = useMemo(() => getModelMemoryLimitErrors(modelMemoryLimitValidationResult), [ - modelMemoryLimitValidationResult, - ]); - - const isJobTypeWithDepVar = - jobType === ANALYSIS_CONFIG_TYPE.REGRESSION || jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION; - - // Find out if index pattern contain numeric fields. Provides a hint in the form - // that an analytics jobs is not able to identify outliers if there are no numeric fields present. - const validateSourceIndexFields = async () => { - try { - const indexPattern: IndexPattern = await mlContext.indexPatterns.get( - indexPatternsMap[sourceIndex].value - ); - const containsNumericalFields: boolean = indexPattern.fields.some( - ({ name, type }) => !OMIT_FIELDS.includes(name) && type === 'number' - ); - - setFormState({ - sourceIndexContainsNumericalFields: containsNumericalFields, - sourceIndexFieldsCheckFailed: false, - }); - } catch (e) { - setFormState({ - sourceIndexFieldsCheckFailed: true, - }); - } - }; - - const onCreateOption = (searchValue: string, flattenedOptions: EuiComboBoxOptionOption[]) => { - const normalizedSearchValue = searchValue.trim().toLowerCase(); - - if (!normalizedSearchValue) { - return; - } - - const newOption = { - label: searchValue, - }; - - // Create the option if it doesn't exist. - if ( - !flattenedOptions.some( - (option: EuiComboBoxOptionOption) => - option.label.trim().toLowerCase() === normalizedSearchValue - ) - ) { - excludesOptions.push(newOption); - setFormState({ excludes: [...excludes, newOption.label] }); - } - }; - - const debouncedGetExplainData = debounce(async () => { - const jobTypeOrIndexChanged = - previousSourceIndex !== sourceIndex || previousJobType !== jobType; - const shouldUpdateModelMemoryLimit = !firstUpdate.current || !modelMemoryLimit; - const shouldUpdateEstimatedMml = - !firstUpdate.current || !modelMemoryLimit || estimatedModelMemoryLimit === ''; - - if (firstUpdate.current) { - firstUpdate.current = false; - } - // Reset if sourceIndex or jobType changes (jobType requires dependent_variable to be set - - // which won't be the case if switching from outlier detection) - if (jobTypeOrIndexChanged) { - setFormState({ - loadingFieldOptions: true, - }); - } - - try { - const jobConfig = getJobConfigFromFormState(form); - delete jobConfig.dest; - delete jobConfig.model_memory_limit; - const resp: DfAnalyticsExplainResponse = await ml.dataFrameAnalytics.explainDataFrameAnalytics( - jobConfig - ); - const expectedMemoryWithoutDisk = resp.memory_estimation?.expected_memory_without_disk; - - if (shouldUpdateEstimatedMml) { - setEstimatedModelMemoryLimit(expectedMemoryWithoutDisk); - } - - const fieldSelection: FieldSelectionItem[] | undefined = resp.field_selection; - - let hasRequiredFields = false; - if (fieldSelection) { - for (let i = 0; i < fieldSelection.length; i++) { - const field = fieldSelection[i]; - if (field.is_included === true && field.is_required === false) { - hasRequiredFields = true; - break; - } - } - } - - // If sourceIndex has changed load analysis field options again - if (jobTypeOrIndexChanged) { - const analyzedFieldsOptions: EuiComboBoxOptionOption[] = []; - - if (resp.field_selection) { - resp.field_selection.forEach((selectedField: FieldSelectionItem) => { - if (selectedField.is_included === true && selectedField.name !== dependentVariable) { - analyzedFieldsOptions.push({ label: selectedField.name }); - } - }); - } - - setFormState({ - ...(shouldUpdateModelMemoryLimit ? { modelMemoryLimit: expectedMemoryWithoutDisk } : {}), - excludesOptions: analyzedFieldsOptions, - loadingFieldOptions: false, - fieldOptionsFetchFail: false, - maxDistinctValuesError: undefined, - requiredFieldsError: !hasRequiredFields ? requiredFieldsErrorText : undefined, - }); - } else { - setFormState({ - ...(shouldUpdateModelMemoryLimit ? { modelMemoryLimit: expectedMemoryWithoutDisk } : {}), - requiredFieldsError: !hasRequiredFields ? requiredFieldsErrorText : undefined, - }); - } - } catch (e) { - let errorMessage; - if ( - jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION && - e.body && - e.body.message !== undefined && - e.body.message.includes('status_exception') && - e.body.message.includes('must have at most') - ) { - errorMessage = e.body.message; - } - const fallbackModelMemoryLimit = - jobType !== undefined - ? DEFAULT_MODEL_MEMORY_LIMIT[jobType] - : DEFAULT_MODEL_MEMORY_LIMIT.outlier_detection; - setEstimatedModelMemoryLimit(fallbackModelMemoryLimit); - setFormState({ - fieldOptionsFetchFail: true, - maxDistinctValuesError: errorMessage, - loadingFieldOptions: false, - ...(shouldUpdateModelMemoryLimit ? { modelMemoryLimit: fallbackModelMemoryLimit } : {}), - }); - } - }, 400); - - const loadDepVarOptions = async (formState: State['form']) => { - setFormState({ - loadingDepVarOptions: true, - // clear when the source index changes - maxDistinctValuesError: undefined, - sourceIndexFieldsCheckFailed: false, - sourceIndexContainsNumericalFields: true, - }); - try { - const indexPattern: IndexPattern = await mlContext.indexPatterns.get( - indexPatternsMap[sourceIndex].value - ); - - if (indexPattern !== undefined) { - const formStateUpdate: { - loadingDepVarOptions: boolean; - dependentVariableFetchFail: boolean; - dependentVariableOptions: State['form']['dependentVariableOptions']; - dependentVariable?: State['form']['dependentVariable']; - } = { - loadingDepVarOptions: false, - dependentVariableFetchFail: false, - dependentVariableOptions: [] as State['form']['dependentVariableOptions'], - }; - - await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false); - // Get fields and filter for supported types for job type - const { fields } = newJobCapsService; - - let resetDependentVariable = true; - for (const field of fields) { - if (shouldAddAsDepVarOption(field, jobType)) { - formStateUpdate.dependentVariableOptions.push({ - label: field.id, - }); - - if (formState.dependentVariable === field.id) { - resetDependentVariable = false; - } - } - } - - if (resetDependentVariable) { - formStateUpdate.dependentVariable = ''; - } - - setFormState(formStateUpdate); - } - } catch (e) { - setFormState({ loadingDepVarOptions: false, dependentVariableFetchFail: true }); - } - }; - - const getSourceIndexErrorMessages = () => { - const errors = []; - if (!sourceIndexNameEmpty && !sourceIndexNameValid) { - errors.push( - - - - ); - } - - if (sourceIndexFieldsCheckFailed === true) { - errors.push( - - - - ); - } - - return errors; - }; - - const onSourceIndexChange = (selectedOptions: EuiComboBoxOptionOption[]) => { - setFormState({ - excludes: [], - excludesOptions: [], - previousSourceIndex: sourceIndex, - sourceIndex: selectedOptions[0].label || '', - requiredFieldsError: undefined, - }); - }; - - useEffect(() => { - if (isJobTypeWithDepVar && sourceIndexNameEmpty === false) { - loadDepVarOptions(form); - } - - if (jobType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION && sourceIndexNameEmpty === false) { - validateSourceIndexFields(); - } - }, [sourceIndex, jobType, sourceIndexNameEmpty]); - - useEffect(() => { - const hasBasicRequiredFields = - jobType !== undefined && sourceIndex !== '' && sourceIndexNameValid === true; - - const hasRequiredAnalysisFields = - (isJobTypeWithDepVar && dependentVariable !== '') || - jobType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION; - - if (hasBasicRequiredFields && hasRequiredAnalysisFields) { - debouncedGetExplainData(); - } - - return () => { - debouncedGetExplainData.cancel(); - }; - }, [ - jobType, - sourceIndex, - sourceIndexNameEmpty, - dependentVariable, - trainingPercent, - JSON.stringify(excludes), - ]); - - // Temp effect to close the context menu popover on Clone button click - useEffect(() => { - if (forceInput.current === null) { - return; - } - const evt = document.createEvent('MouseEvents'); - evt.initEvent('mouseup', true, true); - forceInput.current.dispatchEvent(evt); - }, []); - - const noSupportetdAnalysisFields = - excludesOptions.length === 0 && fieldOptionsFetchFail === false && !sourceIndexNameEmpty; - - return ( - - - {!isJobCreated && ( - - - - - - - { - if (input) { - forceInput.current = input; - } - }} - disabled={isJobCreated} - placeholder={i18n.translate('xpack.ml.dataframe.analytics.create.jobIdPlaceholder', { - defaultMessage: 'Job ID', - })} - value={jobId} - onChange={(e) => setFormState({ jobId: e.target.value })} - aria-label={i18n.translate( - 'xpack.ml.dataframe.analytics.create.jobIdInputAriaLabel', - { - defaultMessage: 'Choose a unique analytics job ID.', - } - )} - isInvalid={(!jobIdEmpty && !jobIdValid) || jobIdExists} - data-test-subj="mlAnalyticsCreateJobFlyoutJobIdInput" - /> - - - - - {!isJobCreated && ( - - a.label.localeCompare(b.label) - )} - selectedOptions={ - indexPatternsMap[sourceIndex] !== undefined ? [{ label: sourceIndex }] : [] - } - onChange={onSourceIndexChange} - isClearable={false} - data-test-subj="mlAnalyticsCreateJobFlyoutSourceIndexSelect" - /> - )} - {isJobCreated && ( - - )} - - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.create.destinationIndexInvalidError', - { - defaultMessage: 'Invalid destination index name.', - } - )} -
- - {i18n.translate( - 'xpack.ml.dataframe.stepDetailsForm.destinationIndexInvalidErrorLink', - { - defaultMessage: 'Learn more about index name limitations.', - } - )} - -
, - ] - } - > - setFormState({ destinationIndex: e.target.value })} - aria-label={i18n.translate( - 'xpack.ml.dataframe.analytics.create.destinationIndexInputAriaLabel', - { - defaultMessage: 'Choose a unique destination index name.', - } - )} - isInvalid={!destinationIndexNameEmpty && !destinationIndexNameValid} - data-test-subj="mlAnalyticsCreateJobFlyoutDestinationIndexInput" - /> - - {(jobType === ANALYSIS_CONFIG_TYPE.REGRESSION || - jobType === ANALYSIS_CONFIG_TYPE.CLASSIFICATION) && ( - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.create.dependentVariableMaxDistictValuesError', - { - defaultMessage: 'Invalid. {message}', - values: { message: maxDistinctValuesError }, - } - )} - , - ] - : []), - ]} - > - - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.create.dependentVariableOptionsFetchError', - { - defaultMessage: - 'There was a problem fetching fields. Please refresh the page and try again.', - } - )} - , - ] - : []), - ]} - > - - setFormState({ - dependentVariable: selectedOptions[0].label || '', - }) - } - isClearable={false} - isInvalid={dependentVariable === ''} - data-test-subj="mlAnalyticsCreateJobFlyoutDependentVariableSelect" - /> - - - setFormState({ trainingPercent: +e.target.value })} - data-test-subj="mlAnalyticsCreateJobFlyoutTrainingPercentSlider" - /> - - {/* num_top_feature_importance_values */} - - {i18n.translate( - 'xpack.ml.dataframe.analytics.create.numTopFeatureImportanceValuesErrorText', - { - defaultMessage: - 'Invalid maximum number of feature importance values.', - } - )} - , - ] - : []), - ]} - > - setFormState({ numTopFeatureImportanceValues: +e.target.value })} - step={1} - value={numTopFeatureImportanceValues} - /> - - - )} - - - - - ({ - label: field, - }))} - onCreateOption={onCreateOption} - onChange={(selectedOptions) => - setFormState({ excludes: selectedOptions.map((option) => option.label) }) - } - isClearable={true} - data-test-subj="mlAnalyticsCreateJobFlyoutExcludesSelect" - /> - - - setFormState({ modelMemoryLimit: e.target.value })} - isInvalid={modelMemoryLimitValidationResult !== null} - data-test-subj="mlAnalyticsCreateJobFlyoutModelMemoryInput" - /> - - - setFormState({ createIndexPattern: !createIndexPattern })} - data-test-subj="mlAnalyticsCreateJobFlyoutCreateIndexPatternSwitch" - /> - - - )} -
- ); -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_description.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_description.tsx deleted file mode 100644 index 46301a6f832e7..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_description.tsx +++ /dev/null @@ -1,37 +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, { FC } from 'react'; -import { EuiFormRow, EuiTextArea } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -const helpText = i18n.translate('xpack.ml.dataframe.analytics.create.jobDescription.helpText', { - defaultMessage: 'Optional descriptive text', -}); - -interface Props { - description: string; - setFormState: React.Dispatch>; -} - -export const JobDescriptionInput: FC = ({ description, setFormState }) => ( - - { - const value = e.target.value; - setFormState({ description: value }); - }} - data-test-subj="mlDFAnalyticsJobCreationJobDescription" - /> - -); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx deleted file mode 100644 index 6daa72dd805b1..0000000000000 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/job_type.tsx +++ /dev/null @@ -1,80 +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, { Fragment, FC } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { EuiFormRow, EuiSelect } from '@elastic/eui'; -import { ANALYSIS_CONFIG_TYPE } from '../../../../common'; - -import { AnalyticsJobType } from '../../hooks/use_create_analytics_form/state'; - -interface Props { - type: AnalyticsJobType; - setFormState: React.Dispatch>; -} - -export const JobType: FC = ({ type, setFormState }) => { - const outlierHelpText = i18n.translate( - 'xpack.ml.dataframe.analytics.create.outlierDetectionHelpText', - { - defaultMessage: - 'Outlier detection jobs require a source index that is mapped as a table-like data structure and analyze only numeric and boolean fields. Use the advanced editor to add custom options to the configuration.', - } - ); - - const regressionHelpText = i18n.translate( - 'xpack.ml.dataframe.analytics.create.outlierRegressionHelpText', - { - defaultMessage: - 'Regression jobs analyze only numeric fields. Use the advanced editor to apply custom options, such as the prediction field name.', - } - ); - - const classificationHelpText = i18n.translate( - 'xpack.ml.dataframe.analytics.create.classificationHelpText', - { - defaultMessage: - 'Classification jobs require a source index that is mapped as a table-like data structure and support fields that are numeric, boolean, text, keyword, or ip. Use the advanced editor to apply custom options, such as the prediction field name.', - } - ); - - const helpText = { - [ANALYSIS_CONFIG_TYPE.REGRESSION]: regressionHelpText, - [ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION]: outlierHelpText, - [ANALYSIS_CONFIG_TYPE.CLASSIFICATION]: classificationHelpText, - }; - - return ( - - - ({ - value: jobType, - text: jobType.replace(/_/g, ' '), - }))} - value={type} - hasNoInitialSelection={true} - onChange={(e) => { - const value = e.target.value as AnalyticsJobType; - setFormState({ - previousJobType: type, - jobType: value, - excludes: [], - requiredFieldsError: undefined, - }); - }} - data-test-subj="mlAnalyticsCreateJobFlyoutJobTypeSelect" - /> - - - ); -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts index c42e03b584a56..a9eedbb2bc5e3 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts @@ -57,11 +57,6 @@ export type Action = } | { type: ACTION.SET_IS_JOB_CREATED; isJobCreated: State['isJobCreated'] } | { type: ACTION.SET_IS_JOB_STARTED; isJobStarted: State['isJobStarted'] } - | { - type: ACTION.SET_IS_MODAL_BUTTON_DISABLED; - isModalButtonDisabled: State['isModalButtonDisabled']; - } - | { type: ACTION.SET_IS_MODAL_VISIBLE; isModalVisible: State['isModalVisible'] } | { type: ACTION.SET_JOB_CONFIG; payload: State['jobConfig'] } | { type: ACTION.SET_JOB_IDS; jobIds: State['jobIds'] } | { type: ACTION.SET_ESTIMATED_MODEL_MEMORY_LIMIT; value: State['estimatedModelMemoryLimit'] } @@ -71,12 +66,10 @@ export type Action = export interface ActionDispatchers { closeModal: () => void; createAnalyticsJob: () => void; - openModal: () => Promise; initiateWizard: () => Promise; resetAdvancedEditorMessages: () => void; setAdvancedEditorRawString: (payload: State['advancedEditorRawString']) => void; setFormState: (payload: Partial) => void; - setIsModalVisible: (payload: State['isModalVisible']) => void; setJobConfig: (payload: State['jobConfig']) => void; startAnalyticsJob: () => void; switchToAdvancedEditor: () => void; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.test.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.test.ts index fc604c9f5eb0b..e6769a7b64e2b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.test.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.test.ts @@ -79,21 +79,6 @@ describe('useCreateAnalyticsForm', () => { expect(resettedState).toEqual(initialState); }); - test('reducer(): open/close the modal', () => { - const initialState = getInitialState(); - expect(initialState.isModalVisible).toBe(false); - - const openModalState = reducer(initialState, { - type: ACTION.OPEN_MODAL, - }); - expect(openModalState.isModalVisible).toBe(true); - - const closedModalState = reducer(openModalState, { - type: ACTION.CLOSE_MODAL, - }); - expect(closedModalState.isModalVisible).toBe(false); - }); - test('reducer(): add/reset request messages', () => { const initialState = getInitialState(); expect(initialState.requestMessages).toHaveLength(0); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts index a79a8fcf61ed4..1353a35d8ecc6 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts @@ -442,12 +442,6 @@ export function reducer(state: State, action: Action): State { case ACTION.RESET_REQUEST_MESSAGES: return { ...state, requestMessages: [] }; - case ACTION.CLOSE_MODAL: - return { ...state, isModalVisible: false }; - - case ACTION.OPEN_MODAL: - return { ...state, isModalVisible: true }; - case ACTION.RESET_ADVANCED_EDITOR_MESSAGES: return { ...state, advancedEditorMessages: [] }; @@ -536,12 +530,6 @@ export function reducer(state: State, action: Action): State { case ACTION.SET_IS_JOB_STARTED: return { ...state, isJobStarted: action.isJobStarted }; - case ACTION.SET_IS_MODAL_BUTTON_DISABLED: - return { ...state, isModalButtonDisabled: action.isModalButtonDisabled }; - - case ACTION.SET_IS_MODAL_VISIBLE: - return { ...state, isModalVisible: action.isModalVisible }; - case ACTION.SET_JOB_CONFIG: return validateAdvancedEditor({ ...state, jobConfig: action.payload }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts index 547a55da7438b..b9a9caadcebd0 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.test.ts @@ -4,7 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getInitialState, getJobConfigFromFormState } from './state'; +import { + getCloneFormStateFromJobConfig, + getInitialState, + getJobConfigFromFormState, +} from './state'; + +const regJobConfig = { + id: 'reg-test-01', + description: 'Reg test job description', + source: { + index: ['reg-test-index'], + query: { + match_all: {}, + }, + }, + dest: { + index: 'reg-test-01-index', + results_field: 'ml', + }, + analysis: { + regression: { + dependent_variable: 'price', + num_top_feature_importance_values: 2, + prediction_field_name: 'airbnb_test', + training_percent: 5, + randomize_seed: 4998776294664380000, + }, + }, + analyzed_fields: { + includes: [], + excludes: [], + }, + model_memory_limit: '22mb', + create_time: 1590514291395, + version: '8.0.0', + allow_lazy_start: false, +}; describe('useCreateAnalyticsForm', () => { test('state: getJobConfigFromFormState()', () => { @@ -28,4 +64,20 @@ describe('useCreateAnalyticsForm', () => { 'the-source-index-2', ]); }); + + test('state: getCloneFormStateFromJobConfig()', () => { + const clonedState = getCloneFormStateFromJobConfig(regJobConfig); + + expect(clonedState?.sourceIndex).toBe('reg-test-index'); + expect(clonedState?.excludes).toStrictEqual([]); + expect(clonedState?.dependentVariable).toBe('price'); + expect(clonedState?.numTopFeatureImportanceValues).toBe(2); + expect(clonedState?.predictionFieldName).toBe('airbnb_test'); + expect(clonedState?.trainingPercent).toBe(5); + expect(clonedState?.randomizeSeed).toBe(4998776294664380000); + expect(clonedState?.modelMemoryLimit).toBe('22mb'); + // destination index and job id should be undefined + expect(clonedState?.destinationIndex).toBe(undefined); + expect(clonedState?.jobId).toBe(undefined); + }); }); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index 387ce89ee4120..8a07704e39910 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -92,7 +92,6 @@ export interface State { outlierFraction: undefined | number; predictionFieldName: undefined | string; previousJobType: null | AnalyticsJobType; - previousSourceIndex: EsIndexName | undefined; requiredFieldsError: string | undefined; randomizeSeed: undefined | number; sourceIndex: EsIndexName; @@ -110,8 +109,6 @@ export interface State { isAdvancedEditorValidJson: boolean; isJobCreated: boolean; isJobStarted: boolean; - isModalButtonDisabled: boolean; - isModalVisible: boolean; isValid: boolean; jobConfig: DeepPartial; jobIds: DataFrameAnalyticsId[]; @@ -167,7 +164,6 @@ export const getInitialState = (): State => ({ outlierFraction: undefined, predictionFieldName: undefined, previousJobType: null, - previousSourceIndex: undefined, requiredFieldsError: undefined, randomizeSeed: undefined, sourceIndex: '', @@ -189,8 +185,6 @@ export const getInitialState = (): State => ({ isAdvancedEditorValidJson: true, isJobCreated: false, isJobStarted: false, - isModalVisible: false, - isModalButtonDisabled: false, isValid: false, jobIds: [], requestMessages: [], @@ -328,6 +322,14 @@ export const getJobConfigFromFormState = ( return jobConfig; }; +function toCamelCase(property: string): string { + const camelCased = property.replace(/_([a-z])/g, function (g) { + return g[1].toUpperCase(); + }); + + return camelCased; +} + /** * Extracts form state for a job clone from the analytics job configuration. * For cloning we keep job id and destination index empty. @@ -353,13 +355,12 @@ export function getCloneFormStateFromJobConfig( ) { const analysisConfig = analyticsJobConfig.analysis[jobType]; - resultState.dependentVariable = analysisConfig.dependent_variable; - resultState.numTopFeatureImportanceValues = analysisConfig.num_top_feature_importance_values; - resultState.trainingPercent = analysisConfig.training_percent; - - if (isClassificationAnalysis(analyticsJobConfig.analysis)) { - // @ts-ignore - resultState.numTopClasses = analysisConfig.num_top_classes; + for (const key in analysisConfig) { + if (analysisConfig.hasOwnProperty(key)) { + const camelCased = toCamelCase(key); + // @ts-ignore + resultState[camelCased] = analysisConfig[key]; + } } } diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx index 182e50a5d74d1..ac1c710e1d106 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.test.tsx @@ -46,39 +46,13 @@ describe('getErrorMessage()', () => { describe('useCreateAnalyticsForm()', () => { test('initialization', () => { const { getLastHookValue } = getMountedHook(); - const { state, actions } = getLastHookValue(); + const { actions } = getLastHookValue(); - expect(state.isModalVisible).toBe(false); - expect(typeof actions.closeModal).toBe('function'); expect(typeof actions.createAnalyticsJob).toBe('function'); - expect(typeof actions.openModal).toBe('function'); expect(typeof actions.startAnalyticsJob).toBe('function'); expect(typeof actions.setFormState).toBe('function'); }); - test('open/close modal', () => { - const { act, getLastHookValue } = getMountedHook(); - const { state, actions } = getLastHookValue(); - - expect(state.isModalVisible).toBe(false); - - act(() => { - // this should be actions.openModal(), but that doesn't work yet because act() doesn't support async yet. - // we need to wait for an update to React 16.9 - actions.setIsModalVisible(true); - }); - const { state: stateModalOpen } = getLastHookValue(); - expect(stateModalOpen.isModalVisible).toBe(true); - - act(() => { - // this should be actions.closeModal(), but that doesn't work yet because act() doesn't support async yet. - // we need to wait for an update to React 16.9 - actions.setIsModalVisible(false); - }); - const { state: stateModalClosed } = getLastHookValue(); - expect(stateModalClosed.isModalVisible).toBe(false); - }); - // TODO // add tests for createAnalyticsJob() and startAnalyticsJob() // once React 16.9 with support for async act() is available. diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts index c4cbe149f88bc..2de9a1dcadd4b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts @@ -87,12 +87,6 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { dispatch({ type: ACTION.SET_IS_JOB_STARTED, isJobStarted }); }; - const setIsModalButtonDisabled = (isModalButtonDisabled: boolean) => - dispatch({ type: ACTION.SET_IS_MODAL_BUTTON_DISABLED, isModalButtonDisabled }); - - const setIsModalVisible = (isModalVisible: boolean) => - dispatch({ type: ACTION.SET_IS_MODAL_VISIBLE, isModalVisible }); - const setJobIds = (jobIds: DataFrameAnalyticsId[]) => dispatch({ type: ACTION.SET_JOB_IDS, jobIds }); @@ -102,7 +96,6 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { const createAnalyticsJob = async () => { resetRequestMessages(); - setIsModalButtonDisabled(true); const analyticsJobConfig = (isAdvancedEditorEnabled ? jobConfig @@ -123,7 +116,6 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { } ), }); - setIsModalButtonDisabled(false); setIsJobCreated(true); if (createIndexPattern) { createKibanaIndexPattern(); @@ -139,7 +131,6 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { } ), }); - setIsModalButtonDisabled(false); } }; @@ -267,13 +258,6 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { } }; - const openModal = async () => { - await mlContext.indexPatterns.clearCache(); - resetForm(); - await prepareFormValidation(); - dispatch({ type: ACTION.OPEN_MODAL }); - }; - const initiateWizard = async () => { await mlContext.indexPatterns.clearCache(); await prepareFormValidation(); @@ -327,8 +311,6 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { const setJobClone = async (cloneJob: DeepReadonly) => { resetForm(); - await prepareFormValidation(); - const config = extractCloningConfig(cloneJob); if (isAdvancedConfig(config)) { setJobConfig(config); @@ -339,18 +321,15 @@ export const useCreateAnalyticsForm = (): CreateAnalyticsFormProps => { } dispatch({ type: ACTION.SET_JOB_CLONE, cloneJob }); - dispatch({ type: ACTION.OPEN_MODAL }); }; const actions: ActionDispatchers = { closeModal, createAnalyticsJob, - openModal, initiateWizard, resetAdvancedEditorMessages, setAdvancedEditorRawString, setFormState, - setIsModalVisible, setJobConfig, startAnalyticsJob, switchToAdvancedEditor, diff --git a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_creation.tsx b/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_creation.tsx index 68af9a2a49cab..ebc7bd95fb0c3 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_creation.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/analytics_job_creation.tsx @@ -30,12 +30,15 @@ export const analyticsJobsCreationRoute: MlRoute = { }; const PageWrapper: FC = ({ location, deps }) => { - const { index, savedSearchId }: Record = parse(location.search, { sort: false }); + const { index, jobId, savedSearchId }: Record = parse(location.search, { + sort: false, + }); + const { context } = useResolver(index, savedSearchId, deps.config, basicResolvers(deps)); return ( - + ); }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5be46ce4bcd2d..76636779001e7 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9654,7 +9654,6 @@ "xpack.ml.dataframe.analytics.classificationExploration.showActions": "アクションを表示", "xpack.ml.dataframe.analytics.classificationExploration.showAllColumns": "すべての列を表示", "xpack.ml.dataframe.analytics.classificationExploration.tableJobIdTitle": "分類ジョブID {jobId}のデスティネーションインデックス", - "xpack.ml.dataframe.analytics.clone.flyoutHeaderTitle": "{job_id} からのジョブのクローンを作成", "xpack.ml.dataframe.analytics.create.advancedEditor.codeEditorAriaLabel": "高度な分析ジョブエディター", "xpack.ml.dataframe.analytics.create.advancedEditor.configRequestBody": "構成リクエスト本文", "xpack.ml.dataframe.analytics.create.advancedEditor.jobIdExistsError": "このIDの分析ジョブが既に存在します。", @@ -9687,22 +9686,12 @@ "xpack.ml.dataframe.analytics.create.destinationIndexLabel": "デスティネーションインデックス", "xpack.ml.dataframe.analytics.create.duplicateIndexPatternErrorMessage": "Kibanaインデックスパターンの作成中にエラーが発生しました。", "xpack.ml.dataframe.analytics.create.duplicateIndexPatternErrorMessageError": "インデックスパターン{indexPatternName}はすでに作成されています。", - "xpack.ml.dataframe.analytics.create.enableAdvancedEditorHelpText": "高度なエディターからこのフォームには戻れません。", - "xpack.ml.dataframe.analytics.create.enableAdvancedEditorSwitch": "詳細エディターを有効にする", "xpack.ml.dataframe.analytics.create.errorCreatingDataFrameAnalyticsJob": "データフレーム分析ジョブの作成中にエラーが発生しました。", "xpack.ml.dataframe.analytics.create.errorGettingDataFrameAnalyticsList": "既存のデータフレーム分析ジョブIDの取得中にエラーが発生しました。", "xpack.ml.dataframe.analytics.create.errorGettingDataFrameIndexNames": "既存のインデックス名の取得中にエラーが発生しました。", "xpack.ml.dataframe.analytics.create.errorGettingIndexPatternTitles": "既存のインデックスパターンのタイトルの取得中にエラーが発生しました。", "xpack.ml.dataframe.analytics.create.errorStartingDataFrameAnalyticsJob": "データフレーム分析ジョブの開始中にエラーが発生しました。", - "xpack.ml.dataframe.analytics.create.excludedFieldsHelpText": "分析から除外するフィールドを選択してください。他のすべてのサポートされるフィールドが含まれます。", "xpack.ml.dataframe.analytics.create.excludedFieldsLabel": "除外されたフィールド", - "xpack.ml.dataframe.analytics.create.excludesInputAriaLabel": "任意。除外するフィールドを入力または選択してください。", - "xpack.ml.dataframe.analytics.create.excludesOptionsNoSupportedFields": "このインデックスパターンのサポートされている分析フィールドが見つかりませんでした。", - "xpack.ml.dataframe.analytics.create.flyoutCancelButton": "キャンセル", - "xpack.ml.dataframe.analytics.create.flyoutCloseButton": "閉じる", - "xpack.ml.dataframe.analytics.create.flyoutCreateButton": "作成", - "xpack.ml.dataframe.analytics.create.flyoutHeaderTitle": "分析ジョブの作成", - "xpack.ml.dataframe.analytics.create.flyoutStartButton": "開始", "xpack.ml.dataframe.analytics.create.indexPatternAlreadyExistsError": "このタイトルのインデックスパターンが既に存在します。", "xpack.ml.dataframe.analytics.create.indexPatternExistsError": "このタイトルのインデックスパターンが既に存在します。", "xpack.ml.dataframe.analytics.create.jobDescription.helpText": "オプションの説明テキストです", @@ -9723,12 +9712,6 @@ "xpack.ml.dataframe.analytics.create.numTopFeatureImportanceValuesLabel": "機能重要度値", "xpack.ml.dataframe.analytics.create.outlierDetectionHelpText": "外れ値検出ジョブは、表に示すようなデータ構造でマッピングされたソースインデックスを必要とし、数字とブール値フィールドのみを分析します。カスタムオプションを構成に追加するには、詳細エディターを使用します。", "xpack.ml.dataframe.analytics.create.outlierRegressionHelpText": "リグレッションジョブは数値フィールドのみを分析します。予測フィールド名などのカスタムオプションを適用するには、詳細エディターを使用します。", - "xpack.ml.dataframe.analytics.create.sourceIndexFieldCheckError": "数値フィールドの確認中に問題が発生しました。ページを更新して再起動してください。", - "xpack.ml.dataframe.analytics.create.sourceIndexHelpText": "このインデックスパターンには数字タイプのフィールドが含まれていません。分析ジョブで外れ値が検出されない可能性があります。", - "xpack.ml.dataframe.analytics.create.sourceIndexInputAriaLabel": "ソースインデックスパターンまたは検索。", - "xpack.ml.dataframe.analytics.create.sourceIndexInvalidError": "無効なソースインデックス名。スペースや{characterList}を含めることはできません", - "xpack.ml.dataframe.analytics.create.sourceIndexLabel": "ソースインデックス", - "xpack.ml.dataframe.analytics.create.sourceIndexPlaceholder": "ソースインデックスパターンを選択してください。", "xpack.ml.dataframe.analytics.create.startDataFrameAnalyticsSuccessMessage": "データフレーム分析 {jobId} の開始リクエストが受け付けられました。", "xpack.ml.dataframe.analytics.create.trainingPercentLabel": "トレーニングパーセンテージ", "xpack.ml.dataframe.analytics.errorCallout.evaluateErrorTitle": "データの読み込み中にエラーが発生しました。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index dff26907b48ed..331e9d67c3897 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9658,7 +9658,6 @@ "xpack.ml.dataframe.analytics.classificationExploration.showActions": "显示操作", "xpack.ml.dataframe.analytics.classificationExploration.showAllColumns": "显示所有列", "xpack.ml.dataframe.analytics.classificationExploration.tableJobIdTitle": "分类作业 ID {jobId} 的目标索引", - "xpack.ml.dataframe.analytics.clone.flyoutHeaderTitle": "从 {job_id} 克隆作业", "xpack.ml.dataframe.analytics.create.advancedEditor.codeEditorAriaLabel": "高级分析作业编辑器", "xpack.ml.dataframe.analytics.create.advancedEditor.configRequestBody": "配置请求正文", "xpack.ml.dataframe.analytics.create.advancedEditor.jobIdExistsError": "已存在具有此 ID 的分析作业。", @@ -9691,22 +9690,12 @@ "xpack.ml.dataframe.analytics.create.destinationIndexLabel": "目标 IP", "xpack.ml.dataframe.analytics.create.duplicateIndexPatternErrorMessage": "创建 Kibana 索引模式时发生错误:", "xpack.ml.dataframe.analytics.create.duplicateIndexPatternErrorMessageError": "索引模式 {indexPatternName} 已存在。", - "xpack.ml.dataframe.analytics.create.enableAdvancedEditorHelpText": "您不能从高级编辑器切回到此表单。", - "xpack.ml.dataframe.analytics.create.enableAdvancedEditorSwitch": "启用高级编辑器", "xpack.ml.dataframe.analytics.create.errorCreatingDataFrameAnalyticsJob": "创建数据帧分析作业时发生错误:", "xpack.ml.dataframe.analytics.create.errorGettingDataFrameAnalyticsList": "获取现有数据帧分析作业 ID 时发生错误:", "xpack.ml.dataframe.analytics.create.errorGettingDataFrameIndexNames": "获取现有索引名称时发生错误:", "xpack.ml.dataframe.analytics.create.errorGettingIndexPatternTitles": "获取现有索引模式标题时发生错误:", "xpack.ml.dataframe.analytics.create.errorStartingDataFrameAnalyticsJob": "启动数据帧分析作业时发生错误:", - "xpack.ml.dataframe.analytics.create.excludedFieldsHelpText": "选择要从分析中排除的字段。包括所有其他支持的字段。", "xpack.ml.dataframe.analytics.create.excludedFieldsLabel": "排除的字段", - "xpack.ml.dataframe.analytics.create.excludesInputAriaLabel": "可选。输入或选择要排除的字段。", - "xpack.ml.dataframe.analytics.create.excludesOptionsNoSupportedFields": "没有为此索引模式找到任何支持的分析字段。", - "xpack.ml.dataframe.analytics.create.flyoutCancelButton": "取消", - "xpack.ml.dataframe.analytics.create.flyoutCloseButton": "关闭", - "xpack.ml.dataframe.analytics.create.flyoutCreateButton": "创建", - "xpack.ml.dataframe.analytics.create.flyoutHeaderTitle": "创建分析作业", - "xpack.ml.dataframe.analytics.create.flyoutStartButton": "开始", "xpack.ml.dataframe.analytics.create.indexPatternAlreadyExistsError": "具有此名称的索引模式已存在。", "xpack.ml.dataframe.analytics.create.indexPatternExistsError": "具有此名称的索引模式已存在。", "xpack.ml.dataframe.analytics.create.jobDescription.helpText": "可选的描述文本", @@ -9727,12 +9716,6 @@ "xpack.ml.dataframe.analytics.create.numTopFeatureImportanceValuesLabel": "功能重要性值", "xpack.ml.dataframe.analytics.create.outlierDetectionHelpText": "离群值检测作业需要映射为表状数据结构的源索引,并仅分析数值和布尔值字段。使用高级编辑器将定制选项添加到配置。", "xpack.ml.dataframe.analytics.create.outlierRegressionHelpText": "回归作业仅分析数值字段。使用高级编辑器来应用定制选项,如预测字段名称。", - "xpack.ml.dataframe.analytics.create.sourceIndexFieldCheckError": "检查数值字段时出现问题。请刷新页面并重试。", - "xpack.ml.dataframe.analytics.create.sourceIndexHelpText": "此索引模式不包含任何数值类型字段。分析作业可能无法提供任何离群值。", - "xpack.ml.dataframe.analytics.create.sourceIndexInputAriaLabel": "源索引模式或搜索。", - "xpack.ml.dataframe.analytics.create.sourceIndexInvalidError": "源索引名称无效,其不能包含空格或以下字符:{characterList}", - "xpack.ml.dataframe.analytics.create.sourceIndexLabel": "源索引", - "xpack.ml.dataframe.analytics.create.sourceIndexPlaceholder": "选择源索引模式。", "xpack.ml.dataframe.analytics.create.startDataFrameAnalyticsSuccessMessage": "数据帧分析 {jobId} 启动请求已确认。", "xpack.ml.dataframe.analytics.create.trainingPercentLabel": "训练百分比", "xpack.ml.dataframe.analytics.errorCallout.evaluateErrorTitle": "加载数据时出错。", From 0306c7a8cf1efc34360f1422690dfffa1b057857 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Tue, 9 Jun 2020 15:07:40 -0600 Subject: [PATCH 11/53] Upgrade EUI to v24.1.0 (#68141) * eui to 24.1.0 * src snapshot updates * x-pack snapshot updates * euiPaletteColorBlind param updates * euiPaletteColorBlind ts-ignore * fix collapsibleNav close button click for functional testing * await focus * increase legacy sass build timeout value Co-authored-by: Elastic Machine --- package.json | 2 +- packages/kbn-ui-shared-deps/package.json | 2 +- .../collapsible_nav.test.tsx.snap | 211 +++++++++--------- .../header/__snapshots__/header.test.tsx.snap | 85 ++++--- src/legacy/server/sass/build.test.js | 2 + .../__snapshots__/new_vis_modal.test.tsx.snap | 2 + test/functional/services/apps_menu.ts | 4 + .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../kbn_sample_panel_action/package.json | 2 +- .../kbn_tp_custom_visualizations/package.json | 2 +- .../kbn_tp_embeddable_explorer/package.json | 2 +- x-pack/package.json | 2 +- .../__test__/__snapshots__/List.test.tsx.snap | 18 ++ .../__snapshots__/asset.examples.storyshot | 8 + .../asset_manager.stories.storyshot | 8 + .../element_controls.stories.storyshot | 2 + .../element_grid.stories.storyshot | 6 + .../saved_elements_modal.stories.storyshot | 8 + .../sidebar_header.stories.storyshot | 4 + .../simple_template.examples.storyshot | 1 + .../public/classes/styles/color_utils.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 43 ++-- .../note_card_body.test.tsx.snap | 43 ++-- yarn.lock | 8 +- 24 files changed, 263 insertions(+), 208 deletions(-) diff --git a/package.json b/package.json index 5bf39a57c1ac5..419edcf268356 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "@elastic/charts": "19.2.0", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.8.0", - "@elastic/eui": "23.3.1", + "@elastic/eui": "24.1.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "^2.5.0", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 744a656c54a7f..2c9251b03059a 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@elastic/charts": "19.2.0", - "@elastic/eui": "23.3.1", + "@elastic/eui": "24.1.0", "@elastic/numeral": "^2.5.0", "@kbn/i18n": "1.0.0", "@kbn/monaco": "1.0.0", diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index f5b17f8d214e9..60963c0acb990 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -1014,7 +1014,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
@@ -1662,7 +1658,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
@@ -3119,38 +3111,43 @@ exports[`CollapsibleNav renders links grouped by category 1`] = `
- - - + +
+
- - - + + +
@@ -4717,7 +4715,7 @@ exports[`CollapsibleNav renders the default nav 3`] = ` @@ -5120,38 +5114,43 @@ exports[`CollapsibleNav renders the default nav 3`] = ` - - - + + +
@@ -9277,7 +9273,7 @@ exports[`Header renders 3`] = `
@@ -9764,38 +9756,43 @@ exports[`Header renders 3`] = ` - - - + + +
@@ -14302,6 +14300,7 @@ exports[`Header renders 4`] = ` > diff --git a/src/legacy/server/sass/build.test.js b/src/legacy/server/sass/build.test.js index 46a898c30f84e..71c43ac010962 100644 --- a/src/legacy/server/sass/build.test.js +++ b/src/legacy/server/sass/build.test.js @@ -33,6 +33,8 @@ afterEach(async () => { }); it('builds light themed SASS', async () => { + // Increased timeout from 5000ms due to intermittent timeout failures + jest.setTimeout(60000); const targetPath = resolve(TMP, 'style.css'); await new Build({ sourcePath: FIXTURE, diff --git a/src/plugins/visualizations/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/plugins/visualizations/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap index 22cc873cbdb5d..53ef164685a1c 100644 --- a/src/plugins/visualizations/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap +++ b/src/plugins/visualizations/public/wizard/__snapshots__/new_vis_modal.test.tsx.snap @@ -1264,6 +1264,7 @@ exports[`NewVisModal filter for visualization types should render as expected 1` > @@ -2772,6 +2773,7 @@ exports[`NewVisModal should render as expected 1`] = ` > diff --git a/test/functional/services/apps_menu.ts b/test/functional/services/apps_menu.ts index 969bddbd30f9a..aa7934d6b1156 100644 --- a/test/functional/services/apps_menu.ts +++ b/test/functional/services/apps_menu.ts @@ -58,6 +58,10 @@ export function AppsMenuProvider({ getService, getPageObjects }: FtrProviderCont public async closeCollapsibleNav() { const CLOSE_BUTTON = '[data-test-subj=collapsibleNav] > button'; if (await find.existsByCssSelector(CLOSE_BUTTON)) { + // Close button is only visible when focused + const button = await find.byCssSelector(CLOSE_BUTTON); + await button.focus(); + await find.clickByCssSelector(CLOSE_BUTTON); } } diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json index acd78cb4955e3..24b38fae96653 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "23.3.1", + "@elastic/eui": "24.1.0", "react": "^16.12.0", "react-dom": "^16.12.0" }, diff --git a/test/plugin_functional/plugins/kbn_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_sample_panel_action/package.json index 45d07933c4209..71a635c444b8c 100644 --- a/test/plugin_functional/plugins/kbn_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_sample_panel_action/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "23.3.1", + "@elastic/eui": "24.1.0", "react": "^16.12.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json index ca99e9b5995c1..78f0b42a6fbda 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "23.3.1", + "@elastic/eui": "24.1.0", "react": "^16.12.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json index 63dde0fa96dd3..6dbc9c71f2e81 100644 --- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json +++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "23.3.1", + "@elastic/eui": "24.1.0", "react": "^16.12.0" }, "scripts": { diff --git a/x-pack/package.json b/x-pack/package.json index b3dcde2194d3f..fb708ab09d841 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -190,7 +190,7 @@ "@elastic/apm-rum-react": "^1.1.1", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.8.0", - "@elastic/eui": "23.3.1", + "@elastic/eui": "24.1.0", "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.3.0", "@elastic/node-crypto": "1.1.1", diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap index 3de725dc58ea7..6a20e3c103709 100644 --- a/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap +++ b/x-pack/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap @@ -161,6 +161,7 @@ exports[`ErrorGroupOverview -> List should render empty state 1`] = ` @@ -575,6 +576,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -754,6 +756,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -859,6 +862,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -889,6 +893,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -958,6 +963,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -984,6 +990,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -1089,6 +1096,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1119,6 +1127,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -1188,6 +1197,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1214,6 +1224,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -1319,6 +1330,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1349,6 +1361,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -1418,6 +1431,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1444,6 +1458,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` @@ -1549,6 +1564,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > @@ -1579,6 +1595,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
@@ -1648,6 +1665,7 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot index 6601f570209e9..14791cd3d8b25 100644 --- a/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot +++ b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot @@ -63,6 +63,7 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -88,6 +89,7 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -118,6 +120,7 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -148,6 +151,7 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = ` > @@ -237,6 +241,7 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > @@ -262,6 +267,7 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > @@ -292,6 +298,7 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > @@ -322,6 +329,7 @@ exports[`Storyshots components/Assets/Asset marker 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot index aff630b21c770..1b8f1480759f6 100644 --- a/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot @@ -422,6 +422,7 @@ Array [ > @@ -447,6 +448,7 @@ Array [ > @@ -477,6 +479,7 @@ Array [ > @@ -507,6 +510,7 @@ Array [ > @@ -585,6 +589,7 @@ Array [ > @@ -610,6 +615,7 @@ Array [ > @@ -640,6 +646,7 @@ Array [ > @@ -670,6 +677,7 @@ Array [ > diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot index 6f12f68356467..408b0679c415f 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot @@ -16,6 +16,7 @@ exports[`Storyshots components/SavedElementsModal/ElementControls has two button > @@ -42,6 +43,7 @@ exports[`Storyshots components/SavedElementsModal/ElementControls has two button > diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot index be0fb0573c394..1c506819df1fb 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot @@ -66,6 +66,7 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -92,6 +93,7 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -170,6 +172,7 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -196,6 +199,7 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -274,6 +278,7 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > @@ -300,6 +305,7 @@ exports[`Storyshots components/SavedElementsModal/ElementGrid default 1`] = ` > diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot index 03093b41300b8..04b2184f27462 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot @@ -362,6 +362,7 @@ Array [ > @@ -388,6 +389,7 @@ Array [ > @@ -466,6 +468,7 @@ Array [ > @@ -492,6 +495,7 @@ Array [ > @@ -570,6 +574,7 @@ Array [ > @@ -596,6 +601,7 @@ Array [ > @@ -851,6 +857,7 @@ Array [ > @@ -877,6 +884,7 @@ Array [ > diff --git a/x-pack/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot b/x-pack/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot index 4d5b9570ee20f..16263aa7ea384 100644 --- a/x-pack/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot @@ -55,6 +55,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > @@ -80,6 +81,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > @@ -105,6 +107,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > @@ -130,6 +133,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader with layer controls 1`] = ` > diff --git a/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot index 14466cab1a698..f8583d7cd0dc0 100644 --- a/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot +++ b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot @@ -169,6 +169,7 @@ exports[`Storyshots arguments/SeriesStyle/components simple: no series 1`] = ` > diff --git a/x-pack/plugins/maps/public/classes/styles/color_utils.tsx b/x-pack/plugins/maps/public/classes/styles/color_utils.tsx index 116e03096b0f5..0192a9d7ca68f 100644 --- a/x-pack/plugins/maps/public/classes/styles/color_utils.tsx +++ b/x-pack/plugins/maps/public/classes/styles/color_utils.tsx @@ -139,11 +139,11 @@ const COLOR_PALETTES_CONFIGS: ColorPalette[] = [ }, { id: 'palette_20', - colors: euiPaletteColorBlind(2), + colors: euiPaletteColorBlind({ rotations: 2 }), }, { id: 'palette_30', - colors: euiPaletteColorBlind(3), + colors: euiPaletteColorBlind({ rotations: 3 }), }, ]; diff --git a/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap index a2c7e72e51a9c..26775608637c0 100644 --- a/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap @@ -115,32 +115,28 @@ exports[`Paginated Table Component rendering it renders the default load more ta }, "euiCardSpacing": "16px", "euiCheckBoxSize": "16px", - "euiCodeBlockAdditionBackgroundColor": "#144212", - "euiCodeBlockAdditionColor": "#e6e1dc", - "euiCodeBlockAttributeColor": "#80cbbf", + "euiCodeBlockAdditionColor": "#54b399", + "euiCodeBlockAttributeColor": "inherit", "euiCodeBlockBackgroundColor": "#25262e", - "euiCodeBlockBuiltInColor": "#0086b3", "euiCodeBlockColor": "#dfe5ef", - "euiCodeBlockCommentColor": "#656565", - "euiCodeBlockDeletionBackgroundColor": "#660000", - "euiCodeBlockDeletionColor": "#e6e1dc", - "euiCodeBlockFunctionTitleColor": "#75a5ff", - "euiCodeBlockKeywordColor": "#c792ea", - "euiCodeBlockMetaColor": "#75a5ff", - "euiCodeBlockNameColor": "#e06c75", - "euiCodeBlockNumberColor": "#f77669", - "euiCodeBlockParamsColor": "#eefff7", - "euiCodeBlockRegexpColor": "#009926", - "euiCodeBlockSectionColor": "#ffc66d", + "euiCodeBlockCommentColor": "#8d919a", + "euiCodeBlockDeletionColor": "#ff6666", + "euiCodeBlockFunctionTitleColor": "inherit", + "euiCodeBlockKeywordColor": "#a184c2", + "euiCodeBlockMetaColor": "#8d919a", + "euiCodeBlockNameColor": "#6092c0", + "euiCodeBlockNumberColor": "#54b399", + "euiCodeBlockParamsColor": "inherit", + "euiCodeBlockSectionColor": "#e7664c", "euiCodeBlockSelectedBackgroundColor": "inherit", - "euiCodeBlockSelectorClassColor": "#ffcb68", - "euiCodeBlockSelectorIdColor": "#f77669", - "euiCodeBlockSelectorTagColor": "#c792ea", - "euiCodeBlockStringColor": "#c3e88d", - "euiCodeBlockSymbolColor": "#c792ea", - "euiCodeBlockTagColor": "#abb2bf", - "euiCodeBlockTitleColor": "#75a5ff", - "euiCodeBlockTypeColor": "#da4939", + "euiCodeBlockSelectorClassColor": "inherit", + "euiCodeBlockSelectorIdColor": "inherit", + "euiCodeBlockSelectorTagColor": "inherit", + "euiCodeBlockStringColor": "#d77092", + "euiCodeBlockSymbolColor": "#e7664c", + "euiCodeBlockTagColor": "#6092c0", + "euiCodeBlockTitleColor": "#da8b45", + "euiCodeBlockTypeColor": "#6092c0", "euiCodeFontFamily": "'Roboto Mono', 'Consolas', 'Menlo', 'Courier', monospace", "euiCollapsibleNavGroupDarkBackgroundColor": "#131317", "euiCollapsibleNavGroupDarkHighContrastColor": "#1ba9f5", @@ -230,6 +226,7 @@ exports[`Paginated Table Component rendering it renders the default load more ta "warning": "#ffce7a", }, "euiFilePickerTallHeight": "128px", + "euiFlyoutBorder": "1px solid #343741", "euiFocusBackgroundColor": "#232635", "euiFocusRingAnimStartColor": "rgba(27, 169, 245, 0)", "euiFocusRingAnimStartSize": "6px", diff --git a/x-pack/plugins/security_solution/public/timelines/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap index 391aaba17ae3a..22f89ffc6927e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/notes/note_card/__snapshots__/note_card_body.test.tsx.snap @@ -115,32 +115,28 @@ exports[`NoteCardBody renders correctly against snapshot 1`] = ` }, "euiCardSpacing": "16px", "euiCheckBoxSize": "16px", - "euiCodeBlockAdditionBackgroundColor": "#144212", - "euiCodeBlockAdditionColor": "#e6e1dc", - "euiCodeBlockAttributeColor": "#80cbbf", + "euiCodeBlockAdditionColor": "#54b399", + "euiCodeBlockAttributeColor": "inherit", "euiCodeBlockBackgroundColor": "#25262e", - "euiCodeBlockBuiltInColor": "#0086b3", "euiCodeBlockColor": "#dfe5ef", - "euiCodeBlockCommentColor": "#656565", - "euiCodeBlockDeletionBackgroundColor": "#660000", - "euiCodeBlockDeletionColor": "#e6e1dc", - "euiCodeBlockFunctionTitleColor": "#75a5ff", - "euiCodeBlockKeywordColor": "#c792ea", - "euiCodeBlockMetaColor": "#75a5ff", - "euiCodeBlockNameColor": "#e06c75", - "euiCodeBlockNumberColor": "#f77669", - "euiCodeBlockParamsColor": "#eefff7", - "euiCodeBlockRegexpColor": "#009926", - "euiCodeBlockSectionColor": "#ffc66d", + "euiCodeBlockCommentColor": "#8d919a", + "euiCodeBlockDeletionColor": "#ff6666", + "euiCodeBlockFunctionTitleColor": "inherit", + "euiCodeBlockKeywordColor": "#a184c2", + "euiCodeBlockMetaColor": "#8d919a", + "euiCodeBlockNameColor": "#6092c0", + "euiCodeBlockNumberColor": "#54b399", + "euiCodeBlockParamsColor": "inherit", + "euiCodeBlockSectionColor": "#e7664c", "euiCodeBlockSelectedBackgroundColor": "inherit", - "euiCodeBlockSelectorClassColor": "#ffcb68", - "euiCodeBlockSelectorIdColor": "#f77669", - "euiCodeBlockSelectorTagColor": "#c792ea", - "euiCodeBlockStringColor": "#c3e88d", - "euiCodeBlockSymbolColor": "#c792ea", - "euiCodeBlockTagColor": "#abb2bf", - "euiCodeBlockTitleColor": "#75a5ff", - "euiCodeBlockTypeColor": "#da4939", + "euiCodeBlockSelectorClassColor": "inherit", + "euiCodeBlockSelectorIdColor": "inherit", + "euiCodeBlockSelectorTagColor": "inherit", + "euiCodeBlockStringColor": "#d77092", + "euiCodeBlockSymbolColor": "#e7664c", + "euiCodeBlockTagColor": "#6092c0", + "euiCodeBlockTitleColor": "#da8b45", + "euiCodeBlockTypeColor": "#6092c0", "euiCodeFontFamily": "'Roboto Mono', 'Consolas', 'Menlo', 'Courier', monospace", "euiCollapsibleNavGroupDarkBackgroundColor": "#131317", "euiCollapsibleNavGroupDarkHighContrastColor": "#1ba9f5", @@ -230,6 +226,7 @@ exports[`NoteCardBody renders correctly against snapshot 1`] = ` "warning": "#ffce7a", }, "euiFilePickerTallHeight": "128px", + "euiFlyoutBorder": "1px solid #343741", "euiFocusBackgroundColor": "#232635", "euiFocusRingAnimStartColor": "rgba(27, 169, 245, 0)", "euiFocusRingAnimStartSize": "6px", diff --git a/yarn.lock b/yarn.lock index f7b310cca7590..cf9126b668e51 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1332,10 +1332,10 @@ tabbable "^1.1.0" uuid "^3.1.0" -"@elastic/eui@23.3.1": - version "23.3.1" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-23.3.1.tgz#08516910d24eb148110f99d3bd7551240f9ef3d4" - integrity sha512-81N5xXeZwm8HEPE5RAPQFFUNUzYlTVJcNhW+DDN0EY8MlxVob9hgHy0AwshQGfrHlqhm+4gix110pW3n9Jweyw== +"@elastic/eui@24.1.0": + version "24.1.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-24.1.0.tgz#40593cc474237e8c464d182faa50c748b3f66822" + integrity sha512-Y7s327h0Z8dsO6MY7Sn1k5pOrf9ZjWH/ZE2gVtfBn2He5aFahS/+A434EBqFG0YV5W1VZtYiXtSj0AE1gjtrrw== dependencies: "@types/chroma-js" "^2.0.0" "@types/enzyme" "^3.1.13" From 2e3578602fcf999b279cf0de4091630cbb4649ee Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Tue, 9 Jun 2020 16:17:28 -0500 Subject: [PATCH 12/53] APM Storybook fixes (#68671) * Resolve core legacy assets in @kbn/storybook webpack configuration * Ignore stories in Jest coverage * Combine effects in Cytoscape component so handlers are always added before events are triggered * Add mock context to ErrorRateAlertTrigger stories * Disable TransactionDurationAlertTrigger stories Changing the Cytoscape effect behavior is necessary because the layout was not being triggered when the final set of elements is provided as props to the component. When this is used in Kibana we're always starting with empty elements and fetching them, but in the Storybook we're starting out with the full elements. --- .../storybook_config/webpack.config.js | 23 ++++++++++++++++++- x-pack/plugins/apm/jest.config.js | 1 + .../app/ServiceMap/Cytoscape.stories.tsx | 2 +- .../components/app/ServiceMap/Cytoscape.tsx | 15 ++++-------- .../ErrorRateAlertTrigger/index.stories.tsx | 23 +++++++++++++------ .../index.stories.tsx | 16 +++++++++---- 6 files changed, 56 insertions(+), 24 deletions(-) diff --git a/packages/kbn-storybook/storybook_config/webpack.config.js b/packages/kbn-storybook/storybook_config/webpack.config.js index 2dd051882bb4b..543bb47656df8 100644 --- a/packages/kbn-storybook/storybook_config/webpack.config.js +++ b/packages/kbn-storybook/storybook_config/webpack.config.js @@ -17,7 +17,7 @@ * under the License. */ -const { resolve } = require('path'); +const { parse, resolve } = require('path'); const webpack = require('webpack'); const { stringifyRequest } = require('loader-utils'); const CopyWebpackPlugin = require('copy-webpack-plugin'); @@ -95,6 +95,27 @@ module.exports = async ({ config }) => { }, }, }, + { + loader: 'resolve-url-loader', + options: { + // If you don't have arguments (_, __) to the join function, the + // resolve-url-loader fails with a loader misconfiguration error. + // + // eslint-disable-next-line no-unused-vars + join: (_, __) => (uri, base) => { + if (!base || !parse(base).dir.includes('legacy')) { + return null; + } + + // URIs on mixins in src/legacy/public/styles need to be resolved. + if (uri.startsWith('ui/assets')) { + return resolve(REPO_ROOT, 'src/core/server/core_app/', uri.replace('ui/', '')); + } + + return null; + }, + }, + }, { loader: 'sass-loader', options: { diff --git a/x-pack/plugins/apm/jest.config.js b/x-pack/plugins/apm/jest.config.js index c3ae694fe8e14..43bdeb583c819 100644 --- a/x-pack/plugins/apm/jest.config.js +++ b/x-pack/plugins/apm/jest.config.js @@ -31,6 +31,7 @@ module.exports = { collectCoverageFrom: [ '**/*.{js,jsx,ts,tsx}', '!**/{__test__,__snapshots__,__examples__,integration_tests,tests}/**', + '!**/*.stories.{js,ts,tsx}', '!**/*.test.{js,ts,tsx}', '!**/dev_docs/**', '!**/e2e/**', diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx index 1c62d3cc03db0..30031a05304bb 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx @@ -346,7 +346,7 @@ storiesOf('app/ServiceMap/Cytoscape', module).add( }, }, ]; - return ; + return ; }, { info: { propTables: false, source: false }, diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index cb908785d64d8..c57d702b9a546 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -121,15 +121,6 @@ export function Cytoscape({ const trackApmEvent = useUiTracker({ app: 'apm' }); - // Trigger a custom "data" event when data changes - useEffect(() => { - if (cy) { - cy.remove(cy.elements()); - cy.add(elements); - cy.trigger('data'); - } - }, [cy, elements]); - // Set up cytoscape event handlers useEffect(() => { const resetConnectedEdgeStyle = (node?: cytoscape.NodeSingular) => { @@ -223,6 +214,10 @@ export function Cytoscape({ cy.on('mouseout', 'edge, node', mouseoutHandler); cy.on('select', 'node', selectHandler); cy.on('unselect', 'node', unselectHandler); + + cy.remove(cy.elements()); + cy.add(elements); + cy.trigger('data'); } return () => { @@ -241,7 +236,7 @@ export function Cytoscape({ } clearTimeout(layoutstopDelayTimeout); }; - }, [cy, height, serviceName, trackApmEvent, width]); + }, [cy, elements, height, serviceName, trackApmEvent, width]); return ( diff --git a/x-pack/plugins/apm/public/components/shared/ErrorRateAlertTrigger/index.stories.tsx b/x-pack/plugins/apm/public/components/shared/ErrorRateAlertTrigger/index.stories.tsx index 8f7ed54f91bd0..ebcb1627984ad 100644 --- a/x-pack/plugins/apm/public/components/shared/ErrorRateAlertTrigger/index.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/ErrorRateAlertTrigger/index.stories.tsx @@ -7,6 +7,11 @@ import { storiesOf } from '@storybook/react'; import React from 'react'; import { ErrorRateAlertTrigger } from '.'; +import { ApmPluginContextValue } from '../../../context/ApmPluginContext'; +import { + mockApmPluginContextValue, + MockApmPluginContextWrapper, +} from '../../../context/ApmPluginContext/MockApmPluginContext'; storiesOf('app/ErrorRateAlertTrigger', module).add('example', () => { const params = { @@ -15,12 +20,16 @@ storiesOf('app/ErrorRateAlertTrigger', module).add('example', () => { }; return ( -
- undefined} - setAlertProperty={() => undefined} - /> -
+ +
+ undefined} + setAlertProperty={() => undefined} + /> +
+
); }); diff --git a/x-pack/plugins/apm/public/components/shared/TransactionDurationAlertTrigger/index.stories.tsx b/x-pack/plugins/apm/public/components/shared/TransactionDurationAlertTrigger/index.stories.tsx index e2429d1225442..da9adbb8dfead 100644 --- a/x-pack/plugins/apm/public/components/shared/TransactionDurationAlertTrigger/index.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/TransactionDurationAlertTrigger/index.stories.tsx @@ -3,18 +3,24 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +// import { storiesOf } from '@storybook/react'; import { cloneDeep, merge } from 'lodash'; -import { storiesOf } from '@storybook/react'; import React from 'react'; import { TransactionDurationAlertTrigger } from '.'; +import { ApmPluginContextValue } from '../../../context/ApmPluginContext'; import { - MockApmPluginContextWrapper, mockApmPluginContextValue, + MockApmPluginContextWrapper, } from '../../../context/ApmPluginContext/MockApmPluginContext'; import { MockUrlParamsContextProvider } from '../../../context/UrlParamsContext/MockUrlParamsContextProvider'; -import { ApmPluginContextValue } from '../../../context/ApmPluginContext'; -storiesOf('app/TransactionDurationAlertTrigger', module).add('example', () => { +// Disabling this because we currently don't have a way to mock `useEnvironments` +// which is used by this component. Using the fetch-mock module should work, but +// our current storybook setup has core-js-related problems when trying to import +// it. +// storiesOf('app/TransactionDurationAlertTrigger', module).add('example', +// eslint-disable-next-line no-unused-expressions +() => { const params = { threshold: 1500, aggregationType: 'avg' as const, @@ -44,4 +50,4 @@ storiesOf('app/TransactionDurationAlertTrigger', module).add('example', () => {
); -}); +}; From 938771a537dfd58fbf79a80a630db16b8b8bc785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Tue, 9 Jun 2020 23:37:26 +0200 Subject: [PATCH 13/53] [Logs + Metrics UI] Clean up async plugin initialization (#67654) This refactors the browser-side plugin bootstrap code such that the eagerly loaded bundle `infra.plugin.js` is minimal and the rest of the logs and metrics app bundles are loaded only when the apps are visited. --- .../components/expression.tsx | 4 + .../components/validation.tsx | 3 +- .../public/alerting/metric_threshold/index.ts | 4 +- .../infra/public/apps/common_providers.tsx | 47 +++++++ .../infra/public/apps/common_styles.ts | 13 ++ .../plugins/infra/public/apps/legacy_app.tsx | 98 +++++++++++++ x-pack/plugins/infra/public/apps/logs_app.tsx | 66 +++++++++ .../plugins/infra/public/apps/metrics_app.tsx | 82 +++++++++++ .../plugins/infra/public/apps/start_app.tsx | 80 ----------- .../infra/public/apps/start_legacy_app.tsx | 100 ------------- .../alerting/inventory/expression.tsx | 4 + .../metric_inventory_threshold_alert_type.ts | 4 +- .../alerting/inventory/validation.tsx | 4 +- .../logs/expression_editor/editor.tsx | 4 + .../alerting/logs/log_threshold_alert_type.ts | 4 +- x-pack/plugins/infra/public/compose_libs.ts | 99 ------------- .../containers/with_state_from_location.tsx | 131 ------------------ .../public/graphql/log_entries.gql_query.ts | 44 ------ .../public/hooks/use_link_props.test.tsx | 14 +- x-pack/plugins/infra/public/index.ts | 5 +- .../observable_api/kibana_observable_api.ts | 45 ------ x-pack/plugins/infra/public/lib/lib.ts | 94 +------------ .../link_to/redirect_to_node_logs.test.tsx | 12 +- .../pages/link_to/redirect_to_node_logs.tsx | 2 +- .../infra/public/pages/logs/page_content.tsx | 1 + .../inventory_view/components/table_view.tsx | 2 +- .../inventory_view/hooks/use_waffle_time.ts | 4 +- .../metric_detail/hooks/metrics_time.test.tsx | 33 ++++- x-pack/plugins/infra/public/plugin.ts | 99 +++++-------- x-pack/plugins/infra/public/routers/index.ts | 15 -- .../infra/public/routers/logs_router.tsx | 31 ----- .../infra/public/routers/metrics_router.tsx | 41 ------ x-pack/plugins/infra/public/types.ts | 25 ++++ .../infra/public/utils/apollo_client.ts | 85 ++++++++++++ .../public/utils/triggers_actions_context.tsx | 6 +- .../infra/public/utils/use_url_state.ts | 3 +- 36 files changed, 528 insertions(+), 780 deletions(-) create mode 100644 x-pack/plugins/infra/public/apps/common_providers.tsx create mode 100644 x-pack/plugins/infra/public/apps/common_styles.ts create mode 100644 x-pack/plugins/infra/public/apps/legacy_app.tsx create mode 100644 x-pack/plugins/infra/public/apps/logs_app.tsx create mode 100644 x-pack/plugins/infra/public/apps/metrics_app.tsx delete mode 100644 x-pack/plugins/infra/public/apps/start_app.tsx delete mode 100644 x-pack/plugins/infra/public/apps/start_legacy_app.tsx delete mode 100644 x-pack/plugins/infra/public/compose_libs.ts delete mode 100644 x-pack/plugins/infra/public/containers/with_state_from_location.tsx delete mode 100644 x-pack/plugins/infra/public/graphql/log_entries.gql_query.ts delete mode 100644 x-pack/plugins/infra/public/lib/adapters/observable_api/kibana_observable_api.ts delete mode 100644 x-pack/plugins/infra/public/routers/index.ts delete mode 100644 x-pack/plugins/infra/public/routers/logs_router.tsx delete mode 100644 x-pack/plugins/infra/public/routers/metrics_router.tsx create mode 100644 x-pack/plugins/infra/public/types.ts create mode 100644 x-pack/plugins/infra/public/utils/apollo_client.ts diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx index 7a71bb68bc54f..d5d61733e8717 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx @@ -384,3 +384,7 @@ export const Expressions: React.FC = (props) => { ); }; + +// required for dynamic import +// eslint-disable-next-line import/no-default-export +export default Expressions; diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx index 2d9524ca158c8..da342f0a45420 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx @@ -5,7 +5,6 @@ */ import { i18n } from '@kbn/i18n'; -import { isNumber } from 'lodash'; import { MetricExpressionParams, Comparator, @@ -106,3 +105,5 @@ export function validateMetricThreshold({ return validationResult; } + +const isNumber = (value: unknown): value is number => typeof value === 'number'; diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts b/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts index a40cb1eaec50c..6a999a86c99d1 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/index.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; +import React from 'react'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types'; -import { Expressions } from './components/expression'; import { validateMetricThreshold } from './components/validation'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { METRIC_THRESHOLD_ALERT_TYPE_ID } from '../../../server/lib/alerting/metric_threshold/types'; @@ -18,7 +18,7 @@ export function createMetricThresholdAlertType(): AlertTypeModel { defaultMessage: 'Metric threshold', }), iconClass: 'bell', - alertParamsExpression: Expressions, + alertParamsExpression: React.lazy(() => import('./components/expression')), validate: validateMetricThreshold, defaultActionMessage: i18n.translate( 'xpack.infra.metrics.alerting.threshold.defaultActionMessage', diff --git a/x-pack/plugins/infra/public/apps/common_providers.tsx b/x-pack/plugins/infra/public/apps/common_providers.tsx new file mode 100644 index 0000000000000..facb0f1539a10 --- /dev/null +++ b/x-pack/plugins/infra/public/apps/common_providers.tsx @@ -0,0 +1,47 @@ +/* + * 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 { CoreStart } from 'kibana/public'; +import { ApolloClient } from 'apollo-client'; +import { + useUiSetting$, + KibanaContextProvider, +} from '../../../../../src/plugins/kibana_react/public'; +import { TriggersActionsProvider } from '../utils/triggers_actions_context'; +import { ClientPluginDeps } from '../types'; +import { TriggersAndActionsUIPublicPluginStart } from '../../../triggers_actions_ui/public'; +import { ApolloClientContext } from '../utils/apollo_context'; +import { EuiThemeProvider } from '../../../observability/public'; +import { NavigationWarningPromptProvider } from '../utils/navigation_warning_prompt'; + +export const CommonInfraProviders: React.FC<{ + apolloClient: ApolloClient<{}>; + triggersActionsUI: TriggersAndActionsUIPublicPluginStart; +}> = ({ apolloClient, children, triggersActionsUI }) => { + const [darkMode] = useUiSetting$('theme:darkMode'); + + return ( + + + + {children} + + + + ); +}; + +export const CoreProviders: React.FC<{ + core: CoreStart; + plugins: ClientPluginDeps; +}> = ({ children, core, plugins }) => { + return ( + + {children} + + ); +}; diff --git a/x-pack/plugins/infra/public/apps/common_styles.ts b/x-pack/plugins/infra/public/apps/common_styles.ts new file mode 100644 index 0000000000000..546b83a69035c --- /dev/null +++ b/x-pack/plugins/infra/public/apps/common_styles.ts @@ -0,0 +1,13 @@ +/* + * 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 const CONTAINER_CLASSNAME = 'infra-container-element'; + +export const prepareMountElement = (element: HTMLElement) => { + // Ensure the element we're handed from application mounting is assigned a class + // for our index.scss styles to apply to. + element.classList.add(CONTAINER_CLASSNAME); +}; diff --git a/x-pack/plugins/infra/public/apps/legacy_app.tsx b/x-pack/plugins/infra/public/apps/legacy_app.tsx new file mode 100644 index 0000000000000..195f252c6b60f --- /dev/null +++ b/x-pack/plugins/infra/public/apps/legacy_app.tsx @@ -0,0 +1,98 @@ +/* + * 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 { EuiErrorBoundary } from '@elastic/eui'; +import { createBrowserHistory, History } from 'history'; +import { AppMountParameters } from 'kibana/public'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Route, RouteProps, Router, Switch } from 'react-router-dom'; +import url from 'url'; + +// This exists purely to facilitate legacy app/infra URL redirects. +// It will be removed in 8.0.0. +export async function renderApp({ element }: AppMountParameters) { + const history = createBrowserHistory(); + + ReactDOM.render(, element); + + return () => { + ReactDOM.unmountComponentAtNode(element); + }; +} + +const LegacyApp: React.FunctionComponent<{ history: History }> = ({ history }) => { + return ( + + + + { + if (!location) { + return null; + } + + let nextPath = ''; + let nextBasePath = ''; + let nextSearch; + + if ( + location.hash.indexOf('#infrastructure') > -1 || + location.hash.indexOf('#/infrastructure') > -1 + ) { + nextPath = location.hash.replace( + new RegExp( + '#infrastructure/|#/infrastructure/|#/infrastructure|#infrastructure', + 'g' + ), + '' + ); + nextBasePath = location.pathname.replace('app/infra', 'app/metrics'); + } else if ( + location.hash.indexOf('#logs') > -1 || + location.hash.indexOf('#/logs') > -1 + ) { + nextPath = location.hash.replace( + new RegExp('#logs/|#/logs/|#/logs|#logs', 'g'), + '' + ); + nextBasePath = location.pathname.replace('app/infra', 'app/logs'); + } else { + // This covers /app/infra and /app/infra/home (both of which used to render + // the metrics inventory page) + nextPath = 'inventory'; + nextBasePath = location.pathname.replace('app/infra', 'app/metrics'); + nextSearch = undefined; + } + + // app/infra#infrastructure/metrics/:type/:node was changed to app/metrics/detail/:type/:node, this + // accounts for that edge case + nextPath = nextPath.replace('metrics/', 'detail/'); + + // Query parameters (location.search) will arrive as part of location.hash and not location.search + const nextPathParts = nextPath.split('?'); + nextPath = nextPathParts[0]; + nextSearch = nextPathParts[1] ? nextPathParts[1] : undefined; + + let nextUrl = url.format({ + pathname: `${nextBasePath}/${nextPath}`, + hash: undefined, + search: nextSearch, + }); + + nextUrl = nextUrl.replace('//', '/'); + + window.location.href = nextUrl; + + return null; + }} + /> + + + + ); +}; diff --git a/x-pack/plugins/infra/public/apps/logs_app.tsx b/x-pack/plugins/infra/public/apps/logs_app.tsx new file mode 100644 index 0000000000000..e0251522bb24c --- /dev/null +++ b/x-pack/plugins/infra/public/apps/logs_app.tsx @@ -0,0 +1,66 @@ +/* + * 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 { ApolloClient } from 'apollo-client'; +import { History } from 'history'; +import { CoreStart } from 'kibana/public'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Route, Router, Switch } from 'react-router-dom'; +import { AppMountParameters } from '../../../../../src/core/public'; +import '../index.scss'; +import { NotFoundPage } from '../pages/404'; +import { LinkToLogsPage } from '../pages/link_to/link_to_logs'; +import { LogsPage } from '../pages/logs'; +import { ClientPluginDeps } from '../types'; +import { createApolloClient } from '../utils/apollo_client'; +import { CommonInfraProviders, CoreProviders } from './common_providers'; +import { prepareMountElement } from './common_styles'; + +export const renderApp = ( + core: CoreStart, + plugins: ClientPluginDeps, + { element, history }: AppMountParameters +) => { + const apolloClient = createApolloClient(core.http.fetch); + + prepareMountElement(element); + + ReactDOM.render( + , + element + ); + + return () => { + ReactDOM.unmountComponentAtNode(element); + }; +}; + +const LogsApp: React.FC<{ + apolloClient: ApolloClient<{}>; + core: CoreStart; + history: History; + plugins: ClientPluginDeps; +}> = ({ apolloClient, core, history, plugins }) => { + const uiCapabilities = core.application.capabilities; + + return ( + + + + + + {uiCapabilities?.logs?.show && } + + + + + + ); +}; diff --git a/x-pack/plugins/infra/public/apps/metrics_app.tsx b/x-pack/plugins/infra/public/apps/metrics_app.tsx new file mode 100644 index 0000000000000..8713abe0510a6 --- /dev/null +++ b/x-pack/plugins/infra/public/apps/metrics_app.tsx @@ -0,0 +1,82 @@ +/* + * 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 { ApolloClient } from 'apollo-client'; +import { History } from 'history'; +import { CoreStart } from 'kibana/public'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Route, Router, Switch } from 'react-router-dom'; +import { AppMountParameters } from '../../../../../src/core/public'; +import '../index.scss'; +import { NotFoundPage } from '../pages/404'; +import { LinkToMetricsPage } from '../pages/link_to/link_to_metrics'; +import { InfrastructurePage } from '../pages/metrics'; +import { MetricDetail } from '../pages/metrics/metric_detail'; +import { ClientPluginDeps } from '../types'; +import { createApolloClient } from '../utils/apollo_client'; +import { RedirectWithQueryParams } from '../utils/redirect_with_query_params'; +import { CommonInfraProviders, CoreProviders } from './common_providers'; +import { prepareMountElement } from './common_styles'; + +export const renderApp = ( + core: CoreStart, + plugins: ClientPluginDeps, + { element, history }: AppMountParameters +) => { + const apolloClient = createApolloClient(core.http.fetch); + + prepareMountElement(element); + + ReactDOM.render( + , + element + ); + + return () => { + ReactDOM.unmountComponentAtNode(element); + }; +}; + +const MetricsApp: React.FC<{ + apolloClient: ApolloClient<{}>; + core: CoreStart; + history: History; + plugins: ClientPluginDeps; +}> = ({ apolloClient, core, history, plugins }) => { + const uiCapabilities = core.application.capabilities; + + return ( + + + + + + {uiCapabilities?.infrastructure?.show && ( + + )} + {uiCapabilities?.infrastructure?.show && ( + + )} + {uiCapabilities?.infrastructure?.show && ( + + )} + {uiCapabilities?.infrastructure?.show && ( + + )} + {uiCapabilities?.infrastructure?.show && ( + + )} + + + + + + ); +}; diff --git a/x-pack/plugins/infra/public/apps/start_app.tsx b/x-pack/plugins/infra/public/apps/start_app.tsx deleted file mode 100644 index 4c213700b62e6..0000000000000 --- a/x-pack/plugins/infra/public/apps/start_app.tsx +++ /dev/null @@ -1,80 +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 ReactDOM from 'react-dom'; -import { ApolloProvider } from 'react-apollo'; -import { CoreStart, AppMountParameters } from 'kibana/public'; - -// TODO use theme provided from parentApp when kibana supports it -import { EuiErrorBoundary } from '@elastic/eui'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { EuiThemeProvider } from '../../../observability/public/typings/eui_styled_components'; -import { InfraFrontendLibs } from '../lib/lib'; -import { ApolloClientContext } from '../utils/apollo_context'; -import { HistoryContext } from '../utils/history_context'; -import { - useUiSetting$, - KibanaContextProvider, -} from '../../../../../src/plugins/kibana_react/public'; -import { AppRouter } from '../routers'; -import { TriggersAndActionsUIPublicPluginSetup } from '../../../triggers_actions_ui/public'; -import { TriggersActionsProvider } from '../utils/triggers_actions_context'; -import '../index.scss'; -import { NavigationWarningPromptProvider } from '../utils/navigation_warning_prompt'; - -export const CONTAINER_CLASSNAME = 'infra-container-element'; - -export async function startApp( - libs: InfraFrontendLibs, - core: CoreStart, - plugins: object, - params: AppMountParameters, - Router: AppRouter, - triggersActionsUI: TriggersAndActionsUIPublicPluginSetup -) { - const { element, history } = params; - - const InfraPluginRoot: React.FunctionComponent = () => { - const [darkMode] = useUiSetting$('theme:darkMode'); - - return ( - - - - - - - - - - - - - - - - - - ); - }; - - const App: React.FunctionComponent = () => ( - - - - ); - - // Ensure the element we're handed from application mounting is assigned a class - // for our index.scss styles to apply to. - element.className += ` ${CONTAINER_CLASSNAME}`; - - ReactDOM.render(, element); - - return () => { - ReactDOM.unmountComponentAtNode(element); - }; -} diff --git a/x-pack/plugins/infra/public/apps/start_legacy_app.tsx b/x-pack/plugins/infra/public/apps/start_legacy_app.tsx deleted file mode 100644 index 6e5960ceb2081..0000000000000 --- a/x-pack/plugins/infra/public/apps/start_legacy_app.tsx +++ /dev/null @@ -1,100 +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 { createBrowserHistory } from 'history'; -import React from 'react'; -import url from 'url'; -import ReactDOM from 'react-dom'; -import { AppMountParameters } from 'kibana/public'; -import { Route, Router, Switch, RouteProps } from 'react-router-dom'; -// TODO use theme provided from parentApp when kibana supports it -import { EuiErrorBoundary } from '@elastic/eui'; - -// This exists purely to facilitate legacy app/infra URL redirects. -// It will be removed in 8.0.0. -export async function startLegacyApp(params: AppMountParameters) { - const { element } = params; - const history = createBrowserHistory(); - - const App: React.FunctionComponent = () => { - return ( - - - - { - if (!location) { - return null; - } - - let nextPath = ''; - let nextBasePath = ''; - let nextSearch; - - if ( - location.hash.indexOf('#infrastructure') > -1 || - location.hash.indexOf('#/infrastructure') > -1 - ) { - nextPath = location.hash.replace( - new RegExp( - '#infrastructure/|#/infrastructure/|#/infrastructure|#infrastructure', - 'g' - ), - '' - ); - nextBasePath = location.pathname.replace('app/infra', 'app/metrics'); - } else if ( - location.hash.indexOf('#logs') > -1 || - location.hash.indexOf('#/logs') > -1 - ) { - nextPath = location.hash.replace( - new RegExp('#logs/|#/logs/|#/logs|#logs', 'g'), - '' - ); - nextBasePath = location.pathname.replace('app/infra', 'app/logs'); - } else { - // This covers /app/infra and /app/infra/home (both of which used to render - // the metrics inventory page) - nextPath = 'inventory'; - nextBasePath = location.pathname.replace('app/infra', 'app/metrics'); - nextSearch = undefined; - } - - // app/inra#infrastructure/metrics/:type/:node was changed to app/metrics/detail/:type/:node, this - // accounts for that edge case - nextPath = nextPath.replace('metrics/', 'detail/'); - - // Query parameters (location.search) will arrive as part of location.hash and not location.search - const nextPathParts = nextPath.split('?'); - nextPath = nextPathParts[0]; - nextSearch = nextPathParts[1] ? nextPathParts[1] : undefined; - - let nextUrl = url.format({ - pathname: `${nextBasePath}/${nextPath}`, - hash: undefined, - search: nextSearch, - }); - - nextUrl = nextUrl.replace('//', '/'); - - window.location.href = nextUrl; - - return null; - }} - /> - - - - ); - }; - - ReactDOM.render(, element); - - return () => { - ReactDOM.unmountComponentAtNode(element); - }; -} diff --git a/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx b/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx index 074464fb55414..ce14897991e60 100644 --- a/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx +++ b/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx @@ -336,6 +336,10 @@ export const Expressions: React.FC = (props) => { ); }; +// required for dynamic import +// eslint-disable-next-line import/no-default-export +export default Expressions; + interface ExpressionRowProps { nodeType: InventoryItemType; expressionId: number; diff --git a/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts b/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts index 9ede2d2a47727..0cb564ec2194e 100644 --- a/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts +++ b/x-pack/plugins/infra/public/components/alerting/inventory/metric_inventory_threshold_alert_type.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; +import React from 'react'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AlertTypeModel } from '../../../../../triggers_actions_ui/public/types'; -import { Expressions } from './expression'; import { validateMetricThreshold } from './validation'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from '../../../../server/lib/alerting/inventory_metric_threshold/types'; @@ -18,7 +18,7 @@ export function getInventoryMetricAlertType(): AlertTypeModel { defaultMessage: 'Inventory', }), iconClass: 'bell', - alertParamsExpression: Expressions, + alertParamsExpression: React.lazy(() => import('./expression')), validate: validateMetricThreshold, defaultActionMessage: i18n.translate( 'xpack.infra.metrics.alerting.inventory.threshold.defaultActionMessage', diff --git a/x-pack/plugins/infra/public/components/alerting/inventory/validation.tsx b/x-pack/plugins/infra/public/components/alerting/inventory/validation.tsx index 441adeec988c7..47ecd3c527fad 100644 --- a/x-pack/plugins/infra/public/components/alerting/inventory/validation.tsx +++ b/x-pack/plugins/infra/public/components/alerting/inventory/validation.tsx @@ -6,8 +6,6 @@ import { i18n } from '@kbn/i18n'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { isNumber } from 'lodash'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths import { MetricExpressionParams } from '../../../../server/lib/alerting/metric_threshold/types'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ValidationResult } from '../../../../../triggers_actions_ui/public/types'; @@ -95,3 +93,5 @@ export function validateMetricThreshold({ return validationResult; } + +const isNumber = (value: unknown): value is number => typeof value === 'number'; diff --git a/x-pack/plugins/infra/public/components/alerting/logs/expression_editor/editor.tsx b/x-pack/plugins/infra/public/components/alerting/logs/expression_editor/editor.tsx index 609f99805fe9c..a3a48d477425b 100644 --- a/x-pack/plugins/infra/public/components/alerting/logs/expression_editor/editor.tsx +++ b/x-pack/plugins/infra/public/components/alerting/logs/expression_editor/editor.tsx @@ -236,3 +236,7 @@ export const Editor: React.FC = (props) => { ); }; + +// required for dynamic import +// eslint-disable-next-line import/no-default-export +export default Editor; diff --git a/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts b/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts index 9bba8bd804f80..4c7811f0d9666 100644 --- a/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts +++ b/x-pack/plugins/infra/public/components/alerting/logs/log_threshold_alert_type.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; +import React from 'react'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AlertTypeModel } from '../../../../../triggers_actions_ui/public/types'; import { LOG_DOCUMENT_COUNT_ALERT_TYPE_ID } from '../../../../common/alerting/logs/types'; -import { ExpressionEditor } from './expression_editor'; import { validateExpression } from './validation'; export function getAlertType(): AlertTypeModel { @@ -17,7 +17,7 @@ export function getAlertType(): AlertTypeModel { defaultMessage: 'Log threshold', }), iconClass: 'bell', - alertParamsExpression: ExpressionEditor, + alertParamsExpression: React.lazy(() => import('./expression_editor/editor')), validate: validateExpression, defaultActionMessage: i18n.translate( 'xpack.infra.logs.alerting.threshold.defaultActionMessage', diff --git a/x-pack/plugins/infra/public/compose_libs.ts b/x-pack/plugins/infra/public/compose_libs.ts deleted file mode 100644 index f2060983e95eb..0000000000000 --- a/x-pack/plugins/infra/public/compose_libs.ts +++ /dev/null @@ -1,99 +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 { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; -import ApolloClient from 'apollo-client'; -import { ApolloLink } from 'apollo-link'; -import { createHttpLink } from 'apollo-link-http'; -import { withClientState } from 'apollo-link-state'; -import { CoreStart, HttpFetchOptions } from 'src/core/public'; -import { InfraFrontendLibs } from './lib/lib'; -import introspectionQueryResultData from './graphql/introspection.json'; -import { InfraKibanaObservableApiAdapter } from './lib/adapters/observable_api/kibana_observable_api'; - -export function composeLibs(core: CoreStart) { - const cache = new InMemoryCache({ - addTypename: false, - fragmentMatcher: new IntrospectionFragmentMatcher({ - introspectionQueryResultData, - }), - }); - - const observableApi = new InfraKibanaObservableApiAdapter({ - basePath: core.http.basePath.get(), - }); - - const wrappedFetch = (path: string, options: HttpFetchOptions) => { - return new Promise(async (resolve, reject) => { - // core.http.fetch isn't 100% compatible with the Fetch API and will - // throw Errors on 401s. This top level try / catch handles those scenarios. - try { - core.http - .fetch(path, { - ...options, - // Set headers to undefined due to this bug: https://github.com/apollographql/apollo-link/issues/249, - // Apollo will try to set a "content-type" header which will conflict with the "Content-Type" header that - // core.http.fetch correctly sets. - headers: undefined, - asResponse: true, - }) - .then((res) => { - if (!res.response) { - return reject(); - } - // core.http.fetch will parse the Response and set a body before handing it back. As such .text() / .json() - // will have already been called on the Response instance. However, Apollo will also want to call - // .text() / .json() on the instance, as it expects the raw Response instance, rather than core's wrapper. - // .text() / .json() can only be called once, and an Error will be thrown if those methods are accessed again. - // This hacks around that by setting up a new .text() method that will restringify the JSON response we already have. - // This does result in an extra stringify / parse cycle, which isn't ideal, but as we only have a few endpoints left using - // GraphQL this shouldn't create excessive overhead. - // Ref: https://github.com/apollographql/apollo-link/blob/master/packages/apollo-link-http/src/httpLink.ts#L134 - // and - // https://github.com/apollographql/apollo-link/blob/master/packages/apollo-link-http-common/src/index.ts#L125 - return resolve({ - ...res.response, - text: () => { - return new Promise(async (resolveText, rejectText) => { - if (res.body) { - return resolveText(JSON.stringify(res.body)); - } else { - return rejectText(); - } - }); - }, - }); - }); - } catch (error) { - reject(error); - } - }); - }; - - const HttpLink = createHttpLink({ - fetch: wrappedFetch, - uri: `/api/infra/graphql`, - }); - - const graphQLOptions = { - cache, - link: ApolloLink.from([ - withClientState({ - cache, - resolvers: {}, - }), - HttpLink, - ]), - }; - - const apolloClient = new ApolloClient(graphQLOptions); - - const libs: InfraFrontendLibs = { - apolloClient, - observableApi, - }; - return libs; -} diff --git a/x-pack/plugins/infra/public/containers/with_state_from_location.tsx b/x-pack/plugins/infra/public/containers/with_state_from_location.tsx deleted file mode 100644 index 2a9676046d451..0000000000000 --- a/x-pack/plugins/infra/public/containers/with_state_from_location.tsx +++ /dev/null @@ -1,131 +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 { parse, stringify } from 'query-string'; -import { Location } from 'history'; -import { omit } from 'lodash'; -import React from 'react'; -import { RouteComponentProps, withRouter } from 'react-router-dom'; -// eslint-disable-next-line @typescript-eslint/camelcase -import { decode_object, encode_object } from 'rison-node'; -import { Omit } from '../lib/lib'; - -interface AnyObject { - [key: string]: any; -} - -interface WithStateFromLocationOptions { - mapLocationToState: (location: Location) => StateInLocation; - mapStateToLocation: (state: StateInLocation, location: Location) => Location; -} - -type InjectedPropsFromLocation = Partial & { - pushStateInLocation?: (state: StateInLocation) => void; - replaceStateInLocation?: (state: StateInLocation) => void; -}; - -export const withStateFromLocation = ({ - mapLocationToState, - mapStateToLocation, -}: WithStateFromLocationOptions) => < - WrappedComponentProps extends InjectedPropsFromLocation ->( - WrappedComponent: React.ComponentType -) => { - const wrappedName = WrappedComponent.displayName || WrappedComponent.name; - - return withRouter( - class WithStateFromLocation extends React.PureComponent< - RouteComponentProps<{}> & - Omit> - > { - public static displayName = `WithStateFromLocation(${wrappedName})`; - - public render() { - const { location } = this.props; - const otherProps = omit(this.props, ['location', 'history', 'match', 'staticContext']); - - const stateFromLocation = mapLocationToState(location); - - return ( - // @ts-ignore - - ); - } - - private pushStateInLocation = (state: StateInLocation) => { - const { history, location } = this.props; - - const newLocation = mapStateToLocation(state, this.props.location); - - if (newLocation !== location) { - history.push(newLocation); - } - }; - - private replaceStateInLocation = (state: StateInLocation) => { - const { history, location } = this.props; - - const newLocation = mapStateToLocation(state, this.props.location); - - if (newLocation !== location) { - history.replace(newLocation); - } - }; - } - ); -}; - -const decodeRisonAppState = (queryValues: { _a?: string }): AnyObject => { - try { - return queryValues && queryValues._a ? decode_object(queryValues._a) : {}; - } catch (error) { - if (error instanceof Error && error.message.startsWith('rison decoder error')) { - return {}; - } - throw error; - } -}; - -const encodeRisonAppState = (state: AnyObject) => ({ - _a: encode_object(state), -}); - -export const mapRisonAppLocationToState = ( - mapState: (risonAppState: AnyObject) => State = (state: AnyObject) => state as State -) => (location: Location): State => { - const queryValues = parse(location.search.substring(1), { sort: false }); - const decodedState = decodeRisonAppState(queryValues); - return mapState(decodedState); -}; - -export const mapStateToRisonAppLocation = ( - mapState: (state: State) => AnyObject = (state: State) => state -) => (state: State, location: Location): Location => { - const previousQueryValues = parse(location.search.substring(1), { sort: false }); - const previousState = decodeRisonAppState(previousQueryValues); - - const encodedState = encodeRisonAppState({ - ...previousState, - ...mapState(state), - }); - const newQueryValues = stringify( - { - ...previousQueryValues, - ...encodedState, - }, - { sort: false } - ); - return { - ...location, - search: `?${newQueryValues}`, - }; -}; diff --git a/x-pack/plugins/infra/public/graphql/log_entries.gql_query.ts b/x-pack/plugins/infra/public/graphql/log_entries.gql_query.ts deleted file mode 100644 index 41ff3c293a713..0000000000000 --- a/x-pack/plugins/infra/public/graphql/log_entries.gql_query.ts +++ /dev/null @@ -1,44 +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 gql from 'graphql-tag'; - -import { sharedFragments } from '../../common/graphql/shared'; - -export const logEntriesQuery = gql` - query LogEntries( - $sourceId: ID = "default" - $timeKey: InfraTimeKeyInput! - $countBefore: Int = 0 - $countAfter: Int = 0 - $filterQuery: String - ) { - source(id: $sourceId) { - id - logEntriesAround( - key: $timeKey - countBefore: $countBefore - countAfter: $countAfter - filterQuery: $filterQuery - ) { - start { - ...InfraTimeKeyFields - } - end { - ...InfraTimeKeyFields - } - hasMoreBefore - hasMoreAfter - entries { - ...InfraLogEntryFields - } - } - } - } - - ${sharedFragments.InfraTimeKey} - ${sharedFragments.InfraLogEntryFields} -`; diff --git a/x-pack/plugins/infra/public/hooks/use_link_props.test.tsx b/x-pack/plugins/infra/public/hooks/use_link_props.test.tsx index f9cfaf71036f6..d93cc44c45623 100644 --- a/x-pack/plugins/infra/public/hooks/use_link_props.test.tsx +++ b/x-pack/plugins/infra/public/hooks/use_link_props.test.tsx @@ -4,15 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { encode } from 'rison-node'; -import { createMemoryHistory } from 'history'; import { renderHook } from '@testing-library/react-hooks'; +import { createMemoryHistory } from 'history'; import React from 'react'; -import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; -import { HistoryContext } from '../utils/history_context'; +import { Router } from 'react-router-dom'; +import { encode } from 'rison-node'; import { coreMock } from 'src/core/public/mocks'; -import { useLinkProps, LinkDescriptor } from './use_link_props'; import { ScopedHistory } from '../../../../../src/core/public'; +import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { LinkDescriptor, useLinkProps } from './use_link_props'; const PREFIX = '/test-basepath/s/test-space/app/'; @@ -30,9 +30,9 @@ const scopedHistory = new ScopedHistory(history, `${PREFIX}${INTERNAL_APP}`); const ProviderWrapper: React.FC = ({ children }) => { return ( - + {children}; - + ); }; diff --git a/x-pack/plugins/infra/public/index.ts b/x-pack/plugins/infra/public/index.ts index 1dfdf827f203b..8f2d37fa1daa9 100644 --- a/x-pack/plugins/infra/public/index.ts +++ b/x-pack/plugins/infra/public/index.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PluginInitializerContext, PluginInitializer } from 'kibana/public'; -import { Plugin, ClientSetup, ClientStart, ClientPluginsSetup, ClientPluginsStart } from './plugin'; +import { PluginInitializer, PluginInitializerContext } from 'kibana/public'; +import { ClientSetup, ClientStart, Plugin } from './plugin'; +import { ClientPluginsSetup, ClientPluginsStart } from './types'; export const plugin: PluginInitializer< ClientSetup, diff --git a/x-pack/plugins/infra/public/lib/adapters/observable_api/kibana_observable_api.ts b/x-pack/plugins/infra/public/lib/adapters/observable_api/kibana_observable_api.ts deleted file mode 100644 index 9ae21d96886f3..0000000000000 --- a/x-pack/plugins/infra/public/lib/adapters/observable_api/kibana_observable_api.ts +++ /dev/null @@ -1,45 +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 { ajax } from 'rxjs/ajax'; -import { map } from 'rxjs/operators'; - -import { - InfraObservableApi, - InfraObservableApiPostParams, - InfraObservableApiResponse, -} from '../../lib'; - -export class InfraKibanaObservableApiAdapter implements InfraObservableApi { - private basePath: string; - private defaultHeaders: { - [headerName: string]: boolean | string; - }; - - constructor({ basePath }: { basePath: string }) { - this.basePath = basePath; - this.defaultHeaders = { - 'kbn-xsrf': true, - }; - } - - public post = ({ - url, - body, - }: InfraObservableApiPostParams): InfraObservableApiResponse => - ajax({ - body: body ? JSON.stringify(body) : undefined, - headers: { - ...this.defaultHeaders, - 'Content-Type': 'application/json', - }, - method: 'POST', - responseType: 'json', - timeout: 30000, - url: `${this.basePath}/api/${url}`, - withCredentials: true, - }).pipe(map(({ response, status }) => ({ response, status }))); -} diff --git a/x-pack/plugins/infra/public/lib/lib.ts b/x-pack/plugins/infra/public/lib/lib.ts index d1ca62b747a24..93f7ef644f795 100644 --- a/x-pack/plugins/infra/public/lib/lib.ts +++ b/x-pack/plugins/infra/public/lib/lib.ts @@ -4,102 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IModule, IScope } from 'angular'; -import { NormalizedCacheObject } from 'apollo-cache-inmemory'; -import ApolloClient from 'apollo-client'; -import { AxiosRequestConfig } from 'axios'; -import React from 'react'; -import { Observable } from 'rxjs'; -import * as rt from 'io-ts'; import { i18n } from '@kbn/i18n'; -import { SourceQuery } from '../graphql/types'; +import * as rt from 'io-ts'; import { - SnapshotMetricInput, - SnapshotGroupBy, InfraTimerangeInput, + SnapshotGroupBy, + SnapshotMetricInput, SnapshotNodeMetric, SnapshotNodePath, } from '../../common/http_api/snapshot_api'; +import { SourceQuery } from '../graphql/types'; import { WaffleSortOption } from '../pages/metrics/inventory_view/hooks/use_waffle_options'; -export interface InfraFrontendLibs { - apolloClient: InfraApolloClient; - observableApi: InfraObservableApi; -} - -export type InfraTimezoneProvider = () => string; - -export type InfraApolloClient = ApolloClient; - -export interface InfraFrameworkAdapter { - // Insstance vars - appState?: object; - kbnVersion?: string; - timezone?: string; - - // Methods - setUISettings(key: string, value: any): void; - render(component: React.ReactElement): void; - renderBreadcrumbs(component: React.ReactElement): void; -} - -export type InfraFramworkAdapterConstructable = new ( - uiModule: IModule, - timezoneProvider: InfraTimezoneProvider -) => InfraFrameworkAdapter; - -// TODO: replace AxiosRequestConfig with something more defined -export type InfraRequestConfig = AxiosRequestConfig; - -export interface InfraApiAdapter { - get(url: string, config?: InfraRequestConfig | undefined): Promise; - post(url: string, data?: any, config?: AxiosRequestConfig | undefined): Promise; - delete(url: string, config?: InfraRequestConfig | undefined): Promise; - put(url: string, data?: any, config?: InfraRequestConfig | undefined): Promise; -} - -export interface InfraObservableApiPostParams { - url: string; - body?: RequestBody; -} - -export type InfraObservableApiResponse = Observable<{ - status: number; - response: BodyType; -}>; - -export interface InfraObservableApi { - post( - params: InfraObservableApiPostParams - ): InfraObservableApiResponse; -} - -export interface InfraUiKibanaAdapterScope extends IScope { - breadcrumbs: any[]; - topNavMenu: any[]; -} - -export interface InfraKibanaUIConfig { - get(key: string): any; - set(key: string, value: any): Promise; -} - -export interface InfraKibanaAdapterServiceRefs { - config: InfraKibanaUIConfig; - rootScope: IScope; -} - -export type InfraBufferedKibanaServiceCall = (serviceRefs: ServiceRefs) => void; - -export interface InfraField { - name: string; - type: string; - searchable: boolean; - aggregatable: boolean; -} - -export type InfraWaffleData = InfraWaffleMapGroup[]; - export interface InfraWaffleMapNode { pathId: string; id: string; @@ -221,8 +137,6 @@ export interface InfraOptions { wafflemap: InfraWaffleMapOptions; } -export type Omit = Pick>; - export interface InfraWaffleMapBounds { min: number; max: number; diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx index 1394fc48107ef..e62b29974674a 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.test.tsx @@ -35,7 +35,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); @@ -47,7 +47,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); @@ -59,7 +59,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); @@ -73,7 +73,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); @@ -89,7 +89,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); @@ -103,7 +103,7 @@ describe('RedirectToNodeLogs component', () => { expect(component).toMatchInlineSnapshot(` `); }); diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx index d9aaa2da7bbc8..10320ebbe7609 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx @@ -71,7 +71,7 @@ export const RedirectToNodeLogs = ({ replaceSourceIdInQueryString(sourceId) )(''); - return ; + return ; }; export const getNodeLogsUrl = ({ diff --git a/x-pack/plugins/infra/public/pages/logs/page_content.tsx b/x-pack/plugins/infra/public/pages/logs/page_content.tsx index 2974939a83215..14c53557ba2c7 100644 --- a/x-pack/plugins/infra/public/pages/logs/page_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/page_content.tsx @@ -96,6 +96,7 @@ export const LogsPageContent: React.FunctionComponent = () => { + ); diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx index 3b68ad314f7df..764eeb154d346 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx @@ -15,7 +15,7 @@ import { fieldToName } from '../lib/field_to_display_name'; import { NodeContextMenu } from './waffle/node_context_menu'; import { InventoryItemType } from '../../../../../common/inventory_models/types'; import { SnapshotNode, SnapshotNodePath } from '../../../../../common/http_api/snapshot_api'; -import { CONTAINER_CLASSNAME } from '../../../../apps/start_app'; +import { CONTAINER_CLASSNAME } from '../../../../apps/common_styles'; interface Props { nodes: SnapshotNode[]; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_time.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_time.ts index 91cf405dcc759..9a1fbee421294 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_time.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_time.ts @@ -26,7 +26,9 @@ export const useWaffleTime = () => { const [state, setState] = useState(urlState); - useEffect(() => setUrlState(state), [setUrlState, state]); + useEffect(() => { + setUrlState(state); + }, [setUrlState, state]); const { currentTime, isAutoReloading } = urlState; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/metrics_time.test.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/metrics_time.test.tsx index 17fcc05406470..d2076ad6df502 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/metrics_time.test.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/metrics_time.test.tsx @@ -4,14 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ +import { createMemoryHistory } from 'history'; +import React from 'react'; +import { Router } from 'react-router-dom'; import { mountHook } from 'test_utils/enzyme_helpers'; - +import { ScopedHistory } from '../../../../../../../../src/core/public'; import { useMetricsTime } from './use_metrics_time'; describe('useMetricsTime hook', () => { describe('timeRange state', () => { it('has a default value', () => { - const { getLastHookValue } = mountHook(() => useMetricsTime().timeRange); + const { getLastHookValue } = mountHook( + () => useMetricsTime().timeRange, + createProviderWrapper() + ); const hookValue = getLastHookValue(); expect(hookValue).toHaveProperty('from'); expect(hookValue).toHaveProperty('to'); @@ -19,7 +25,7 @@ describe('useMetricsTime hook', () => { }); it('can be updated', () => { - const { act, getLastHookValue } = mountHook(() => useMetricsTime()); + const { act, getLastHookValue } = mountHook(() => useMetricsTime(), createProviderWrapper()); const timeRange = { from: 'now-15m', @@ -37,12 +43,15 @@ describe('useMetricsTime hook', () => { describe('AutoReloading state', () => { it('has a default value', () => { - const { getLastHookValue } = mountHook(() => useMetricsTime().isAutoReloading); + const { getLastHookValue } = mountHook( + () => useMetricsTime().isAutoReloading, + createProviderWrapper() + ); expect(getLastHookValue()).toBe(false); }); it('can be updated', () => { - const { act, getLastHookValue } = mountHook(() => useMetricsTime()); + const { act, getLastHookValue } = mountHook(() => useMetricsTime(), createProviderWrapper()); act(({ setAutoReload }) => { setAutoReload(true); @@ -52,3 +61,17 @@ describe('useMetricsTime hook', () => { }); }); }); + +const createProviderWrapper = () => { + const INITIAL_URL = '/test-basepath/s/test-space/app/metrics'; + const history = createMemoryHistory(); + + history.push(INITIAL_URL); + const scopedHistory = new ScopedHistory(history, INITIAL_URL); + + const ProviderWrapper: React.FC = ({ children }) => { + return {children}; + }; + + return ProviderWrapper; +}; diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index deae78e22c6a1..b3765db43335a 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -4,54 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { merge } from 'lodash'; import { - Plugin as PluginClass, + AppMountParameters, CoreSetup, CoreStart, + Plugin as PluginClass, PluginInitializerContext, - AppMountParameters, } from 'kibana/public'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; +import { createMetricThresholdAlertType } from './alerting/metric_threshold'; +import { getInventoryMetricAlertType } from './components/alerting/inventory/metric_inventory_threshold_alert_type'; +import { getAlertType as getLogsAlertType } from './components/alerting/logs/log_threshold_alert_type'; import { registerStartSingleton } from './legacy_singletons'; import { registerFeatures } from './register_feature'; -import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; -import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public'; -import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; -import { DataEnhancedSetup, DataEnhancedStart } from '../../data_enhanced/public'; - -import { TriggersAndActionsUIPublicPluginSetup } from '../../../plugins/triggers_actions_ui/public'; -import { getAlertType as getLogsAlertType } from './components/alerting/logs/log_threshold_alert_type'; -import { getInventoryMetricAlertType } from './components/alerting/inventory/metric_inventory_threshold_alert_type'; -import { createMetricThresholdAlertType } from './alerting/metric_threshold'; +import { ClientPluginsSetup, ClientPluginsStart } from './types'; export type ClientSetup = void; export type ClientStart = void; -export interface ClientPluginsSetup { - home: HomePublicPluginSetup; - data: DataPublicPluginSetup; - usageCollection: UsageCollectionSetup; - dataEnhanced: DataEnhancedSetup; - triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; -} - -export interface ClientPluginsStart { - data: DataPublicPluginStart; - dataEnhanced: DataEnhancedStart; -} - -export type InfraPlugins = ClientPluginsSetup & ClientPluginsStart; - -const getMergedPlugins = (setup: ClientPluginsSetup, start: ClientPluginsStart): InfraPlugins => { - return merge({}, setup, start); -}; - export class Plugin implements PluginClass { - constructor(context: PluginInitializerContext) {} + constructor(_context: PluginInitializerContext) {} - setup(core: CoreSetup, pluginsSetup: ClientPluginsSetup) { + setup(core: CoreSetup, pluginsSetup: ClientPluginsSetup) { registerFeatures(pluginsSetup.home); pluginsSetup.triggers_actions_ui.alertTypeRegistry.register(getInventoryMetricAlertType()); @@ -69,16 +44,18 @@ export class Plugin category: DEFAULT_APP_CATEGORIES.observability, mount: async (params: AppMountParameters) => { const [coreStart, pluginsStart] = await core.getStartServices(); - const plugins = getMergedPlugins(pluginsSetup, pluginsStart as ClientPluginsStart); - const { startApp, composeLibs, LogsRouter } = await this.downloadAssets(); + const { renderApp } = await import('./apps/logs_app'); - return startApp( - composeLibs(coreStart), + return renderApp( coreStart, - plugins, - params, - LogsRouter, - pluginsSetup.triggers_actions_ui + { + data: pluginsStart.data, + dataEnhanced: pluginsSetup.dataEnhanced, + home: pluginsSetup.home, + triggers_actions_ui: pluginsStart.triggers_actions_ui, + usageCollection: pluginsSetup.usageCollection, + }, + params ); }, }); @@ -94,16 +71,18 @@ export class Plugin category: DEFAULT_APP_CATEGORIES.observability, mount: async (params: AppMountParameters) => { const [coreStart, pluginsStart] = await core.getStartServices(); - const plugins = getMergedPlugins(pluginsSetup, pluginsStart as ClientPluginsStart); - const { startApp, composeLibs, MetricsRouter } = await this.downloadAssets(); + const { renderApp } = await import('./apps/metrics_app'); - return startApp( - composeLibs(coreStart), + return renderApp( coreStart, - plugins, - params, - MetricsRouter, - pluginsSetup.triggers_actions_ui + { + data: pluginsStart.data, + dataEnhanced: pluginsSetup.dataEnhanced, + home: pluginsSetup.home, + triggers_actions_ui: pluginsStart.triggers_actions_ui, + usageCollection: pluginsSetup.usageCollection, + }, + params ); }, }); @@ -116,28 +95,14 @@ export class Plugin title: 'infra', navLinkStatus: 3, mount: async (params: AppMountParameters) => { - const { startLegacyApp } = await import('./apps/start_legacy_app'); - return startLegacyApp(params); + const { renderApp } = await import('./apps/legacy_app'); + + return renderApp(params); }, }); } - start(core: CoreStart, plugins: ClientPluginsStart) { + start(core: CoreStart, _plugins: ClientPluginsStart) { registerStartSingleton(core); } - - private async downloadAssets() { - const [{ startApp }, { composeLibs }, { LogsRouter, MetricsRouter }] = await Promise.all([ - import('./apps/start_app'), - import('./compose_libs'), - import('./routers'), - ]); - - return { - startApp, - composeLibs, - LogsRouter, - MetricsRouter, - }; - } } diff --git a/x-pack/plugins/infra/public/routers/index.ts b/x-pack/plugins/infra/public/routers/index.ts deleted file mode 100644 index 71ab2613d8dc1..0000000000000 --- a/x-pack/plugins/infra/public/routers/index.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 { History } from 'history'; - -export * from './logs_router'; -export * from './metrics_router'; - -interface RouterProps { - history: History; -} - -export type AppRouter = React.FC; diff --git a/x-pack/plugins/infra/public/routers/logs_router.tsx b/x-pack/plugins/infra/public/routers/logs_router.tsx deleted file mode 100644 index 8258f087b5872..0000000000000 --- a/x-pack/plugins/infra/public/routers/logs_router.tsx +++ /dev/null @@ -1,31 +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 { Route, Router, Switch } from 'react-router-dom'; - -import { NotFoundPage } from '../pages/404'; -import { LinkToLogsPage } from '../pages/link_to'; -import { LogsPage } from '../pages/logs'; -import { RedirectWithQueryParams } from '../utils/redirect_with_query_params'; -import { useKibana } from '../../../../../src/plugins/kibana_react/public'; -import { AppRouter } from './index'; - -export const LogsRouter: AppRouter = ({ history }) => { - const uiCapabilities = useKibana().services.application?.capabilities; - return ( - - - - {uiCapabilities?.logs?.show && ( - - )} - {uiCapabilities?.logs?.show && } - - - - ); -}; diff --git a/x-pack/plugins/infra/public/routers/metrics_router.tsx b/x-pack/plugins/infra/public/routers/metrics_router.tsx deleted file mode 100644 index 0e427150a46cc..0000000000000 --- a/x-pack/plugins/infra/public/routers/metrics_router.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { Route, Router, Switch } from 'react-router-dom'; - -import { NotFoundPage } from '../pages/404'; -import { InfrastructurePage } from '../pages/metrics'; -import { MetricDetail } from '../pages/metrics/metric_detail'; -import { RedirectWithQueryParams } from '../utils/redirect_with_query_params'; -import { useKibana } from '../../../../../src/plugins/kibana_react/public'; -import { AppRouter } from './index'; -import { LinkToMetricsPage } from '../pages/link_to'; - -export const MetricsRouter: AppRouter = ({ history }) => { - const uiCapabilities = useKibana().services.application?.capabilities; - return ( - - - - {uiCapabilities?.infrastructure?.show && ( - - )} - {uiCapabilities?.infrastructure?.show && ( - - )} - {uiCapabilities?.infrastructure?.show && ( - - )} - {uiCapabilities?.infrastructure?.show && ( - - )} - {uiCapabilities?.infrastructure?.show && } - - - - ); -}; diff --git a/x-pack/plugins/infra/public/types.ts b/x-pack/plugins/infra/public/types.ts new file mode 100644 index 0000000000000..8181da3301c92 --- /dev/null +++ b/x-pack/plugins/infra/public/types.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; +import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; +import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; +import { TriggersAndActionsUIPublicPluginSetup } from '../../../plugins/triggers_actions_ui/public'; +import { DataEnhancedSetup } from '../../data_enhanced/public'; + +export interface ClientPluginsSetup { + dataEnhanced: DataEnhancedSetup; + home: HomePublicPluginSetup; + triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; + usageCollection: UsageCollectionSetup; +} + +export interface ClientPluginsStart { + data: DataPublicPluginStart; + triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup; +} + +export type ClientPluginDeps = ClientPluginsSetup & ClientPluginsStart; diff --git a/x-pack/plugins/infra/public/utils/apollo_client.ts b/x-pack/plugins/infra/public/utils/apollo_client.ts new file mode 100644 index 0000000000000..3c69ef4c98fac --- /dev/null +++ b/x-pack/plugins/infra/public/utils/apollo_client.ts @@ -0,0 +1,85 @@ +/* + * 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 { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; +import ApolloClient from 'apollo-client'; +import { ApolloLink } from 'apollo-link'; +import { createHttpLink } from 'apollo-link-http'; +import { withClientState } from 'apollo-link-state'; +import { HttpFetchOptions, HttpHandler } from 'src/core/public'; +import introspectionQueryResultData from '../graphql/introspection.json'; + +export const createApolloClient = (fetch: HttpHandler) => { + const cache = new InMemoryCache({ + addTypename: false, + fragmentMatcher: new IntrospectionFragmentMatcher({ + introspectionQueryResultData, + }), + }); + + const wrappedFetch = (path: string, options: HttpFetchOptions) => { + return new Promise(async (resolve, reject) => { + // core.http.fetch isn't 100% compatible with the Fetch API and will + // throw Errors on 401s. This top level try / catch handles those scenarios. + try { + fetch(path, { + ...options, + // Set headers to undefined due to this bug: https://github.com/apollographql/apollo-link/issues/249, + // Apollo will try to set a "content-type" header which will conflict with the "Content-Type" header that + // core.http.fetch correctly sets. + headers: undefined, + asResponse: true, + }).then((res) => { + if (!res.response) { + return reject(); + } + // core.http.fetch will parse the Response and set a body before handing it back. As such .text() / .json() + // will have already been called on the Response instance. However, Apollo will also want to call + // .text() / .json() on the instance, as it expects the raw Response instance, rather than core's wrapper. + // .text() / .json() can only be called once, and an Error will be thrown if those methods are accessed again. + // This hacks around that by setting up a new .text() method that will restringify the JSON response we already have. + // This does result in an extra stringify / parse cycle, which isn't ideal, but as we only have a few endpoints left using + // GraphQL this shouldn't create excessive overhead. + // Ref: https://github.com/apollographql/apollo-link/blob/master/packages/apollo-link-http/src/httpLink.ts#L134 + // and + // https://github.com/apollographql/apollo-link/blob/master/packages/apollo-link-http-common/src/index.ts#L125 + return resolve({ + ...res.response, + text: () => { + return new Promise(async (resolveText, rejectText) => { + if (res.body) { + return resolveText(JSON.stringify(res.body)); + } else { + return rejectText(); + } + }); + }, + }); + }); + } catch (error) { + reject(error); + } + }); + }; + + const HttpLink = createHttpLink({ + fetch: wrappedFetch, + uri: `/api/infra/graphql`, + }); + + const graphQLOptions = { + cache, + link: ApolloLink.from([ + withClientState({ + cache, + resolvers: {}, + }), + HttpLink, + ]), + }; + + return new ApolloClient(graphQLOptions); +}; diff --git a/x-pack/plugins/infra/public/utils/triggers_actions_context.tsx b/x-pack/plugins/infra/public/utils/triggers_actions_context.tsx index 1cff3663280fd..6b51714893a6d 100644 --- a/x-pack/plugins/infra/public/utils/triggers_actions_context.tsx +++ b/x-pack/plugins/infra/public/utils/triggers_actions_context.tsx @@ -5,10 +5,10 @@ */ import * as React from 'react'; -import { TriggersAndActionsUIPublicPluginSetup } from '../../../triggers_actions_ui/public'; +import { TriggersAndActionsUIPublicPluginStart } from '../../../triggers_actions_ui/public'; interface ContextProps { - triggersActionsUI: TriggersAndActionsUIPublicPluginSetup | null; + triggersActionsUI: TriggersAndActionsUIPublicPluginStart | null; } export const TriggerActionsContext = React.createContext({ @@ -16,7 +16,7 @@ export const TriggerActionsContext = React.createContext({ }); interface Props { - triggersActionsUI: TriggersAndActionsUIPublicPluginSetup; + triggersActionsUI: TriggersAndActionsUIPublicPluginStart; } export const TriggersActionsProvider: React.FC = (props) => { diff --git a/x-pack/plugins/infra/public/utils/use_url_state.ts b/x-pack/plugins/infra/public/utils/use_url_state.ts index 7a63b48fa9a1a..ab0ca1311194f 100644 --- a/x-pack/plugins/infra/public/utils/use_url_state.ts +++ b/x-pack/plugins/infra/public/utils/use_url_state.ts @@ -8,10 +8,9 @@ import { parse, stringify } from 'query-string'; import { Location } from 'history'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { decode, encode, RisonValue } from 'rison-node'; +import { useHistory } from 'react-router-dom'; import { url } from '../../../../../src/plugins/kibana_utils/public'; -import { useHistory } from './history_context'; - export const useUrlState = ({ defaultState, decodeUrlState, From 4f2c199f0ed7cf461565cb021e7576046fd1573a Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Tue, 9 Jun 2020 15:05:50 -0700 Subject: [PATCH 14/53] Fix edit datasource not working following changes in #67234 (#68583) --- .../components/custom_configure_datasource.tsx | 3 ++- .../step_configure_datasource.tsx | 7 +++++-- .../agent_config/edit_datasource_page/index.tsx | 5 +++-- .../configure_datasource.tsx | 15 +++------------ 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx index aff764cb8ba3e..4263feb7cd8c7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/custom_configure_datasource.tsx @@ -12,7 +12,8 @@ import { CreateDatasourceFrom } from '../types'; export interface CustomConfigureDatasourceProps { packageName: string; from: CreateDatasourceFrom; - datasource: NewDatasource | (NewDatasource & { id: string }); + datasource: NewDatasource; + datasourceId?: string; } /** diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx index d9cf0fbfb7987..5499ac287ff05 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_configure_datasource.tsx @@ -16,7 +16,8 @@ import { CreateDatasourceFrom } from './types'; export const StepConfigureDatasource: React.FunctionComponent<{ from?: CreateDatasourceFrom; packageInfo: PackageInfo; - datasource: NewDatasource | (NewDatasource & { id: string }); + datasource: NewDatasource; + datasourceId?: string; updateDatasource: (fields: Partial) => void; validationResults: DatasourceValidationResults; submitAttempted: boolean; @@ -24,6 +25,7 @@ export const StepConfigureDatasource: React.FunctionComponent<{ from = 'config', packageInfo, datasource, + datasourceId, updateDatasource, validationResults, submitAttempted, @@ -70,9 +72,10 @@ export const StepConfigureDatasource: React.FunctionComponent<{ ) : ( ); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx index 4bb42faedf7f6..d47eea80da8b7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/edit_datasource_page/index.tsx @@ -69,8 +69,7 @@ export const EditDatasourcePage: React.FunctionComponent = () => { const [loadingError, setLoadingError] = useState(); const [agentConfig, setAgentConfig] = useState(); const [packageInfo, setPackageInfo] = useState(); - const [datasource, setDatasource] = useState({ - id: '', + const [datasource, setDatasource] = useState({ name: '', description: '', config_id: '', @@ -94,6 +93,7 @@ export const EditDatasourcePage: React.FunctionComponent = () => { } if (datasourceData?.item) { const { + id, revision, inputs, created_by, @@ -302,6 +302,7 @@ export const EditDatasourcePage: React.FunctionComponent = () => { from={'edit'} packageInfo={packageInfo} datasource={datasource} + datasourceId={datasourceId} updateDatasource={updateDatasource} validationResults={validationResults!} submitAttempted={formState === 'INVALID'} diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx index ebcb46c3fb5b7..db5196bfc4eb4 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/configure_datasource.tsx @@ -12,30 +12,21 @@ import { LinkToApp } from '../../../../../common/components/endpoint/link_to_app import { CustomConfigureDatasourceContent, CustomConfigureDatasourceProps, - NewDatasource, } from '../../../../../../../ingest_manager/public'; import { getManagementUrl } from '../../../..'; -type DatasourceWithId = NewDatasource & { id: string }; - /** * Exports Endpoint-specific datasource configuration instructions * for use in the Ingest app create / edit datasource config */ export const ConfigureEndpointDatasource = memo( - ({ - from, - datasource, - }: { - from: string; - datasource: CustomConfigureDatasourceProps['datasource']; - }) => { + ({ from, datasourceId }: CustomConfigureDatasourceProps) => { const { services } = useKibana(); let policyUrl = ''; - if (from === 'edit') { + if (from === 'edit' && datasourceId) { policyUrl = getManagementUrl({ name: 'policyDetails', - policyId: (datasource as DatasourceWithId).id, + policyId: datasourceId, }); } From aec0b976151415bee54f94aefc1a6a803264d5f0 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Tue, 9 Jun 2020 16:05:48 -0700 Subject: [PATCH 15/53] Surface data streams in Index Management. (#67806) --- .../helpers/http_requests.ts | 9 ++ .../client_integration/helpers/index.ts | 42 +----- .../helpers/test_subjects.ts | 51 +++++++ .../home/data_streams_tab.helpers.ts | 101 +++++++++++++ .../home/data_streams_tab.test.ts | 137 +++++++++++++++++ .../home/indices_tab.helpers.ts | 27 +++- .../home/indices_tab.test.ts | 44 ++++++ .../common/lib/data_stream_serialization.ts | 21 +++ .../index_management/common/lib/index.ts | 3 + .../common/types/data_streams.ts | 29 ++++ .../index_management/common/types/index.ts | 2 + .../public/application/app.tsx | 6 +- .../data_stream_detail_panel.tsx | 104 +++++++++++++ .../data_stream_detail_panel/index.ts | 7 + .../data_stream_list/data_stream_list.tsx | 127 ++++++++++++++++ .../data_stream_table/data_stream_table.tsx | 139 ++++++++++++++++++ .../data_stream_table/index.ts | 7 + .../index.ts} | 2 +- .../public/application/sections/home/home.tsx | 23 ++- .../detail_panel/detail_panel.container.d.ts | 7 + .../detail_panel/{index.js => index.ts} | 0 .../{index_list.js => index_list.tsx} | 8 +- .../index_table/{index.js => index.ts} | 0 .../index_table/index_table.container.d.ts | 7 + .../index_list/index_table/index_table.js | 40 ++++- .../template_details/template_details.tsx | 4 +- .../template_table/template_table.tsx | 6 +- .../template_clone/template_clone.tsx | 4 +- .../sections/template_edit/template_edit.tsx | 4 +- .../public/application/services/api.ts | 21 ++- .../public/application/services/routing.ts | 19 ++- .../index_management/public/shared_imports.ts | 2 + .../server/client/elasticsearch.ts | 69 +++++++++ .../server/routes/api/data_streams/index.ts | 13 ++ .../api/data_streams/register_get_route.ts | 34 +++++ .../index_management/server/routes/index.ts | 2 + .../index_management/data_streams.ts | 89 +++++++++++ .../apis/management/index_management/index.js | 1 + .../index_management/lib/elasticsearch.js | 1 + .../apps/index_management/home_page.ts | 24 ++- .../page_objects/index_management_page.ts | 5 +- 41 files changed, 1161 insertions(+), 80 deletions(-) create mode 100644 x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts create mode 100644 x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts create mode 100644 x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts create mode 100644 x-pack/plugins/index_management/common/lib/data_stream_serialization.ts create mode 100644 x-pack/plugins/index_management/common/types/data_streams.ts create mode 100644 x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/data_stream_detail_panel.tsx create mode 100644 x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/index.ts create mode 100644 x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx create mode 100644 x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx create mode 100644 x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/index.ts rename x-pack/plugins/index_management/public/application/sections/home/{index_list/index_list.d.ts => data_stream_list/index.ts} (82%) create mode 100644 x-pack/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.container.d.ts rename x-pack/plugins/index_management/public/application/sections/home/index_list/detail_panel/{index.js => index.ts} (100%) rename x-pack/plugins/index_management/public/application/sections/home/index_list/{index_list.js => index_list.tsx} (71%) rename x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/{index.js => index.ts} (100%) create mode 100644 x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.d.ts create mode 100644 x-pack/plugins/index_management/server/routes/api/data_streams/index.ts create mode 100644 x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts create mode 100644 x-pack/test/api_integration/apis/management/index_management/data_streams.ts diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts index 75d1b69eb6157..56d76da522ac2 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts @@ -27,6 +27,14 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { ]); }; + const setLoadDataStreamsResponse = (response: HttpResponse = []) => { + server.respondWith('GET', `${API_BASE_PATH}/data_streams`, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(response), + ]); + }; + const setDeleteTemplateResponse = (response: HttpResponse = []) => { server.respondWith('POST', `${API_BASE_PATH}/delete_index_templates`, [ 200, @@ -71,6 +79,7 @@ const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { return { setLoadTemplatesResponse, setLoadIndicesResponse, + setLoadDataStreamsResponse, setDeleteTemplateResponse, setLoadTemplateResponse, setCreateTemplateResponse, diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts index 8e7755a65af3c..f581083e28cc6 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts @@ -10,44 +10,4 @@ export { nextTick, getRandomString, findTestSubject, TestBed } from '../../../.. export { setupEnvironment, WithAppDependencies, services } from './setup_environment'; -export type TestSubjects = - | 'aliasesTab' - | 'appTitle' - | 'cell' - | 'closeDetailsButton' - | 'createTemplateButton' - | 'createLegacyTemplateButton' - | 'deleteSystemTemplateCallOut' - | 'deleteTemplateButton' - | 'deleteTemplatesConfirmation' - | 'documentationLink' - | 'emptyPrompt' - | 'manageTemplateButton' - | 'mappingsTab' - | 'noAliasesCallout' - | 'noMappingsCallout' - | 'noSettingsCallout' - | 'indicesList' - | 'indicesTab' - | 'indexTableIncludeHiddenIndicesToggle' - | 'indexTableIndexNameLink' - | 'reloadButton' - | 'reloadIndicesButton' - | 'row' - | 'sectionError' - | 'sectionLoading' - | 'settingsTab' - | 'summaryTab' - | 'summaryTitle' - | 'systemTemplatesSwitch' - | 'templateDetails' - | 'templateDetails.manageTemplateButton' - | 'templateDetails.sectionLoading' - | 'templateDetails.tab' - | 'templateDetails.title' - | 'templateList' - | 'templateTable' - | 'templatesTab' - | 'legacyTemplateTable' - | 'viewButton' - | 'filterList.filterItem'; +export { TestSubjects } from './test_subjects'; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts new file mode 100644 index 0000000000000..4e297118b0fdd --- /dev/null +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts @@ -0,0 +1,51 @@ +/* + * 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 type TestSubjects = + | 'aliasesTab' + | 'appTitle' + | 'cell' + | 'closeDetailsButton' + | 'createLegacyTemplateButton' + | 'createTemplateButton' + | 'dataStreamsEmptyPromptTemplateLink' + | 'dataStreamTable' + | 'dataStreamTable' + | 'deleteSystemTemplateCallOut' + | 'deleteTemplateButton' + | 'deleteTemplatesConfirmation' + | 'documentationLink' + | 'emptyPrompt' + | 'filterList.filterItem' + | 'indexTable' + | 'indexTableIncludeHiddenIndicesToggle' + | 'indexTableIndexNameLink' + | 'indicesList' + | 'indicesTab' + | 'legacyTemplateTable' + | 'manageTemplateButton' + | 'mappingsTab' + | 'noAliasesCallout' + | 'noMappingsCallout' + | 'noSettingsCallout' + | 'reloadButton' + | 'reloadIndicesButton' + | 'row' + | 'sectionError' + | 'sectionLoading' + | 'settingsTab' + | 'summaryTab' + | 'summaryTitle' + | 'systemTemplatesSwitch' + | 'templateDetails' + | 'templateDetails.manageTemplateButton' + | 'templateDetails.sectionLoading' + | 'templateDetails.tab' + | 'templateDetails.title' + | 'templateList' + | 'templatesTab' + | 'templateTable' + | 'viewButton'; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts new file mode 100644 index 0000000000000..ef6aca44a1754 --- /dev/null +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts @@ -0,0 +1,101 @@ +/* + * 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 { act } from 'react-dom/test-utils'; + +import { + registerTestBed, + TestBed, + TestBedConfig, + findTestSubject, +} from '../../../../../test_utils'; +import { DataStream } from '../../../common'; +import { IndexManagementHome } from '../../../public/application/sections/home'; // eslint-disable-line @kbn/eslint/no-restricted-paths +import { indexManagementStore } from '../../../public/application/store'; // eslint-disable-line @kbn/eslint/no-restricted-paths +import { WithAppDependencies, services, TestSubjects } from '../helpers'; + +const testBedConfig: TestBedConfig = { + store: () => indexManagementStore(services as any), + memoryRouter: { + initialEntries: [`/indices`], + componentRoutePath: `/:section(indices|data_streams|templates)`, + }, + doMountAsync: true, +}; + +const initTestBed = registerTestBed(WithAppDependencies(IndexManagementHome), testBedConfig); + +export interface DataStreamsTabTestBed extends TestBed { + actions: { + goToDataStreamsList: () => void; + clickEmptyPromptIndexTemplateLink: () => void; + clickReloadButton: () => void; + clickIndicesAt: (index: number) => void; + }; +} + +export const setup = async (): Promise => { + const testBed = await initTestBed(); + + /** + * User Actions + */ + + const goToDataStreamsList = () => { + testBed.find('data_streamsTab').simulate('click'); + }; + + const clickEmptyPromptIndexTemplateLink = async () => { + const { find, component, router } = testBed; + + const templateLink = find('dataStreamsEmptyPromptTemplateLink'); + + await act(async () => { + router.navigateTo(templateLink.props().href!); + }); + + component.update(); + }; + + const clickReloadButton = () => { + const { find } = testBed; + find('reloadButton').simulate('click'); + }; + + const clickIndicesAt = async (index: number) => { + const { component, table, router } = testBed; + const { rows } = table.getMetaData('dataStreamTable'); + const indicesLink = findTestSubject(rows[index].reactWrapper, 'indicesLink'); + + await act(async () => { + router.navigateTo(indicesLink.props().href!); + }); + + component.update(); + }; + + return { + ...testBed, + actions: { + goToDataStreamsList, + clickEmptyPromptIndexTemplateLink, + clickReloadButton, + clickIndicesAt, + }, + }; +}; + +export const createDataStreamPayload = (name: string): DataStream => ({ + name, + timeStampField: '@timestamp', + indices: [ + { + name: 'indexName', + uuid: 'indexId', + }, + ], + generation: 1, +}); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts new file mode 100644 index 0000000000000..efe2e2d0c74ae --- /dev/null +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts @@ -0,0 +1,137 @@ +/* + * 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 { act } from 'react-dom/test-utils'; + +import { API_BASE_PATH } from '../../../common/constants'; +import { setupEnvironment } from '../helpers'; + +import { DataStreamsTabTestBed, setup, createDataStreamPayload } from './data_streams_tab.helpers'; + +describe('Data Streams tab', () => { + const { server, httpRequestsMockHelpers } = setupEnvironment(); + let testBed: DataStreamsTabTestBed; + + afterAll(() => { + server.restore(); + }); + + beforeEach(async () => { + httpRequestsMockHelpers.setLoadIndicesResponse([ + { + health: '', + status: '', + primary: '', + replica: '', + documents: '', + documents_deleted: '', + size: '', + primary_size: '', + name: 'data-stream-index', + data_stream: 'dataStream1', + }, + { + health: 'green', + status: 'open', + primary: 1, + replica: 1, + documents: 10000, + documents_deleted: 100, + size: '156kb', + primary_size: '156kb', + name: 'non-data-stream-index', + }, + ]); + + await act(async () => { + testBed = await setup(); + }); + }); + + describe('when there are no data streams', () => { + beforeEach(async () => { + const { actions, component } = testBed; + + httpRequestsMockHelpers.setLoadDataStreamsResponse([]); + httpRequestsMockHelpers.setLoadTemplatesResponse({ templates: [], legacyTemplates: [] }); + + await act(async () => { + actions.goToDataStreamsList(); + }); + + component.update(); + }); + + test('displays an empty prompt', async () => { + const { exists } = testBed; + + expect(exists('sectionLoading')).toBe(false); + expect(exists('emptyPrompt')).toBe(true); + }); + + test('goes to index templates tab when "Get started" link is clicked', async () => { + const { actions, exists } = testBed; + + await act(async () => { + actions.clickEmptyPromptIndexTemplateLink(); + }); + + expect(exists('templateList')).toBe(true); + }); + }); + + describe('when there are data streams', () => { + beforeEach(async () => { + const { actions, component } = testBed; + + httpRequestsMockHelpers.setLoadDataStreamsResponse([ + createDataStreamPayload('dataStream1'), + createDataStreamPayload('dataStream2'), + ]); + + await act(async () => { + actions.goToDataStreamsList(); + }); + + component.update(); + }); + + test('lists them in the table', async () => { + const { table } = testBed; + + const { tableCellsValues } = table.getMetaData('dataStreamTable'); + + expect(tableCellsValues).toEqual([ + ['dataStream1', '1', '@timestamp', '1'], + ['dataStream2', '1', '@timestamp', '1'], + ]); + }); + + test('has a button to reload the data streams', async () => { + const { exists, actions } = testBed; + const totalRequests = server.requests.length; + + expect(exists('reloadButton')).toBe(true); + + await act(async () => { + actions.clickReloadButton(); + }); + + expect(server.requests.length).toBe(totalRequests + 1); + expect(server.requests[server.requests.length - 1].url).toBe(`${API_BASE_PATH}/data_streams`); + }); + + test('clicking the indices count navigates to the backing indices', async () => { + const { table, actions } = testBed; + + await actions.clickIndicesAt(0); + + expect(table.getMetaData('indexTable').tableCellsValues).toEqual([ + ['', '', '', '', '', '', '', 'dataStream1'], + ]); + }); + }); +}); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.helpers.ts index e995932dfa00d..f00348aacbf08 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.helpers.ts @@ -6,8 +6,13 @@ import { act } from 'react-dom/test-utils'; -import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils'; -import { IndexList } from '../../../public/application/sections/home/index_list'; // eslint-disable-line @kbn/eslint/no-restricted-paths +import { + registerTestBed, + TestBed, + TestBedConfig, + findTestSubject, +} from '../../../../../test_utils'; +import { IndexManagementHome } from '../../../public/application/sections/home'; // eslint-disable-line @kbn/eslint/no-restricted-paths import { indexManagementStore } from '../../../public/application/store'; // eslint-disable-line @kbn/eslint/no-restricted-paths import { WithAppDependencies, services, TestSubjects } from '../helpers'; @@ -15,18 +20,19 @@ const testBedConfig: TestBedConfig = { store: () => indexManagementStore(services as any), memoryRouter: { initialEntries: [`/indices?includeHiddenIndices=true`], - componentRoutePath: `/:section(indices|templates)`, + componentRoutePath: `/:section(indices|data_streams)`, }, doMountAsync: true, }; -const initTestBed = registerTestBed(WithAppDependencies(IndexList), testBedConfig); +const initTestBed = registerTestBed(WithAppDependencies(IndexManagementHome), testBedConfig); export interface IndicesTestBed extends TestBed { actions: { selectIndexDetailsTab: (tab: 'settings' | 'mappings' | 'stats' | 'edit_settings') => void; getIncludeHiddenIndicesToggleStatus: () => boolean; clickIncludeHiddenIndicesToggle: () => void; + clickDataStreamAt: (index: number) => void; }; } @@ -59,12 +65,25 @@ export const setup = async (): Promise => { component.update(); }; + const clickDataStreamAt = async (index: number) => { + const { component, table, router } = testBed; + const { rows } = table.getMetaData('indexTable'); + const dataStreamLink = findTestSubject(rows[index].reactWrapper, 'dataStreamLink'); + + await act(async () => { + router.navigateTo(dataStreamLink.props().href!); + }); + + component.update(); + }; + return { ...testBed, actions: { selectIndexDetailsTab, getIncludeHiddenIndicesToggleStatus, clickIncludeHiddenIndicesToggle, + clickDataStreamAt, }, }; }; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts index 11c25ffbb590f..c2d955bb4dfce 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts @@ -9,6 +9,7 @@ import { act } from 'react-dom/test-utils'; import { API_BASE_PATH } from '../../../common/constants'; import { setupEnvironment, nextTick } from '../helpers'; import { IndicesTestBed, setup } from './indices_tab.helpers'; +import { createDataStreamPayload } from './data_streams_tab.helpers'; /** * The below import is required to avoid a console error warn from the "brace" package @@ -52,6 +53,49 @@ describe('', () => { }); }); + describe('data stream column', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadIndicesResponse([ + { + health: '', + status: '', + primary: '', + replica: '', + documents: '', + documents_deleted: '', + size: '', + primary_size: '', + name: 'data-stream-index', + data_stream: 'dataStream1', + }, + ]); + + httpRequestsMockHelpers.setLoadDataStreamsResponse([ + createDataStreamPayload('dataStream1'), + createDataStreamPayload('dataStream2'), + ]); + + testBed = await setup(); + + await act(async () => { + const { component } = testBed; + + await nextTick(); + component.update(); + }); + }); + + test('navigates to the data stream in the Data Streams tab', async () => { + const { table, actions } = testBed; + + await actions.clickDataStreamAt(0); + + expect(table.getMetaData('dataStreamTable').tableCellsValues).toEqual([ + ['dataStream1', '1', '@timestamp', '1'], + ]); + }); + }); + describe('index detail panel with % character in index name', () => { const indexName = 'test%'; beforeEach(async () => { diff --git a/x-pack/plugins/index_management/common/lib/data_stream_serialization.ts b/x-pack/plugins/index_management/common/lib/data_stream_serialization.ts new file mode 100644 index 0000000000000..9d267210a6b31 --- /dev/null +++ b/x-pack/plugins/index_management/common/lib/data_stream_serialization.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { DataStream, DataStreamFromEs } from '../types'; + +export function deserializeDataStreamList(dataStreamsFromEs: DataStreamFromEs[]): DataStream[] { + return dataStreamsFromEs.map(({ name, timestamp_field, indices, generation }) => ({ + name, + timeStampField: timestamp_field, + indices: indices.map( + ({ index_name, index_uuid }: { index_name: string; index_uuid: string }) => ({ + name: index_name, + uuid: index_uuid, + }) + ), + generation, + })); +} diff --git a/x-pack/plugins/index_management/common/lib/index.ts b/x-pack/plugins/index_management/common/lib/index.ts index c67d28da2c24b..fce4d8ccc2502 100644 --- a/x-pack/plugins/index_management/common/lib/index.ts +++ b/x-pack/plugins/index_management/common/lib/index.ts @@ -3,6 +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. */ + +export { deserializeDataStreamList } from './data_stream_serialization'; + export { deserializeLegacyTemplateList, deserializeTemplateList, diff --git a/x-pack/plugins/index_management/common/types/data_streams.ts b/x-pack/plugins/index_management/common/types/data_streams.ts new file mode 100644 index 0000000000000..5b743296d868b --- /dev/null +++ b/x-pack/plugins/index_management/common/types/data_streams.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export interface DataStreamFromEs { + name: string; + timestamp_field: string; + indices: DataStreamIndexFromEs[]; + generation: number; +} + +export interface DataStreamIndexFromEs { + index_name: string; + index_uuid: string; +} + +export interface DataStream { + name: string; + timeStampField: string; + indices: DataStreamIndex[]; + generation: number; +} + +export interface DataStreamIndex { + name: string; + uuid: string; +} diff --git a/x-pack/plugins/index_management/common/types/index.ts b/x-pack/plugins/index_management/common/types/index.ts index 81a06156dd291..c4ba60573d430 100644 --- a/x-pack/plugins/index_management/common/types/index.ts +++ b/x-pack/plugins/index_management/common/types/index.ts @@ -12,4 +12,6 @@ export * from './mappings'; export * from './templates'; +export { DataStreamFromEs, DataStream, DataStreamIndex } from './data_streams'; + export * from './component_templates'; diff --git a/x-pack/plugins/index_management/public/application/app.tsx b/x-pack/plugins/index_management/public/application/app.tsx index bfd99de6949e5..92197bee30c88 100644 --- a/x-pack/plugins/index_management/public/application/app.tsx +++ b/x-pack/plugins/index_management/public/application/app.tsx @@ -31,9 +31,9 @@ export const App = ({ history }: { history: ScopedHistory }) => { // Export this so we can test it with a different router. export const AppWithoutRouter = () => ( - - - + + + diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/data_stream_detail_panel.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/data_stream_detail_panel.tsx new file mode 100644 index 0000000000000..a6c8b83a05f98 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/data_stream_detail_panel.tsx @@ -0,0 +1,104 @@ +/* + * 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, { Fragment } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiFlyout, + EuiFlyoutHeader, + EuiTitle, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, +} from '@elastic/eui'; + +import { SectionLoading, SectionError, Error } from '../../../../components'; +import { useLoadDataStream } from '../../../../services/api'; + +interface Props { + dataStreamName: string; + onClose: () => void; +} + +/** + * NOTE: This currently isn't in use by data_stream_list.tsx because it doesn't contain any + * information that doesn't already exist in the table. We'll use it once we add additional + * info, e.g. storage size, docs count. + */ +export const DataStreamDetailPanel: React.FunctionComponent = ({ + dataStreamName, + onClose, +}) => { + const { error, data: dataStream, isLoading } = useLoadDataStream(dataStreamName); + + let content; + + if (isLoading) { + content = ( + + + + ); + } else if (error) { + content = ( + + } + error={error as Error} + data-test-subj="sectionError" + /> + ); + } else if (dataStream) { + content = {JSON.stringify(dataStream)}; + } + + return ( + + + +

+ {dataStreamName} +

+
+
+ + {content} + + + + + + + + + + +
+ ); +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/index.ts b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/index.ts new file mode 100644 index 0000000000000..3f45267c032ed --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_detail_panel/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 { DataStreamDetailPanel } from './data_stream_detail_panel'; diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx new file mode 100644 index 0000000000000..951c4a0d7f3c3 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx @@ -0,0 +1,127 @@ +/* + * 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 { RouteComponentProps } from 'react-router-dom'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { EuiTitle, EuiText, EuiSpacer, EuiEmptyPrompt, EuiLink } from '@elastic/eui'; +import { ScopedHistory } from 'kibana/public'; + +import { reactRouterNavigate } from '../../../../shared_imports'; +import { SectionError, SectionLoading, Error } from '../../../components'; +import { useLoadDataStreams } from '../../../services/api'; +import { DataStreamTable } from './data_stream_table'; + +interface MatchParams { + dataStreamName?: string; +} + +export const DataStreamList: React.FunctionComponent> = ({ + match: { + params: { dataStreamName }, + }, + history, +}) => { + const { error, isLoading, data: dataStreams, sendRequest: reload } = useLoadDataStreams(); + + let content; + + if (isLoading) { + content = ( + + + + ); + } else if (error) { + content = ( + + } + error={error as Error} + /> + ); + } else if (Array.isArray(dataStreams) && dataStreams.length === 0) { + content = ( + + + + } + body={ +

+ + {i18n.translate('xpack.idxMgmt.dataStreamList.emptyPrompt.getStartedLink', { + defaultMessage: 'composable index template', + })} + + ), + }} + /> +

+ } + data-test-subj="emptyPrompt" + /> + ); + } else if (Array.isArray(dataStreams) && dataStreams.length > 0) { + content = ( + <> + {/* TODO: Add a switch for toggling on data streams created by Ingest Manager */} + + + + + + + + + + + {/* TODO: Implement this once we have something to put in here, e.g. storage size, docs count */} + {/* dataStreamName && ( + { + history.push('/data_streams'); + }} + /> + )*/} + + ); + } + + return
{content}
; +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx new file mode 100644 index 0000000000000..54b215e561b46 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiInMemoryTable, EuiBasicTableColumn, EuiButton, EuiLink } from '@elastic/eui'; +import { ScopedHistory } from 'kibana/public'; + +import { DataStream } from '../../../../../../common/types'; +import { reactRouterNavigate } from '../../../../../shared_imports'; +import { encodePathForReactRouter } from '../../../../services/routing'; + +interface Props { + dataStreams?: DataStream[]; + reload: () => {}; + history: ScopedHistory; + filters?: string; +} + +export const DataStreamTable: React.FunctionComponent = ({ + dataStreams, + reload, + history, + filters, +}) => { + const columns: Array> = [ + { + field: 'name', + name: i18n.translate('xpack.idxMgmt.dataStreamList.table.nameColumnTitle', { + defaultMessage: 'Name', + }), + truncateText: true, + sortable: true, + // TODO: Render as a link to open the detail panel + }, + { + field: 'indices', + name: i18n.translate('xpack.idxMgmt.dataStreamList.table.indicesColumnTitle', { + defaultMessage: 'Indices', + }), + truncateText: true, + sortable: true, + render: (indices: DataStream['indices'], dataStream) => ( + + {indices.length} + + ), + }, + { + field: 'timeStampField', + name: i18n.translate('xpack.idxMgmt.dataStreamList.table.timeStampFieldColumnTitle', { + defaultMessage: 'Timestamp field', + }), + truncateText: true, + sortable: true, + }, + { + field: 'generation', + name: i18n.translate('xpack.idxMgmt.dataStreamList.table.generationFieldColumnTitle', { + defaultMessage: 'Generation', + }), + truncateText: true, + sortable: true, + }, + ]; + + const pagination = { + initialPageSize: 20, + pageSizeOptions: [10, 20, 50], + }; + + const sorting = { + sort: { + field: 'name', + direction: 'asc', + }, + } as const; + + const searchConfig = { + query: filters, + box: { + incremental: true, + }, + toolsLeft: undefined /* TODO: Actions menu */, + toolsRight: [ + + + , + ], + }; + + return ( + <> + ({ + 'data-test-subj': 'row', + })} + cellProps={() => ({ + 'data-test-subj': 'cell', + })} + data-test-subj="dataStreamTable" + message={ + + } + /> + + ); +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/index.ts b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/index.ts new file mode 100644 index 0000000000000..3922ca5c1d50c --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/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 { DataStreamTable } from './data_stream_table'; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_list.d.ts b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/index.ts similarity index 82% rename from x-pack/plugins/index_management/public/application/sections/home/index_list/index_list.d.ts rename to x-pack/plugins/index_management/public/application/sections/home/data_stream_list/index.ts index f03f483c0e821..e2f588cc2a0fb 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_list.d.ts +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export declare function IndexList(match: any): any; +export { DataStreamList } from './data_stream_list'; diff --git a/x-pack/plugins/index_management/public/application/sections/home/home.tsx b/x-pack/plugins/index_management/public/application/sections/home/home.tsx index 0ddf4fefce466..51deaf42cc72c 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/home.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/home.tsx @@ -19,6 +19,7 @@ import { EuiTitle, } from '@elastic/eui'; import { documentationService } from '../../services/documentation'; +import { DataStreamList } from './data_stream_list'; import { IndexList } from './index_list'; import { TemplateList } from './template_list'; import { ComponentTemplateList } from '../../components/component_templates'; @@ -26,11 +27,17 @@ import { breadcrumbService } from '../../services/breadcrumbs'; export enum Section { Indices = 'indices', + DataStreams = 'data_streams', IndexTemplates = 'templates', ComponentTemplates = 'component_templates', } -export const homeSections = [Section.Indices, Section.IndexTemplates, Section.ComponentTemplates]; +export const homeSections = [ + Section.Indices, + Section.DataStreams, + Section.IndexTemplates, + Section.ComponentTemplates, +]; interface MatchParams { section: Section; @@ -47,6 +54,15 @@ export const IndexManagementHome: React.FunctionComponent, }, + { + id: Section.DataStreams, + name: ( + + ), + }, { id: Section.IndexTemplates, name: ( @@ -122,6 +138,11 @@ export const IndexManagementHome: React.FunctionComponent + = ({ history }) => { return (
- +
); -} +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index.ts similarity index 100% rename from x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index.js rename to x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index.ts diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.d.ts b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.d.ts new file mode 100644 index 0000000000000..35ddfc4813617 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.d.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 declare function IndexTable(props: any): any; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js index f33d486520a29..c3acff087146a 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js @@ -37,8 +37,10 @@ import { } from '@elastic/eui'; import { UIM_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; +import { reactRouterNavigate } from '../../../../../shared_imports'; import { REFRESH_RATE_INDEX_LIST } from '../../../../constants'; import { healthToColor } from '../../../../services'; +import { encodePathForReactRouter } from '../../../../services/routing'; import { AppContextConsumer } from '../../../../app_context'; import { renderBadges } from '../../../../lib/render_badges'; import { NoMatch, PageErrorForbidden } from '../../../../components'; @@ -117,6 +119,7 @@ export class IndexTable extends Component { } } } + componentWillUnmount() { clearInterval(this.interval); } @@ -146,11 +149,14 @@ export class IndexTable extends Component { const newIsSortAscending = sortField === column ? !isSortAscending : true; sortChanged(column, newIsSortAscending); }; + renderFilterError() { const { filterError } = this.state; + if (!filterError) { return; } + return ( <> @@ -169,6 +175,7 @@ export class IndexTable extends Component { ); } + onFilterChanged = ({ query, error }) => { if (error) { this.setState({ filterError: error }); @@ -177,6 +184,7 @@ export class IndexTable extends Component { this.setState({ filterError: null }); } }; + getFilters = (extensionsService) => { const { allIndices } = this.props; return extensionsService.filters.reduce((accum, filterExtension) => { @@ -184,6 +192,7 @@ export class IndexTable extends Component { return [...accum, ...filtersToAdd]; }, []); }; + toggleAll = () => { const allSelected = this.areAllItemsSelected(); if (allSelected) { @@ -243,7 +252,8 @@ export class IndexTable extends Component { } buildRowCell(fieldName, value, index, appServices) { - const { openDetailPanel, filterChanged } = this.props; + const { openDetailPanel, filterChanged, history } = this.props; + if (fieldName === 'health') { return {value}; } else if (fieldName === 'name') { @@ -261,7 +271,19 @@ export class IndexTable extends Component { {renderBadges(index, filterChanged, appServices.extensionsService)} ); + } else if (fieldName === 'data_stream') { + return ( + + {value} + + ); } + return value; } @@ -480,12 +502,14 @@ export class IndexTable extends Component { + {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( {extensionsService.toggles.map((toggle) => { return this.renderToggleControl(toggle); })} + + + {this.renderBanners(extensionsService)} + {indicesError && this.renderError()} + {atLeastOneItemSelected ? ( @@ -523,6 +551,7 @@ export class IndexTable extends Component { /> ) : null} + {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( @@ -572,11 +601,14 @@ export class IndexTable extends Component { )} + {this.renderFilterError()} + + {indices.length > 0 ? (
- + + {this.buildHeader()} + {this.buildRows(services)}
) : ( emptyState )} + + {indices.length > 0 ? this.renderPager() : null} ); diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_details/template_details.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_details/template_details.tsx index ec2956973d4f6..807229fb36267 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_details/template_details.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_details/template_details.tsx @@ -38,7 +38,7 @@ import { Error, } from '../../../../../components'; import { useLoadIndexTemplate } from '../../../../../services/api'; -import { decodePath } from '../../../../../services/routing'; +import { decodePathFromReactRouter } from '../../../../../services/routing'; import { SendRequestResponse } from '../../../../../../shared_imports'; import { useServices } from '../../../../../app_context'; import { TabSummary, TabMappings, TabSettings, TabAliases } from '../../template_details/tabs'; @@ -107,7 +107,7 @@ export const LegacyTemplateDetails: React.FunctionComponent = ({ reload, }) => { const { uiMetricService } = useServices(); - const decodedTemplateName = decodePath(templateName); + const decodedTemplateName = decodePathFromReactRouter(templateName); const { error, data: templateDetails, isLoading } = useLoadIndexTemplate( decodedTemplateName, isLegacy diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx index 92fedd5d68f00..edce05018ce39 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx @@ -9,12 +9,12 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiInMemoryTable, EuiIcon, EuiButton, EuiLink, EuiBasicTableColumn } from '@elastic/eui'; import { ScopedHistory } from 'kibana/public'; -import { reactRouterNavigate } from '../../../../../../../../../../src/plugins/kibana_react/public'; +import { SendRequestResponse, reactRouterNavigate } from '../../../../../../shared_imports'; import { TemplateListItem } from '../../../../../../../common'; import { UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../../common/constants'; import { TemplateDeleteModal } from '../../../../../components'; +import { encodePathForReactRouter } from '../../../../../services/routing'; import { useServices } from '../../../../../app_context'; -import { SendRequestResponse } from '../../../../../../shared_imports'; interface Props { templates: TemplateListItem[]; @@ -52,7 +52,7 @@ export const LegacyTemplateTable: React.FunctionComponent = ({ {...reactRouterNavigate( history, { - pathname: `/templates/${encodeURIComponent(encodeURIComponent(name))}`, + pathname: `/templates/${encodePathForReactRouter(name)}`, search: `legacy=${Boolean(item._kbnMeta.isLegacy)}`, }, () => uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK) diff --git a/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx b/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx index 8bdd230f89952..82835c56a3877 100644 --- a/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx +++ b/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx @@ -11,7 +11,7 @@ import { EuiPageBody, EuiPageContent, EuiSpacer, EuiTitle } from '@elastic/eui'; import { TemplateDeserialized } from '../../../../common'; import { TemplateForm, SectionLoading, SectionError, Error } from '../../components'; import { breadcrumbService } from '../../services/breadcrumbs'; -import { decodePath, getTemplateDetailsLink } from '../../services/routing'; +import { decodePathFromReactRouter, getTemplateDetailsLink } from '../../services/routing'; import { saveTemplate, useLoadIndexTemplate } from '../../services/api'; import { getIsLegacyFromQueryParams } from '../../lib/index_templates'; @@ -26,7 +26,7 @@ export const TemplateClone: React.FunctionComponent { - const decodedTemplateName = decodePath(name); + const decodedTemplateName = decodePathFromReactRouter(name); const isLegacy = getIsLegacyFromQueryParams(location); const [isSaving, setIsSaving] = useState(false); diff --git a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx index d3e539989bc96..7cacb5ee97a60 100644 --- a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx +++ b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx @@ -11,7 +11,7 @@ import { EuiPageBody, EuiPageContent, EuiTitle, EuiSpacer, EuiCallOut } from '@e import { TemplateDeserialized } from '../../../../common'; import { breadcrumbService } from '../../services/breadcrumbs'; import { useLoadIndexTemplate, updateTemplate } from '../../services/api'; -import { decodePath, getTemplateDetailsLink } from '../../services/routing'; +import { decodePathFromReactRouter, getTemplateDetailsLink } from '../../services/routing'; import { SectionLoading, SectionError, TemplateForm, Error } from '../../components'; import { getIsLegacyFromQueryParams } from '../../lib/index_templates'; @@ -26,7 +26,7 @@ export const TemplateEdit: React.FunctionComponent { - const decodedTemplateName = decodePath(name); + const decodedTemplateName = decodePathFromReactRouter(name); const isLegacy = getIsLegacyFromQueryParams(location); const [isSaving, setIsSaving] = useState(false); diff --git a/x-pack/plugins/index_management/public/application/services/api.ts b/x-pack/plugins/index_management/public/application/services/api.ts index d1950ae714550..5ad84395d24c2 100644 --- a/x-pack/plugins/index_management/public/application/services/api.ts +++ b/x-pack/plugins/index_management/public/application/services/api.ts @@ -31,14 +31,12 @@ import { UIM_TEMPLATE_UPDATE, UIM_TEMPLATE_CLONE, } from '../../../common/constants'; - +import { TemplateDeserialized, TemplateListItem, DataStream } from '../../../common'; +import { IndexMgmtMetricsType } from '../../types'; import { TAB_SETTINGS, TAB_MAPPING, TAB_STATS } from '../constants'; - import { useRequest, sendRequest } from './use_request'; import { httpService } from './http'; import { UiMetricService } from './ui_metric'; -import { TemplateDeserialized, TemplateListItem } from '../../../common'; -import { IndexMgmtMetricsType } from '../../types'; // Temporary hack to provide the uiMetricService instance to this file. // TODO: Refactor and export an ApiService instance through the app dependencies context @@ -48,6 +46,21 @@ export const setUiMetricService = (_uiMetricService: UiMetricService({ + path: `${API_BASE_PATH}/data_streams`, + method: 'get', + }); +} + +// TODO: Implement this API endpoint once we have content to surface in the detail panel. +export function useLoadDataStream(name: string) { + return useRequest({ + path: `${API_BASE_PATH}/data_stream/${encodeURIComponent(name)}`, + method: 'get', + }); +} + export async function loadIndices() { const response = await httpService.httpClient.get(`${API_BASE_PATH}/indices`); return response.data ? response.data : response; diff --git a/x-pack/plugins/index_management/public/application/services/routing.ts b/x-pack/plugins/index_management/public/application/services/routing.ts index a999c58f5bb42..2a895196189d0 100644 --- a/x-pack/plugins/index_management/public/application/services/routing.ts +++ b/x-pack/plugins/index_management/public/application/services/routing.ts @@ -6,10 +6,8 @@ export const getTemplateListLink = () => `/templates`; -// Need to add some additonal encoding/decoding logic to work with React Router -// For background, see: https://github.com/ReactTraining/history/issues/505 export const getTemplateDetailsLink = (name: string, isLegacy?: boolean, withHash = false) => { - const baseUrl = `/templates/${encodeURIComponent(encodeURIComponent(name))}`; + const baseUrl = `/templates/${encodePathForReactRouter(name)}`; let url = withHash ? `#${baseUrl}` : baseUrl; if (isLegacy) { url = `${url}?legacy=${isLegacy}`; @@ -18,18 +16,14 @@ export const getTemplateDetailsLink = (name: string, isLegacy?: boolean, withHas }; export const getTemplateEditLink = (name: string, isLegacy?: boolean) => { - return encodeURI( - `/edit_template/${encodeURIComponent(encodeURIComponent(name))}?legacy=${isLegacy === true}` - ); + return encodeURI(`/edit_template/${encodePathForReactRouter(name)}?legacy=${isLegacy === true}`); }; export const getTemplateCloneLink = (name: string, isLegacy?: boolean) => { - return encodeURI( - `/clone_template/${encodeURIComponent(encodeURIComponent(name))}?legacy=${isLegacy === true}` - ); + return encodeURI(`/clone_template/${encodePathForReactRouter(name)}?legacy=${isLegacy === true}`); }; -export const decodePath = (pathname: string): string => { +export const decodePathFromReactRouter = (pathname: string): string => { let decodedPath; try { decodedPath = decodeURI(pathname); @@ -39,3 +33,8 @@ export const decodePath = (pathname: string): string => { } return decodeURIComponent(decodedPath); }; + +// Need to add some additonal encoding/decoding logic to work with React Router +// For background, see: https://github.com/ReactTraining/history/issues/505 +export const encodePathForReactRouter = (pathname: string): string => + encodeURIComponent(encodeURIComponent(pathname)); diff --git a/x-pack/plugins/index_management/public/shared_imports.ts b/x-pack/plugins/index_management/public/shared_imports.ts index 8942367261511..afd5a5cf650e1 100644 --- a/x-pack/plugins/index_management/public/shared_imports.ts +++ b/x-pack/plugins/index_management/public/shared_imports.ts @@ -31,3 +31,5 @@ export { export { getFormRow, Field } from '../../../../src/plugins/es_ui_shared/static/forms/components'; export { isJSON } from '../../../../src/plugins/es_ui_shared/static/validators/string'; + +export { reactRouterNavigate } from '../../../../src/plugins/kibana_react/public'; diff --git a/x-pack/plugins/index_management/server/client/elasticsearch.ts b/x-pack/plugins/index_management/server/client/elasticsearch.ts index b51f7d924dba7..6b1bf47512b21 100644 --- a/x-pack/plugins/index_management/server/client/elasticsearch.ts +++ b/x-pack/plugins/index_management/server/client/elasticsearch.ts @@ -10,6 +10,46 @@ export const elasticsearchJsPlugin = (Client: any, config: any, components: any) Client.prototype.dataManagement = components.clientAction.namespaceFactory(); const dataManagement = Client.prototype.dataManagement.prototype; + // Data streams + dataManagement.getDataStreams = ca({ + urls: [ + { + fmt: '/_data_stream', + }, + ], + method: 'GET', + }); + + // We don't allow the user to create a data stream in the UI or API. We're just adding this here + // to enable the API integration tests. + dataManagement.createDataStream = ca({ + urls: [ + { + fmt: '/_data_stream/<%=name%>', + req: { + name: { + type: 'string', + }, + }, + }, + ], + method: 'PUT', + }); + + dataManagement.deleteDataStream = ca({ + urls: [ + { + fmt: '/_data_stream/<%=name%>', + req: { + name: { + type: 'string', + }, + }, + }, + ], + method: 'DELETE', + }); + // Component templates dataManagement.getComponentTemplates = ca({ urls: [ @@ -71,4 +111,33 @@ export const elasticsearchJsPlugin = (Client: any, config: any, components: any) ], method: 'GET', }); + + dataManagement.saveComposableIndexTemplate = ca({ + urls: [ + { + fmt: '/_index_template/<%=name%>', + req: { + name: { + type: 'string', + }, + }, + }, + ], + needBody: true, + method: 'PUT', + }); + + dataManagement.deleteComposableIndexTemplate = ca({ + urls: [ + { + fmt: '/_index_template/<%=name%>', + req: { + name: { + type: 'string', + }, + }, + }, + ], + method: 'DELETE', + }); }; diff --git a/x-pack/plugins/index_management/server/routes/api/data_streams/index.ts b/x-pack/plugins/index_management/server/routes/api/data_streams/index.ts new file mode 100644 index 0000000000000..56c514e30f242 --- /dev/null +++ b/x-pack/plugins/index_management/server/routes/api/data_streams/index.ts @@ -0,0 +1,13 @@ +/* + * 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 { RouteDependencies } from '../../../types'; + +import { registerGetAllRoute } from './register_get_route'; + +export function registerDataStreamRoutes(dependencies: RouteDependencies) { + registerGetAllRoute(dependencies); +} diff --git a/x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts b/x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts new file mode 100644 index 0000000000000..9128556130bf4 --- /dev/null +++ b/x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts @@ -0,0 +1,34 @@ +/* + * 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 { deserializeDataStreamList } from '../../../../common/lib'; +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../index'; + +export function registerGetAllRoute({ router, license, lib: { isEsError } }: RouteDependencies) { + router.get( + { path: addBasePath('/data_streams'), validate: false }, + license.guardApiRoute(async (ctx, req, res) => { + const { callAsCurrentUser } = ctx.dataManagement!.client; + + try { + const dataStreams = await callAsCurrentUser('dataManagement.getDataStreams'); + const body = deserializeDataStreamList(dataStreams); + + return res.ok({ body }); + } catch (error) { + if (isEsError(error)) { + return res.customError({ + statusCode: error.statusCode, + body: error, + }); + } + + return res.internalError({ body: error }); + } + }) + ); +} diff --git a/x-pack/plugins/index_management/server/routes/index.ts b/x-pack/plugins/index_management/server/routes/index.ts index 1e5aaf8087624..202e6919f7b13 100644 --- a/x-pack/plugins/index_management/server/routes/index.ts +++ b/x-pack/plugins/index_management/server/routes/index.ts @@ -6,6 +6,7 @@ import { RouteDependencies } from '../types'; +import { registerDataStreamRoutes } from './api/data_streams'; import { registerIndicesRoutes } from './api/indices'; import { registerTemplateRoutes } from './api/templates'; import { registerMappingRoute } from './api/mapping'; @@ -15,6 +16,7 @@ import { registerComponentTemplateRoutes } from './api/component_templates'; export class ApiRoutes { setup(dependencies: RouteDependencies) { + registerDataStreamRoutes(dependencies); registerIndicesRoutes(dependencies); registerTemplateRoutes(dependencies); registerSettingsRoutes(dependencies); diff --git a/x-pack/test/api_integration/apis/management/index_management/data_streams.ts b/x-pack/test/api_integration/apis/management/index_management/data_streams.ts new file mode 100644 index 0000000000000..9a8511b4331ea --- /dev/null +++ b/x-pack/test/api_integration/apis/management/index_management/data_streams.ts @@ -0,0 +1,89 @@ +/* + * 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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; +// @ts-ignore +import { API_BASE_PATH } from './constants'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('legacyEs'); + + const createDataStream = (name: string) => { + // A data stream requires an index template before it can be created. + return es.dataManagement + .saveComposableIndexTemplate({ + name, + body: { + index_patterns: ['*'], + template: { + settings: {}, + }, + data_stream: { + timestamp_field: '@timestamp', + }, + }, + }) + .then(() => + es.dataManagement.createDataStream({ + name, + }) + ); + }; + + const deleteDataStream = (name: string) => { + return es.dataManagement + .deleteComposableIndexTemplate({ + name, + }) + .then(() => + es.dataManagement.deleteDataStream({ + name, + }) + ); + }; + + describe('Data streams', function () { + const testDataStreamName = 'test-data-stream'; + + describe('Get', () => { + before(async () => await createDataStream(testDataStreamName)); + after(async () => await deleteDataStream(testDataStreamName)); + + describe('all data streams', () => { + it('returns an array of data streams', async () => { + const { body: dataStreams } = await supertest + .get(`${API_BASE_PATH}/data_streams`) + .set('kbn-xsrf', 'xxx') + .expect(200); + + // ES determines these values so we'll just echo them back. + const { name: indexName, uuid } = dataStreams[0].indices[0]; + expect(dataStreams).to.eql([ + { + name: testDataStreamName, + timeStampField: '@timestamp', + indices: [ + { + name: indexName, + uuid, + }, + ], + generation: 1, + }, + ]); + }); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/management/index_management/index.js b/x-pack/test/api_integration/apis/management/index_management/index.js index fdee325938ff4..93e8a4a8d6130 100644 --- a/x-pack/test/api_integration/apis/management/index_management/index.js +++ b/x-pack/test/api_integration/apis/management/index_management/index.js @@ -10,6 +10,7 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./mapping')); loadTestFile(require.resolve('./settings')); loadTestFile(require.resolve('./stats')); + loadTestFile(require.resolve('./data_streams')); loadTestFile(require.resolve('./templates')); loadTestFile(require.resolve('./component_templates')); }); diff --git a/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js b/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js index b950a56a913db..1a1517567eaed 100644 --- a/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js +++ b/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js @@ -3,6 +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 { getRandomString } from './random'; /** diff --git a/x-pack/test/functional/apps/index_management/home_page.ts b/x-pack/test/functional/apps/index_management/home_page.ts index cca0a5d1ad1bd..90bc3603c1613 100644 --- a/x-pack/test/functional/apps/index_management/home_page.ts +++ b/x-pack/test/functional/apps/index_management/home_page.ts @@ -18,12 +18,17 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.common.navigateToApp('indexManagement'); }); - it('Loads the app', async () => { + it('Loads the app and renders the indices tab by default', async () => { await log.debug('Checking for section heading to say Index Management.'); const headingText = await pageObjects.indexManagement.sectionHeadingText(); expect(headingText).to.be('Index Management'); + // Verify url + const url = await browser.getCurrentUrl(); + expect(url).to.contain(`/indices`); + + // Verify content const indicesList = await testSubjects.exists('indicesList'); expect(indicesList).to.be(true); @@ -31,6 +36,23 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(await reloadIndicesButton.isDisplayed()).to.be(true); }); + describe('Data streams', () => { + it('renders the data streams tab', async () => { + // Navigate to the data streams tab + await pageObjects.indexManagement.changeTabs('data_streamsTab'); + + await pageObjects.header.waitUntilLoadingHasFinished(); + + // Verify url + const url = await browser.getCurrentUrl(); + expect(url).to.contain(`/data_streams`); + + // Verify content + const dataStreamList = await testSubjects.exists('dataStreamList'); + expect(dataStreamList).to.be(true); + }); + }); + describe('Index templates', () => { it('renders the index templates tab', async () => { // Navigate to the index templates tab diff --git a/x-pack/test/functional/page_objects/index_management_page.ts b/x-pack/test/functional/page_objects/index_management_page.ts index 9bfcd79671b4d..5e5d0e7583450 100644 --- a/x-pack/test/functional/page_objects/index_management_page.ts +++ b/x-pack/test/functional/page_objects/index_management_page.ts @@ -44,7 +44,10 @@ export function IndexManagementPageProvider({ getService }: FtrProviderContext) }; }); }, - async changeTabs(tab: 'indicesTab' | 'templatesTab' | 'component_templatesTab') { + + async changeTabs( + tab: 'indicesTab' | 'data_streamsTab' | 'templatesTab' | 'component_templatesTab' + ) { await testSubjects.click(tab); }, }; From 80958568e75577e3b35f5307e6b88fab2fc16ac8 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Tue, 9 Jun 2020 21:37:37 -0400 Subject: [PATCH 16/53] [SIEM][Exceptions] - ExceptionsViewer UI component part 2 (#68294) ### Summary This PR is a follow up to #68027 . It brings it all together to complete the exceptions viewer component. This component is meant to display all exception items and allow a user to create, edit, delete, and search these exception items. - Moves ExceptionItem (from part 1) into its own folder - Adds exceptions_viewer_header component that includes the search, list toggle, and add exception buttons - Adds actual ExceptionViewer component - Updates the useExceptionList hook refresh function logic. Noticed that the previous version was creating some issues --- .../lists/public/exceptions/hooks/use_api.tsx | 111 +++++ .../hooks/use_exception_list.test.tsx | 79 ++-- .../exceptions/hooks/use_exception_list.tsx | 120 +++-- .../plugins/lists/public/exceptions/types.ts | 40 +- x-pack/plugins/lists/public/index.tsx | 2 + .../new/exception_list_detection.json | 9 + .../new/exception_list_item_auto_id.json | 1 + ...exception_list_item_detection_auto_id.json | 26 + .../detection_engine/rules/details/index.tsx | 20 + .../rules/details/translations.ts | 7 + ...stories.tsx => exception_item.stories.tsx} | 25 +- .../exceptions_search.stories.tsx | 70 +++ .../components/exceptions/helpers.test.tsx | 6 +- .../common/components/exceptions/mocks.ts | 21 +- .../components/exceptions/translations.ts | 90 ++++ .../common/components/exceptions/types.ts | 49 +- .../exception_details.test.tsx | 6 +- .../exception_details.tsx | 15 +- .../exception_entries.test.tsx | 10 +- .../exception_entries.tsx | 12 +- .../viewer/exception_item/index.test.tsx | 121 +++++ .../viewer/exception_item/index.tsx | 112 +++++ .../viewer/exceptions_pagination.test.tsx | 158 +++++++ .../viewer/exceptions_pagination.tsx | 123 +++++ .../viewer/exceptions_viewer_header.test.tsx | 337 +++++++++++++ .../viewer/exceptions_viewer_header.tsx | 204 ++++++++ .../exceptions/viewer/index.test.tsx | 168 ++++--- .../components/exceptions/viewer/index.tsx | 446 +++++++++++++++--- .../components/exceptions/viewer/reducer.ts | 122 +++++ .../public/lists_plugin_deps.ts | 10 +- 30 files changed, 2266 insertions(+), 254 deletions(-) create mode 100644 x-pack/plugins/lists/public/exceptions/hooks/use_api.tsx create mode 100644 x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json create mode 100644 x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json rename x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/{index.stories.tsx => exception_item.stories.tsx} (86%) create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx rename x-pack/plugins/security_solution/public/common/components/exceptions/viewer/{ => exception_item}/exception_details.test.tsx (98%) rename x-pack/plugins/security_solution/public/common/components/exceptions/viewer/{ => exception_item}/exception_details.tsx (85%) rename x-pack/plugins/security_solution/public/common/components/exceptions/viewer/{ => exception_item}/exception_entries.test.tsx (94%) rename x-pack/plugins/security_solution/public/common/components/exceptions/viewer/{ => exception_item}/exception_entries.tsx (93%) create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_api.tsx b/x-pack/plugins/lists/public/exceptions/hooks/use_api.tsx new file mode 100644 index 0000000000000..45e180d9d617c --- /dev/null +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_api.tsx @@ -0,0 +1,111 @@ +/* + * 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 { useMemo } from 'react'; + +import * as Api from '../api'; +import { HttpStart } from '../../../../../../src/core/public'; +import { ExceptionListItemSchema, ExceptionListSchema } from '../../../common/schemas'; +import { ApiCallMemoProps } from '../types'; + +export interface ExceptionsApi { + deleteExceptionItem: (arg: ApiCallMemoProps) => Promise; + deleteExceptionList: (arg: ApiCallMemoProps) => Promise; + getExceptionItem: ( + arg: ApiCallMemoProps & { onSuccess: (arg: ExceptionListItemSchema) => void } + ) => Promise; + getExceptionList: ( + arg: ApiCallMemoProps & { onSuccess: (arg: ExceptionListSchema) => void } + ) => Promise; +} + +export const useApi = (http: HttpStart): ExceptionsApi => { + return useMemo( + (): ExceptionsApi => ({ + async deleteExceptionItem({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps): Promise { + const abortCtrl = new AbortController(); + + try { + await Api.deleteExceptionListItemById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(); + } catch (error) { + onError(error); + } + }, + async deleteExceptionList({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps): Promise { + const abortCtrl = new AbortController(); + + try { + await Api.deleteExceptionListById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(); + } catch (error) { + onError(error); + } + }, + async getExceptionItem({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps & { onSuccess: (arg: ExceptionListItemSchema) => void }): Promise { + const abortCtrl = new AbortController(); + + try { + const item = await Api.fetchExceptionListItemById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(item); + } catch (error) { + onError(error); + } + }, + async getExceptionList({ + id, + namespaceType, + onSuccess, + onError, + }: ApiCallMemoProps & { onSuccess: (arg: ExceptionListSchema) => void }): Promise { + const abortCtrl = new AbortController(); + + try { + const list = await Api.fetchExceptionListById({ + http, + id, + namespaceType, + signal: abortCtrl.signal, + }); + onSuccess(list); + } catch (error) { + onError(error); + } + }, + }), + [http] + ); +}; diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx index a6a25ab4d4e9d..fbd43787a822e 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx @@ -10,7 +10,8 @@ import * as api from '../api'; import { createKibanaCoreStartMock } from '../../common/mocks/kibana_core'; import { getExceptionListSchemaMock } from '../../../common/schemas/response/exception_list_schema.mock'; import { getExceptionListItemSchemaMock } from '../../../common/schemas/response/exception_list_item_schema.mock'; -import { ExceptionListAndItems, UseExceptionListProps } from '../types'; +import { ExceptionListItemSchema } from '../../../common/schemas'; +import { ExceptionList, UseExceptionListProps } from '../types'; import { ReturnExceptionListAndItems, useExceptionList } from './use_exception_list'; @@ -34,15 +35,23 @@ describe('useExceptionList', () => { >(() => useExceptionList({ http: mockKibanaHttpService, - id: 'myListId', - namespaceType: 'single', + lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, }) ); await waitForNextUpdate(); - expect(result.current).toEqual([true, null, result.current[2]]); - expect(typeof result.current[2]).toEqual('function'); + expect(result.current).toEqual([ + true, + [], + [], + { + page: 1, + perPage: 20, + total: 0, + }, + null, + ]); }); }); @@ -54,27 +63,32 @@ describe('useExceptionList', () => { >(() => useExceptionList({ http: mockKibanaHttpService, - id: 'myListId', - namespaceType: 'single', + lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, }) ); await waitForNextUpdate(); await waitForNextUpdate(); - const expectedResult: ExceptionListAndItems = { - ...getExceptionListSchemaMock(), - exceptionItems: { - items: [{ ...getExceptionListItemSchemaMock() }], - pagination: { - page: 1, - perPage: 20, - total: 1, - }, - }, - }; + const expectedListResult: ExceptionList[] = [ + { ...getExceptionListSchemaMock(), totalItems: 1 }, + ]; + + const expectedListItemsResult: ExceptionListItemSchema[] = [ + { ...getExceptionListItemSchemaMock() }, + ]; - expect(result.current).toEqual([false, expectedResult, result.current[2]]); + expect(result.current).toEqual([ + false, + expectedListResult, + expectedListItemsResult, + { + page: 1, + perPage: 20, + total: 1, + }, + result.current[4], + ]); }); }); @@ -86,13 +100,12 @@ describe('useExceptionList', () => { UseExceptionListProps, ReturnExceptionListAndItems >( - ({ filterOptions, http, id, namespaceType, pagination, onError }) => - useExceptionList({ filterOptions, http, id, namespaceType, onError, pagination }), + ({ filterOptions, http, lists, pagination, onError }) => + useExceptionList({ filterOptions, http, lists, onError, pagination }), { initialProps: { http: mockKibanaHttpService, - id: 'myListId', - namespaceType: 'single', + lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, }, } @@ -100,8 +113,7 @@ describe('useExceptionList', () => { await waitForNextUpdate(); rerender({ http: mockKibanaHttpService, - id: 'newListId', - namespaceType: 'single', + lists: [{ id: 'newListId', namespaceType: 'single' }], onError: onErrorMock, }); await waitForNextUpdate(); @@ -121,14 +133,19 @@ describe('useExceptionList', () => { >(() => useExceptionList({ http: mockKibanaHttpService, - id: 'myListId', - namespaceType: 'single', + lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, }) ); await waitForNextUpdate(); await waitForNextUpdate(); - result.current[2](); + + expect(typeof result.current[4]).toEqual('function'); + + if (result.current[4] != null) { + result.current[4](); + } + await waitForNextUpdate(); expect(spyOnfetchExceptionListById).toHaveBeenCalledTimes(2); @@ -147,8 +164,7 @@ describe('useExceptionList', () => { () => useExceptionList({ http: mockKibanaHttpService, - id: 'myListId', - namespaceType: 'single', + lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, }) ); @@ -170,8 +186,7 @@ describe('useExceptionList', () => { () => useExceptionList({ http: mockKibanaHttpService, - id: 'myListId', - namespaceType: 'single', + lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, }) ); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx index 116233cd89348..1d7a63ba880bf 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx @@ -4,12 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useCallback, useEffect, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { fetchExceptionListById, fetchExceptionListItemsByListId } from '../api'; -import { ExceptionListAndItems, UseExceptionListProps } from '../types'; +import { ExceptionIdentifiers, ExceptionList, Pagination, UseExceptionListProps } from '../types'; +import { ExceptionListItemSchema } from '../../../common/schemas'; -export type ReturnExceptionListAndItems = [boolean, ExceptionListAndItems | null, () => void]; +type Func = () => void; +export type ReturnExceptionListAndItems = [ + boolean, + ExceptionList[], + ExceptionListItemSchema[], + Pagination, + Func | null +]; /** * Hook for using to get an ExceptionList and it's ExceptionListItems @@ -24,8 +32,7 @@ export type ReturnExceptionListAndItems = [boolean, ExceptionListAndItems | null */ export const useExceptionList = ({ http, - id, - namespaceType, + lists, pagination = { page: 1, perPage: 20, @@ -36,20 +43,37 @@ export const useExceptionList = ({ tags: [], }, onError, + dispatchListsInReducer, }: UseExceptionListProps): ReturnExceptionListAndItems => { - const [exceptionListAndItems, setExceptionList] = useState(null); - const [shouldRefresh, setRefresh] = useState(true); - const refreshExceptionList = useCallback(() => setRefresh(true), [setRefresh]); + const [exceptionLists, setExceptionLists] = useState([]); + const [exceptionItems, setExceptionListItems] = useState([]); + const [paginationInfo, setPagination] = useState(pagination); + const fetchExceptionList = useRef(null); const [loading, setLoading] = useState(true); - const tags = filterOptions.tags.sort().join(); + const tags = useMemo(() => filterOptions.tags.sort().join(), [filterOptions.tags]); + const listIds = useMemo( + () => + lists + .map((t) => t.id) + .sort() + .join(), + [lists] + ); useEffect( () => { - let isSubscribed = true; - const abortCtrl = new AbortController(); + let isSubscribed = false; + let abortCtrl: AbortController; + + const fetchLists = async (): Promise => { + isSubscribed = true; + abortCtrl = new AbortController(); - const fetchData = async (idToFetch: string): Promise => { - if (shouldRefresh) { + // TODO: workaround until api updated, will be cleaned up + let exceptions: ExceptionListItemSchema[] = []; + let exceptionListsReturned: ExceptionList[] = []; + + const fetchData = async ({ id, namespaceType }: ExceptionIdentifiers): Promise => { try { setLoading(true); @@ -59,7 +83,7 @@ export const useExceptionList = ({ ...restOfExceptionList } = await fetchExceptionListById({ http, - id: idToFetch, + id, namespaceType, signal: abortCtrl.signal, }); @@ -72,40 +96,68 @@ export const useExceptionList = ({ signal: abortCtrl.signal, }); - setRefresh(false); - if (isSubscribed) { - setExceptionList({ - list_id, - namespace_type, - ...restOfExceptionList, - exceptionItems: { - items: [...fetchListItemsResult.data], + exceptionListsReturned = [ + ...exceptionListsReturned, + { + list_id, + namespace_type, + ...restOfExceptionList, + totalItems: fetchListItemsResult.total, + }, + ]; + setExceptionLists(exceptionListsReturned); + setPagination({ + page: fetchListItemsResult.page, + perPage: fetchListItemsResult.per_page, + total: fetchListItemsResult.total, + }); + + exceptions = [...exceptions, ...fetchListItemsResult.data]; + setExceptionListItems(exceptions); + + if (dispatchListsInReducer != null) { + dispatchListsInReducer({ + exceptions, + lists: exceptionListsReturned, pagination: { page: fetchListItemsResult.page, perPage: fetchListItemsResult.per_page, total: fetchListItemsResult.total, }, - }, - }); + }); + } } } catch (error) { - setRefresh(false); if (isSubscribed) { - setExceptionList(null); + setExceptionLists([]); + setExceptionListItems([]); + setPagination({ + page: 1, + perPage: 20, + total: 0, + }); onError(error); } } - } + }; + + // TODO: Workaround for now. Once api updated, we can pass in array of lists to fetch + await Promise.all( + lists.map( + ({ id, namespaceType }: ExceptionIdentifiers): Promise => + fetchData({ id, namespaceType }) + ) + ); if (isSubscribed) { setLoading(false); } }; - if (id != null) { - fetchData(id); - } + fetchLists(); + + fetchExceptionList.current = fetchLists; return (): void => { isSubscribed = false; abortCtrl.abort(); @@ -113,9 +165,9 @@ export const useExceptionList = ({ }, // eslint-disable-next-line react-hooks/exhaustive-deps [ http, - id, - onError, - shouldRefresh, + listIds, + setExceptionLists, + setExceptionListItems, pagination.page, pagination.perPage, filterOptions.filter, @@ -123,5 +175,5 @@ export const useExceptionList = ({ ] ); - return [loading, exceptionListAndItems, refreshExceptionList]; + return [loading, exceptionLists, exceptionItems, paginationInfo, fetchExceptionList.current]; }; diff --git a/x-pack/plugins/lists/public/exceptions/types.ts b/x-pack/plugins/lists/public/exceptions/types.ts index cf6b6c3ec1c59..286eb0570ebb8 100644 --- a/x-pack/plugins/lists/public/exceptions/types.ts +++ b/x-pack/plugins/lists/public/exceptions/types.ts @@ -24,15 +24,6 @@ export interface Pagination { total: number; } -export interface ExceptionItemsAndPagination { - items: ExceptionListItemSchema[]; - pagination: Pagination; -} - -export interface ExceptionListAndItems extends ExceptionListSchema { - exceptionItems: ExceptionItemsAndPagination; -} - export type AddExceptionList = ExceptionListSchema | CreateExceptionListSchemaPartial; export type AddExceptionListItem = CreateExceptionListItemSchemaPartial | ExceptionListItemSchema; @@ -42,13 +33,31 @@ export interface PersistHookProps { onError: (arg: Error) => void; } +export interface ExceptionList extends ExceptionListSchema { + totalItems: number; +} + export interface UseExceptionListProps { - filterOptions?: FilterExceptionsOptions; http: HttpStart; - id: string | undefined; - namespaceType: NamespaceType; + lists: ExceptionIdentifiers[]; onError: (arg: Error) => void; + filterOptions?: FilterExceptionsOptions; pagination?: Pagination; + dispatchListsInReducer?: ({ + lists, + exceptions, + pagination, + }: { + lists: ExceptionList[]; + exceptions: ExceptionListItemSchema[]; + pagination: Pagination; + }) => void; +} + +export interface ExceptionIdentifiers { + id: string; + namespaceType: NamespaceType; + type?: string; } export interface ApiCallByListIdProps { @@ -67,6 +76,13 @@ export interface ApiCallByIdProps { signal: AbortSignal; } +export interface ApiCallMemoProps { + id: string; + namespaceType: NamespaceType; + onError: (arg: Error) => void; + onSuccess: () => void; +} + export interface AddExceptionListProps { http: HttpStart; list: AddExceptionList; diff --git a/x-pack/plugins/lists/public/index.tsx b/x-pack/plugins/lists/public/index.tsx index fb4d5de06ae54..1e25275a0d38b 100644 --- a/x-pack/plugins/lists/public/index.tsx +++ b/x-pack/plugins/lists/public/index.tsx @@ -4,7 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ // Exports to be shared with plugins +export { useApi } from './exceptions/hooks/use_api'; export { usePersistExceptionItem } from './exceptions/hooks/persist_exception_item'; export { usePersistExceptionList } from './exceptions/hooks/persist_exception_list'; export { useExceptionList } from './exceptions/hooks/use_exception_list'; +export { ExceptionList, ExceptionIdentifiers } from './exceptions/types'; export { mockNewExceptionItem, mockNewExceptionList } from './exceptions/mock'; diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json b/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json new file mode 100644 index 0000000000000..306195f4226e3 --- /dev/null +++ b/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_detection.json @@ -0,0 +1,9 @@ +{ + "list_id": "detection_list", + "_tags": ["detection"], + "tags": ["detection", "sample_tag"], + "type": "detection", + "description": "This is a sample detection type exception list", + "name": "Sample Detection Exception List", + "namespace_type": "single" +} diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json b/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json index d68a26eb8ffe2..c89c7a8f080cf 100644 --- a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json +++ b/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_auto_id.json @@ -5,6 +5,7 @@ "type": "simple", "description": "This is a sample endpoint type exception that has no item_id so it creates a new id each time", "name": "Sample Endpoint Exception List", + "comment": [], "entries": [ { "field": "actingProcess.file.signer", diff --git a/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json b/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json new file mode 100644 index 0000000000000..3fe4458a73769 --- /dev/null +++ b/x-pack/plugins/lists/server/scripts/exception_lists/new/exception_list_item_detection_auto_id.json @@ -0,0 +1,26 @@ +{ + "list_id": "detection_list", + "_tags": ["detection"], + "tags": ["test_tag", "detection", "no_more_bad_guys"], + "type": "simple", + "description": "This is a sample detection type exception that has no item_id so it creates a new id each time", + "name": "Sample Detection Exception List Item", + "comment": [], + "entries": [ + { + "field": "host.name", + "operator": "included", + "match": "sampleHostName" + }, + { + "field": "event.category", + "operator": "included", + "match_any": ["process", "malware"] + }, + { + "field": "event.action", + "operator": "included", + "match": "user-password-change" + } + ] +} diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx index 43792e8bd19f4..0e527bf4dfc72 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx @@ -5,6 +5,7 @@ */ /* eslint-disable react-hooks/rules-of-hooks */ +/* eslint-disable complexity */ import { EuiButton, @@ -70,10 +71,13 @@ import { FailureHistory } from './failure_history'; import { RuleStatus } from '../../../../components/rules//rule_status'; import { useMlCapabilities } from '../../../../../common/components/ml_popover/hooks/use_ml_capabilities'; import { hasMlAdminPermissions } from '../../../../../../common/machine_learning/has_ml_admin_permissions'; +import { ExceptionsViewer } from '../../../../../common/components/exceptions/viewer'; +import { ExceptionListType } from '../../../../../common/components/exceptions/types'; enum RuleDetailTabs { alerts = 'alerts', failures = 'failures', + exceptions = 'exceptions', } const ruleDetailTabs = [ @@ -82,6 +86,11 @@ const ruleDetailTabs = [ name: detectionI18n.ALERT, disabled: false, }, + { + id: RuleDetailTabs.exceptions, + name: i18n.EXCEPTIONS_TAB, + disabled: false, + }, { id: RuleDetailTabs.failures, name: i18n.FAILURE_HISTORY_TAB, @@ -387,6 +396,17 @@ export const RuleDetailsPageComponent: FC = ({ )} )} + {ruleDetailTab === RuleDetailTabs.exceptions && ( + + )} {ruleDetailTab === RuleDetailTabs.failures && } diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/translations.ts b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/translations.ts index 9cf510f4a9b5d..94dfdc3e9daa0 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/translations.ts +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/translations.ts @@ -89,3 +89,10 @@ export const TYPE_FAILED = i18n.translate( defaultMessage: 'Failed', } ); + +export const EXCEPTIONS_TAB = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.exceptionsTab', + { + defaultMessage: 'Exceptions', + } +); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/index.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx similarity index 86% rename from x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/index.stories.tsx rename to x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx index b6620ed103bc8..8942832798a5e 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/index.stories.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx @@ -8,15 +8,15 @@ import React from 'react'; import { ThemeProvider } from 'styled-components'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; -import { ExceptionItem } from '../viewer'; +import { ExceptionItem } from '../viewer/exception_item'; import { Operator } from '../types'; import { getExceptionItemMock } from '../mocks'; -storiesOf('components/exceptions', module) - .add('ExceptionItem/with os', () => { +storiesOf('ExceptionItem', module) + .add('with os', () => { const payload = getExceptionItemMock(); payload.description = ''; - payload.comments = []; + payload.comment = []; payload.entries = [ { field: 'actingProcess.file.signer', @@ -29,6 +29,7 @@ storiesOf('components/exceptions', module) return ( ({ eui: euiLightVars, darkMode: false })}> {}} @@ -37,10 +38,10 @@ storiesOf('components/exceptions', module) ); }) - .add('ExceptionItem/with description', () => { + .add('with description', () => { const payload = getExceptionItemMock(); payload._tags = []; - payload.comments = []; + payload.comment = []; payload.entries = [ { field: 'actingProcess.file.signer', @@ -53,6 +54,7 @@ storiesOf('components/exceptions', module) return ( ({ eui: euiLightVars, darkMode: false })}> {}} @@ -61,7 +63,7 @@ storiesOf('components/exceptions', module) ); }) - .add('ExceptionItem/with comments', () => { + .add('with comments', () => { const payload = getExceptionItemMock(); payload._tags = []; payload.description = ''; @@ -77,6 +79,7 @@ storiesOf('components/exceptions', module) return ( ({ eui: euiLightVars, darkMode: false })}> {}} @@ -85,15 +88,16 @@ storiesOf('components/exceptions', module) ); }) - .add('ExceptionItem/with nested entries', () => { + .add('with nested entries', () => { const payload = getExceptionItemMock(); payload._tags = []; payload.description = ''; - payload.comments = []; + payload.comment = []; return ( ({ eui: euiLightVars, darkMode: false })}> {}} @@ -102,12 +106,13 @@ storiesOf('components/exceptions', module) ); }) - .add('ExceptionItem/with everything', () => { + .add('with everything', () => { const payload = getExceptionItemMock(); return ( ({ eui: euiLightVars, darkMode: false })}> {}} diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx new file mode 100644 index 0000000000000..29cded8f69165 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx @@ -0,0 +1,70 @@ +/* + * 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 { storiesOf } from '@storybook/react'; +import React from 'react'; +import { ThemeProvider } from 'styled-components'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { ExceptionsViewerHeader } from '../viewer/exceptions_viewer_header'; +import { ExceptionListType } from '../types'; + +storiesOf('ExceptionsViewerHeader', module) + .add('loading', () => { + return ( + ({ eui: euiLightVars, darkMode: false })}> + {}} + onAddExceptionClick={() => {}} + /> + + ); + }) + .add('all lists', () => { + return ( + ({ eui: euiLightVars, darkMode: false })}> + {}} + onAddExceptionClick={() => {}} + /> + + ); + }) + .add('endpoint only', () => { + return ( + ({ eui: euiLightVars, darkMode: false })}> + {}} + onAddExceptionClick={() => {}} + /> + + ); + }) + .add('detections only', () => { + return ( + ({ eui: euiLightVars, darkMode: false })}> + {}} + onAddExceptionClick={() => {}} + /> + + ); + }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx index 223eabb0ea4ee..7698605588e76 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx @@ -439,7 +439,7 @@ describe('Exception helpers', () => { describe('#getFormattedComments', () => { test('it returns formatted comment object with username and timestamp', () => { - const payload = getExceptionItemMock().comments; + const payload = getExceptionItemMock().comment; const result = getFormattedComments(payload); expect(result[0].username).toEqual('user_name'); @@ -447,7 +447,7 @@ describe('Exception helpers', () => { }); test('it returns formatted timeline icon with comment users initial', () => { - const payload = getExceptionItemMock().comments; + const payload = getExceptionItemMock().comment; const result = getFormattedComments(payload); const wrapper = mount(result[0].timelineIcon as React.ReactElement); @@ -456,7 +456,7 @@ describe('Exception helpers', () => { }); test('it returns comment text', () => { - const payload = getExceptionItemMock().comments; + const payload = getExceptionItemMock().comment; const result = getFormattedComments(payload); const wrapper = mount(result[0].children as React.ReactElement); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/mocks.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/mocks.ts index 15aec3533b325..0dba3fd26c487 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/mocks.ts +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/mocks.ts @@ -11,6 +11,25 @@ import { NestedExceptionEntry, FormattedEntry, } from './types'; +import { ExceptionList } from '../../../lists_plugin_deps'; + +export const getExceptionListMock = (): ExceptionList => ({ + id: '5b543420', + created_at: '2020-04-23T00:19:13.289Z', + created_by: 'user_name', + list_id: 'test-exception', + tie_breaker_id: '77fd1909-6786-428a-a671-30229a719c1f', + updated_at: '2020-04-23T00:19:13.289Z', + updated_by: 'user_name', + namespace_type: 'single', + name: '', + description: 'This is a description', + _tags: ['os:windows'], + tags: [], + type: 'endpoint', + meta: {}, + totalItems: 0, +}); export const getExceptionItemEntryMock = (): ExceptionEntry => ({ field: 'actingProcess.file.signer', @@ -44,7 +63,7 @@ export const getExceptionItemMock = (): ExceptionListItemSchema => ({ namespace_type: 'single', name: '', description: 'This is a description', - comments: [ + comment: [ { user: 'user_name', timestamp: '2020-04-23T00:19:13.289Z', diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts index 704849430daf9..23e9f64caf695 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts @@ -5,6 +5,17 @@ */ import { i18n } from '@kbn/i18n'; +export const DETECTION_LIST = i18n.translate( + 'xpack.securitySolution.exceptions.detectionListLabel', + { + defaultMessage: 'Detection list', + } +); + +export const ENDPOINT_LIST = i18n.translate('xpack.securitySolution.exceptions.endpointListLabel', { + defaultMessage: 'Endpoint list', +}); + export const EDIT = i18n.translate('xpack.securitySolution.exceptions.editButtonLabel', { defaultMessage: 'Edit', }); @@ -47,3 +58,82 @@ export const OPERATING_SYSTEM = i18n.translate( defaultMessage: 'OS', } ); + +export const SEARCH_DEFAULT = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.searchDefaultPlaceholder', + { + defaultMessage: 'Search field (ex: host.name)', + } +); + +export const ADD_EXCEPTION_LABEL = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.addExceptionLabel', + { + defaultMessage: 'Add new exception', + } +); + +export const ADD_TO_ENDPOINT_LIST = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.addToEndpointListLabel', + { + defaultMessage: 'Add to endpoint list', + } +); + +export const ADD_TO_DETECTIONS_LIST = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel', + { + defaultMessage: 'Add to detections list', + } +); + +export const EXCEPTION_EMPTY_PROMPT_TITLE = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.emptyPromptTitle', + { + defaultMessage: 'You have no exceptions', + } +); + +export const EXCEPTION_EMPTY_PROMPT_BODY = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.emptyPromptBody', + { + defaultMessage: + 'You can add an exception to fine tune the rule so that it suppresses alerts that meet specified conditions. Exceptions leverage detection accuracy, which can help reduce the number of false positives.', + } +); + +export const FETCH_LIST_ERROR = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.fetchingListError', + { + defaultMessage: 'Error fetching exceptions', + } +); + +export const DELETE_EXCEPTION_ERROR = i18n.translate( + 'xpack.securitySolution.exceptions.viewer.deleteExceptionError', + { + defaultMessage: 'Error deleting exception', + } +); + +export const ITEMS_PER_PAGE = (items: number) => + i18n.translate('xpack.securitySolution.exceptions.exceptionsPaginationLabel', { + values: { items }, + defaultMessage: 'Items per page: {items}', + }); + +export const NUMBER_OF_ITEMS = (items: number) => + i18n.translate('xpack.securitySolution.exceptions.paginationNumberOfItemsLabel', { + values: { items }, + defaultMessage: '{items} items', + }); + +export const REFRESH = i18n.translate('xpack.securitySolution.exceptions.utilityRefreshLabel', { + defaultMessage: 'Refresh', +}); + +export const SHOWING_EXCEPTIONS = (items: number) => + i18n.translate('xpack.securitySolution.exceptions.utilityNumberExceptionsLabel', { + values: { items }, + defaultMessage: 'Showing {items} exceptions', + }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts index e8393610e459d..d60d1ef71e502 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/types.ts @@ -5,6 +5,12 @@ */ import { ReactNode } from 'react'; +import { + NamespaceType, + ExceptionList, + ExceptionListItemSchema as ExceptionItem, +} from '../../../lists_plugin_deps'; + export interface OperatorOption { message: string; value: string; @@ -56,10 +62,51 @@ export interface Comment { comment: string; } +export enum ExceptionListType { + DETECTION_ENGINE = 'detection', + ENDPOINT = 'endpoint', +} + +export interface FilterOptions { + filter: string; + showDetectionsList: boolean; + showEndpointList: boolean; + tags: string[]; +} + +export interface Filter { + filter: Partial; + pagination: Partial; +} + +export interface SetExceptionsProps { + lists: ExceptionList[]; + exceptions: ExceptionItem[]; + pagination: Pagination; +} + +export interface ApiProps { + id: string; + namespaceType: NamespaceType; +} + +export interface Pagination { + page: number; + perPage: number; + total: number; +} + +export interface ExceptionsPagination { + pageIndex: number; + pageSize: number; + totalItemCount: number; + pageSizeOptions: number[]; +} + // TODO: Delete once types are updated export interface ExceptionListItemSchema { _tags: string[]; - comments: Comment[]; + comment: Comment[]; created_at: string; created_by: string; description?: string; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_details.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.test.tsx similarity index 98% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_details.test.tsx rename to x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.test.tsx index 536d005c57b6e..c5d2ffc7ac2bf 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_details.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.test.tsx @@ -11,7 +11,7 @@ import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; import moment from 'moment-timezone'; import { ExceptionDetails } from './exception_details'; -import { getExceptionItemMock } from '../mocks'; +import { getExceptionItemMock } from '../../mocks'; describe('ExceptionDetails', () => { beforeEach(() => { @@ -24,7 +24,7 @@ describe('ExceptionDetails', () => { test('it renders no comments button if no comments exist', () => { const exceptionItem = getExceptionItemMock(); - exceptionItem.comments = []; + exceptionItem.comment = []; const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> @@ -77,7 +77,7 @@ describe('ExceptionDetails', () => { test('it renders comments plural if more than one', () => { const exceptionItem = getExceptionItemMock(); - exceptionItem.comments = [ + exceptionItem.comment = [ { user: 'user_1', timestamp: '2020-04-23T00:19:13.289Z', diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_details.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx similarity index 85% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_details.tsx rename to x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx index 8745e80a21548..6f418808b239a 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_details.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx @@ -9,9 +9,9 @@ import React, { useMemo } from 'react'; import styled, { css } from 'styled-components'; import { transparentize } from 'polished'; -import { ExceptionListItemSchema } from '../types'; -import { getDescriptionListContent } from '../helpers'; -import * as i18n from '../translations'; +import { ExceptionListItemSchema } from '../../types'; +import { getDescriptionListContent } from '../../helpers'; +import * as i18n from '../../translations'; const StyledExceptionDetails = styled(EuiFlexItem)` ${({ theme }) => css` @@ -40,8 +40,9 @@ const ExceptionDetailsComponent = ({ const descriptionList = useMemo(() => getDescriptionListContent(exceptionItem), [exceptionItem]); const commentsSection = useMemo((): JSX.Element => { - const { comments } = exceptionItem; - if (comments.length > 0) { + // TODO: return back to exceptionItem.comments once updated + const { comment } = exceptionItem; + if (comment.length > 0) { return ( - {!showComments - ? i18n.COMMENTS_SHOW(comments.length) - : i18n.COMMENTS_HIDE(comments.length)} + {!showComments ? i18n.COMMENTS_SHOW(comment.length) : i18n.COMMENTS_HIDE(comment.length)} ); } else { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_entries.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx similarity index 94% rename from x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_entries.test.tsx rename to x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx index e0c62f51d032a..10f11231ace01 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_entries.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx @@ -10,14 +10,15 @@ import { mount } from 'enzyme'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; import { ExceptionEntries } from './exception_entries'; -import { getFormattedEntryMock } from '../mocks'; -import { getEmptyValue } from '../../empty_value'; +import { getFormattedEntryMock } from '../../mocks'; +import { getEmptyValue } from '../../../empty_value'; describe('ExceptionEntries', () => { test('it does NOT render the and badge if only one exception item entry exists', () => { const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> { const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> { const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> { const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> { const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> { const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> theme.eui.euiSize}; @@ -47,12 +47,14 @@ const AndOrBadgeContainer = styled(EuiFlexItem)` interface ExceptionEntriesComponentProps { entries: FormattedEntry[]; + disableDelete: boolean; handleDelete: () => void; handleEdit: () => void; } const ExceptionEntriesComponent = ({ entries, + disableDelete, handleDelete, handleEdit, }: ExceptionEntriesComponentProps): JSX.Element => { @@ -141,6 +143,7 @@ const ExceptionEntriesComponent = ({ size="s" color="primary" onClick={handleEdit} + isDisabled={disableDelete} data-test-subj="exceptionsViewerEditBtn" > {i18n.EDIT} @@ -151,6 +154,7 @@ const ExceptionEntriesComponent = ({ size="s" color="danger" onClick={handleDelete} + isLoading={disableDelete} data-test-subj="exceptionsViewerDeleteBtn" > {i18n.REMOVE} diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx new file mode 100644 index 0000000000000..784fc4336a5ff --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { ThemeProvider } from 'styled-components'; +import { mount } from 'enzyme'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { ExceptionItem } from './'; +import { getExceptionItemMock } from '../../mocks'; + +describe('ExceptionItem', () => { + it('it renders ExceptionDetails and ExceptionEntries', () => { + const exceptionItem = getExceptionItemMock(); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('ExceptionDetails')).toHaveLength(1); + expect(wrapper.find('ExceptionEntries')).toHaveLength(1); + }); + + it('it invokes "handleEdit" when edit button clicked', () => { + const mockHandleEdit = jest.fn(); + const exceptionItem = getExceptionItemMock(); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button').at(0); + editBtn.simulate('click'); + + expect(mockHandleEdit).toHaveBeenCalledTimes(1); + }); + + it('it invokes "handleDelete" when delete button clicked', () => { + const mockHandleDelete = jest.fn(); + const exceptionItem = getExceptionItemMock(); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + const editBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0); + editBtn.simulate('click'); + + expect(mockHandleDelete).toHaveBeenCalledTimes(1); + }); + + it('it renders comment accordion closed to begin with', () => { + const mockHandleDelete = jest.fn(); + const exceptionItem = getExceptionItemMock(); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('.euiAccordion-isOpen')).toHaveLength(0); + }); + + it('it renders comment accordion open when showComments is true', () => { + const mockHandleDelete = jest.fn(); + const exceptionItem = getExceptionItemMock(); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + const commentsBtn = wrapper + .find('.euiButtonEmpty[data-test-subj="exceptionsViewerItemCommentsBtn"]') + .at(0); + commentsBtn.simulate('click'); + + expect(wrapper.find('.euiAccordion-isOpen')).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx new file mode 100644 index 0000000000000..386ab6f3c3c7c --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx @@ -0,0 +1,112 @@ +/* + * 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 { + EuiPanel, + EuiFlexGroup, + EuiCommentProps, + EuiCommentList, + EuiAccordion, + EuiFlexItem, +} from '@elastic/eui'; +import React, { useEffect, useState, useMemo, useCallback } from 'react'; +import styled from 'styled-components'; + +import { ExceptionDetails } from './exception_details'; +import { ExceptionEntries } from './exception_entries'; +import { getFormattedEntries, getFormattedComments } from '../../helpers'; +import { FormattedEntry, ExceptionListItemSchema, ApiProps } from '../../types'; + +const MyFlexItem = styled(EuiFlexItem)` + &.comments--show { + padding: ${({ theme }) => theme.eui.euiSize}; + border-top: ${({ theme }) => `${theme.eui.euiBorderThin}`} + +`; + +interface ExceptionItemProps { + loadingItemIds: ApiProps[]; + exceptionItem: ExceptionListItemSchema; + commentsAccordionId: string; + handleDelete: (arg: ApiProps) => void; + handleEdit: (item: ExceptionListItemSchema) => void; +} + +const ExceptionItemComponent = ({ + loadingItemIds, + exceptionItem, + commentsAccordionId, + handleDelete, + handleEdit, +}: ExceptionItemProps): JSX.Element => { + const [entryItems, setEntryItems] = useState([]); + const [showComments, setShowComments] = useState(false); + + useEffect((): void => { + const formattedEntries = getFormattedEntries(exceptionItem.entries); + setEntryItems(formattedEntries); + }, [exceptionItem.entries]); + + const onDelete = useCallback((): void => { + handleDelete({ id: exceptionItem.id, namespaceType: exceptionItem.namespace_type }); + }, [handleDelete, exceptionItem]); + + const onEdit = useCallback((): void => { + handleEdit(exceptionItem); + }, [handleEdit, exceptionItem]); + + const onCommentsClick = useCallback((): void => { + setShowComments(!showComments); + }, [setShowComments, showComments]); + + const formattedComments = useMemo((): EuiCommentProps[] => { + // TODO: return back to exceptionItem.comments once updated + return getFormattedComments(exceptionItem.comment); + }, [exceptionItem]); + + const disableDelete = useMemo((): boolean => { + const foundItems = loadingItemIds.filter((t) => t.id === exceptionItem.id); + return foundItems.length > 0; + }, [loadingItemIds, exceptionItem.id]); + + return ( + + + + + + + + + + + + + + + + ); +}; + +ExceptionItemComponent.displayName = 'ExceptionItemComponent'; + +export const ExceptionItem = React.memo(ExceptionItemComponent); + +ExceptionItem.displayName = 'ExceptionItem'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.test.tsx new file mode 100644 index 0000000000000..dcc8611cd7298 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.test.tsx @@ -0,0 +1,158 @@ +/* + * 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 { ThemeProvider } from 'styled-components'; +import { mount } from 'enzyme'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { ExceptionsViewerPagination } from './exceptions_pagination'; + +describe('ExceptionsViewerPagination', () => { + it('it renders passed in "pageSize" as selected option', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsPerPageBtn"]').at(0).text()).toEqual( + 'Items per page: 50' + ); + }); + + it('it renders all passed in page size options when per page button clicked', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsPerPageBtn"] button').simulate('click'); + + expect(wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(0).text()).toEqual( + '20 items' + ); + expect(wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(1).text()).toEqual( + '50 items' + ); + expect(wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(2).text()).toEqual( + '100 items' + ); + }); + + it('it invokes "onPaginationChange" when per page item is clicked', () => { + const mockOnPaginationChange = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsPerPageBtn"] button').simulate('click'); + wrapper.find('button[data-test-subj="exceptionsPerPageItem"]').at(0).simulate('click'); + + expect(mockOnPaginationChange).toHaveBeenCalledWith({ + filter: {}, + pagination: { pageIndex: 0, pageSize: 20, totalItemCount: 1 }, + }); + }); + + it('it renders correct total page count', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsPagination"]').at(0).prop('pageCount')).toEqual( + 4 + ); + expect( + wrapper.find('[data-test-subj="exceptionsPagination"]').at(0).prop('activePage') + ).toEqual(0); + }); + + it('it invokes "onPaginationChange" when next clicked', () => { + const mockOnPaginationChange = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="pagination-button-next"]').at(1).simulate('click'); + + expect(mockOnPaginationChange).toHaveBeenCalledWith({ + filter: {}, + pagination: { pageIndex: 2, pageSize: 50, totalItemCount: 160 }, + }); + }); + + it('it invokes "onPaginationChange" when page clicked', () => { + const mockOnPaginationChange = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('button[data-test-subj="pagination-button-3"]').simulate('click'); + + expect(mockOnPaginationChange).toHaveBeenCalledWith({ + filter: {}, + pagination: { pageIndex: 4, pageSize: 50, totalItemCount: 160 }, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx new file mode 100644 index 0000000000000..0953a5c666c5d --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx @@ -0,0 +1,123 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { ReactElement, useCallback, useState, useMemo } from 'react'; +import { + EuiContextMenuItem, + EuiButtonEmpty, + EuiPagination, + EuiFlexItem, + EuiFlexGroup, + EuiPopover, + EuiContextMenuPanel, +} from '@elastic/eui'; + +import * as i18n from '../translations'; +import { ExceptionsPagination, Filter } from '../types'; + +interface ExceptionsViewerPaginationProps { + pagination: ExceptionsPagination; + onPaginationChange: (arg: Filter) => void; +} + +const ExceptionsViewerPaginationComponent = ({ + pagination, + onPaginationChange, +}: ExceptionsViewerPaginationProps): JSX.Element => { + const [isOpen, setIsOpen] = useState(false); + + const closePerPageMenu = useCallback((): void => setIsOpen(false), [setIsOpen]); + + const onPerPageMenuClick = useCallback((): void => setIsOpen((isPopoverOpen) => !isPopoverOpen), [ + setIsOpen, + ]); + + const onPageClick = useCallback( + (pageIndex: number): void => { + onPaginationChange({ + filter: {}, + pagination: { + pageIndex: pageIndex + 1, + pageSize: pagination.pageSize, + totalItemCount: pagination.totalItemCount, + }, + }); + }, + [pagination, onPaginationChange] + ); + + const items = useMemo((): ReactElement[] => { + return pagination.pageSizeOptions.map((rows) => ( + { + onPaginationChange({ + filter: {}, + pagination: { + pageIndex: pagination.pageIndex, + pageSize: rows, + totalItemCount: pagination.totalItemCount, + }, + }); + closePerPageMenu(); + }} + data-test-subj="exceptionsPerPageItem" + > + {i18n.NUMBER_OF_ITEMS(rows)} + + )); + }, [pagination, onPaginationChange, closePerPageMenu]); + + const totalPages = useMemo((): number => { + if (pagination.totalItemCount > 0) { + return Math.ceil(pagination.totalItemCount / pagination.pageSize); + } else { + return 1; + } + }, [pagination]); + + return ( + + + + {i18n.ITEMS_PER_PAGE(pagination.pageSize)} + + } + isOpen={isOpen} + closePopover={closePerPageMenu} + panelPaddingSize="none" + > + + + + + + + + + ); +}; + +ExceptionsViewerPaginationComponent.displayName = 'ExceptionsViewerPaginationComponent'; + +export const ExceptionsViewerPagination = React.memo(ExceptionsViewerPaginationComponent); + +ExceptionsViewerPagination.displayName = 'ExceptionsViewerPagination'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx new file mode 100644 index 0000000000000..bdc99370a6293 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx @@ -0,0 +1,337 @@ +/* + * 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 { ThemeProvider } from 'styled-components'; +import { mount } from 'enzyme'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { ExceptionsViewerHeader } from './exceptions_viewer_header'; +import { ExceptionListType } from '../types'; + +describe('ExceptionsViewerHeader', () => { + it('it renders all disabled if "isInitLoading" is true', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect( + wrapper.find('input[data-test-subj="exceptionsHeaderSearch"]').at(0).prop('disabled') + ).toBeTruthy(); + expect( + wrapper.find('[data-test-subj="exceptionsDetectionFilterBtn"] button').at(0).prop('disabled') + ).toBeTruthy(); + expect( + wrapper.find('[data-test-subj="exceptionsEndpointFilterBtn"] button').at(0).prop('disabled') + ).toBeTruthy(); + expect( + wrapper + .find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"] button') + .at(0) + .prop('disabled') + ).toBeTruthy(); + }); + + it('it displays toggles and add exception popover when more than one list type available', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsFilterGroupBtns"]').exists()).toBeTruthy(); + expect( + wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"]').exists() + ).toBeTruthy(); + }); + + it('it does not display toggles and add exception popover if only one list type is available', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsFilterGroupBtns"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"]')).toHaveLength( + 0 + ); + }); + + it('it displays add exception button without popover if only one list type is available', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect( + wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"]').exists() + ).toBeTruthy(); + }); + + it('it renders detections filter toggle selected when clicked', () => { + const mockOnFilterChange = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsDetectionFilterBtn"] button').simulate('click'); + + expect( + wrapper + .find('EuiFilterButton[data-test-subj="exceptionsDetectionFilterBtn"]') + .at(0) + .prop('hasActiveFilters') + ).toBeTruthy(); + expect( + wrapper + .find('EuiFilterButton[data-test-subj="exceptionsEndpointFilterBtn"]') + .at(0) + .prop('hasActiveFilters') + ).toBeFalsy(); + expect(mockOnFilterChange).toHaveBeenCalledWith({ + filter: { + filter: '', + showDetectionsList: true, + showEndpointList: false, + tags: [], + }, + pagination: {}, + }); + }); + + it('it renders endpoint filter toggle selected and invokes "onFilterChange" when clicked', () => { + const mockOnFilterChange = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsEndpointFilterBtn"] button').simulate('click'); + + expect( + wrapper + .find('EuiFilterButton[data-test-subj="exceptionsEndpointFilterBtn"]') + .at(0) + .prop('hasActiveFilters') + ).toBeTruthy(); + expect( + wrapper + .find('EuiFilterButton[data-test-subj="exceptionsDetectionFilterBtn"]') + .at(0) + .prop('hasActiveFilters') + ).toBeFalsy(); + expect(mockOnFilterChange).toHaveBeenCalledWith({ + filter: { + filter: '', + showDetectionsList: false, + showEndpointList: true, + tags: [], + }, + pagination: {}, + }); + }); + + it('it invokes "onAddExceptionClick" when user selects to add an exception item and only endpoint exception lists are available', () => { + const mockOnAddExceptionClick = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"] button').simulate('click'); + + expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); + }); + + it('it invokes "onAddDetectionsExceptionClick" when user selects to add an exception item and only endpoint detections lists are available', () => { + const mockOnAddExceptionClick = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsHeaderAddExceptionBtn"] button').simulate('click'); + + expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); + }); + + it('it invokes "onAddEndpointExceptionClick" when user selects to add an exception item to endpoint list from popover', () => { + const mockOnAddExceptionClick = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper + .find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"] button') + .simulate('click'); + wrapper.find('[data-test-subj="addEndpointExceptionBtn"] button').simulate('click'); + + expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); + }); + + it('it invokes "onAddDetectionsExceptionClick" when user selects to add an exception item to endpoint list from popover', () => { + const mockOnAddExceptionClick = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper + .find('[data-test-subj="exceptionsHeaderAddExceptionPopoverBtn"] button') + .simulate('click'); + wrapper.find('[data-test-subj="addDetectionsExceptionBtn"] button').simulate('click'); + + expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); + }); + + it('it invokes "onFilterChange" with filter value when search used', () => { + const mockOnFilterChange = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper + .find('input[data-test-subj="exceptionsHeaderSearch"]') + .at(0) + .simulate('change', { + target: { value: 'host' }, + }); + + expect(mockOnFilterChange).toHaveBeenCalledWith({ + filter: { + filter: 'host', + showDetectionsList: false, + showEndpointList: false, + tags: [], + }, + pagination: {}, + }); + }); + + it('it invokes "onFilterChange" with tags values when search value includes "tags:..."', () => { + const mockOnFilterChange = jest.fn(); + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper + .find('input[data-test-subj="exceptionsHeaderSearch"]') + .at(0) + .simulate('change', { + target: { value: 'tags:malware' }, + }); + + expect(mockOnFilterChange).toHaveBeenCalledWith({ + filter: { + filter: '', + showDetectionsList: false, + showEndpointList: false, + tags: ['malware'], + }, + pagination: {}, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx new file mode 100644 index 0000000000000..92a8830310b51 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx @@ -0,0 +1,204 @@ +/* + * 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 { + EuiFieldSearch, + EuiFlexGroup, + EuiFlexItem, + EuiPopover, + EuiContextMenu, + EuiButton, + EuiFilterGroup, + EuiFilterButton, + EuiContextMenuPanelDescriptor, +} from '@elastic/eui'; +import React, { useEffect, useState, useCallback, useMemo } from 'react'; + +import * as i18n from '../translations'; +import { ExceptionListType, Filter } from '../types'; + +interface ExceptionsViewerHeaderProps { + isInitLoading: boolean; + supportedListTypes: ExceptionListType[]; + detectionsListItems: number; + endpointListItems: number; + onFilterChange: (arg: Filter) => void; + onAddExceptionClick: (type: ExceptionListType) => void; +} + +/** + * Collection of filters and toggles for filtering exception items. + */ +const ExceptionsViewerHeaderComponent = ({ + isInitLoading, + supportedListTypes, + detectionsListItems, + endpointListItems, + onFilterChange, + onAddExceptionClick, +}: ExceptionsViewerHeaderProps): JSX.Element => { + const [filter, setFilter] = useState(''); + const [tags, setTags] = useState([]); + const [showDetectionsList, setShowDetectionsList] = useState(false); + const [showEndpointList, setShowEndpointList] = useState(false); + const [isAddExceptionMenuOpen, setAddExceptionMenuOpen] = useState(false); + + useEffect((): void => { + onFilterChange({ + filter: { filter, showDetectionsList, showEndpointList, tags }, + pagination: {}, + }); + }, [filter, tags, showDetectionsList, showEndpointList, onFilterChange]); + + const onAddExceptionDropdownClick = useCallback( + (): void => setAddExceptionMenuOpen(!isAddExceptionMenuOpen), + [setAddExceptionMenuOpen, isAddExceptionMenuOpen] + ); + + const handleDetectionsListClick = useCallback((): void => { + setShowDetectionsList(!showDetectionsList); + setShowEndpointList(false); + }, [showDetectionsList, setShowDetectionsList, setShowEndpointList]); + + const handleEndpointListClick = useCallback((): void => { + setShowEndpointList(!showEndpointList); + setShowDetectionsList(false); + }, [showEndpointList, setShowEndpointList, setShowDetectionsList]); + + const handleOnSearch = useCallback( + (event: React.ChangeEvent): void => { + const searchValue = event.target.value; + const tagsRegex = /(tags:[^\s]*)/i; + const tagsMatch = searchValue.match(tagsRegex); + const foundTags: string = tagsMatch != null ? tagsMatch[0].split(':')[1] : ''; + const filterString = tagsMatch != null ? searchValue.replace(tagsRegex, '') : searchValue; + + if (foundTags.length > 0) { + setTags(foundTags.split(',')); + } + + setFilter(filterString.trim()); + }, + [setTags, setFilter] + ); + + const onAddException = useCallback( + (type: ExceptionListType): void => { + onAddExceptionClick(type); + setAddExceptionMenuOpen(false); + }, + [onAddExceptionClick, setAddExceptionMenuOpen] + ); + + const addExceptionButtonOptions = useMemo( + (): EuiContextMenuPanelDescriptor[] => [ + { + id: 0, + items: [ + { + name: i18n.ADD_TO_ENDPOINT_LIST, + onClick: () => onAddException(ExceptionListType.ENDPOINT), + 'data-test-subj': 'addEndpointExceptionBtn', + }, + { + name: i18n.ADD_TO_DETECTIONS_LIST, + onClick: () => onAddException(ExceptionListType.DETECTION_ENGINE), + 'data-test-subj': 'addDetectionsExceptionBtn', + }, + ], + }, + ], + [onAddException] + ); + + return ( + + + + + + {supportedListTypes.length < 2 && ( + + onAddException(supportedListTypes[0])} + isDisabled={isInitLoading} + fill + > + {i18n.ADD_EXCEPTION_LABEL} + + + )} + + {supportedListTypes.length > 1 && ( + + + + + + {i18n.DETECTION_LIST} + {detectionsListItems != null ? ` (${detectionsListItems})` : ''} + + + {i18n.ENDPOINT_LIST} + {endpointListItems != null ? ` (${endpointListItems})` : ''} + + + + + + + {i18n.ADD_EXCEPTION_LABEL} + + } + isOpen={isAddExceptionMenuOpen} + closePopover={onAddExceptionDropdownClick} + anchorPosition="downCenter" + panelPaddingSize="none" + repositionOnScroll + > + + + + + + )} + + ); +}; + +ExceptionsViewerHeaderComponent.displayName = 'ExceptionsViewerHeaderComponent'; + +export const ExceptionsViewerHeader = React.memo(ExceptionsViewerHeaderComponent); + +ExceptionsViewerHeader.displayName = 'ExceptionsViewerHeader'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx index 7d3b7195def80..cc8e8111064bc 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx @@ -9,108 +9,120 @@ import { ThemeProvider } from 'styled-components'; import { mount } from 'enzyme'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; -import { ExceptionItem } from './'; -import { getExceptionItemMock } from '../mocks'; - -describe('ExceptionItem', () => { - it('it renders ExceptionDetails and ExceptionEntries', () => { - const exceptionItem = getExceptionItemMock(); - - const wrapper = mount( - ({ eui: euiLightVars, darkMode: false })}> - - - ); - - expect(wrapper.find('ExceptionDetails')).toHaveLength(1); - expect(wrapper.find('ExceptionEntries')).toHaveLength(1); - }); - - it('it invokes "handleEdit" when edit button clicked', () => { - const mockHandleEdit = jest.fn(); - const exceptionItem = getExceptionItemMock(); - - const wrapper = mount( - ({ eui: euiLightVars, darkMode: false })}> - - - ); - - const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button').at(0); - editBtn.simulate('click'); - - expect(mockHandleEdit).toHaveBeenCalledTimes(1); +import { ExceptionsViewer } from './'; +import { ExceptionListType } from '../types'; +import { useKibana } from '../../../../common/lib/kibana'; +import { useExceptionList, useApi } from '../../../../../public/lists_plugin_deps'; +import { getExceptionListMock } from '../mocks'; + +jest.mock('../../../../common/lib/kibana'); +jest.mock('../../../../../public/lists_plugin_deps'); + +describe('ExceptionsViewer', () => { + beforeEach(() => { + (useKibana as jest.Mock).mockReturnValue({ + services: { + http: {}, + application: { + getUrlForApp: () => 'some/url', + }, + }, + }); + + (useApi as jest.Mock).mockReturnValue({ + deleteExceptionItem: jest.fn().mockResolvedValue(true), + }); + + (useExceptionList as jest.Mock).mockReturnValue([ + false, + [], + [], + { + page: 1, + perPage: 20, + total: 0, + }, + jest.fn(), + ]); }); - it('it invokes "handleDelete" when delete button clicked', () => { - const mockHandleDelete = jest.fn(); - const exceptionItem = getExceptionItemMock(); - + it('it renders loader if "initLoading" is true', () => { + (useExceptionList as jest.Mock).mockReturnValue([ + true, + [], + [], + { + page: 1, + perPage: 20, + total: 0, + }, + jest.fn(), + ]); const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> - ); - const editBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0); - editBtn.simulate('click'); - - expect(mockHandleDelete).toHaveBeenCalledTimes(1); + expect(wrapper.find('[data-test-subj="loadingPanelAllRulesTable"]').exists()).toBeTruthy(); }); - it('it renders comment accordion closed to begin with', () => { - const mockHandleDelete = jest.fn(); - const exceptionItem = getExceptionItemMock(); - + it('it renders empty prompt if no "exceptionListMeta" passed in', () => { const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> - ); - expect(wrapper.find('.euiAccordion-isOpen')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); }); - it('it renders comment accordion open when showComments is true', () => { - const mockHandleDelete = jest.fn(); - const exceptionItem = getExceptionItemMock(); + it('it renders empty prompt if no exception items exist', () => { + (useExceptionList as jest.Mock).mockReturnValue([ + false, + [getExceptionListMock()], + [], + { + page: 1, + perPage: 20, + total: 0, + }, + jest.fn(), + ]); const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> - ); - const commentsBtn = wrapper - .find('.euiButtonEmpty[data-test-subj="exceptionsViewerItemCommentsBtn"]') - .at(0); - commentsBtn.simulate('click'); - - expect(wrapper.find('.euiAccordion-isOpen')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx index f4cdce62f56b3..ff52e395c3b1e 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx @@ -4,96 +4,412 @@ * you may not use this file except in compliance with the Elastic License. */ +import React, { useCallback, useState, useMemo, useEffect, useReducer } from 'react'; import { - EuiPanel, + EuiEmptyPrompt, + EuiText, + EuiLink, + EuiOverlayMask, + EuiModal, + EuiModalBody, + EuiCodeBlock, EuiFlexGroup, - EuiCommentProps, - EuiCommentList, - EuiAccordion, EuiFlexItem, + EuiSpacer, } from '@elastic/eui'; -import React, { useEffect, useState, useMemo, useCallback } from 'react'; +import { FormattedMessage } from 'react-intl'; import styled from 'styled-components'; +import uuid from 'uuid'; -import { ExceptionDetails } from './exception_details'; -import { ExceptionEntries } from './exception_entries'; -import { getFormattedEntries, getFormattedComments } from '../helpers'; -import { FormattedEntry, ExceptionListItemSchema } from '../types'; +import * as i18n from '../translations'; +import { useStateToaster } from '../../toasters'; +import { useKibana } from '../../../../common/lib/kibana'; +import { Panel } from '../../../../common/components/panel'; +import { Loader } from '../../../../common/components/loader'; +import { ExceptionsViewerHeader } from './exceptions_viewer_header'; +import { + ExceptionListType, + ExceptionListItemSchema, + ApiProps, + Filter, + SetExceptionsProps, +} from '../types'; +import { allExceptionItemsReducer, State } from './reducer'; +import { + useExceptionList, + ExceptionIdentifiers, + useApi, +} from '../../../../../public/lists_plugin_deps'; +import { ExceptionItem } from './exception_item'; +import { AndOrBadge } from '../../and_or_badge'; +import { ExceptionsViewerPagination } from './exceptions_pagination'; +import { + UtilityBar, + UtilityBarSection, + UtilityBarGroup, + UtilityBarText, + UtilityBarAction, +} from '../../utility_bar'; -const MyFlexItem = styled(EuiFlexItem)` - &.comments--show { - padding: ${({ theme }) => theme.eui.euiSize}; - border-top: ${({ theme }) => `${theme.eui.euiBorderThin}`} +const StyledText = styled(EuiText)` + font-style: italic; +`; +const MyExceptionsContainer = styled.div` + height: 600px; + overflow: hidden; `; -interface ExceptionItemProps { - exceptionItem: ExceptionListItemSchema; +const initialState: State = { + filterOptions: { filter: '', showEndpointList: false, showDetectionsList: false, tags: [] }, + pagination: { + pageIndex: 0, + pageSize: 20, + totalItemCount: 0, + pageSizeOptions: [5, 10, 20, 50, 100, 200, 300], + }, + endpointList: null, + detectionsList: null, + allExceptions: [], + exceptions: [], + exceptionToEdit: null, + loadingItemIds: [], + isModalOpen: false, +}; + +enum ModalAction { + CREATE = 'CREATE', + EDIT = 'EDIT', +} + +interface ExceptionsViewerProps { + ruleId: string; + exceptionListsMeta: ExceptionIdentifiers[]; + availableListTypes: ExceptionListType[]; commentsAccordionId: string; - handleDelete: ({ id }: { id: string }) => void; - handleEdit: (item: ExceptionListItemSchema) => void; + onAssociateList?: (listId: string) => void; } -const ExceptionItemComponent = ({ - exceptionItem, +const ExceptionsViewerComponent = ({ + ruleId, + exceptionListsMeta, + availableListTypes, + onAssociateList, commentsAccordionId, - handleDelete, - handleEdit, -}: ExceptionItemProps): JSX.Element => { - const [entryItems, setEntryItems] = useState([]); - const [showComments, setShowComments] = useState(false); +}: ExceptionsViewerProps): JSX.Element => { + const { services } = useKibana(); + const [, dispatchToaster] = useStateToaster(); + const [initLoading, setInitLoading] = useState(true); + const onDispatchToaster = useCallback( + ({ title, color, iconType }) => (): void => { + dispatchToaster({ + type: 'addToaster', + toast: { + id: uuid.v4(), + title, + color, + iconType, + }, + }); + }, + [dispatchToaster] + ); + const { deleteExceptionItem } = useApi(services.http); + const [ + { + endpointList, + detectionsList, + exceptions, + filterOptions, + pagination, + loadingItemIds, + isModalOpen, + }, + dispatch, + ] = useReducer(allExceptionItemsReducer(), initialState); - useEffect((): void => { - const formattedEntries = getFormattedEntries(exceptionItem.entries); - setEntryItems(formattedEntries); - }, [exceptionItem.entries]); + // TODO: Update icky typing once api updated + const setExceptions = useCallback( + ({ + lists: newLists, + exceptions: newExceptions, + pagination: newPagination, + }: SetExceptionsProps) => { + dispatch({ + type: 'setExceptions', + lists: newLists, + exceptions: (newExceptions as unknown) as ExceptionListItemSchema[], + pagination: newPagination, + }); + }, + [dispatch] + ); + const [loadingList, , , , fetchList] = useExceptionList({ + http: services.http, + lists: exceptionListsMeta, + filterOptions, + pagination: { + page: pagination.pageIndex + 1, + perPage: pagination.pageSize, + total: pagination.totalItemCount, + }, + dispatchListsInReducer: setExceptions, + onError: onDispatchToaster({ + color: 'danger', + title: i18n.FETCH_LIST_ERROR, + iconType: 'alert', + }), + }); - const onDelete = useCallback((): void => { - handleDelete({ id: exceptionItem.id }); - }, [handleDelete, exceptionItem]); + const setIsModalOpen = useCallback( + (isOpen: boolean): void => { + dispatch({ + type: 'updateModalOpen', + isOpen, + }); + }, + [dispatch] + ); + + const onFetchList = useCallback((): void => { + if (fetchList != null) { + fetchList(); + } + }, [fetchList]); + + const onFiltersChange = useCallback( + ({ filter, pagination: pag }: Filter): void => { + dispatch({ + type: 'updateFilterOptions', + filterOptions: filter, + pagination: pag, + }); + }, + [dispatch] + ); + + const onAddException = useCallback( + (type: ExceptionListType): void => { + setIsModalOpen(true); + }, + [setIsModalOpen] + ); + + const onEditExceptionItem = useCallback( + (exception: ExceptionListItemSchema): void => { + // TODO: Added this just for testing. Update + // modal state logic as needed once ready + dispatch({ + type: 'updateExceptionToEdit', + exception, + }); - const onEdit = useCallback((): void => { - handleEdit(exceptionItem); - }, [handleEdit, exceptionItem]); + setIsModalOpen(true); + }, + [setIsModalOpen] + ); - const onCommentsClick = useCallback((): void => { - setShowComments(!showComments); - }, [setShowComments, showComments]); + const onCloseExceptionModal = useCallback( + ({ actionType, listId }): void => { + setIsModalOpen(false); - const formattedComments = useMemo((): EuiCommentProps[] => { - return getFormattedComments(exceptionItem.comments); - }, [exceptionItem]); + // TODO: This callback along with fetchList can probably get + // passed to the modal for it to call itself maybe + if (actionType === ModalAction.CREATE && listId != null && onAssociateList != null) { + onAssociateList(listId); + } + + onFetchList(); + }, + [setIsModalOpen, onFetchList, onAssociateList] + ); + + const setLoadingItemIds = useCallback( + (items: ApiProps[]): void => { + dispatch({ + type: 'updateLoadingItemIds', + items, + }); + }, + [dispatch] + ); + + const onDeleteException = useCallback( + ({ id, namespaceType }: ApiProps) => { + deleteExceptionItem({ + id, + namespaceType, + onSuccess: () => { + setLoadingItemIds(loadingItemIds.filter((t) => t.id !== id)); + onFetchList(); + }, + onError: () => { + const dispatchToasterError = onDispatchToaster({ + color: 'danger', + title: i18n.DELETE_EXCEPTION_ERROR, + iconType: 'alert', + }); + + dispatchToasterError(); + setLoadingItemIds(loadingItemIds.filter((t) => t.id !== id)); + }, + }); + }, + [setLoadingItemIds, deleteExceptionItem, loadingItemIds, onFetchList, onDispatchToaster] + ); + + // Logic for initial render + useEffect((): void => { + if (initLoading && !loadingList && (exceptions.length === 0 || exceptions != null)) { + setInitLoading(false); + } + }, [initLoading, exceptions, loadingList]); + + const ruleSettingsUrl = useMemo((): string => { + return services.application.getUrlForApp( + `security#/detections/rules/id/${encodeURI(ruleId)}/edit` + ); + }, [ruleId, services.application]); + + const exceptionsSubtext = useMemo((): JSX.Element => { + if (filterOptions.showEndpointList) { + return ( + + + + ), + }} + /> + ); + } else if (filterOptions.showDetectionsList) { + return ( + + + + ), + }} + /> + ); + } else { + return <>; + } + }, [filterOptions.showEndpointList, filterOptions.showDetectionsList, ruleSettingsUrl]); + + const showEmpty = useMemo((): boolean => { + return !initLoading && !loadingList && exceptions.length === 0; + }, [initLoading, exceptions.length, loadingList]); return ( - - - - - + {isModalOpen && ( + + + + + {`Modal goes here`} + + + + + )} + + + {initLoading && } + + + + {(filterOptions.showEndpointList || filterOptions.showDetectionsList) && ( + <> + + {exceptionsSubtext} + + )} + + + + + + + + {i18n.SHOWING_EXCEPTIONS(pagination.totalItemCount ?? 0)} + + + + + + {i18n.REFRESH} + + + + + + + + + {showEmpty && ( + {i18n.EXCEPTION_EMPTY_PROMPT_TITLE}} + body={

{i18n.EXCEPTION_EMPTY_PROMPT_BODY}

} + data-test-subj="exceptionsEmptyPrompt" /> - + )} + + + + + {!initLoading && + exceptions.length > 0 && + exceptions.map((exception, index) => ( + + {index !== 0 && ( + <> + + + + )} + + + ))} -
- - - - - -
-
+ + + + ); }; -ExceptionItemComponent.displayName = 'ExceptionItemComponent'; +ExceptionsViewerComponent.displayName = 'ExceptionsViewerComponent'; -export const ExceptionItem = React.memo(ExceptionItemComponent); +export const ExceptionsViewer = React.memo(ExceptionsViewerComponent); -ExceptionItem.displayName = 'ExceptionItem'; +ExceptionsViewer.displayName = 'ExceptionsViewer'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts new file mode 100644 index 0000000000000..40d5bb5f0a297 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts @@ -0,0 +1,122 @@ +/* + * 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 { + ApiProps, + FilterOptions, + ExceptionsPagination, + ExceptionListItemSchema, + Pagination, +} from '../types'; +import { ExceptionList } from '../../../../../public/lists_plugin_deps'; + +export interface State { + filterOptions: FilterOptions; + pagination: ExceptionsPagination; + endpointList: ExceptionList | null; + detectionsList: ExceptionList | null; + allExceptions: ExceptionListItemSchema[]; + exceptions: ExceptionListItemSchema[]; + exceptionToEdit: ExceptionListItemSchema | null; + loadingItemIds: ApiProps[]; + isModalOpen: boolean; +} + +export type Action = + | { + type: 'setExceptions'; + lists: ExceptionList[]; + exceptions: ExceptionListItemSchema[]; + pagination: Pagination; + } + | { + type: 'updateFilterOptions'; + filterOptions: Partial; + pagination: Partial; + } + | { type: 'updateModalOpen'; isOpen: boolean } + | { type: 'updateExceptionToEdit'; exception: ExceptionListItemSchema } + | { type: 'updateLoadingItemIds'; items: ApiProps[] }; + +export const allExceptionItemsReducer = () => (state: State, action: Action): State => { + switch (action.type) { + case 'setExceptions': { + const endpointList = action.lists.filter((t) => t.type === 'endpoint'); + const detectionsList = action.lists.filter((t) => t.type === 'detection'); + + return { + ...state, + endpointList: state.filterOptions.showDetectionsList + ? state.endpointList + : endpointList[0] ?? null, + detectionsList: state.filterOptions.showEndpointList + ? state.detectionsList + : detectionsList[0] ?? null, + pagination: { + ...state.pagination, + pageIndex: action.pagination.page - 1, + pageSize: action.pagination.perPage, + totalItemCount: action.pagination.total, + }, + allExceptions: action.exceptions, + exceptions: action.exceptions, + }; + } + case 'updateFilterOptions': { + const returnState = { + ...state, + filterOptions: { + ...state.filterOptions, + ...action.filterOptions, + }, + pagination: { + ...state.pagination, + ...action.pagination, + }, + }; + + if (action.filterOptions.showEndpointList) { + const exceptions = state.allExceptions.filter((t) => t._tags.includes('endpoint')); + + return { + ...returnState, + exceptions, + }; + } else if (action.filterOptions.showDetectionsList) { + const exceptions = state.allExceptions.filter((t) => t._tags.includes('detection')); + + return { + ...returnState, + exceptions, + }; + } else { + return { + ...returnState, + exceptions: state.allExceptions, + }; + } + } + case 'updateLoadingItemIds': { + return { + ...state, + loadingItemIds: [...state.loadingItemIds, ...action.items], + }; + } + case 'updateExceptionToEdit': { + return { + ...state, + exceptionToEdit: action.exception, + }; + } + case 'updateModalOpen': { + return { + ...state, + isModalOpen: action.isOpen, + }; + } + default: + return state; + } +}; diff --git a/x-pack/plugins/security_solution/public/lists_plugin_deps.ts b/x-pack/plugins/security_solution/public/lists_plugin_deps.ts index 350b53ef52f4e..113bfaa860f00 100644 --- a/x-pack/plugins/security_solution/public/lists_plugin_deps.ts +++ b/x-pack/plugins/security_solution/public/lists_plugin_deps.ts @@ -5,10 +5,18 @@ */ export { + useApi, useExceptionList, usePersistExceptionItem, usePersistExceptionList, + ExceptionIdentifiers, + ExceptionList, mockNewExceptionItem, mockNewExceptionList, } from '../../lists/public'; -export { ExceptionListItemSchema, Entries } from '../../lists/common/schemas'; +export { + ExceptionListSchema, + ExceptionListItemSchema, + Entries, + NamespaceType, +} from '../../lists/common/schemas'; From d00e91a2e551363d94cfe402b0da199a1681e01c Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 9 Jun 2020 20:06:50 -0700 Subject: [PATCH 17/53] [skip test] apis Kerberos security Kerberos authentication finishing SPNEGO should properly set cookie and authenticate user https://github.com/elastic/kibana/issues/68720 Signed-off-by: Tyler Smalley --- .../kerberos_api_integration/apis/security/kerberos_login.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts index 926dcc95b5513..6a93b94920d6d 100644 --- a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts +++ b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts @@ -98,7 +98,8 @@ export default function ({ getService }: FtrProviderContext) { }); describe('finishing SPNEGO', () => { - it('should properly set cookie and authenticate user', async () => { + // Skipped: https://github.com/elastic/kibana/issues/68720 + it.skip('should properly set cookie and authenticate user', async () => { const response = await supertest .get('/internal/security/me') .set('Authorization', `Negotiate ${spnegoToken}`) From cac9018f81a30212ab06ef5195dd5b4f8a4de9b4 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 9 Jun 2020 20:58:46 -0700 Subject: [PATCH 18/53] [APM] Service maps - Fix missing ML status for services with jobs but no anomalies (#68486) * Closes #68485 by: - use the ML plugin to query for all APM jobs - inspect the ml job groups to find all jobs related to a particular service - use the mlAnomalySearch client to get ml job buckets with the max anomaly score - query for the model_plot buckets to obtain actual/median values for the ML description - return the relevant ML job with the max anomaly score for a service - indicate to the user that no anomalies were found for a service with an ml job * - Use the anomalyDetectorsProvider jobs API rather than the search endpoint directly - Defines a specific return type for the ml jobs api - Update the empty anomaly data message * Code and types cleanup * Return to using record result type on anomaly queries. These are the same values used in the anomaly explorer and it includes actual & typical values which greatly improve performance of the previous query. * - If anomaly data is missing show a gray border around node * - moved AnomalyDetection out of service map Contents into own component Co-authored-by: Elastic Machine --- x-pack/plugins/apm/common/ml_job_constants.ts | 2 + x-pack/plugins/apm/common/service_map.ts | 10 ++ x-pack/plugins/apm/common/utils/left_join.ts | 21 +++ x-pack/plugins/apm/kibana.json | 3 +- .../app/ServiceMap/Popover/Contents.tsx | 133 +-------------- .../ServiceMap/Popover/anomaly_detection.tsx | 156 ++++++++++++++++++ .../app/ServiceMap/cytoscapeOptions.ts | 25 +-- x-pack/plugins/apm/public/services/rest/ml.ts | 3 +- .../server/lib/helpers/setup_request.test.ts | 3 + .../apm/server/lib/helpers/setup_request.ts | 15 ++ .../lib/service_map/get_service_anomalies.ts | 129 +++++++++++++++ .../server/lib/service_map/get_service_map.ts | 63 +++---- .../server/lib/service_map/ml_helpers.test.ts | 76 +++------ .../apm/server/lib/service_map/ml_helpers.ts | 94 +++++------ .../transform_service_map_responses.test.ts | 14 +- .../transform_service_map_responses.ts | 32 +++- x-pack/plugins/apm/server/plugin.ts | 5 +- x-pack/plugins/apm/server/routes/typings.ts | 3 + x-pack/plugins/ml/server/shared.ts | 1 + .../providers/anomaly_detectors.ts | 3 +- 20 files changed, 488 insertions(+), 303 deletions(-) create mode 100644 x-pack/plugins/apm/common/utils/left_join.ts create mode 100644 x-pack/plugins/apm/public/components/app/ServiceMap/Popover/anomaly_detection.tsx create mode 100644 x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts diff --git a/x-pack/plugins/apm/common/ml_job_constants.ts b/x-pack/plugins/apm/common/ml_job_constants.ts index 6df0d324981a1..0f0add7c4226b 100644 --- a/x-pack/plugins/apm/common/ml_job_constants.ts +++ b/x-pack/plugins/apm/common/ml_job_constants.ts @@ -11,6 +11,8 @@ export enum severity { warning = 'warning', } +export const APM_ML_JOB_GROUP_NAME = 'apm'; + export function getMlPrefix(serviceName: string, transactionType?: string) { const maybeTransactionType = transactionType ? `${transactionType}-` : ''; return encodeForMlApi(`${serviceName}-${maybeTransactionType}`); diff --git a/x-pack/plugins/apm/common/service_map.ts b/x-pack/plugins/apm/common/service_map.ts index 43f3585d0ebb2..7d7a7811eeba2 100644 --- a/x-pack/plugins/apm/common/service_map.ts +++ b/x-pack/plugins/apm/common/service_map.ts @@ -34,6 +34,16 @@ export interface Connection { destination: ConnectionNode; } +export interface ServiceAnomaly { + anomaly_score: number; + anomaly_severity: string; + actual_value: number; + typical_value: number; + ml_job_id: string; +} + +export type ServiceNode = ConnectionNode & Partial; + export interface ServiceNodeMetrics { avgMemoryUsage: number | null; avgCpuUsage: number | null; diff --git a/x-pack/plugins/apm/common/utils/left_join.ts b/x-pack/plugins/apm/common/utils/left_join.ts new file mode 100644 index 0000000000000..f3c4e48df755b --- /dev/null +++ b/x-pack/plugins/apm/common/utils/left_join.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { Assign, Omit } from 'utility-types'; + +export function leftJoin< + TL extends object, + K extends keyof TL, + TR extends Pick +>(leftRecords: TL[], matchKey: K, rightRecords: TR[]) { + const rightLookup = new Map( + rightRecords.map((record) => [record[matchKey], record]) + ); + return leftRecords.map((record) => { + const matchProp = (record[matchKey] as unknown) as TR[K]; + const matchingRightRecord = rightLookup.get(matchProp); + return { ...record, ...matchingRightRecord }; + }) as Array>>>; +} diff --git a/x-pack/plugins/apm/kibana.json b/x-pack/plugins/apm/kibana.json index 2de3c9c97065d..1b8e7c4dc5431 100644 --- a/x-pack/plugins/apm/kibana.json +++ b/x-pack/plugins/apm/kibana.json @@ -17,7 +17,8 @@ "actions", "alerts", "observability", - "security" + "security", + "ml" ], "server": true, "ui": true, diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx index d9254b487d037..ff68288916af4 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx @@ -9,24 +9,15 @@ import { EuiFlexItem, EuiHorizontalRule, EuiTitle, - EuiIconTip, - EuiHealth, } from '@elastic/eui'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { i18n } from '@kbn/i18n'; import cytoscape from 'cytoscape'; import React, { MouseEvent } from 'react'; -import styled from 'styled-components'; -import { fontSize, px } from '../../../../style/variables'; import { Buttons } from './Buttons'; import { Info } from './Info'; import { ServiceMetricFetcher } from './ServiceMetricFetcher'; -import { MLJobLink } from '../../../shared/Links/MachineLearningLinks/MLJobLink'; -import { getSeverityColor } from '../cytoscapeOptions'; -import { asInteger } from '../../../../utils/formatters'; -import { getMetricChangeDescription } from '../../../../../../ml/public'; - -const popoverMinWidth = 280; +import { AnomalyDetection } from './anomaly_detection'; +import { ServiceNode } from '../../../../../common/service_map'; +import { popoverMinWidth } from '../cytoscapeOptions'; interface ContentsProps { isService: boolean; @@ -36,31 +27,6 @@ interface ContentsProps { selectedNodeServiceName: string; } -const HealthStatusTitle = styled(EuiTitle)` - display: inline; - text-transform: uppercase; -`; - -const VerticallyCentered = styled.div` - display: flex; - align-items: center; -`; - -const SubduedText = styled.span` - color: ${theme.euiTextSubduedColor}; -`; - -const EnableText = styled.section` - color: ${theme.euiTextSubduedColor}; - line-height: 1.4; - font-size: ${fontSize}; - width: ${px(popoverMinWidth)}; -`; - -export const ContentLine = styled.section` - line-height: 2; -`; - // IE 11 does not handle flex properties as expected. With browser detection, // we can use regular div elements to render contents that are almost identical. // @@ -85,37 +51,6 @@ const FlexColumnGroup = (props: { const FlexColumnItem = (props: { children: React.ReactNode }) => isIE11 ?
: ; -const ANOMALY_DETECTION_TITLE = i18n.translate( - 'xpack.apm.serviceMap.anomalyDetectionPopoverTitle', - { defaultMessage: 'Anomaly Detection' } -); - -const ANOMALY_DETECTION_TOOLTIP = i18n.translate( - 'xpack.apm.serviceMap.anomalyDetectionPopoverTooltip', - { - defaultMessage: - 'Service health indicators are powered by the anomaly detection feature in machine learning', - } -); - -const ANOMALY_DETECTION_SCORE_METRIC = i18n.translate( - 'xpack.apm.serviceMap.anomalyDetectionPopoverScoreMetric', - { defaultMessage: 'Score (max.)' } -); - -const ANOMALY_DETECTION_LINK = i18n.translate( - 'xpack.apm.serviceMap.anomalyDetectionPopoverLink', - { defaultMessage: 'View anomalies' } -); - -const ANOMALY_DETECTION_DISABLED_TEXT = i18n.translate( - 'xpack.apm.serviceMap.anomalyDetectionPopoverDisabled', - { - defaultMessage: - 'Display service health indicators by enabling anomaly detection from the Integrations menu in the Service details view.', - } -); - export function Contents({ selectedNodeData, isService, @@ -123,23 +58,6 @@ export function Contents({ onFocusClick, selectedNodeServiceName, }: ContentsProps) { - // Anomaly Detection - const severity = selectedNodeData.severity; - const maxScore = selectedNodeData.max_score; - const actualValue = selectedNodeData.actual_value; - const typicalValue = selectedNodeData.typical_value; - const jobId = selectedNodeData.job_id; - const hasAnomalyDetection = [ - severity, - maxScore, - actualValue, - typicalValue, - jobId, - ].every((value) => value !== undefined); - const anomalyDescription = hasAnomalyDetection - ? getMetricChangeDescription(actualValue, typicalValue).message - : null; - return ( {isService && ( - {hasAnomalyDetection ? ( - <> -
- -

{ANOMALY_DETECTION_TITLE}

-
-   - -
- - - - - - - {ANOMALY_DETECTION_SCORE_METRIC} - - - - -
- {asInteger(maxScore)} -  ({anomalyDescription}) -
-
-
-
- - - {ANOMALY_DETECTION_LINK} - - - - ) : ( - <> - -

{ANOMALY_DETECTION_TITLE}

-
- {ANOMALY_DETECTION_DISABLED_TEXT} - - )} +
)} diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/anomaly_detection.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/anomaly_detection.tsx new file mode 100644 index 0000000000000..ad4dc2ced2bfb --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/anomaly_detection.tsx @@ -0,0 +1,156 @@ +/* + * 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 React from 'react'; +import styled from 'styled-components'; +import theme from '@elastic/eui/dist/eui_theme_light.json'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiIconTip, + EuiHealth, +} from '@elastic/eui'; +import { fontSize, px } from '../../../../style/variables'; +import { asInteger } from '../../../../utils/formatters'; +import { MLJobLink } from '../../../shared/Links/MachineLearningLinks/MLJobLink'; +import { getSeverityColor, popoverMinWidth } from '../cytoscapeOptions'; +import { getMetricChangeDescription } from '../../../../../../ml/public'; +import { ServiceNode } from '../../../../../common/service_map'; + +const HealthStatusTitle = styled(EuiTitle)` + display: inline; + text-transform: uppercase; +`; + +const VerticallyCentered = styled.div` + display: flex; + align-items: center; +`; + +const SubduedText = styled.span` + color: ${theme.euiTextSubduedColor}; +`; + +const EnableText = styled.section` + color: ${theme.euiTextSubduedColor}; + line-height: 1.4; + font-size: ${fontSize}; + width: ${px(popoverMinWidth)}; +`; + +export const ContentLine = styled.section` + line-height: 2; +`; + +interface AnomalyDetectionProps { + serviceNodeData: cytoscape.NodeDataDefinition & ServiceNode; +} + +export function AnomalyDetection({ serviceNodeData }: AnomalyDetectionProps) { + const anomalySeverity = serviceNodeData.anomaly_severity; + const anomalyScore = serviceNodeData.anomaly_score; + const actualValue = serviceNodeData.actual_value; + const typicalValue = serviceNodeData.typical_value; + const mlJobId = serviceNodeData.ml_job_id; + const hasAnomalyDetectionScore = + anomalySeverity !== undefined && anomalyScore !== undefined; + const anomalyDescription = + hasAnomalyDetectionScore && + actualValue !== undefined && + typicalValue !== undefined + ? getMetricChangeDescription(actualValue, typicalValue).message + : null; + + return ( + <> +
+ +

{ANOMALY_DETECTION_TITLE}

+
+   + + {!mlJobId && {ANOMALY_DETECTION_DISABLED_TEXT}} +
+ {hasAnomalyDetectionScore && ( + + + + + + {ANOMALY_DETECTION_SCORE_METRIC} + + + +
+ {getDisplayedAnomalyScore(anomalyScore as number)} + {anomalyDescription && ( +  ({anomalyDescription}) + )} +
+
+
+
+ )} + {mlJobId && !hasAnomalyDetectionScore && ( + {ANOMALY_DETECTION_NO_DATA_TEXT} + )} + {mlJobId && ( + + + {ANOMALY_DETECTION_LINK} + + + )} + + ); +} + +function getDisplayedAnomalyScore(score: number) { + if (score > 0 && score < 1) { + return '< 1'; + } + return asInteger(score); +} + +const ANOMALY_DETECTION_TITLE = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverTitle', + { defaultMessage: 'Anomaly Detection' } +); + +const ANOMALY_DETECTION_TOOLTIP = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverTooltip', + { + defaultMessage: + 'Service health indicators are powered by the anomaly detection feature in machine learning', + } +); + +const ANOMALY_DETECTION_SCORE_METRIC = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverScoreMetric', + { defaultMessage: 'Score (max.)' } +); + +const ANOMALY_DETECTION_LINK = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverLink', + { defaultMessage: 'View anomalies' } +); + +const ANOMALY_DETECTION_DISABLED_TEXT = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverDisabled', + { + defaultMessage: + 'Display service health indicators by enabling anomaly detection from the Integrations menu in the Service details view.', + } +); + +const ANOMALY_DETECTION_NO_DATA_TEXT = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverNoData', + { + defaultMessage: `We couldn't find an anomaly score within the selected time range. See details in the anomaly explorer.`, + } +); diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts index 0e4666b7bff17..9b35b0b33a70d 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts @@ -13,7 +13,9 @@ import { import { severity } from '../../../../common/ml_job_constants'; import { defaultIcon, iconForNode } from './icons'; -export const getSeverityColor = (nodeSeverity: string) => { +export const popoverMinWidth = 280; + +export const getSeverityColor = (nodeSeverity?: string) => { switch (nodeSeverity) { case severity.warning: return theme.euiColorVis0; @@ -27,24 +29,26 @@ export const getSeverityColor = (nodeSeverity: string) => { } }; -const getBorderColor = (el: cytoscape.NodeSingular) => { - const nodeSeverity = el.data('severity'); - const severityColor = getSeverityColor(nodeSeverity); - if (severityColor) { - return severityColor; +const getBorderColor: cytoscape.Css.MapperFunction< + cytoscape.NodeSingular, + string +> = (el: cytoscape.NodeSingular) => { + const hasAnomalyDetectionJob = el.data('ml_job_id') !== undefined; + const nodeSeverity = el.data('anomaly_severity'); + if (hasAnomalyDetectionJob) { + return getSeverityColor(nodeSeverity) || theme.euiColorMediumShade; } if (el.hasClass('primary') || el.selected()) { return theme.euiColorPrimary; - } else { - return theme.euiColorMediumShade; } + return theme.euiColorMediumShade; }; const getBorderStyle: cytoscape.Css.MapperFunction< cytoscape.NodeSingular, cytoscape.Css.LineStyle > = (el: cytoscape.NodeSingular) => { - const nodeSeverity = el.data('severity'); + const nodeSeverity = el.data('anomaly_severity'); if (nodeSeverity === severity.critical) { return 'double'; } else { @@ -53,7 +57,7 @@ const getBorderStyle: cytoscape.Css.MapperFunction< }; const getBorderWidth = (el: cytoscape.NodeSingular) => { - const nodeSeverity = el.data('severity'); + const nodeSeverity = el.data('anomaly_severity'); if (nodeSeverity === severity.minor || nodeSeverity === severity.major) { return 4; @@ -183,6 +187,7 @@ const style: cytoscape.Stylesheet[] = [ // actually "hidden" { selector: 'edge[isInverseEdge]', + // @ts-ignore style: { visibility: 'hidden' }, }, { diff --git a/x-pack/plugins/apm/public/services/rest/ml.ts b/x-pack/plugins/apm/public/services/rest/ml.ts index 99c162bde02da..47032501d9fbe 100644 --- a/x-pack/plugins/apm/public/services/rest/ml.ts +++ b/x-pack/plugins/apm/public/services/rest/ml.ts @@ -11,6 +11,7 @@ import { TRANSACTION_TYPE, } from '../../../common/elasticsearch_fieldnames'; import { + APM_ML_JOB_GROUP_NAME, getMlJobId, getMlPrefix, encodeForMlApi, @@ -55,7 +56,7 @@ export async function startMLJob({ }) { const transactionIndices = await getTransactionIndices(); const groups = [ - 'apm', + APM_ML_JOB_GROUP_NAME, encodeForMlApi(serviceName), encodeForMlApi(transactionType), ]; diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts index e529f4d4ab1ed..5a4bc62b87486 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -59,6 +59,9 @@ function getMockRequest() { }, }, }, + plugins: { + ml: undefined, + }, } as unknown) as APMRequestHandlerContext & { core: { elasticsearch: { diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts index 34f3fd9b40bb0..c41dff79a916a 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts @@ -36,6 +36,7 @@ function decodeUiFilters( export interface Setup { client: ESClient; internalClient: ESClient; + ml?: ReturnType; config: APMConfig; indices: ApmIndicesConfig; dynamicIndexPattern?: IIndexPattern; @@ -93,6 +94,7 @@ export async function setupRequest( internalClient: getESClient(context, request, { clientAsInternalUser: true, }), + ml: getMlSetup(context, request), config, dynamicIndexPattern, }; @@ -104,3 +106,16 @@ export async function setupRequest( ...coreSetupRequest, } as InferSetup; } + +function getMlSetup(context: APMRequestHandlerContext, request: KibanaRequest) { + if (!context.plugins.ml) { + return; + } + const ml = context.plugins.ml; + const mlClient = ml.mlClient.asScoped(request).callAsCurrentUser; + return { + mlSystem: ml.mlSystemProvider(mlClient, request), + anomalyDetectors: ml.anomalyDetectorsProvider(mlClient), + mlClient, + }; +} diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts new file mode 100644 index 0000000000000..7b26078d5ffbf --- /dev/null +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts @@ -0,0 +1,129 @@ +/* + * 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 { intersection } from 'lodash'; +import { leftJoin } from '../../../common/utils/left_join'; +import { Job as AnomalyDetectionJob } from '../../../../ml/server'; +import { PromiseReturnType } from '../../../typings/common'; +import { IEnvOptions } from './get_service_map'; +import { APM_ML_JOB_GROUP_NAME } from '../../../common/ml_job_constants'; + +type ApmMlJobCategory = NonNullable>; +const getApmMlJobCategory = ( + mlJob: AnomalyDetectionJob, + serviceNames: string[] +) => { + const apmJobGroups = mlJob.groups.filter( + (groupName) => groupName !== APM_ML_JOB_GROUP_NAME + ); + if (apmJobGroups.length === mlJob.groups.length) { + // ML job missing "apm" group name + return; + } + const [serviceName] = intersection(apmJobGroups, serviceNames); + if (!serviceName) { + // APM ML job service was not found + return; + } + const [transactionType] = apmJobGroups.filter( + (groupName) => groupName !== serviceName + ); + if (!transactionType) { + // APM ML job transaction type was not found. + return; + } + return { jobId: mlJob.job_id, serviceName, transactionType }; +}; + +export type ServiceAnomalies = PromiseReturnType; + +export async function getServiceAnomalies( + options: IEnvOptions, + serviceNames: string[] +) { + const { start, end, ml } = options.setup; + + if (!ml || serviceNames.length === 0) { + return []; + } + + const { jobs: apmMlJobs } = await ml.anomalyDetectors.jobs('apm'); + const apmMlJobCategories = apmMlJobs + .map((job) => getApmMlJobCategory(job, serviceNames)) + .filter( + (apmJobCategory) => apmJobCategory !== undefined + ) as ApmMlJobCategory[]; + const apmJobIds = apmMlJobs.map((job) => job.job_id); + const params = { + body: { + size: 0, + query: { + bool: { + filter: [ + { term: { result_type: 'record' } }, + { + terms: { + job_id: apmJobIds, + }, + }, + { + range: { + timestamp: { gte: start, lte: end, format: 'epoch_millis' }, + }, + }, + ], + }, + }, + aggs: { + jobs: { + terms: { field: 'job_id', size: apmJobIds.length }, + aggs: { + top_score_hits: { + top_hits: { + sort: [{ record_score: { order: 'desc' as const } }], + _source: ['record_score', 'timestamp', 'typical', 'actual'], + size: 1, + }, + }, + }, + }, + }, + }, + }; + + const response = (await ml.mlSystem.mlAnomalySearch(params)) as { + aggregations: { + jobs: { + buckets: Array<{ + key: string; + top_score_hits: { + hits: { + hits: Array<{ + _source: { + record_score: number; + timestamp: number; + typical: number[]; + actual: number[]; + }; + }>; + }; + }; + }>; + }; + }; + }; + const anomalyScores = response.aggregations.jobs.buckets.map((jobBucket) => { + const jobId = jobBucket.key; + const bucketSource = jobBucket.top_score_hits.hits.hits?.[0]?._source; + return { + jobId, + anomalyScore: bucketSource.record_score, + timestamp: bucketSource.timestamp, + typical: bucketSource.typical[0], + actual: bucketSource.actual[0], + }; + }); + return leftJoin(apmMlJobCategories, 'jobId', anomalyScores); +} diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts index 47ba9ecc78ffc..9f3ded82d7cbd 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts @@ -9,15 +9,18 @@ import { SERVICE_ENVIRONMENT, SERVICE_NAME, } from '../../../common/elasticsearch_fieldnames'; -import { getMlIndex } from '../../../common/ml_job_constants'; import { getServicesProjection } from '../../../common/projections/services'; import { mergeProjection } from '../../../common/projections/util/merge_projection'; import { PromiseReturnType } from '../../../typings/common'; -import { rangeFilter } from '../helpers/range_filter'; import { Setup, SetupTimeRange } from '../helpers/setup_request'; -import { transformServiceMapResponses } from './transform_service_map_responses'; +import { + transformServiceMapResponses, + getAllNodes, + getServiceNodes, +} from './transform_service_map_responses'; import { getServiceMapFromTraceIds } from './get_service_map_from_trace_ids'; import { getTraceSampleIds } from './get_trace_sample_ids'; +import { getServiceAnomalies, ServiceAnomalies } from './get_service_anomalies'; export interface IEnvOptions { setup: Setup & SetupTimeRange; @@ -129,58 +132,30 @@ async function getServicesData(options: IEnvOptions) { ); } -function getAnomaliesData(options: IEnvOptions) { - const { start, end, client } = options.setup; - const rangeQuery = { range: rangeFilter(start, end, 'timestamp') }; - - const params = { - index: getMlIndex('*'), - body: { - size: 0, - query: { - bool: { filter: [{ term: { result_type: 'record' } }, rangeQuery] }, - }, - aggs: { - jobs: { - terms: { field: 'job_id', size: 10 }, - aggs: { - top_score_hits: { - top_hits: { - sort: [{ record_score: { order: 'desc' as const } }], - _source: ['job_id', 'record_score', 'typical', 'actual'], - size: 1, - }, - }, - }, - }, - }, - }, - }; - - return client.search(params); -} - -export type AnomaliesResponse = PromiseReturnType; +export { ServiceAnomalies }; export type ConnectionsResponse = PromiseReturnType; export type ServicesResponse = PromiseReturnType; export type ServiceMapAPIResponse = PromiseReturnType; export async function getServiceMap(options: IEnvOptions) { - const [connectionData, servicesData, anomaliesData]: [ - // explicit types to avoid TS "excessively deep" error - ConnectionsResponse, - ServicesResponse, - AnomaliesResponse - // @ts-ignore - ] = await Promise.all([ + const [connectionData, servicesData] = await Promise.all([ getConnectionData(options), getServicesData(options), - getAnomaliesData(options), ]); + // Derive all related service names from connection and service data + const allNodes = getAllNodes(servicesData, connectionData.connections); + const serviceNodes = getServiceNodes(allNodes); + const serviceNames = serviceNodes.map( + (serviceData) => serviceData[SERVICE_NAME] + ); + + // Get related service anomalies + const serviceAnomalies = await getServiceAnomalies(options, serviceNames); + return transformServiceMapResponses({ ...connectionData, - anomalies: anomaliesData, + anomalies: serviceAnomalies, services: servicesData, }); } diff --git a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts index 6d2bd783e9cde..f07b575cc0a35 100644 --- a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AnomaliesResponse } from './get_service_map'; +import { ServiceAnomalies } from './get_service_map'; import { addAnomaliesDataToNodes } from './ml_helpers'; describe('addAnomaliesDataToNodes', () => { @@ -22,76 +22,54 @@ describe('addAnomaliesDataToNodes', () => { }, ]; - const anomaliesResponse = { - aggregations: { - jobs: { - buckets: [ - { - key: 'opbeans-ruby-request-high_mean_response_time', - top_score_hits: { - hits: { - hits: [ - { - _source: { - record_score: 50, - actual: [2000], - typical: [1000], - job_id: 'opbeans-ruby-request-high_mean_response_time', - }, - }, - ], - }, - }, - }, - { - key: 'opbeans-java-request-high_mean_response_time', - top_score_hits: { - hits: { - hits: [ - { - _source: { - record_score: 100, - actual: [9000], - typical: [3000], - job_id: 'opbeans-java-request-high_mean_response_time', - }, - }, - ], - }, - }, - }, - ], - }, + const serviceAnomalies: ServiceAnomalies = [ + { + jobId: 'opbeans-ruby-request-high_mean_response_time', + serviceName: 'opbeans-ruby', + transactionType: 'request', + anomalyScore: 50, + timestamp: 1591351200000, + actual: 2000, + typical: 1000, + }, + { + jobId: 'opbeans-java-request-high_mean_response_time', + serviceName: 'opbeans-java', + transactionType: 'request', + anomalyScore: 100, + timestamp: 1591351200000, + actual: 9000, + typical: 3000, }, - }; + ]; const result = [ { 'service.name': 'opbeans-ruby', 'agent.name': 'ruby', 'service.environment': null, - max_score: 50, - severity: 'major', + anomaly_score: 50, + anomaly_severity: 'major', actual_value: 2000, typical_value: 1000, - job_id: 'opbeans-ruby-request-high_mean_response_time', + ml_job_id: 'opbeans-ruby-request-high_mean_response_time', }, { 'service.name': 'opbeans-java', 'agent.name': 'java', 'service.environment': null, - max_score: 100, - severity: 'critical', + anomaly_score: 100, + anomaly_severity: 'critical', actual_value: 9000, typical_value: 3000, - job_id: 'opbeans-java-request-high_mean_response_time', + ml_job_id: 'opbeans-java-request-high_mean_response_time', }, ]; expect( addAnomaliesDataToNodes( nodes, - (anomaliesResponse as unknown) as AnomaliesResponse + (serviceAnomalies as unknown) as ServiceAnomalies ) ).toEqual(result); }); diff --git a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts index 3289958733b2b..8162417616b6c 100644 --- a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts +++ b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts @@ -5,65 +5,59 @@ */ import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; -import { - getMlJobServiceName, - getSeverity, -} from '../../../common/ml_job_constants'; -import { ConnectionNode } from '../../../common/service_map'; -import { AnomaliesResponse } from './get_service_map'; +import { getSeverity } from '../../../common/ml_job_constants'; +import { ConnectionNode, ServiceNode } from '../../../common/service_map'; +import { ServiceAnomalies } from './get_service_map'; export function addAnomaliesDataToNodes( nodes: ConnectionNode[], - anomaliesResponse: AnomaliesResponse + serviceAnomalies: ServiceAnomalies ) { - const anomaliesMap = ( - anomaliesResponse.aggregations?.jobs.buckets ?? [] - ).reduce<{ - [key: string]: { - max_score?: number; - actual_value?: number; - typical_value?: number; - job_id?: string; - }; - }>((previousValue, currentValue) => { - const key = getMlJobServiceName(currentValue.key.toString()); - const hitSource = currentValue.top_score_hits.hits.hits[0]._source as { - record_score: number; - actual: [number]; - typical: [number]; - job_id: string; - }; - const maxScore = hitSource.record_score; - const actualValue = hitSource.actual[0]; - const typicalValue = hitSource.typical[0]; - const jobId = hitSource.job_id; + const anomaliesMap = serviceAnomalies.reduce( + (acc, anomalyJob) => { + const serviceAnomaly: typeof acc[string] | undefined = + acc[anomalyJob.serviceName]; + const hasAnomalyJob = serviceAnomaly !== undefined; + const hasAnomalyScore = serviceAnomaly?.anomaly_score !== undefined; + const hasNewAnomalyScore = anomalyJob.anomalyScore !== undefined; + const hasNewMaxAnomalyScore = + hasNewAnomalyScore && + (!hasAnomalyScore || + (anomalyJob?.anomalyScore ?? 0) > + (serviceAnomaly?.anomaly_score ?? 0)); - if ((previousValue[key]?.max_score ?? 0) > maxScore) { - return previousValue; - } + if (!hasAnomalyJob || hasNewMaxAnomalyScore) { + acc[anomalyJob.serviceName] = { + anomaly_score: anomalyJob.anomalyScore, + actual_value: anomalyJob.actual, + typical_value: anomalyJob.typical, + ml_job_id: anomalyJob.jobId, + }; + } - return { - ...previousValue, - [key]: { - max_score: maxScore, - actual_value: actualValue, - typical_value: typicalValue, - job_id: jobId, - }, - }; - }, {}); + return acc; + }, + {} as { + [serviceName: string]: { + anomaly_score?: number; + actual_value?: number; + typical_value?: number; + ml_job_id: string; + }; + } + ); - const servicesDataWithAnomalies = nodes.map((service) => { - const serviceAnomalies = anomaliesMap[service[SERVICE_NAME]]; - if (serviceAnomalies) { - const maxScore = serviceAnomalies.max_score; + const servicesDataWithAnomalies: ServiceNode[] = nodes.map((service) => { + const serviceAnomaly = anomaliesMap[service[SERVICE_NAME]]; + if (serviceAnomaly) { + const anomalyScore = serviceAnomaly.anomaly_score; return { ...service, - max_score: maxScore, - severity: getSeverity(maxScore), - actual_value: serviceAnomalies.actual_value, - typical_value: serviceAnomalies.typical_value, - job_id: serviceAnomalies.job_id, + anomaly_score: anomalyScore, + anomaly_severity: getSeverity(anomalyScore), + actual_value: serviceAnomaly.actual_value, + typical_value: serviceAnomaly.typical_value, + ml_job_id: serviceAnomaly.ml_job_id, }; } return service; diff --git a/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.test.ts b/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.test.ts index 0aa3f13b9b90c..6c9880c2dc4df 100644 --- a/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.test.ts @@ -12,7 +12,7 @@ import { SPAN_SUBTYPE, SPAN_TYPE, } from '../../../common/elasticsearch_fieldnames'; -import { AnomaliesResponse } from './get_service_map'; +import { ServiceAnomalies } from './get_service_map'; import { transformServiceMapResponses, ServiceMapResponse, @@ -36,14 +36,12 @@ const javaService = { [AGENT_NAME]: 'java', }; -const anomalies = ({ - aggregations: { jobs: { buckets: [] } }, -} as unknown) as AnomaliesResponse; +const serviceAnomalies: ServiceAnomalies = []; describe('transformServiceMapResponses', () => { it('maps external destinations to internal services', () => { const response: ServiceMapResponse = { - anomalies, + anomalies: serviceAnomalies, services: [nodejsService, javaService], discoveredServices: [ { @@ -75,7 +73,7 @@ describe('transformServiceMapResponses', () => { it('collapses external destinations based on span.destination.resource.name', () => { const response: ServiceMapResponse = { - anomalies, + anomalies: serviceAnomalies, services: [nodejsService, javaService], discoveredServices: [ { @@ -111,7 +109,7 @@ describe('transformServiceMapResponses', () => { it('picks the first span.type/subtype in an alphabetically sorted list', () => { const response: ServiceMapResponse = { - anomalies, + anomalies: serviceAnomalies, services: [javaService], discoveredServices: [], connections: [ @@ -150,7 +148,7 @@ describe('transformServiceMapResponses', () => { it('processes connections without a matching "service" aggregation', () => { const response: ServiceMapResponse = { - anomalies, + anomalies: serviceAnomalies, services: [javaService], discoveredServices: [], connections: [ diff --git a/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.ts b/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.ts index 8580fed587567..53abf54cbcf31 100644 --- a/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.ts +++ b/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.ts @@ -20,7 +20,7 @@ import { import { ConnectionsResponse, ServicesResponse, - AnomaliesResponse, + ServiceAnomalies, } from './get_service_map'; import { addAnomaliesDataToNodes } from './ml_helpers'; @@ -38,14 +38,10 @@ function getConnectionId(connection: Connection) { )}`; } -export type ServiceMapResponse = ConnectionsResponse & { - anomalies: AnomaliesResponse; - services: ServicesResponse; -}; - -export function transformServiceMapResponses(response: ServiceMapResponse) { - const { anomalies, discoveredServices, services, connections } = response; - +export function getAllNodes( + services: ServiceMapResponse['services'], + connections: ServiceMapResponse['connections'] +) { // Derive the rest of the map nodes from the connections and add the services // from the services data query const allNodes: ConnectionNode[] = connections @@ -58,11 +54,29 @@ export function transformServiceMapResponses(response: ServiceMapResponse) { })) ); + return allNodes; +} + +export function getServiceNodes(allNodes: ConnectionNode[]) { // List of nodes that are services const serviceNodes = allNodes.filter( (node) => SERVICE_NAME in node ) as ServiceConnectionNode[]; + return serviceNodes; +} + +export type ServiceMapResponse = ConnectionsResponse & { + anomalies: ServiceAnomalies; + services: ServicesResponse; +}; + +export function transformServiceMapResponses(response: ServiceMapResponse) { + const { anomalies, discoveredServices, services, connections } = response; + + const allNodes = getAllNodes(services, connections); + const serviceNodes = getServiceNodes(allNodes); + // List of nodes that are externals const externalNodes = allNodes.filter( (node) => SPAN_DESTINATION_SERVICE_RESOURCE in node diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index d32d16d4c3cc8..f0a05dfc0df30 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -31,10 +31,11 @@ import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_ import { LicensingPluginSetup } from '../../licensing/public'; import { registerApmAlerts } from './lib/alerts/register_apm_alerts'; import { createApmTelemetry } from './lib/apm_telemetry'; -import { PluginSetupContract as FeaturesPluginSetup } from '../../../plugins/features/server'; +import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; import { APM_FEATURE } from './feature'; import { apmIndices, apmTelemetry } from './saved_objects'; import { createElasticCloudInstructions } from './tutorial/elastic_cloud'; +import { MlPluginSetup } from '../../ml/server'; export interface APMPluginSetup { config$: Observable; @@ -62,6 +63,7 @@ export class APMPlugin implements Plugin { observability?: ObservabilityPluginSetup; features: FeaturesPluginSetup; security?: SecurityPluginSetup; + ml?: MlPluginSetup; } ) { this.logger = this.initContext.logger.get(); @@ -126,6 +128,7 @@ export class APMPlugin implements Plugin { plugins: { observability: plugins.observability, security: plugins.security, + ml: plugins.ml, }, }); diff --git a/x-pack/plugins/apm/server/routes/typings.ts b/x-pack/plugins/apm/server/routes/typings.ts index 05f52f1732c98..bc31cb7a582af 100644 --- a/x-pack/plugins/apm/server/routes/typings.ts +++ b/x-pack/plugins/apm/server/routes/typings.ts @@ -18,6 +18,7 @@ import { ObservabilityPluginSetup } from '../../../observability/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { FetchOptions } from '../../public/services/rest/callApi'; import { SecurityPluginSetup } from '../../../security/public'; +import { MlPluginSetup } from '../../../ml/server'; import { APMConfig } from '..'; export interface Params { @@ -67,6 +68,7 @@ export type APMRequestHandlerContext< plugins: { observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; + ml?: MlPluginSetup; }; }; @@ -114,6 +116,7 @@ export interface ServerAPI { plugins: { observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; + ml?: MlPluginSetup; }; } ) => void; diff --git a/x-pack/plugins/ml/server/shared.ts b/x-pack/plugins/ml/server/shared.ts index 1e50950bc3bce..be27ee2d44a82 100644 --- a/x-pack/plugins/ml/server/shared.ts +++ b/x-pack/plugins/ml/server/shared.ts @@ -5,3 +5,4 @@ */ export * from '../common/types/anomalies'; +export * from '../common/types/anomaly_detection_jobs'; diff --git a/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts b/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts index 73696dfdeef86..880aebfde409c 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/anomaly_detectors.ts @@ -6,12 +6,13 @@ import { APICaller } from 'kibana/server'; import { LicenseCheck } from '../license_checks'; +import { Job } from '../../../common/types/anomaly_detection_jobs'; export interface AnomalyDetectorsProvider { anomalyDetectorsProvider( callAsCurrentUser: APICaller ): { - jobs(jobId?: string): Promise; + jobs(jobId?: string): Promise<{ count: number; jobs: Job[] }>; }; } From 50d47a2ed5388795166e7f2555cb216448d99ba1 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Wed, 10 Jun 2020 08:01:01 +0200 Subject: [PATCH 19/53] adapt some snapshot test (#68489) --- .../saved_objects_table.test.tsx.snap | 132 ------------------ .../saved_objects_table.test.tsx | 4 +- 2 files changed, 2 insertions(+), 134 deletions(-) diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 707e65d60870c..f7d5cc760f1bb 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -197,138 +197,6 @@ exports[`SavedObjectsTable export should allow the user to choose when exporting `; -exports[`SavedObjectsTable import should show the flyout 1`] = ` - -`; - -exports[`SavedObjectsTable relationships should show the flyout 1`] = ` - -`; - exports[`SavedObjectsTable should render normally 1`] = ` { component.instance().showImportFlyout(); component.update(); - expect(component.find(Flyout)).toMatchSnapshot(); + expect(component.find(Flyout).length).toBe(1); }); it('should hide the flyout', async () => { @@ -450,7 +450,7 @@ describe('SavedObjectsTable', () => { } as SavedObjectWithMetadata); component.update(); - expect(component.find(Relationships)).toMatchSnapshot(); + expect(component.find(Relationships).length).toBe(1); expect(component.state('relationshipObject')).toEqual({ id: '2', type: 'search', From 204977c6ce9f64ccf524a4cde5b89dce5c921d7e Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Wed, 10 Jun 2020 09:10:23 +0200 Subject: [PATCH 20/53] Partial revert of "Sync Kerberos + Anonymous access tests with the latest `security/_authenticate` API (user roles now include roles of anonymous user)." (#68624) --- .../apis/security/kerberos_login.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts index 6a93b94920d6d..8d2e575fad313 100644 --- a/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts +++ b/x-pack/test/kerberos_api_integration/apis/security/kerberos_login.ts @@ -98,8 +98,7 @@ export default function ({ getService }: FtrProviderContext) { }); describe('finishing SPNEGO', () => { - // Skipped: https://github.com/elastic/kibana/issues/68720 - it.skip('should properly set cookie and authenticate user', async () => { + it('should properly set cookie and authenticate user', async () => { const response = await supertest .get('/internal/security/me') .set('Authorization', `Negotiate ${spnegoToken}`) @@ -116,14 +115,7 @@ export default function ({ getService }: FtrProviderContext) { const sessionCookie = request.cookie(cookies[0])!; checkCookieIsSet(sessionCookie); - const isAnonymousAccessEnabled = (config.get( - 'esTestCluster.serverArgs' - ) as string[]).some((setting) => setting.startsWith('xpack.security.authc.anonymous')); - - // `superuser_anonymous` role is derived from the enabled anonymous access. - const expectedUserRoles = isAnonymousAccessEnabled - ? ['kibana_admin', 'superuser_anonymous'] - : ['kibana_admin']; + const expectedUserRoles = ['kibana_admin']; await supertest .get('/internal/security/me') From 028c19e7b4ddf3deb2127795c878637f2d7dc5ab Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Wed, 10 Jun 2020 12:00:40 +0200 Subject: [PATCH 21/53] [SIEM] Cypress renaming (#68659) * updates naming in integration * updates naming in objects * updates naming in screens * updates naming in support * updates naming in tasks * fixes failing test Co-authored-by: Elastic Machine --- .../cypress/integration/events_viewer.spec.ts | 2 +- .../cypress/integration/fields_browser.spec.ts | 2 +- .../cypress/integration/inspect.spec.ts | 10 +++++----- .../cypress/integration/ml_conditional_links.spec.ts | 2 +- .../cypress/integration/navigation.spec.ts | 6 +++--- .../cypress/integration/overview.spec.ts | 2 +- .../cypress/integration/pagination.spec.ts | 2 +- .../integration/timeline_data_providers.spec.ts | 2 +- .../cypress/integration/timeline_flyout_button.spec.ts | 2 +- .../integration/timeline_search_or_filter.spec.ts | 2 +- .../cypress/integration/timeline_toggle_column.spec.ts | 2 +- .../cypress/integration/url_state.spec.ts | 8 ++++---- .../security_solution/cypress/screens/inspect.ts | 4 ++-- .../screens/{siem_header.ts => security_header.ts} | 0 .../cypress/screens/{siem_main.ts => security_main.ts} | 0 .../security_solution/cypress/support/commands.js | 2 +- .../security_solution/cypress/support/index.d.ts | 2 +- .../security_solution/cypress/tasks/configure_cases.ts | 2 +- .../security_solution/cypress/tasks/detections.ts | 2 +- .../cypress/tasks/hosts/authentications.ts | 2 +- .../cypress/tasks/hosts/uncommon_processes.ts | 2 +- .../tasks/{siem_header.ts => security_header.ts} | 2 +- .../cypress/tasks/{siem_main.ts => security_main.ts} | 2 +- 23 files changed, 31 insertions(+), 31 deletions(-) rename x-pack/plugins/security_solution/cypress/screens/{siem_header.ts => security_header.ts} (100%) rename x-pack/plugins/security_solution/cypress/screens/{siem_main.ts => security_main.ts} (100%) rename x-pack/plugins/security_solution/cypress/tasks/{siem_header.ts => security_header.ts} (90%) rename x-pack/plugins/security_solution/cypress/tasks/{siem_main.ts => security_main.ts} (86%) diff --git a/x-pack/plugins/security_solution/cypress/integration/events_viewer.spec.ts b/x-pack/plugins/security_solution/cypress/integration/events_viewer.spec.ts index 82b4f4f0fbe34..82395de91abfa 100644 --- a/x-pack/plugins/security_solution/cypress/integration/events_viewer.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/events_viewer.spec.ts @@ -32,7 +32,7 @@ import { resetFields, waitsForEventsToBeLoaded, } from '../tasks/hosts/events'; -import { clearSearchBar, kqlSearch } from '../tasks/siem_header'; +import { clearSearchBar, kqlSearch } from '../tasks/security_header'; import { HOSTS_PAGE } from '../urls/navigation'; diff --git a/x-pack/plugins/security_solution/cypress/integration/fields_browser.spec.ts b/x-pack/plugins/security_solution/cypress/integration/fields_browser.spec.ts index b058c9fb51fd1..b0dbf94c0efb9 100644 --- a/x-pack/plugins/security_solution/cypress/integration/fields_browser.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/fields_browser.spec.ts @@ -28,7 +28,7 @@ import { resetFields, } from '../tasks/fields_browser'; import { loginAndWaitForPage } from '../tasks/login'; -import { openTimeline } from '../tasks/siem_main'; +import { openTimeline } from '../tasks/security_main'; import { openTimelineFieldsBrowser, populateTimeline } from '../tasks/timeline'; import { HOSTS_PAGE } from '../urls/navigation'; diff --git a/x-pack/plugins/security_solution/cypress/integration/inspect.spec.ts b/x-pack/plugins/security_solution/cypress/integration/inspect.spec.ts index d770eb6c761cf..0529c797ee07a 100644 --- a/x-pack/plugins/security_solution/cypress/integration/inspect.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/inspect.spec.ts @@ -5,14 +5,14 @@ */ import { - INSPECT_HOSTS_BUTTONS_IN_SIEM, + INSPECT_HOSTS_BUTTONS_IN_SECURITY, INSPECT_MODAL, - INSPECT_NETWORK_BUTTONS_IN_SIEM, + INSPECT_NETWORK_BUTTONS_IN_SECURITY, } from '../screens/inspect'; import { closesModal, openStatsAndTables } from '../tasks/inspect'; import { loginAndWaitForPage } from '../tasks/login'; -import { openTimeline } from '../tasks/siem_main'; +import { openTimeline } from '../tasks/security_main'; import { executeTimelineKQL, openTimelineInspectButton, @@ -30,7 +30,7 @@ describe('Inspect', () => { closesModal(); }); - INSPECT_HOSTS_BUTTONS_IN_SIEM.forEach((table) => + INSPECT_HOSTS_BUTTONS_IN_SECURITY.forEach((table) => it(`inspects the ${table.title}`, () => { openStatsAndTables(table); cy.get(INSPECT_MODAL).should('be.visible'); @@ -46,7 +46,7 @@ describe('Inspect', () => { closesModal(); }); - INSPECT_NETWORK_BUTTONS_IN_SIEM.forEach((table) => + INSPECT_NETWORK_BUTTONS_IN_SECURITY.forEach((table) => it(`inspects the ${table.title}`, () => { openStatsAndTables(table); cy.get(INSPECT_MODAL).should('be.visible'); diff --git a/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts b/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts index e96c1fe691966..785df4a0c2f9e 100644 --- a/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/ml_conditional_links.spec.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { KQL_INPUT } from '../screens/siem_header'; +import { KQL_INPUT } from '../screens/security_header'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; diff --git a/x-pack/plugins/security_solution/cypress/integration/navigation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/navigation.spec.ts index a9e5a848d54a8..2014e34c11886 100644 --- a/x-pack/plugins/security_solution/cypress/integration/navigation.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/navigation.spec.ts @@ -3,14 +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 { DETECTIONS, HOSTS, NETWORK, OVERVIEW, TIMELINES } from '../screens/siem_header'; +import { DETECTIONS, HOSTS, NETWORK, OVERVIEW, TIMELINES } from '../screens/security_header'; import { loginAndWaitForPage } from '../tasks/login'; -import { navigateFromHeaderTo } from '../tasks/siem_header'; +import { navigateFromHeaderTo } from '../tasks/security_header'; import { TIMELINES_PAGE } from '../urls/navigation'; -describe('top-level navigation common to all pages in the SIEM app', () => { +describe('top-level navigation common to all pages in the Security app', () => { before(() => { loginAndWaitForPage(TIMELINES_PAGE); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts b/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts index 55bcbfafaa092..284deb67e1386 100644 --- a/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts @@ -13,7 +13,7 @@ import { OVERVIEW_PAGE } from '../urls/navigation'; describe('Overview Page', () => { before(() => { - cy.stubSIEMapi('overview'); + cy.stubSecurityApi('overview'); loginAndWaitForPage(OVERVIEW_PAGE); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/pagination.spec.ts b/x-pack/plugins/security_solution/cypress/integration/pagination.spec.ts index e430520fe1dc4..5dc3182cd9f83 100644 --- a/x-pack/plugins/security_solution/cypress/integration/pagination.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/pagination.spec.ts @@ -12,7 +12,7 @@ import { openAuthentications, openUncommonProcesses } from '../tasks/hosts/main' import { waitForUncommonProcessesToBeLoaded } from '../tasks/hosts/uncommon_processes'; import { loginAndWaitForPage } from '../tasks/login'; import { goToFirstPage, goToThirdPage } from '../tasks/pagination'; -import { refreshPage } from '../tasks/siem_header'; +import { refreshPage } from '../tasks/security_header'; import { HOSTS_PAGE_TAB_URLS } from '../urls/navigation'; diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_data_providers.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_data_providers.spec.ts index 243886752706d..33394760c4da9 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_data_providers.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_data_providers.spec.ts @@ -19,7 +19,7 @@ import { } from '../tasks/hosts/all_hosts'; import { loginAndWaitForPage } from '../tasks/login'; -import { openTimeline } from '../tasks/siem_main'; +import { openTimeline } from '../tasks/security_main'; import { createNewTimeline } from '../tasks/timeline'; import { HOSTS_PAGE } from '../urls/navigation'; diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts index 02da7cbc28462..fe420ae9dccbb 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts @@ -8,7 +8,7 @@ import { TIMELINE_FLYOUT_HEADER, TIMELINE_NOT_READY_TO_DROP_BUTTON } from '../sc import { dragFirstHostToTimeline, waitForAllHostsToBeLoaded } from '../tasks/hosts/all_hosts'; import { loginAndWaitForPage } from '../tasks/login'; -import { openTimeline, openTimelineIfClosed } from '../tasks/siem_main'; +import { openTimeline, openTimelineIfClosed } from '../tasks/security_main'; import { createNewTimeline } from '../tasks/timeline'; import { HOSTS_PAGE } from '../urls/navigation'; diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_search_or_filter.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_search_or_filter.spec.ts index 0668b91ca4fc1..00994f7a87a7b 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_search_or_filter.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_search_or_filter.spec.ts @@ -7,7 +7,7 @@ import { SERVER_SIDE_EVENT_COUNT } from '../screens/timeline'; import { loginAndWaitForPage } from '../tasks/login'; -import { openTimeline } from '../tasks/siem_main'; +import { openTimeline } from '../tasks/security_main'; import { executeTimelineKQL } from '../tasks/timeline'; import { HOSTS_PAGE } from '../urls/navigation'; diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_toggle_column.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_toggle_column.spec.ts index 7b2c6f3b55b2e..841d41782b350 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_toggle_column.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_toggle_column.spec.ts @@ -12,7 +12,7 @@ import { } from '../screens/timeline'; import { loginAndWaitForPage } from '../tasks/login'; -import { openTimeline } from '../tasks/siem_main'; +import { openTimeline } from '../tasks/security_main'; import { checkIdToggleField, createNewTimeline, diff --git a/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts b/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts index cf69a83dbf951..425ed23bdafec 100644 --- a/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/url_state.spec.ts @@ -13,7 +13,7 @@ import { } from '../screens/date_picker'; import { HOSTS_NAMES } from '../screens/hosts/all_hosts'; import { ANOMALIES_TAB } from '../screens/hosts/main'; -import { BREADCRUMBS, HOSTS, KQL_INPUT, NETWORK } from '../screens/siem_header'; +import { BREADCRUMBS, HOSTS, KQL_INPUT, NETWORK } from '../screens/security_header'; import { SERVER_SIDE_EVENT_COUNT, TIMELINE_TITLE } from '../screens/timeline'; import { loginAndWaitForPage, loginAndWaitForPageWithoutDateRange } from '../tasks/login'; @@ -29,8 +29,8 @@ import { openFirstHostDetails, waitForAllHostsToBeLoaded } from '../tasks/hosts/ import { openAllHosts } from '../tasks/hosts/main'; import { waitForIpsTableToBeLoaded } from '../tasks/network/flows'; -import { clearSearchBar, kqlSearch, navigateFromHeaderTo } from '../tasks/siem_header'; -import { openTimeline } from '../tasks/siem_main'; +import { clearSearchBar, kqlSearch, navigateFromHeaderTo } from '../tasks/security_header'; +import { openTimeline } from '../tasks/security_main'; import { addDescriptionToTimeline, addNameToTimeline, @@ -243,7 +243,7 @@ describe('url state', () => { cy.wrap(intCount).should('be.above', 0); }); - const timelineName = 'SIEM'; + const timelineName = 'Security'; addNameToTimeline(timelineName); addDescriptionToTimeline('This is the best timeline of the world'); cy.wait(5000); diff --git a/x-pack/plugins/security_solution/cypress/screens/inspect.ts b/x-pack/plugins/security_solution/cypress/screens/inspect.ts index 8f2ff4ef401e7..f472509bda6b5 100644 --- a/x-pack/plugins/security_solution/cypress/screens/inspect.ts +++ b/x-pack/plugins/security_solution/cypress/screens/inspect.ts @@ -14,7 +14,7 @@ export interface InspectButtonMetadata { tabId?: string; } -export const INSPECT_HOSTS_BUTTONS_IN_SIEM: InspectButtonMetadata[] = [ +export const INSPECT_HOSTS_BUTTONS_IN_SECURITY: InspectButtonMetadata[] = [ { id: '[data-test-subj="stat-hosts"]', title: 'Hosts Stat', @@ -50,7 +50,7 @@ export const INSPECT_HOSTS_BUTTONS_IN_SIEM: InspectButtonMetadata[] = [ }, ]; -export const INSPECT_NETWORK_BUTTONS_IN_SIEM: InspectButtonMetadata[] = [ +export const INSPECT_NETWORK_BUTTONS_IN_SECURITY: InspectButtonMetadata[] = [ { id: '[data-test-subj="stat-networkEvents"]', title: 'Network events Stat', diff --git a/x-pack/plugins/security_solution/cypress/screens/siem_header.ts b/x-pack/plugins/security_solution/cypress/screens/security_header.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/screens/siem_header.ts rename to x-pack/plugins/security_solution/cypress/screens/security_header.ts diff --git a/x-pack/plugins/security_solution/cypress/screens/siem_main.ts b/x-pack/plugins/security_solution/cypress/screens/security_main.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/screens/siem_main.ts rename to x-pack/plugins/security_solution/cypress/screens/security_main.ts diff --git a/x-pack/plugins/security_solution/cypress/support/commands.js b/x-pack/plugins/security_solution/cypress/support/commands.js index d086981cb98f7..8b75f068a53da 100644 --- a/x-pack/plugins/security_solution/cypress/support/commands.js +++ b/x-pack/plugins/security_solution/cypress/support/commands.js @@ -30,7 +30,7 @@ // -- This is will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) -Cypress.Commands.add('stubSIEMapi', function (dataFileName) { +Cypress.Commands.add('stubSecurityApi', function (dataFileName) { cy.on('window:before:load', (win) => { // @ts-ignore no null, this is a temp hack see issue above win.fetch = null; diff --git a/x-pack/plugins/security_solution/cypress/support/index.d.ts b/x-pack/plugins/security_solution/cypress/support/index.d.ts index 5d5173170a9f9..12c11ffd27750 100644 --- a/x-pack/plugins/security_solution/cypress/support/index.d.ts +++ b/x-pack/plugins/security_solution/cypress/support/index.d.ts @@ -6,6 +6,6 @@ declare namespace Cypress { interface Chainable { - stubSIEMapi(dataFileName: string): Chainable; + stubSecurityApi(dataFileName: string): Chainable; } } diff --git a/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts b/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts index 8ff8fbf4b0cb7..b39cbeba7b85e 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts @@ -15,7 +15,7 @@ import { URL, USERNAME, } from '../screens/configure_cases'; -import { MAIN_PAGE } from '../screens/siem_main'; +import { MAIN_PAGE } from '../screens/security_main'; import { Connector } from '../objects/case'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/detections.ts b/x-pack/plugins/security_solution/cypress/tasks/detections.ts index f53dd83635d85..a6596bfbcc3e9 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/detections.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/detections.ts @@ -16,7 +16,7 @@ import { ALERTS, ALERT_CHECKBOX, } from '../screens/detections'; -import { REFRESH_BUTTON } from '../screens/siem_header'; +import { REFRESH_BUTTON } from '../screens/security_header'; export const closeFirstAlert = () => { cy.get(OPEN_CLOSE_ALERT_BTN).first().click({ force: true }); diff --git a/x-pack/plugins/security_solution/cypress/tasks/hosts/authentications.ts b/x-pack/plugins/security_solution/cypress/tasks/hosts/authentications.ts index 7ba7f227964ab..cd64fe4ff1726 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/hosts/authentications.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/hosts/authentications.ts @@ -5,7 +5,7 @@ */ import { AUTHENTICATIONS_TABLE } from '../../screens/hosts/authentications'; -import { REFRESH_BUTTON } from '../../screens/siem_header'; +import { REFRESH_BUTTON } from '../../screens/security_header'; export const waitForAuthenticationsToBeLoaded = () => { cy.get(AUTHENTICATIONS_TABLE).should('exist'); diff --git a/x-pack/plugins/security_solution/cypress/tasks/hosts/uncommon_processes.ts b/x-pack/plugins/security_solution/cypress/tasks/hosts/uncommon_processes.ts index c86b169d60a13..598def9ed41d0 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/hosts/uncommon_processes.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/hosts/uncommon_processes.ts @@ -5,7 +5,7 @@ */ import { UNCOMMON_PROCESSES_TABLE } from '../../screens/hosts/uncommon_processes'; -import { REFRESH_BUTTON } from '../../screens/siem_header'; +import { REFRESH_BUTTON } from '../../screens/security_header'; export const waitForUncommonProcessesToBeLoaded = () => { cy.get(UNCOMMON_PROCESSES_TABLE).should('exist'); diff --git a/x-pack/plugins/security_solution/cypress/tasks/siem_header.ts b/x-pack/plugins/security_solution/cypress/tasks/security_header.ts similarity index 90% rename from x-pack/plugins/security_solution/cypress/tasks/siem_header.ts rename to x-pack/plugins/security_solution/cypress/tasks/security_header.ts index 2cc9199a42bbb..7427104a9d889 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/siem_header.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/security_header.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { KQL_INPUT, REFRESH_BUTTON } from '../screens/siem_header'; +import { KQL_INPUT, REFRESH_BUTTON } from '../screens/security_header'; export const clearSearchBar = () => { cy.get(KQL_INPUT).clear().type('{enter}'); diff --git a/x-pack/plugins/security_solution/cypress/tasks/siem_main.ts b/x-pack/plugins/security_solution/cypress/tasks/security_main.ts similarity index 86% rename from x-pack/plugins/security_solution/cypress/tasks/siem_main.ts rename to x-pack/plugins/security_solution/cypress/tasks/security_main.ts index eece7edcb2b44..47b73db8b96df 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/siem_main.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/security_main.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { MAIN_PAGE, TIMELINE_TOGGLE_BUTTON } from '../screens/siem_main'; +import { MAIN_PAGE, TIMELINE_TOGGLE_BUTTON } from '../screens/security_main'; export const openTimeline = () => { cy.get(TIMELINE_TOGGLE_BUTTON).click(); From 3eced03bb180c43b00300416bb575b6bea399173 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Wed, 10 Jun 2020 12:01:13 +0200 Subject: [PATCH 22/53] [SIEM] Fixes flyout flaky test (#68683) * fixes flaky test * Update x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts Co-authored-by: patrykkopycinski Co-authored-by: patrykkopycinski --- .../cypress/integration/timeline_flyout_button.spec.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts index fe420ae9dccbb..e462d6ade5dc4 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_flyout_button.spec.ts @@ -29,14 +29,13 @@ describe('timeline flyout button', () => { cy.get(TIMELINE_FLYOUT_HEADER).should('have.css', 'visibility', 'visible'); }); - // FLAKY: https://github.com/elastic/kibana/issues/60369 - it.skip('sets the flyout button background to euiColorSuccess with a 10% alpha channel when the user starts dragging a host, but is not hovering over the flyout button', () => { + it('sets the flyout button background to euiColorSuccess with a 20% alpha channel when the user starts dragging a host, but is not hovering over the flyout button', () => { dragFirstHostToTimeline(); cy.get(TIMELINE_NOT_READY_TO_DROP_BUTTON).should( 'have.css', 'background', - 'rgba(1, 125, 115, 0.1) none repeat scroll 0% 0% / auto padding-box border-box' + 'rgba(1, 125, 115, 0.2) none repeat scroll 0% 0% / auto padding-box border-box' ); }); }); From 83771811e05dc9cb427353eca8b96517ad9a2a68 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Wed, 10 Jun 2020 08:08:57 -0400 Subject: [PATCH 23/53] [SIEM][Detections Engine] - Exceptions viewer cleanup (#68651) ### Summary This PR is a follow up to #68027 where some feedback didn't make it in. It cleans up the and_or_badge component, updates some css, and cleans up stories. --- .../__examples__/index.stories.tsx | 37 ++++---- .../components/and_or_badge/index.test.tsx | 18 +++- .../common/components/and_or_badge/index.tsx | 93 +------------------ .../and_or_badge/rounded_badge.test.tsx | 34 +++++++ .../components/and_or_badge/rounded_badge.tsx | 42 +++++++++ .../rounded_badge_antenna.test.tsx | 46 +++++++++ .../and_or_badge/rounded_badge_antenna.tsx | 62 +++++++++++++ .../__examples__/exception_item.stories.tsx | 89 +++++++++--------- .../components/exceptions/helpers.test.tsx | 8 +- .../common/components/exceptions/helpers.tsx | 4 +- .../exception_item/exception_details.tsx | 51 +++++----- .../exception_item/exception_entries.test.tsx | 34 +++---- .../exception_item/exception_entries.tsx | 28 ++++-- .../viewer/exception_item/index.test.tsx | 36 +++---- .../viewer/exception_item/index.tsx | 32 +++---- .../components/exceptions/viewer/index.tsx | 8 +- .../security_solution/public/graphql/types.ts | 2 + .../security_solution/scripts/storybook.js | 2 +- 18 files changed, 371 insertions(+), 255 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/and_or_badge/__examples__/index.stories.tsx b/x-pack/plugins/security_solution/public/common/components/and_or_badge/__examples__/index.stories.tsx index f939cf81d1bd3..7465d3ca1e63a 100644 --- a/x-pack/plugins/security_solution/public/common/components/and_or_badge/__examples__/index.stories.tsx +++ b/x-pack/plugins/security_solution/public/common/components/and_or_badge/__examples__/index.stories.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { storiesOf } from '@storybook/react'; -import React from 'react'; +import React, { ReactNode } from 'react'; import { ThemeProvider } from 'styled-components'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; @@ -14,26 +14,21 @@ import { AndOrBadge } from '..'; const sampleText = 'Doggo ipsum i am bekom fat snoot wow such tempt waggy wags floofs, ruff heckin good boys and girls mlem. Ruff heckin good boys and girls mlem stop it fren borkf borking doggo very hand that feed shibe, you are doing me the shock big ol heck smol borking doggo with a long snoot for pats heckin good boys. You are doing me the shock smol borking doggo with a long snoot for pats wow very biscit, length boy. Doggo ipsum i am bekom fat snoot wow such tempt waggy wags floofs, ruff heckin good boys and girls mlem. Ruff heckin good boys and girls mlem stop it fren borkf borking doggo very hand that feed shibe, you are doing me the shock big ol heck smol borking doggo with a long snoot for pats heckin good boys.'; +const withTheme = (storyFn: () => ReactNode) => ( + ({ eui: euiLightVars, darkMode: true })}>{storyFn()} +); + storiesOf('components/AndOrBadge', module) - .add('and', () => ( - ({ eui: euiLightVars, darkMode: true })}> - - - )) - .add('or', () => ( - ({ eui: euiLightVars, darkMode: true })}> - - - )) + .addDecorator(withTheme) + .add('and', () => ) + .add('or', () => ) .add('antennas', () => ( - ({ eui: euiLightVars, darkMode: true })}> - - - - - -

{sampleText}

-
-
-
+ + + + + +

{sampleText}

+
+
)); diff --git a/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.test.tsx index ed918a59a514a..f2c7d6884bae3 100644 --- a/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.test.tsx @@ -20,8 +20,20 @@ describe('AndOrBadge', () => { ); expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND'); - expect(wrapper.find('EuiFlexItem[data-test-subj="andOrBadgeBarTop"]')).toHaveLength(1); - expect(wrapper.find('EuiFlexItem[data-test-subj="andOrBadgeBarBottom"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="andOrBadgeBarTop"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="andOrBadgeBarBottom"]').exists()).toBeTruthy(); + }); + + test('it does not render top and bottom antenna bars when "includeAntennas" is false', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR'); + expect(wrapper.find('[data-test-subj="andOrBadgeBarTop"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="andOrBadgeBarBottom"]').exists()).toBeFalsy(); }); test('it renders "and" when "type" is "and"', () => { @@ -32,7 +44,6 @@ describe('AndOrBadge', () => { ); expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND'); - expect(wrapper.find('EuiFlexItem[data-test-subj="and-or-badge-bar"]')).toHaveLength(0); }); test('it renders "or" when "type" is "or"', () => { @@ -43,6 +54,5 @@ describe('AndOrBadge', () => { ); expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR'); - expect(wrapper.find('EuiFlexItem[data-test-subj="and-or-badge-bar"]')).toHaveLength(0); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.tsx b/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.tsx index ba3f880d9757e..e427e57a2c616 100644 --- a/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/and_or_badge/index.tsx @@ -3,70 +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 { EuiFlexGroup, EuiBadge, EuiFlexItem } from '@elastic/eui'; import React from 'react'; -import styled, { css } from 'styled-components'; - -import * as i18n from './translations'; - -const AndOrBadgeAntenna = styled(EuiFlexItem)` - ${({ theme }) => css` - background: ${theme.eui.euiColorLightShade}; - position: relative; - width: 2px; - &:after { - background: ${theme.eui.euiColorLightShade}; - content: ''; - height: 8px; - right: -4px; - position: absolute; - width: 9px; - clip-path: circle(); - } - &.topAndOrBadgeAntenna { - &:after { - top: -1px; - } - } - &.bottomAndOrBadgeAntenna { - &:after { - bottom: -1px; - } - } - &.euiFlexItem { - margin: 0 12px 0 0; - } - `} -`; - -const EuiFlexItemWrapper = styled(EuiFlexItem)` - &.euiFlexItem { - margin: 0 12px 0 0; - } -`; -const RoundedBadge = (styled(EuiBadge)` - align-items: center; - border-radius: 100%; - display: inline-flex; - font-size: 9px; - height: 34px; - justify-content: center; - margin: 0 5px 0 5px; - padding: 7px 6px 4px 6px; - user-select: none; - width: 34px; - .euiBadge__content { - position: relative; - top: -1px; - } - .euiBadge__text { - text-overflow: clip; - } -` as unknown) as typeof EuiBadge; - -RoundedBadge.displayName = 'RoundedBadge'; +import { RoundedBadge } from './rounded_badge'; +import { RoundedBadgeAntenna } from './rounded_badge_antenna'; export type AndOr = 'and' | 'or'; @@ -74,34 +14,7 @@ export type AndOr = 'and' | 'or'; // Ref: https://github.com/elastic/eui/issues/1655 export const AndOrBadge = React.memo<{ type: AndOr; includeAntennas?: boolean }>( ({ type, includeAntennas = false }) => { - const getBadge = () => ( - - {type === 'and' ? i18n.AND : i18n.OR} - - ); - - const getBadgeWithAntennas = () => ( - - - {getBadge()} - - - ); - - return includeAntennas ? getBadgeWithAntennas() : getBadge(); + return includeAntennas ? : ; } ); diff --git a/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.test.tsx b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.test.tsx new file mode 100644 index 0000000000000..14d9627d48ad7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.test.tsx @@ -0,0 +1,34 @@ +/* + * 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 { ThemeProvider } from 'styled-components'; +import { mount } from 'enzyme'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { RoundedBadge } from './rounded_badge'; + +describe('RoundedBadge', () => { + test('it renders "and" when "type" is "and"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND'); + }); + + test('it renders "or" when "type" is "or"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.tsx b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.tsx new file mode 100644 index 0000000000000..1a03e8c73f252 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiBadge } from '@elastic/eui'; +import React from 'react'; +import styled from 'styled-components'; + +import * as i18n from './translations'; +import { AndOr } from '.'; + +const RoundBadge = (styled(EuiBadge)` + align-items: center; + border-radius: 100%; + display: inline-flex; + font-size: 9px; + height: 34px; + justify-content: center; + margin: 0 5px 0 5px; + padding: 7px 6px 4px 6px; + user-select: none; + width: 34px; + .euiBadge__content { + position: relative; + top: -1px; + } + .euiBadge__text { + text-overflow: clip; + } +` as unknown) as typeof EuiBadge; + +RoundBadge.displayName = 'RoundBadge'; + +export const RoundedBadge: React.FC<{ type: AndOr }> = ({ type }) => ( + + {type === 'and' ? i18n.AND : i18n.OR} + +); + +RoundedBadge.displayName = 'RoundedBadge'; diff --git a/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.test.tsx b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.test.tsx new file mode 100644 index 0000000000000..e6362f8798fa6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.test.tsx @@ -0,0 +1,46 @@ +/* + * 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 { ThemeProvider } from 'styled-components'; +import { mount } from 'enzyme'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { RoundedBadgeAntenna } from './rounded_badge_antenna'; + +describe('RoundedBadgeAntenna', () => { + test('it renders top and bottom antenna bars', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND'); + expect(wrapper.find('[data-test-subj="andOrBadgeBarTop"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="andOrBadgeBarBottom"]').exists()).toBeTruthy(); + }); + + test('it renders "and" when "type" is "and"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND'); + }); + + test('it renders "or" when "type" is "or"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.tsx b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.tsx new file mode 100644 index 0000000000000..1076d8b41b955 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/and_or_badge/rounded_badge_antenna.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React from 'react'; +import styled, { css } from 'styled-components'; + +import { RoundedBadge } from './rounded_badge'; +import { AndOr } from '.'; + +const antennaStyles = css` + background: ${({ theme }) => theme.eui.euiColorLightShade}; + position: relative; + width: 2px; + margin: 0 12px 0 0; + &:after { + background: ${({ theme }) => theme.eui.euiColorLightShade}; + content: ''; + height: 8px; + right: -4px; + position: absolute; + width: 10px; + clip-path: circle(); + } +`; + +const TopAntenna = styled(EuiFlexItem)` + ${antennaStyles} + &:after { + top: 0; + } +`; +const BottomAntenna = styled(EuiFlexItem)` + ${antennaStyles} + &:after { + bottom: 0; + } +`; + +const EuiFlexItemWrapper = styled(EuiFlexItem)` + margin: 0 12px 0 0; +`; + +export const RoundedBadgeAntenna: React.FC<{ type: AndOr }> = ({ type }) => ( + + + + + + + +); + +RoundedBadgeAntenna.displayName = 'RoundedBadgeAntenna'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx index 8942832798a5e..5f2b0b93e9df0 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { storiesOf } from '@storybook/react'; -import React from 'react'; +import React, { ReactNode } from 'react'; import { ThemeProvider } from 'styled-components'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; @@ -12,8 +12,13 @@ import { ExceptionItem } from '../viewer/exception_item'; import { Operator } from '../types'; import { getExceptionItemMock } from '../mocks'; +const withTheme = (storyFn: () => ReactNode) => ( + ({ eui: euiLightVars, darkMode: false })}>{storyFn()} +); + storiesOf('ExceptionItem', module) - .add('with os', () => { + .addDecorator(withTheme) + .add('ExceptionItem/with os', () => { const payload = getExceptionItemMock(); payload.description = ''; payload.comment = []; @@ -27,15 +32,13 @@ storiesOf('ExceptionItem', module) ]; return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - handleEdit={() => {}} - /> - + {}} + onEditException={() => {}} + /> ); }) .add('with description', () => { @@ -52,15 +55,13 @@ storiesOf('ExceptionItem', module) ]; return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - handleEdit={() => {}} - /> - + {}} + onEditException={() => {}} + /> ); }) .add('with comments', () => { @@ -77,15 +78,13 @@ storiesOf('ExceptionItem', module) ]; return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - handleEdit={() => {}} - /> - + {}} + onEditException={() => {}} + /> ); }) .add('with nested entries', () => { @@ -95,29 +94,25 @@ storiesOf('ExceptionItem', module) payload.comment = []; return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - handleEdit={() => {}} - /> - + {}} + onEditException={() => {}} + /> ); }) .add('with everything', () => { const payload = getExceptionItemMock(); return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - handleEdit={() => {}} - /> - + {}} + onEditException={() => {}} + /> ); }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx index 7698605588e76..2893c7dc961f2 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx @@ -10,7 +10,7 @@ import moment from 'moment-timezone'; import { getOperatorType, getExceptionOperatorSelect, - determineIfIsNested, + isEntryNested, getFormattedEntries, formatEntry, getOperatingSystems, @@ -159,21 +159,21 @@ describe('Exception helpers', () => { }); }); - describe('#determineIfIsNested', () => { + describe('#isEntryNested', () => { test('it returns true if type NestedExceptionEntry', () => { const payload: NestedExceptionEntry = { field: 'actingProcess.file.signer', type: 'nested', entries: [], }; - const result = determineIfIsNested(payload); + const result = isEntryNested(payload); expect(result).toBeTruthy(); }); test('it returns false if NOT type NestedExceptionEntry', () => { const payload = getExceptionItemEntryMock(); - const result = determineIfIsNested(payload); + const result = isEntryNested(payload); expect(result).toBeFalsy(); }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx index bd22de636bf6c..155c8a3e2926c 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx @@ -56,7 +56,7 @@ export const getExceptionOperatorSelect = (entry: ExceptionEntry): OperatorOptio return foundOperator ?? isOperator; }; -export const determineIfIsNested = ( +export const isEntryNested = ( tbd: ExceptionEntry | NestedExceptionEntry ): tbd is NestedExceptionEntry => { if (tbd.type === 'nested') { @@ -75,7 +75,7 @@ export const getFormattedEntries = ( entries: Array ): FormattedEntry[] => { const formattedEntries = entries.map((entry) => { - if (determineIfIsNested(entry)) { + if (isEntryNested(entry)) { const parent = { fieldName: entry.field, operator: null, value: null, isNested: false }; return entry.entries.reduce( (acc, nestedEntry) => { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx index 6f418808b239a..12287f7cd0fa9 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx @@ -4,28 +4,34 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexItem, EuiFlexGroup, EuiDescriptionList, EuiButtonEmpty } from '@elastic/eui'; -import React, { useMemo } from 'react'; +import { + EuiFlexItem, + EuiFlexGroup, + EuiDescriptionList, + EuiButtonEmpty, + EuiDescriptionListTitle, + EuiDescriptionListDescription, +} from '@elastic/eui'; +import React, { useMemo, Fragment } from 'react'; import styled, { css } from 'styled-components'; -import { transparentize } from 'polished'; -import { ExceptionListItemSchema } from '../../types'; +import { DescriptionListItem, ExceptionListItemSchema } from '../../types'; import { getDescriptionListContent } from '../../helpers'; import * as i18n from '../../translations'; const StyledExceptionDetails = styled(EuiFlexItem)` ${({ theme }) => css` - background-color: ${transparentize(0.95, theme.eui.euiColorPrimary)}; + background-color: ${theme.eui.euiColorLightestShade}; padding: ${theme.eui.euiSize}; + `} +`; - .euiDescriptionList__title.listTitle--width { - width: 40%; - } +const MyDescriptionListTitle = styled(EuiDescriptionListTitle)` + width: 40%; +`; - .euiDescriptionList__description.listDescription--width { - width: 60%; - } - `} +const MyDescriptionListDescription = styled(EuiDescriptionListDescription)` + width: 60%; `; const ExceptionDetailsComponent = ({ @@ -37,7 +43,10 @@ const ExceptionDetailsComponent = ({ exceptionItem: ExceptionListItemSchema; onCommentsClick: () => void; }): JSX.Element => { - const descriptionList = useMemo(() => getDescriptionListContent(exceptionItem), [exceptionItem]); + const descriptionListItems = useMemo( + (): DescriptionListItem[] => getDescriptionListContent(exceptionItem), + [exceptionItem] + ); const commentsSection = useMemo((): JSX.Element => { // TODO: return back to exceptionItem.comments once updated @@ -62,14 +71,14 @@ const ExceptionDetailsComponent = ({ - + + {descriptionListItems.map((item) => ( + + {item.title} + {item.description} + + ))} + {commentsSection} diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx index 10f11231ace01..b2408a654b1c6 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx @@ -20,8 +20,8 @@ describe('ExceptionEntries', () => { ); @@ -35,8 +35,8 @@ describe('ExceptionEntries', () => { ); @@ -45,39 +45,39 @@ describe('ExceptionEntries', () => { }); test('it invokes "handlEdit" when edit button clicked', () => { - const mockHandleEdit = jest.fn(); + const mockOnEdit = jest.fn(); const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> ); const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button').at(0); editBtn.simulate('click'); - expect(mockHandleEdit).toHaveBeenCalledTimes(1); + expect(mockOnEdit).toHaveBeenCalledTimes(1); }); - test('it invokes "handleDelete" when delete button clicked', () => { - const mockHandleDelete = jest.fn(); + test('it invokes "onDelete" when delete button clicked', () => { + const mockOnDelete = jest.fn(); const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> ); const deleteBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0); deleteBtn.simulate('click'); - expect(mockHandleDelete).toHaveBeenCalledTimes(1); + expect(mockOnDelete).toHaveBeenCalledTimes(1); }); test('it renders nested entry', () => { @@ -90,8 +90,8 @@ describe('ExceptionEntries', () => { ); @@ -132,8 +132,8 @@ describe('ExceptionEntries', () => { ); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx index 6f29875784e61..8c758e3b84f42 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx @@ -11,6 +11,7 @@ import { EuiFlexGroup, EuiButton, EuiTableFieldDataColumnType, + EuiHideFor, } from '@elastic/eui'; import React, { useMemo } from 'react'; import styled, { css } from 'styled-components'; @@ -48,15 +49,15 @@ const AndOrBadgeContainer = styled(EuiFlexItem)` interface ExceptionEntriesComponentProps { entries: FormattedEntry[]; disableDelete: boolean; - handleDelete: () => void; - handleEdit: () => void; + onDelete: () => void; + onEdit: () => void; } const ExceptionEntriesComponent = ({ entries, disableDelete, - handleDelete, - handleEdit, + onDelete, + onEdit, }: ExceptionEntriesComponentProps): JSX.Element => { const columns = useMemo( (): Array> => [ @@ -65,6 +66,7 @@ const ExceptionEntriesComponent = ({ name: 'Field', sortable: false, truncateText: true, + textOnly: true, 'data-test-subj': 'exceptionFieldNameCell', width: '30%', render: (value: string | null, data: FormattedEntry) => { @@ -121,9 +123,15 @@ const ExceptionEntriesComponent = ({ {entries.length > 1 && ( - - - + + + + + )} - + @@ -153,7 +161,7 @@ const ExceptionEntriesComponent = ({ diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx index 784fc4336a5ff..dca3afe4f9069 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx @@ -21,8 +21,8 @@ describe('ExceptionItem', () => { @@ -32,8 +32,8 @@ describe('ExceptionItem', () => { expect(wrapper.find('ExceptionEntries')).toHaveLength(1); }); - it('it invokes "handleEdit" when edit button clicked', () => { - const mockHandleEdit = jest.fn(); + it('it invokes "onEditException" when edit button clicked', () => { + const mockOnEditException = jest.fn(); const exceptionItem = getExceptionItemMock(); const wrapper = mount( @@ -41,8 +41,8 @@ describe('ExceptionItem', () => { @@ -51,11 +51,11 @@ describe('ExceptionItem', () => { const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button').at(0); editBtn.simulate('click'); - expect(mockHandleEdit).toHaveBeenCalledTimes(1); + expect(mockOnEditException).toHaveBeenCalledTimes(1); }); - it('it invokes "handleDelete" when delete button clicked', () => { - const mockHandleDelete = jest.fn(); + it('it invokes "onDeleteException" when delete button clicked', () => { + const mockOnDeleteException = jest.fn(); const exceptionItem = getExceptionItemMock(); const wrapper = mount( @@ -63,8 +63,8 @@ describe('ExceptionItem', () => { @@ -73,11 +73,11 @@ describe('ExceptionItem', () => { const editBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0); editBtn.simulate('click'); - expect(mockHandleDelete).toHaveBeenCalledTimes(1); + expect(mockOnDeleteException).toHaveBeenCalledTimes(1); }); it('it renders comment accordion closed to begin with', () => { - const mockHandleDelete = jest.fn(); + const mockOnDeleteException = jest.fn(); const exceptionItem = getExceptionItemMock(); const wrapper = mount( @@ -85,8 +85,8 @@ describe('ExceptionItem', () => { @@ -96,7 +96,7 @@ describe('ExceptionItem', () => { }); it('it renders comment accordion open when showComments is true', () => { - const mockHandleDelete = jest.fn(); + const mockOnDeleteException = jest.fn(); const exceptionItem = getExceptionItemMock(); const wrapper = mount( @@ -104,8 +104,8 @@ describe('ExceptionItem', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx index 386ab6f3c3c7c..ba6ffb109be04 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.tsx @@ -21,26 +21,26 @@ import { getFormattedEntries, getFormattedComments } from '../../helpers'; import { FormattedEntry, ExceptionListItemSchema, ApiProps } from '../../types'; const MyFlexItem = styled(EuiFlexItem)` - &.comments--show { - padding: ${({ theme }) => theme.eui.euiSize}; - border-top: ${({ theme }) => `${theme.eui.euiBorderThin}`} - + &.comments--show { + padding: ${({ theme }) => theme.eui.euiSize}; + border-top: ${({ theme }) => `${theme.eui.euiBorderThin}`}; + } `; interface ExceptionItemProps { loadingItemIds: ApiProps[]; exceptionItem: ExceptionListItemSchema; commentsAccordionId: string; - handleDelete: (arg: ApiProps) => void; - handleEdit: (item: ExceptionListItemSchema) => void; + onDeleteException: (arg: ApiProps) => void; + onEditException: (item: ExceptionListItemSchema) => void; } const ExceptionItemComponent = ({ loadingItemIds, exceptionItem, commentsAccordionId, - handleDelete, - handleEdit, + onDeleteException, + onEditException, }: ExceptionItemProps): JSX.Element => { const [entryItems, setEntryItems] = useState([]); const [showComments, setShowComments] = useState(false); @@ -50,13 +50,13 @@ const ExceptionItemComponent = ({ setEntryItems(formattedEntries); }, [exceptionItem.entries]); - const onDelete = useCallback((): void => { - handleDelete({ id: exceptionItem.id, namespaceType: exceptionItem.namespace_type }); - }, [handleDelete, exceptionItem]); + const handleDelete = useCallback((): void => { + onDeleteException({ id: exceptionItem.id, namespaceType: exceptionItem.namespace_type }); + }, [onDeleteException, exceptionItem]); - const onEdit = useCallback((): void => { - handleEdit(exceptionItem); - }, [handleEdit, exceptionItem]); + const handleEdit = useCallback((): void => { + onEditException(exceptionItem); + }, [onEditException, exceptionItem]); const onCommentsClick = useCallback((): void => { setShowComments(!showComments); @@ -85,8 +85,8 @@ const ExceptionItemComponent = ({ diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx index ff52e395c3b1e..3cf59c7dda023 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx @@ -195,7 +195,7 @@ const ExceptionsViewerComponent = ({ [setIsModalOpen] ); - const onEditExceptionItem = useCallback( + const handleEditException = useCallback( (exception: ExceptionListItemSchema): void => { // TODO: Added this just for testing. Update // modal state logic as needed once ready @@ -234,7 +234,7 @@ const ExceptionsViewerComponent = ({ [dispatch] ); - const onDeleteException = useCallback( + const handleDeleteException = useCallback( ({ id, namespaceType }: ApiProps) => { deleteExceptionItem({ id, @@ -395,8 +395,8 @@ const ExceptionsViewerComponent = ({ loadingItemIds={loadingItemIds} commentsAccordionId={commentsAccordionId} exceptionItem={exception} - handleDelete={onDeleteException} - handleEdit={onEditExceptionItem} + onDeleteException={handleDeleteException} + onEditException={handleEditException} /> ))} diff --git a/x-pack/plugins/security_solution/public/graphql/types.ts b/x-pack/plugins/security_solution/public/graphql/types.ts index 628d56ebb647c..dc4a8ae78bf46 100644 --- a/x-pack/plugins/security_solution/public/graphql/types.ts +++ b/x-pack/plugins/security_solution/public/graphql/types.ts @@ -4340,6 +4340,8 @@ export namespace GetAllTimeline { pinnedEventIds: Maybe; + status: Maybe; + title: Maybe; timelineType: Maybe; diff --git a/x-pack/plugins/security_solution/scripts/storybook.js b/x-pack/plugins/security_solution/scripts/storybook.js index 5f06f2a4ebb12..cd4d16d89c48d 100644 --- a/x-pack/plugins/security_solution/scripts/storybook.js +++ b/x-pack/plugins/security_solution/scripts/storybook.js @@ -9,5 +9,5 @@ import { join } from 'path'; // eslint-disable-next-line require('@kbn/storybook').runStorybookCli({ name: 'siem', - storyGlobs: [join(__dirname, '..', 'public', '**', 'components', '**', '*.stories.tsx')], + storyGlobs: [join(__dirname, '..', 'public', '**', '*.stories.tsx')], }); From 951114d66b66d3af8edb31c10693e2f9b8314a38 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Wed, 10 Jun 2020 05:47:04 -0700 Subject: [PATCH 24/53] [Metrics UI] Fix fatal error when no data is available for Metric Threshold Alerts (#68678) * [Metrics UI] Fix fatal error when no data is available for Metric Threshold Alerts * Adding i18n support for error message * Adding test --- .../components/expression_chart.test.tsx | 119 ++++++++++++++++++ .../components/expression_chart.tsx | 9 +- 2 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx new file mode 100644 index 0000000000000..0b43883728a6f --- /dev/null +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; +import { actionTypeRegistryMock } from '../../../../../triggers_actions_ui/public/application/action_type_registry.mock'; +import { alertTypeRegistryMock } from '../../../../../triggers_actions_ui/public/application/alert_type_registry.mock'; +import { coreMock } from '../../../../../../../src/core/public/mocks'; +import { AlertsContextValue } from '../../../../../triggers_actions_ui/public/application/context/alerts_context'; +import { AlertContextMeta, MetricExpression } from '../types'; +import { IIndexPattern } from 'src/plugins/data/public'; +import { InfraSource } from '../../../../common/http_api/source_api'; +import React from 'react'; +import { ExpressionChart } from './expression_chart'; +import { act } from 'react-dom/test-utils'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { Aggregators, Comparator } from '../../../../server/lib/alerting/metric_threshold/types'; +import { MetricsExplorerResponse } from '../../../../common/http_api'; + +describe('ExpressionChart', () => { + async function setup( + expression: MetricExpression, + response: MetricsExplorerResponse | null, + filterQuery?: string, + groupBy?: string + ) { + const mocks = coreMock.createSetup(); + const [ + { + application: { capabilities }, + }, + ] = await mocks.getStartServices(); + + const context: AlertsContextValue = { + http: mocks.http, + toastNotifications: mocks.notifications.toasts, + actionTypeRegistry: actionTypeRegistryMock.create() as any, + alertTypeRegistry: alertTypeRegistryMock.create() as any, + docLinks: mocks.docLinks, + capabilities: { + ...capabilities, + actions: { + delete: true, + save: true, + show: true, + }, + }, + }; + const derivedIndexPattern: IIndexPattern = { + title: 'metricbeat-*', + fields: [], + }; + + const source: InfraSource = { + id: 'default', + origin: 'fallback', + configuration: { + name: 'default', + description: 'The default configuration', + logColumns: [], + metricAlias: 'metricbeat-*', + logAlias: 'filebeat-*', + fields: { + timestamp: '@timestamp', + message: ['message'], + container: 'container.id', + host: 'host.name', + pod: 'kubernetes.pod.uid', + tiebreaker: '_doc', + }, + }, + }; + + mocks.http.fetch.mockImplementation(() => Promise.resolve(response)); + + const wrapper = mountWithIntl( + + ); + + const update = async () => + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + await update(); + + return { wrapper, update, fetchMock: mocks.http.fetch }; + } + + it('should display no data message', async () => { + const expression: MetricExpression = { + aggType: Aggregators.AVERAGE, + timeSize: 1, + timeUnit: 'm', + sourceId: 'default', + threshold: [1], + comparator: Comparator.GT_OR_EQ, + }; + const response = { + pageInfo: { + afterKey: null, + total: 0, + }, + series: [{ id: 'Everything', rows: [], columns: [] }], + }; + const { wrapper } = await setup(expression, response); + expect(wrapper.find('[data-test-subj~="noChartData"]').exists()).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx index a886dccf105cf..64a9d27961499 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx @@ -111,10 +111,15 @@ export const ExpressionChart: React.FC = ({ // Creating a custom series where the ID is changed to 0 // so that we can get a proper domian const firstSeries = first(data.series); - if (!firstSeries) { + if (!firstSeries || !firstSeries.rows || firstSeries.rows.length === 0) { return ( - Oops, no chart data available + + + ); } From 08ca314faf095325ef18f985472c6d4e8246a609 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Wed, 10 Jun 2020 08:51:43 -0400 Subject: [PATCH 25/53] [Ingest Manager] Document fleet configuration flags (#66736) --- .../settings/ingest-manager-settings.asciidoc | 65 +++++++++++++++++++ docs/settings/settings-xkb.asciidoc | 1 + docs/setup/settings.asciidoc | 1 + 3 files changed, 67 insertions(+) create mode 100644 docs/settings/ingest-manager-settings.asciidoc diff --git a/docs/settings/ingest-manager-settings.asciidoc b/docs/settings/ingest-manager-settings.asciidoc new file mode 100644 index 0000000000000..15f64e344d7c6 --- /dev/null +++ b/docs/settings/ingest-manager-settings.asciidoc @@ -0,0 +1,65 @@ +[role="xpack"] +[[ingest-manager-settings-kb]] +=== {ingest-manager} settings in {kib} +++++ +{ingest-manager} settings +++++ + +You can configure `xpack.ingestManager` settings in your `kibana.yml`. +By default, {ingest-manager} is not enabled. You need to enable it. To use {fleet}, you also need to configure {kib} and {es} hosts. + +[[general-ingest-manager-settings-kb]] +==== General {ingest-manager} settings + +[cols="2*<"] +|=== +| `xpack.ingestManager.enabled` {ess-icon} + | Set to `true` to enable {ingest-manager}. +|=== + +[cols="2*<"] +|=== +| `xpack.ingestManager.epm.enabled` {ess-icon} + | Set to `true` (default) to enable {package-manager}. +|=== + +[cols="2*<"] +|=== +| `xpack.ingestManager.fleet.enabled` {ess-icon} + | Set to `true` (default) to enable {fleet}. +|=== + +[[ingest-manager-data-visualizer-settings]] + +==== {package-manager} settings + +[cols="2*<"] +|=== +| `xpack.ingestManager.epm.registryUrl` + | The address to use to reach {package-manager} registry. +|=== + +==== {fleet} settings + +[cols="2*<"] +|=== +| `xpack.ingestManager.fleet.kibana.host` + | The hostname used by {agent} for accessing {kib}. +|=== + +[cols="2*<"] +|=== +| `xpack.ingestManager.fleet.elasticsearch.host` + | The hostname used by {agent} for accessing {es}. +|=== + +[cols="2*<"] +|=== +| `xpack.ingestManager.fleet.tlsCheckDisabled` + | Set to `true` to allow {fleet} to run on a {kib} instance without TLS enabled. +|=== + +[NOTE] +==== +In {ecloud}, {fleet} flags are already configured. +==== diff --git a/docs/settings/settings-xkb.asciidoc b/docs/settings/settings-xkb.asciidoc index 4d594b4113e69..04fed0d6204b7 100644 --- a/docs/settings/settings-xkb.asciidoc +++ b/docs/settings/settings-xkb.asciidoc @@ -20,3 +20,4 @@ include::ml-settings.asciidoc[] include::reporting-settings.asciidoc[] include::spaces-settings.asciidoc[] include::i18n-settings.asciidoc[] +include::ingest-manager-settings.asciidoc[] diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index c4f5439e25489..62f4a615a86c7 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -643,3 +643,4 @@ include::secure-settings.asciidoc[] include::{kib-repo-dir}/settings/security-settings.asciidoc[] include::{kib-repo-dir}/settings/spaces-settings.asciidoc[] include::{kib-repo-dir}/settings/telemetry-settings.asciidoc[] +include::{docdir}/settings/ingest-manager-settings.asciidoc[] From dab193fa46722d3e043b2b741299c4adf5c5d5b9 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Wed, 10 Jun 2020 15:08:16 +0200 Subject: [PATCH 26/53] Renames detections missing parts (#68408) * renames SIEM for Security * changes from 'Security advanced settings' to 'Security Solution advanced settings' Co-authored-by: Elastic Machine --- .../components/rules/pre_packaged_rules/translations.ts | 2 +- .../alerts/components/rules/step_define_rule/translations.tsx | 4 ++-- .../detection_engine_user_unauthenticated.tsx | 2 +- .../alerts/pages/detection_engine/rules/translations.ts | 2 +- .../public/alerts/pages/detection_engine/translations.ts | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/pre_packaged_rules/translations.ts b/x-pack/plugins/security_solution/public/alerts/components/rules/pre_packaged_rules/translations.ts index b43ef8c615003..4d2ba8b861cce 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/pre_packaged_rules/translations.ts +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/pre_packaged_rules/translations.ts @@ -17,7 +17,7 @@ export const PRE_BUILT_MSG = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.prePackagedRules.emptyPromptMessage', { defaultMessage: - 'Elastic SIEM comes with prebuilt detection rules that run in the background and create alerts when their conditions are met. By default, all prebuilt rules are disabled and you select which rules you want to activate.', + 'Elastic Security comes with prebuilt detection rules that run in the background and create alerts when their conditions are met. By default, all prebuilt rules are disabled and you select which rules you want to activate.', } ); diff --git a/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/translations.tsx b/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/translations.tsx index a371db72d2ee1..860ed1831fdc6 100644 --- a/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/translations.tsx +++ b/x-pack/plugins/security_solution/public/alerts/components/rules/step_define_rule/translations.tsx @@ -23,7 +23,7 @@ export const INVALID_CUSTOM_QUERY = i18n.translate( export const CONFIG_INDICES = i18n.translate( 'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesFromConfigDescription', { - defaultMessage: 'Use Elasticsearch indices from SIEM advanced settings', + defaultMessage: 'Use Elasticsearch indices from Security Solution advanced settings', } ); @@ -38,7 +38,7 @@ export const INDEX_HELPER_TEXT = i18n.translate( 'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.indicesHelperDescription', { defaultMessage: - 'Enter the pattern of Elasticsearch indices where you would like this rule to run. By default, these will include index patterns defined in SIEM advanced settings.', + 'Enter the pattern of Elasticsearch indices where you would like this rule to run. By default, these will include index patterns defined in Security Solution advanced settings.', } ); diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_user_unauthenticated.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_user_unauthenticated.tsx index fc1fee1077bd6..a353be80c7239 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_user_unauthenticated.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/detection_engine_user_unauthenticated.tsx @@ -17,7 +17,7 @@ export const DetectionEngineUserUnauthenticated = React.memo(() => { Date: Wed, 10 Jun 2020 07:09:58 -0600 Subject: [PATCH 27/53] [Security] [Timeline] Fix filter manager bug (#68708) --- .../draggable_wrapper_hover_content.tsx | 16 +++++++--------- .../components/manage_timeline/index.tsx | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx index 4eeefdbe2fca0..f916f42fe41cd 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper_hover_content.tsx @@ -13,7 +13,7 @@ import { useAddToTimeline } from '../../hooks/use_add_to_timeline'; import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'; import { useKibana } from '../../lib/kibana'; import { createFilter } from '../add_filter_to_global_search_bar'; -import { StatefulTopN } from '../top_n'; +import { ACTIVE_TIMELINE_REDUX_ID, StatefulTopN } from '../top_n'; import { allowTopN } from './helpers'; import * as i18n from './translations'; @@ -34,7 +34,7 @@ const DraggableWrapperHoverContentComponent: React.FC = ({ field, onFilterAdded, showTopN, - timelineId, + timelineId = ACTIVE_TIMELINE_REDUX_ID, toggleTopN, value, }) => { @@ -44,13 +44,11 @@ const DraggableWrapperHoverContentComponent: React.FC = ({ kibana.services.data.query.filterManager, ]); const { getTimelineFilterManager } = useManageTimeline(); - const filterManager = useMemo( - () => - timelineId - ? getTimelineFilterManager(timelineId) ?? filterManagerBackup - : filterManagerBackup, - [timelineId, getTimelineFilterManager, filterManagerBackup] - ); + const filterManager = useMemo(() => getTimelineFilterManager(timelineId) ?? filterManagerBackup, [ + timelineId, + getTimelineFilterManager, + filterManagerBackup, + ]); const filterForValue = useCallback(() => { const filter = value?.length === 0 ? createFilter(field, undefined) : createFilter(field, value); diff --git a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx index 8856805e6b660..44d4ff3ec1980 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx @@ -61,7 +61,7 @@ type ActionManageTimeline = | { type: 'SET_TIMELINE_FILTER_MANAGER'; id: string; - payload: FilterManager; + payload: { filterManager: FilterManager }; }; export const timelineDefaults = { @@ -161,7 +161,7 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT dispatch({ type: 'SET_TIMELINE_FILTER_MANAGER', id, - payload: filterManager, + payload: { filterManager }, }); }, [] From d7d9544a6f7c9c98e55e3a474a3fba07207551e0 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 10 Jun 2020 09:25:49 -0400 Subject: [PATCH 28/53] [IM] Refactor component templates API integration tests (#68282) Co-authored-by: Elastic Machine --- .../index_management/component_templates.ts | 100 +++++++++++++----- .../index_management/lib/elasticsearch.js | 18 +++- 2 files changed, 88 insertions(+), 30 deletions(-) diff --git a/x-pack/test/api_integration/apis/management/index_management/component_templates.ts b/x-pack/test/api_integration/apis/management/index_management/component_templates.ts index 64bf03a043b55..10ab35714b1ce 100644 --- a/x-pack/test/api_integration/apis/management/index_management/component_templates.ts +++ b/x-pack/test/api_integration/apis/management/index_management/component_templates.ts @@ -16,11 +16,19 @@ export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('legacyEs'); - const { createComponentTemplate, deleteComponentTemplate } = initElasticsearchHelpers(es); + const { + createComponentTemplate, + cleanUpComponentTemplates, + deleteComponentTemplate, + } = initElasticsearchHelpers(es); describe('Component templates', function () { + after(async () => { + await cleanUpComponentTemplates(); + }); + describe('Get', () => { - const COMPONENT_NAME = 'test_component_template'; + const COMPONENT_NAME = 'test_get_component_template'; const COMPONENT = { template: { settings: { @@ -45,8 +53,16 @@ export default function ({ getService }: FtrProviderContext) { }, }; - before(() => createComponentTemplate({ body: COMPONENT, name: COMPONENT_NAME })); - after(() => deleteComponentTemplate(COMPONENT_NAME)); + // Create component template to verify GET requests + before(async () => { + try { + await createComponentTemplate({ body: COMPONENT, name: COMPONENT_NAME }, true); + } catch (err) { + // eslint-disable-next-line no-console + console.log('[Setup error] Error creating component template'); + throw err; + } + }); describe('all component templates', () => { it('should return an array of component templates', async () => { @@ -90,9 +106,15 @@ export default function ({ getService }: FtrProviderContext) { const COMPONENT_NAME = 'test_create_component_template'; const REQUIRED_FIELDS_COMPONENT_NAME = 'test_create_required_fields_component_template'; - after(() => { - deleteComponentTemplate(COMPONENT_NAME); - deleteComponentTemplate(REQUIRED_FIELDS_COMPONENT_NAME); + after(async () => { + // Clean up any component templates created in test cases + await Promise.all( + [COMPONENT_NAME, REQUIRED_FIELDS_COMPONENT_NAME].map(deleteComponentTemplate) + ).catch((err) => { + // eslint-disable-next-line no-console + console.log(`[Cleanup error] Error deleting component templates: ${err.message}`); + throw err; + }); }); it('should create a component template', async () => { @@ -167,7 +189,7 @@ export default function ({ getService }: FtrProviderContext) { }); describe('Update', () => { - const COMPONENT_NAME = 'test_component_template'; + const COMPONENT_NAME = 'test_update_component_template'; const COMPONENT = { template: { settings: { @@ -192,8 +214,16 @@ export default function ({ getService }: FtrProviderContext) { }, }; - before(() => createComponentTemplate({ body: COMPONENT, name: COMPONENT_NAME })); - after(() => deleteComponentTemplate(COMPONENT_NAME)); + before(async () => { + // Create component template that can be used to test PUT request + try { + await createComponentTemplate({ body: COMPONENT, name: COMPONENT_NAME }, true); + } catch (err) { + // eslint-disable-next-line no-console + console.log('[Setup error] Error creating component template'); + throw err; + } + }); it('should allow an existing component template to be updated', async () => { const uri = `${API_BASE_PATH}/component_templates/${COMPONENT_NAME}`; @@ -244,29 +274,44 @@ export default function ({ getService }: FtrProviderContext) { }, }; - it('should delete a component template', async () => { - // Create component template to be deleted - const COMPONENT_NAME = 'test_delete_component_template'; - createComponentTemplate({ body: COMPONENT, name: COMPONENT_NAME }); + const componentTemplateA = { body: COMPONENT, name: 'test_delete_component_template_a' }; + const componentTemplateB = { body: COMPONENT, name: 'test_delete_component_template_b' }; + const componentTemplateC = { body: COMPONENT, name: 'test_delete_component_template_c' }; + const componentTemplateD = { body: COMPONENT, name: 'test_delete_component_template_d' }; + + before(async () => { + // Create several component templates that can be used to test deletion + await Promise.all( + [ + componentTemplateA, + componentTemplateB, + componentTemplateC, + componentTemplateD, + ].map((template) => createComponentTemplate(template, false)) + ).catch((err) => { + // eslint-disable-next-line no-console + console.log(`[Setup error] Error creating component templates: ${err.message}`); + throw err; + }); + }); - const uri = `${API_BASE_PATH}/component_templates/${COMPONENT_NAME}`; + it('should delete a component template', async () => { + const { name } = componentTemplateA; + const uri = `${API_BASE_PATH}/component_templates/${name}`; const { body } = await supertest.delete(uri).set('kbn-xsrf', 'xxx').expect(200); expect(body).to.eql({ - itemsDeleted: [COMPONENT_NAME], + itemsDeleted: [name], errors: [], }); }); it('should delete multiple component templates', async () => { - // Create component templates to be deleted - const COMPONENT_ONE_NAME = 'test_delete_component_1'; - const COMPONENT_TWO_NAME = 'test_delete_component_2'; - createComponentTemplate({ body: COMPONENT, name: COMPONENT_ONE_NAME }); - createComponentTemplate({ body: COMPONENT, name: COMPONENT_TWO_NAME }); + const { name: componentTemplate1Name } = componentTemplateB; + const { name: componentTemplate2Name } = componentTemplateC; - const uri = `${API_BASE_PATH}/component_templates/${COMPONENT_ONE_NAME},${COMPONENT_TWO_NAME}`; + const uri = `${API_BASE_PATH}/component_templates/${componentTemplate1Name},${componentTemplate2Name}`; const { body: { itemsDeleted, errors }, @@ -275,23 +320,20 @@ export default function ({ getService }: FtrProviderContext) { expect(errors).to.eql([]); // The itemsDeleted array order isn't guaranteed, so we assert against each name instead - [COMPONENT_ONE_NAME, COMPONENT_TWO_NAME].forEach((componentName) => { + [componentTemplate1Name, componentTemplate2Name].forEach((componentName) => { expect(itemsDeleted.includes(componentName)).to.be(true); }); }); it('should return an error for any component templates not sucessfully deleted', async () => { const COMPONENT_DOES_NOT_EXIST = 'component_does_not_exist'; + const { name: componentTemplateName } = componentTemplateD; - // Create component template to be deleted - const COMPONENT_ONE_NAME = 'test_delete_component_1'; - createComponentTemplate({ body: COMPONENT, name: COMPONENT_ONE_NAME }); - - const uri = `${API_BASE_PATH}/component_templates/${COMPONENT_ONE_NAME},${COMPONENT_DOES_NOT_EXIST}`; + const uri = `${API_BASE_PATH}/component_templates/${componentTemplateName},${COMPONENT_DOES_NOT_EXIST}`; const { body } = await supertest.delete(uri).set('kbn-xsrf', 'xxx').expect(200); - expect(body.itemsDeleted).to.eql([COMPONENT_ONE_NAME]); + expect(body.itemsDeleted).to.eql([componentTemplateName]); expect(body.errors[0].name).to.eql(COMPONENT_DOES_NOT_EXIST); expect(body.errors[0].error.msg).to.contain('index_template_missing_exception'); }); diff --git a/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js b/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js index 1a1517567eaed..6dcfbecb6bd0d 100644 --- a/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js +++ b/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js @@ -13,6 +13,7 @@ import { getRandomString } from './random'; */ export const initElasticsearchHelpers = (es) => { let indicesCreated = []; + let componentTemplatesCreated = []; const createIndex = (index = getRandomString(), body) => { indicesCreated.push(index); @@ -35,7 +36,11 @@ export const initElasticsearchHelpers = (es) => { const catTemplate = (name) => es.cat.templates({ name, format: 'json' }); - const createComponentTemplate = (componentTemplate) => { + const createComponentTemplate = (componentTemplate, shouldCacheTemplate) => { + if (shouldCacheTemplate) { + componentTemplatesCreated.push(componentTemplate.name); + } + return es.dataManagement.saveComponentTemplate(componentTemplate); }; @@ -43,6 +48,16 @@ export const initElasticsearchHelpers = (es) => { return es.dataManagement.deleteComponentTemplate({ name: componentTemplateName }); }; + const cleanUpComponentTemplates = () => + Promise.all(componentTemplatesCreated.map(deleteComponentTemplate)) + .then(() => { + componentTemplatesCreated = []; + }) + .catch((err) => { + // eslint-disable-next-line no-console + console.log(`[Cleanup error] Error deleting ES resources: ${err.message}`); + }); + return { createIndex, deleteIndex, @@ -53,5 +68,6 @@ export const initElasticsearchHelpers = (es) => { catTemplate, createComponentTemplate, deleteComponentTemplate, + cleanUpComponentTemplates, }; }; From 324393db36952c42d92ab9cbbd7a3f0f36d40d70 Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Wed, 10 Jun 2020 15:28:08 +0200 Subject: [PATCH 29/53] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20update=20Dri?= =?UTF-8?q?lldown=20description=20in=20docs=20(#68762)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/drilldowns/drilldowns.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/drilldowns/drilldowns.asciidoc b/docs/drilldowns/drilldowns.asciidoc index 2687441c99340..e2dfaa5af39ce 100644 --- a/docs/drilldowns/drilldowns.asciidoc +++ b/docs/drilldowns/drilldowns.asciidoc @@ -15,8 +15,8 @@ that shows a single data center or server. [[how-drilldowns-work]] === How drilldowns work -Drilldowns are {kib} actions that you configure and store -in the dashboard saved object. Drilldowns are specific to the dashboard panel +Drilldowns are user-configurable {kib} actions that are stored with the +dashboard metadata. Drilldowns are specific to the dashboard panel for which you create them—they are not shared across panels. A panel can have multiple drilldowns. From a462e2c7b0505613e5aef28e4c69259ba8c3e8c6 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 10 Jun 2020 15:44:59 +0200 Subject: [PATCH 30/53] [Lens] Keep global filters, time range and refresh interval on refresh (#68075) --- .../lens/public/app_plugin/app.test.tsx | 10 ++++ x-pack/plugins/lens/public/app_plugin/app.tsx | 24 +++++++- .../lens/public/app_plugin/mounter.tsx | 1 + x-pack/test/functional/apps/lens/index.ts | 1 + .../apps/lens/persistent_context.ts | 60 +++++++++++++++++++ 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 x-pack/test/functional/apps/lens/persistent_context.ts diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index 33f4f46681a28..811f42590f07b 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -13,6 +13,7 @@ import { AppMountParameters } from 'kibana/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { Document, SavedObjectStore } from '../persistence'; import { mount } from 'enzyme'; +import { createMemoryHistory, History } from 'history'; import { SavedObjectSaveModal } from '../../../../../src/plugins/saved_objects/public'; import { esFilters, @@ -27,6 +28,7 @@ const dataStartMock = dataPluginMock.createStartContract(); import { navigationPluginMock } from '../../../../../src/plugins/navigation/public/mocks'; import { TopNavMenuData } from '../../../../../src/plugins/navigation/public'; import { coreMock } from 'src/core/public/mocks'; +import { Observable } from 'rxjs'; jest.mock('../persistence'); jest.mock('src/core/public'); @@ -90,6 +92,8 @@ function createMockTimefilter() { return unsubscribe; }, }), + getRefreshInterval: () => {}, + getRefreshIntervalDefaults: () => {}, }; } @@ -114,6 +118,7 @@ describe('Lens App', () => { ) => void; originatingApp: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; + history: History; }> { return ({ navigation: navigationStartMock, @@ -134,6 +139,7 @@ describe('Lens App', () => { timefilter: { timefilter: createMockTimefilter(), }, + state$: new Observable(), }, indexPatterns: { get: jest.fn((id) => { @@ -157,6 +163,7 @@ describe('Lens App', () => { ) => {} ), onAppLeave: jest.fn(), + history: createMemoryHistory(), } as unknown) as jest.Mocked<{ navigation: typeof navigationStartMock; editorFrame: EditorFrameInstance; @@ -173,6 +180,7 @@ describe('Lens App', () => { ) => void; originatingApp: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; + history: History; }>; } @@ -186,6 +194,8 @@ describe('Lens App', () => { return { from: 'now-7d', to: 'now' }; } else if (type === UI_SETTINGS.SEARCH_QUERY_LANGUAGE) { return 'kuery'; + } else if (type === 'state:storeInSessionStorage') { + return false; } else { return []; } diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index 1349d33983fcd..f88c1c5aca31d 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -8,10 +8,18 @@ import _ from 'lodash'; import React, { useState, useEffect, useCallback } from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { Query, DataPublicPluginStart } from 'src/plugins/data/public'; import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; import { AppMountContext, AppMountParameters, NotificationsStart } from 'kibana/public'; -import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; +import { History } from 'history'; +import { + Query, + DataPublicPluginStart, + syncQueryStateWithUrl, +} from '../../../../../src/plugins/data/public'; +import { + createKbnUrlStateStorage, + IStorageWrapper, +} from '../../../../../src/plugins/kibana_utils/public'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; import { SavedObjectSaveModalOrigin, @@ -59,6 +67,7 @@ export function App({ originatingAppFromUrl, navigation, onAppLeave, + history, }: { editorFrame: EditorFrameInstance; data: DataPublicPluginStart; @@ -75,6 +84,7 @@ export function App({ ) => void; originatingAppFromUrl?: string | undefined; onAppLeave: AppMountParameters['onAppLeave']; + history: History; }) { const language = storage.get('kibana.userQueryLanguage') || @@ -129,7 +139,17 @@ export function App({ }, }); + const kbnUrlStateStorage = createKbnUrlStateStorage({ + history, + useHash: core.uiSettings.get('state:storeInSessionStorage'), + }); + const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( + data.query, + kbnUrlStateStorage + ); + return () => { + stopSyncingQueryServiceStateWithUrl(); filterSubscription.unsubscribe(); timeSubscription.unsubscribe(); }; diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index 032ce8325dca1..e6a9119ad4306 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -93,6 +93,7 @@ export async function mountApp( } originatingAppFromUrl={originatingAppFromUrl} onAppLeave={params.onAppLeave} + history={routeProps.history} /> ); }; diff --git a/x-pack/test/functional/apps/lens/index.ts b/x-pack/test/functional/apps/lens/index.ts index ff40cde070416..9e04f6e9df22b 100644 --- a/x-pack/test/functional/apps/lens/index.ts +++ b/x-pack/test/functional/apps/lens/index.ts @@ -29,6 +29,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { this.tags(['ciGroup4', 'skipFirefox']); loadTestFile(require.resolve('./smokescreen')); + loadTestFile(require.resolve('./persistent_context')); loadTestFile(require.resolve('./lens_reporting')); }); }); diff --git a/x-pack/test/functional/apps/lens/persistent_context.ts b/x-pack/test/functional/apps/lens/persistent_context.ts new file mode 100644 index 0000000000000..00d9208772798 --- /dev/null +++ b/x-pack/test/functional/apps/lens/persistent_context.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import _ from 'lodash'; +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['visualize', 'header', 'timePicker']); + const browser = getService('browser'); + const filterBar = getService('filterBar'); + const appsMenu = getService('appsMenu'); + + describe('lens query context', () => { + it('should carry over time range and pinned filters to discover', async () => { + await PageObjects.visualize.navigateToNewVisualization(); + await PageObjects.visualize.clickVisType('lens'); + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 06, 2015 @ 06:31:44.000', + 'Sep 18, 2025 @ 06:31:44.000' + ); + await filterBar.addFilter('ip', 'is', '97.220.3.248'); + await filterBar.toggleFilterPinned('ip'); + await PageObjects.header.clickDiscover(); + const timeRange = await PageObjects.timePicker.getTimeConfig(); + expect(timeRange.start).to.equal('Sep 6, 2015 @ 06:31:44.000'); + expect(timeRange.end).to.equal('Sep 18, 2025 @ 06:31:44.000'); + await filterBar.hasFilter('ip', '97.220.3.248', true, true); + }); + + it('should remember time range and pinned filters from discover', async () => { + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 07, 2015 @ 06:31:44.000', + 'Sep 19, 2025 @ 06:31:44.000' + ); + await filterBar.toggleFilterEnabled('ip'); + await appsMenu.clickLink('Visualize', { category: 'kibana' }); + await PageObjects.visualize.clickNewVisualization(); + await PageObjects.visualize.waitForVisualizationSelectPage(); + await PageObjects.visualize.clickVisType('lens'); + const timeRange = await PageObjects.timePicker.getTimeConfig(); + expect(timeRange.start).to.equal('Sep 7, 2015 @ 06:31:44.000'); + expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000'); + await filterBar.hasFilter('ip', '97.220.3.248', false, true); + }); + + it('keep time range and pinned filters after refresh', async () => { + await browser.refresh(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const timeRange = await PageObjects.timePicker.getTimeConfig(); + expect(timeRange.start).to.equal('Sep 7, 2015 @ 06:31:44.000'); + expect(timeRange.end).to.equal('Sep 19, 2025 @ 06:31:44.000'); + await filterBar.hasFilter('ip', '97.220.3.248', false, true); + }); + }); +} From 4b620616bcd383ef3cbb22cf5b151e829246ff33 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Wed, 10 Jun 2020 07:20:55 -0700 Subject: [PATCH 31/53] [DOCS] Fixes titles in Discover, Graph, & Install for consistency (#68685) * [DOCS] Fixes titles in Discover, Graph, & Install for consistency * [DOCS] More docs tweaks for consistency --- docs/discover/context.asciidoc | 2 +- docs/discover/document-data.asciidoc | 2 +- docs/discover/field-filter.asciidoc | 2 +- docs/discover/kuery.asciidoc | 4 ++-- docs/discover/search.asciidoc | 10 ++++---- docs/discover/set-time-filter.asciidoc | 27 +++++++++++----------- docs/discover/viewing-field-stats.asciidoc | 2 +- docs/management/index-patterns.asciidoc | 2 +- docs/setup/docker.asciidoc | 6 ++++- docs/setup/install/brew.asciidoc | 5 +++- docs/setup/install/deb.asciidoc | 3 +++ docs/setup/install/rpm.asciidoc | 4 ++++ docs/setup/install/targz.asciidoc | 3 +++ docs/setup/install/windows.asciidoc | 3 +++ docs/user/graph/configuring-graph.asciidoc | 6 ++--- docs/user/graph/getting-started.asciidoc | 4 ++-- docs/user/graph/index.asciidoc | 2 +- docs/user/graph/troubleshooting.asciidoc | 2 +- 18 files changed, 54 insertions(+), 35 deletions(-) diff --git a/docs/discover/context.asciidoc b/docs/discover/context.asciidoc index c402a734a16fa..17ed78a163571 100644 --- a/docs/discover/context.asciidoc +++ b/docs/discover/context.asciidoc @@ -1,5 +1,5 @@ [[document-context]] -== Viewing a document in context +== View a document in context Once you've narrowed your search to a specific event, you might want to inspect the documents that occurred diff --git a/docs/discover/document-data.asciidoc b/docs/discover/document-data.asciidoc index 477c2ec90e95c..ee130e8405483 100644 --- a/docs/discover/document-data.asciidoc +++ b/docs/discover/document-data.asciidoc @@ -1,5 +1,5 @@ [[document-data]] -== Viewing document data +== View document data When you submit a search query in *Discover*, the most recent documents that match the query are listed in the documents table. diff --git a/docs/discover/field-filter.asciidoc b/docs/discover/field-filter.asciidoc index 49bb6078cdc58..949cab2c2f976 100644 --- a/docs/discover/field-filter.asciidoc +++ b/docs/discover/field-filter.asciidoc @@ -1,5 +1,5 @@ [[field-filter]] -== Filtering by field +== Filter by field *Discover* offers various types of filters, so you can restrict your documents to the exact data you want. diff --git a/docs/discover/kuery.asciidoc b/docs/discover/kuery.asciidoc index 48a7c65bdbf15..1a481c46b3816 100644 --- a/docs/discover/kuery.asciidoc +++ b/docs/discover/kuery.asciidoc @@ -5,7 +5,7 @@ In Kibana 6.3, we introduced a number of exciting experimental query language en features are now available by default in 7.0. Out of the box, Kibana's query language now includes scripted field support and a simplified, easier to use syntax. If you have a Basic license or above, autocomplete functionality will also be enabled. -==== Language Syntax +==== Language syntax If you're familiar with Kibana's old Lucene query syntax, you should feel right at home with the new syntax. The basics stay the same, we've simply refined things to make the query language easier to use. @@ -72,7 +72,7 @@ set these terms will be matched against all fields. For example, a query for `re in the response field, but a query for just `200` will search for 200 across all fields in your index. ============ -==== Nested Field Support +==== Nested field support KQL supports querying on {ref}/nested.html[nested fields] through a special syntax. You can query nested fields in subtly different ways, depending on the results you want, so crafting nested queries requires extra thought. diff --git a/docs/discover/search.asciidoc b/docs/discover/search.asciidoc index 9fe35f0302760..c6e1daee9b072 100644 --- a/docs/discover/search.asciidoc +++ b/docs/discover/search.asciidoc @@ -1,5 +1,5 @@ [[search]] -== Searching your data +== Search data Many Kibana apps embed a query bar for real-time search, including *Discover*, *Visualize*, and *Dashboard*. @@ -83,14 +83,14 @@ query language you can also submit queries using the {ref}/query-dsl.html[Elasti [[save-open-search]] -=== Saving searches +=== Save a search A saved search persists your current view of Discover for later retrieval and reuse. You can reload a saved search into Discover, add it to a dashboard, and use it as the basis for a <>. A saved search includes the query text, filters, and optionally, the time filter. A saved search also includes the selected columns in the document table, the sort order, and the current index pattern. [role="xpack"] [[discover-read-only-access]] -==== Read only access +==== Read-only access When you have insufficient privileges to save searches, the following indicator in Kibana will be displayed and the *Save* button won't be visible. For more information on granting access to Kibana see <>. @@ -117,7 +117,7 @@ selected, opening the saved search changes the selected index pattern. The query used for the saved search will also be automatically selected. [[save-load-delete-query]] -=== Saving queries +=== Save a query A saved query is a portable collection of query text and filters that you can reuse in <>, <>, and <>. Save a query when you want to: * Retrieve results from the same query at a later time without having to reenter the query text, add the filters or set the time filter @@ -127,7 +127,7 @@ A saved query is a portable collection of query text and filters that you can re Saved queries don't include information specific to Discover, such as the currently selected columns in the document table, the sort order, and the index pattern. If you want to save your current view of Discover for later retrieval and reuse, create a <> instead. [role="xpack"] -==== Read only access +==== Read-only access If you have insufficient privileges to save queries, the *Save current query* button isn't visible in the saved query management popover. For more information, see <> ==== Save a query diff --git a/docs/discover/set-time-filter.asciidoc b/docs/discover/set-time-filter.asciidoc index c53850b38a2b0..a5b81b0fa461c 100644 --- a/docs/discover/set-time-filter.asciidoc +++ b/docs/discover/set-time-filter.asciidoc @@ -1,39 +1,39 @@ [[set-time-filter]] -== Setting the time filter -If your index contains time-based events, and a time-field is configured for the +== Set the time filter +If your index contains time-based events, and a time-field is configured for the selected <>, set a time filter that displays only the data within the specified time range. -You can use the time filter to change the time range, or select a specific time +You can use the time filter to change the time range, or select a specific time range in the histogram. [float] [[use-time-filter]] === Use the time filter -Use the time filter to change the time range. By default, the time filter is set +Use the time filter to change the time range. By default, the time filter is set to the last 15 minutes. -. Click image:images/time-filter-calendar.png[]. +. Click image:images/time-filter-calendar.png[]. . Choose one of the following: -* *Quick select* to use a recent time range, then use the back and forward +* *Quick select* to use a recent time range, then use the back and forward arrows to move through the time ranges. - -* *Commonly used* to use a time range from options such as *Last 15 minutes*, + +* *Commonly used* to use a time range from options such as *Last 15 minutes*, *Today*, and *Week to date*. - -* *Recently used date ranges* to use a previously selected data range that + +* *Recently used date ranges* to use a previously selected data range that you recently used. - + * *Refresh every* to specify an automatic refresh rate. + [role="screenshot"] image::images/Timepicker-View.png[Time filter menu] -. To set the start and end times, click the bar next to the time filter. -In the popup, select *Absolute*, *Relative* or *Now*, then specify the required +. To set the start and end times, click the bar next to the time filter. +In the popup, select *Absolute*, *Relative* or *Now*, then specify the required options. + [role="screenshot"] @@ -54,4 +54,3 @@ when you hover over a valid start point. [role="screenshot"] image::images/Histogram-Time.png[Time range selector in Histogram] - diff --git a/docs/discover/viewing-field-stats.asciidoc b/docs/discover/viewing-field-stats.asciidoc index 3631aba73fb20..5ada5839fd344 100644 --- a/docs/discover/viewing-field-stats.asciidoc +++ b/docs/discover/viewing-field-stats.asciidoc @@ -1,5 +1,5 @@ [[viewing-field-stats]] -== Viewing Field Data Statistics +== View field data statistics From the fields list, you can see how many of the documents in the documents table contain a particular field, what the top 5 values are, and what diff --git a/docs/management/index-patterns.asciidoc b/docs/management/index-patterns.asciidoc index bb16faab7fe5a..37980e2b15c6b 100644 --- a/docs/management/index-patterns.asciidoc +++ b/docs/management/index-patterns.asciidoc @@ -1,5 +1,5 @@ [[index-patterns]] -== Creating an index pattern +== Create an index pattern To explore and visualize data in {kib}, you must create an index pattern. An index pattern tells {kib} which {es} indices contain the data that diff --git a/docs/setup/docker.asciidoc b/docs/setup/docker.asciidoc index fb4cbbada9a33..1a0b13edf8086 100644 --- a/docs/setup/docker.asciidoc +++ b/docs/setup/docker.asciidoc @@ -1,5 +1,9 @@ [[docker]] -=== Install Kibana with Docker +=== Install {kib} with Docker +++++ +Install with Docker +++++ + Docker images for Kibana are available from the Elastic Docker registry. The base image is https://hub.docker.com/_/centos/[centos:7]. diff --git a/docs/setup/install/brew.asciidoc b/docs/setup/install/brew.asciidoc index 3fe104bd04794..07d740361d505 100644 --- a/docs/setup/install/brew.asciidoc +++ b/docs/setup/install/brew.asciidoc @@ -1,5 +1,8 @@ [[brew]] === Install {kib} on macOS with Homebrew +++++ +Install on macOS with Homebrew +++++ Elastic publishes Homebrew formulae so you can install {kib} with the https://brew.sh/[Homebrew] package manager. @@ -44,7 +47,7 @@ and data directory are stored in the following locations. | conf | Configuration files including `kibana.yml` | /usr/local/etc/kibana - d| + d| | data | The location of the data files of each index / shard allocated diff --git a/docs/setup/install/deb.asciidoc b/docs/setup/install/deb.asciidoc index 8193a088c8b7e..dfa1e3a37fd05 100644 --- a/docs/setup/install/deb.asciidoc +++ b/docs/setup/install/deb.asciidoc @@ -1,5 +1,8 @@ [[deb]] === Install {kib} with Debian package +++++ +Install with Debian package +++++ The Debian package for Kibana can be <> or from our <>. It can be used to install diff --git a/docs/setup/install/rpm.asciidoc b/docs/setup/install/rpm.asciidoc index c3922ffba1efa..ccc38c2696158 100644 --- a/docs/setup/install/rpm.asciidoc +++ b/docs/setup/install/rpm.asciidoc @@ -1,5 +1,9 @@ [[rpm]] === Install {kib} with RPM +++++ +Install with RPM +++++ + The RPM for Kibana can be <> or from our <>. It can be used to install diff --git a/docs/setup/install/targz.asciidoc b/docs/setup/install/targz.asciidoc index a53360900657e..c8bff5d58889d 100644 --- a/docs/setup/install/targz.asciidoc +++ b/docs/setup/install/targz.asciidoc @@ -1,5 +1,8 @@ [[targz]] === Install {kib} from archive on Linux or macOS +++++ +Install from archive on Linux or macOS +++++ Kibana is provided for Linux and Darwin as a `.tar.gz` package. These packages are the easiest formats to use when trying out Kibana. diff --git a/docs/setup/install/windows.asciidoc b/docs/setup/install/windows.asciidoc index 1cfbaaa0eda2f..24bf74f607fef 100644 --- a/docs/setup/install/windows.asciidoc +++ b/docs/setup/install/windows.asciidoc @@ -1,5 +1,8 @@ [[windows]] === Install {kib} on Windows +++++ +Install on Windows +++++ Kibana can be installed on Windows using the `.zip` package. diff --git a/docs/user/graph/configuring-graph.asciidoc b/docs/user/graph/configuring-graph.asciidoc index 5427bdee79ecb..4eb8939b004ba 100644 --- a/docs/user/graph/configuring-graph.asciidoc +++ b/docs/user/graph/configuring-graph.asciidoc @@ -1,6 +1,6 @@ [role="xpack"] [[graph-configuration]] -== Configuring Graph +== Configure Graph When a user saves a graph workspace in Kibana, it is stored in the `.kibana` index along with other saved objects like visualizations and dashboards. @@ -48,7 +48,7 @@ Only the configuration is saved unless the user explicitly selects the include data option. [float] -=== Using Security to grant access +=== Use Security to grant access You can also use security to grant read only or all access to different roles. When security is used to grant read only access, the following indicator in Kibana is displayed. For more information on granting access to Kibana, see @@ -59,7 +59,7 @@ image::user/graph/images/graph-read-only-badge.png[Example of Graph's read only [discrete] [[disable-drill-down]] -=== Disabling drilldown configuration +=== Disable drilldown configuration By default, users can configure _drilldown_ URLs to display additional information about a selected vertex in a new browser window. For example, diff --git a/docs/user/graph/getting-started.asciidoc b/docs/user/graph/getting-started.asciidoc index a155017f1bb22..4f61b62da5cce 100644 --- a/docs/user/graph/getting-started.asciidoc +++ b/docs/user/graph/getting-started.asciidoc @@ -1,13 +1,13 @@ [role="xpack"] [[graph-getting-started]] -== Using Graph +== Create a graph You must index data into {es} before you can create a graph. <> or get started with a <>. [float] [[exploring-connections]] -=== Graph connections in your data +=== Graph a data connection . From the side navigation, open *Graph*. + diff --git a/docs/user/graph/index.asciidoc b/docs/user/graph/index.asciidoc index f9094f5b594b1..40c75c868e237 100644 --- a/docs/user/graph/index.asciidoc +++ b/docs/user/graph/index.asciidoc @@ -1,6 +1,6 @@ [role="xpack"] [[xpack-graph]] -= Graph data connections += Graph [partintro] -- diff --git a/docs/user/graph/troubleshooting.asciidoc b/docs/user/graph/troubleshooting.asciidoc index 4ce287396f809..3819d99036f98 100644 --- a/docs/user/graph/troubleshooting.asciidoc +++ b/docs/user/graph/troubleshooting.asciidoc @@ -2,7 +2,7 @@ [[graph-troubleshooting]] == Graph troubleshooting ++++ -Troubleshooting +Troubleshoot ++++ [discrete] From 8118b13ff7993feea5a7c1ef67bf930a4e1477a6 Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Wed, 10 Jun 2020 08:54:27 -0600 Subject: [PATCH 32/53] [SIEM][Detection Engine] Follow up issues from PR 68127 (#68612) ## Summary * Smaller follow ups and bug fixes from: https://github.com/elastic/kibana/pull/68127 * Added unknown to `findDifferencesRecursive` * Added linter rule to catch NodeJS code in the common folders for both `lists` and `security_solution` * Removed the Hapi server type from the common folder of lists ### Checklist * Added unknown to the correct locations - [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios --- .eslintrc.js | 24 ++- .../request/import_list_item_schema.ts | 17 -- .../server/routes/import_list_item_route.ts | 22 ++- .../services/items/buffer_lines.test.ts | 3 +- .../services/items}/test_readable.mock.ts | 0 .../write_lines_to_bulk_list_items.mock.ts | 3 +- .../schemas/common/schemas.ts | 22 ++- .../request/create_rules_schema.mock.ts | 19 +- .../request/import_rules_schema.mock.ts | 35 +++- .../schemas/response/error_schema.mocks.ts | 17 ++ .../schemas/response/error_schema.test.ts | 12 +- .../response/find_rules_schema.mocks.ts | 15 ++ .../response/find_rules_schema.test.ts | 29 +-- .../response/rules_bulk_schema.mocks.ts | 10 ++ .../response/rules_bulk_schema.test.ts | 32 ++-- .../utils.ts => rules_schema.mocks.ts} | 56 +++--- .../schemas/response/rules_schema.test.ts | 102 +++++------ .../security_solution/common/exact_check.ts | 2 +- .../test_files/expected_rules_export.ndjson | 2 +- .../rules_notification_alert_type.ts | 3 +- .../routes/__mocks__/request_responses.ts | 48 ++--- .../routes/__mocks__/utils.ts | 66 +------ .../rules/create_rules_bulk_route.test.ts | 11 +- .../routes/rules/create_rules_route.test.ts | 8 +- .../routes/rules/import_rules_route.test.ts | 22 ++- .../rules/patch_rules_bulk_route.test.ts | 8 +- .../routes/rules/patch_rules_route.test.ts | 8 +- .../rules/update_rules_bulk_route.test.ts | 8 +- .../routes/rules/update_rules_route.test.ts | 8 +- .../routes/rules/utils.test.ts | 27 ++- .../detection_engine/routes/rules/utils.ts | 36 ++-- .../detection_engine/routes/rules/validate.ts | 3 +- .../rules/get_export_by_object_ids.ts | 12 +- .../rules/get_export_details_ndjson.test.ts | 10 +- .../rules/get_export_details_ndjson.ts | 4 +- .../lib/detection_engine/rules/patch_rules.ts | 3 +- .../lib/detection_engine/rules/types.ts | 28 ++- .../detection_engine/rules/update_rules.ts | 4 +- .../lib/detection_engine/rules/utils.test.ts | 103 +++++++++-- .../lib/detection_engine/rules/utils.ts | 64 ++++++- .../signals/__mocks__/es_results.ts | 30 +--- .../signals/build_bulk_body.test.ts | 12 +- .../signals/build_exceptions_query.test.ts | 29 --- .../signals/build_exceptions_query.ts | 14 +- .../signals/build_rule.test.ts | 11 +- .../detection_engine/signals/build_rule.ts | 13 +- .../signals/build_signal.test.ts | 33 ++-- .../detection_engine/signals/build_signal.ts | 17 +- .../signals/filter_events_with_list.test.ts | 4 +- .../signals/filter_events_with_list.ts | 4 +- .../signals/get_filter.test.ts | 14 -- .../detection_engine/signals/get_filter.ts | 37 ++-- .../signals/rule_status_service.ts | 5 +- .../signals/search_after_bulk_create.ts | 5 +- .../signals/signal_params_schema.ts | 63 +++---- .../signals/signal_rule_alert_type.test.ts | 18 +- .../signals/signal_rule_alert_type.ts | 2 +- .../lib/detection_engine/signals/types.ts | 24 +-- .../server/lib/detection_engine/types.ts | 170 ++++++------------ .../create_stream_from_ndjson.test.ts | 12 +- .../basic/tests/update_rules.ts | 34 ++-- .../basic/tests/update_rules_bulk.ts | 56 +++--- .../security_and_spaces/tests/update_rules.ts | 31 ++-- .../tests/update_rules_bulk.ts | 56 +++--- .../detection_engine_api_integration/utils.ts | 64 +++++-- 65 files changed, 867 insertions(+), 797 deletions(-) rename x-pack/plugins/lists/{common => server/services/items}/test_readable.mock.ts (100%) create mode 100644 x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.mocks.ts create mode 100644 x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.mocks.ts create mode 100644 x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.mocks.ts rename x-pack/plugins/security_solution/common/detection_engine/schemas/response/{__mocks__/utils.ts => rules_schema.mocks.ts} (65%) diff --git a/.eslintrc.js b/.eslintrc.js index 3cac46e7d2605..b5f8d106392d5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -589,8 +589,11 @@ module.exports = { * Security Solution overrides */ { - // front end typescript and javascript files only - files: ['x-pack/plugins/security_solution/public/**/*.{js,ts,tsx}'], + // front end and common typescript and javascript files only + files: [ + 'x-pack/plugins/security_solution/public/**/*.{js,ts,tsx}', + 'x-pack/plugins/security_solution/common/**/*.{js,ts,tsx}', + ], rules: { 'import/no-nodejs-modules': 'error', 'no-restricted-imports': [ @@ -766,6 +769,23 @@ module.exports = { /** * Lists overrides */ + { + // front end and common typescript and javascript files only + files: [ + 'x-pack/plugins/lists/public/**/*.{js,ts,tsx}', + 'x-pack/plugins/lists/common/**/*.{js,ts,tsx}', + ], + rules: { + 'import/no-nodejs-modules': 'error', + 'no-restricted-imports': [ + 'error', + { + // prevents UI code from importing server side code and then webpack including it when doing builds + patterns: ['**/server/*'], + }, + ], + }, + }, { // typescript and javascript for front and back end files: ['x-pack/plugins/lists/**/*.{js,ts,tsx}'], diff --git a/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts b/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts index 0a5e861d84483..ee6a2aa0b339a 100644 --- a/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts +++ b/x-pack/plugins/lists/common/schemas/request/import_list_item_schema.ts @@ -6,9 +6,6 @@ /* eslint-disable @typescript-eslint/camelcase */ -// TODO: You cannot import a stream from common into the front end code! CHANGE THIS -import { Readable } from 'stream'; - import * as t from 'io-ts'; import { file } from '../common/schemas'; @@ -20,17 +17,3 @@ export const importListItemSchema = t.exact( ); export type ImportListItemSchema = t.TypeOf; - -// TODO: You cannot import a stream from common into the front end code! CHANGE THIS -export interface HapiReadableStream extends Readable { - hapi: { - filename: string; - }; -} - -/** - * Special interface since we are streaming in a file through a reader - */ -export interface ImportListItemHapiFileSchema { - file: HapiReadableStream; -} diff --git a/x-pack/plugins/lists/server/routes/import_list_item_route.ts b/x-pack/plugins/lists/server/routes/import_list_item_route.ts index 36cf9bac373eb..c951c9b337131 100644 --- a/x-pack/plugins/lists/server/routes/import_list_item_route.ts +++ b/x-pack/plugins/lists/server/routes/import_list_item_route.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Readable } from 'stream'; + import { IRouter } from 'kibana/server'; import { LIST_ITEM_URL } from '../../common/constants'; @@ -13,15 +15,23 @@ import { transformError, validate, } from '../siem_server_deps'; -import { - ImportListItemHapiFileSchema, - importListItemQuerySchema, - importListItemSchema, - listSchema, -} from '../../common/schemas'; +import { importListItemQuerySchema, importListItemSchema, listSchema } from '../../common/schemas'; import { getListClient } from '.'; +export interface HapiReadableStream extends Readable { + hapi: { + filename: string; + }; +} + +/** + * Special interface since we are streaming in a file through a reader + */ +export interface ImportListItemHapiFileSchema { + file: HapiReadableStream; +} + export const importListItemRoute = (router: IRouter): void => { router.post( { diff --git a/x-pack/plugins/lists/server/services/items/buffer_lines.test.ts b/x-pack/plugins/lists/server/services/items/buffer_lines.test.ts index 9413bf9a3d84e..a283269271bd0 100644 --- a/x-pack/plugins/lists/server/services/items/buffer_lines.test.ts +++ b/x-pack/plugins/lists/server/services/items/buffer_lines.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TestReadable } from '../../../common/test_readable.mock'; - import { BufferLines } from './buffer_lines'; +import { TestReadable } from './test_readable.mock'; describe('buffer_lines', () => { test('it can read a single line', (done) => { diff --git a/x-pack/plugins/lists/common/test_readable.mock.ts b/x-pack/plugins/lists/server/services/items/test_readable.mock.ts similarity index 100% rename from x-pack/plugins/lists/common/test_readable.mock.ts rename to x-pack/plugins/lists/server/services/items/test_readable.mock.ts diff --git a/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts b/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts index 3d9902e1d43dd..ccacdfbb5ff65 100644 --- a/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts +++ b/x-pack/plugins/lists/server/services/items/write_lines_to_bulk_list_items.mock.ts @@ -3,11 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { TestReadable } from '../../../common/test_readable.mock'; import { getCallClusterMock } from '../../../common/get_call_cluster.mock'; import { ImportListItemsToStreamOptions, WriteBufferToItemsOptions } from '../items'; import { LIST_ID, LIST_ITEM_INDEX, META, TYPE, USER } from '../../../common/constants.mock'; +import { TestReadable } from './test_readable.mock'; + export const getImportListItemsToStreamOptionsMock = (): ImportListItemsToStreamOptions => ({ callCluster: getCallClusterMock(), listId: LIST_ID, diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts index 7db8e57421d02..b0b9d70a76c32 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/common/schemas.ts @@ -143,6 +143,9 @@ export type Throttle = t.TypeOf; export const throttleOrNull = t.union([throttle, t.null]); export type ThrottleOrNull = t.TypeOf; +export const throttleOrNullOrUndefined = t.union([throttle, t.null, t.undefined]); +export type ThrottleOrUndefinedOrNull = t.TypeOf; + export const anomaly_threshold = PositiveInteger; export type AnomalyThreshold = t.TypeOf; @@ -156,11 +159,8 @@ export const machineLearningJobIdOrUndefined = t.union([machine_learning_job_id, export type MachineLearningJobIdOrUndefined = t.TypeOf; /** - * Note that this is a plain unknown object because we allow the UI - * to send us extra additional information as "meta" which can be anything. - * - * TODO: Strip away extra information and possibly even "freeze" this object - * so we have tighter control over 3rd party data structures. + * Note that this is a non-exact io-ts type as we allow extra meta information + * to be added to the meta object */ export const meta = t.object; export type Meta = t.TypeOf; @@ -192,8 +192,10 @@ export const severityOrUndefined = t.union([severity, t.undefined]); export type SeverityOrUndefined = t.TypeOf; export const status = t.keyof({ open: null, closed: null }); +export type Status = t.TypeOf; export const job_status = t.keyof({ succeeded: null, failed: null, 'going to run': null }); +export type JobStatus = t.TypeOf; // TODO: Create a regular expression type or custom date math part type here export const to = t.string; @@ -307,10 +309,20 @@ export const versionOrUndefined = t.union([version, t.undefined]); export type VersionOrUndefined = t.TypeOf; export const last_success_at = IsoDateString; +export type LastSuccessAt = t.TypeOf; + export const last_success_message = t.string; +export type LastSuccessMessage = t.TypeOf; + export const last_failure_at = IsoDateString; +export type LastFailureAt = t.TypeOf; + export const last_failure_message = t.string; +export type LastFailureMessage = t.TypeOf; + export const status_date = IsoDateString; +export type StatusDate = t.TypeOf; + export const rules_installed = PositiveInteger; export const rules_updated = PositiveInteger; export const status_code = PositiveInteger; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_schema.mock.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_schema.mock.ts index a9ab6f8959e24..2847bd32df514 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_schema.mock.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/create_rules_schema.mock.ts @@ -7,19 +7,30 @@ import { CreateRulesSchema, CreateRulesSchemaDecoded } from './create_rules_schema'; import { DEFAULT_MAX_SIGNALS } from '../../../constants'; -export const getCreateRulesSchemaMock = (): CreateRulesSchema => ({ - description: 'some description', +export const getCreateRulesSchemaMock = (ruleId = 'rule-1'): CreateRulesSchema => ({ + description: 'Detecting root and admin users', name: 'Query with a rule id', query: 'user.name: root or user.name: admin', severity: 'high', type: 'query', risk_score: 55, language: 'kuery', - rule_id: 'rule-1', + rule_id: ruleId, }); +export const getCreateMlRulesSchemaMock = (ruleId = 'rule-1') => { + const { query, language, index, ...mlParams } = getCreateRulesSchemaMock(ruleId); + + return { + ...mlParams, + type: 'machine_learning', + anomaly_threshold: 58, + machine_learning_job_id: 'typical-ml-job-id', + }; +}; + export const getCreateRulesSchemaDecodedMock = (): CreateRulesSchemaDecoded => ({ - description: 'some description', + description: 'Detecting root and admin users', name: 'Query with a rule id', query: 'user.name: root or user.name: admin', severity: 'high', diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/import_rules_schema.mock.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/import_rules_schema.mock.ts index 92fab202c9ddc..aaeb90ffc5bcf 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/import_rules_schema.mock.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/import_rules_schema.mock.ts @@ -7,7 +7,7 @@ import { ImportRulesSchema, ImportRulesSchemaDecoded } from './import_rules_schema'; import { DEFAULT_MAX_SIGNALS } from '../../../constants'; -export const getImportRulesSchemaMock = (): ImportRulesSchema => ({ +export const getImportRulesSchemaMock = (ruleId = 'rule-1'): ImportRulesSchema => ({ description: 'some description', name: 'Query with a rule id', query: 'user.name: root or user.name: admin', @@ -15,7 +15,19 @@ export const getImportRulesSchemaMock = (): ImportRulesSchema => ({ type: 'query', risk_score: 55, language: 'kuery', - rule_id: 'rule-1', + rule_id: ruleId, +}); + +export const getImportRulesWithIdSchemaMock = (ruleId = 'rule-1'): ImportRulesSchema => ({ + id: '6afb8ce1-ea94-4790-8653-fd0b021d2113', + description: 'some description', + name: 'Query with a rule id', + query: 'user.name: root or user.name: admin', + severity: 'high', + type: 'query', + risk_score: 55, + language: 'kuery', + rule_id: ruleId, }); export const getImportRulesSchemaDecodedMock = (): ImportRulesSchemaDecoded => ({ @@ -42,3 +54,22 @@ export const getImportRulesSchemaDecodedMock = (): ImportRulesSchemaDecoded => ( rule_id: 'rule-1', immutable: false, }); + +/** + * Given an array of rules, builds an NDJSON string of rules + * as we might import/export + * @param rules Array of rule objects with which to generate rule JSON + */ +export const rulesToNdJsonString = (rules: ImportRulesSchema[]) => { + return rules.map((rule) => JSON.stringify(rule)).join('\r\n'); +}; + +/** + * Given an array of rule IDs, builds an NDJSON string of rules + * as we might import + * @param ruleIds Array of ruleIds with which to generate rule JSON + */ +export const ruleIdsToNdJsonString = (ruleIds: string[]) => { + const rules = ruleIds.map((ruleId) => getImportRulesSchemaMock(ruleId)); + return rulesToNdJsonString(rules); +}; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.mocks.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.mocks.ts new file mode 100644 index 0000000000000..52b2de316ddd5 --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.mocks.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 { ErrorSchema } from './error_schema'; + +export const getErrorSchemaMock = ( + id: string = '819eded6-e9c8-445b-a647-519aea39e063' +): ErrorSchema => ({ + id, + error: { + status_code: 404, + message: 'id: "819eded6-e9c8-445b-a647-519aea39e063" not found', + }, +}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.test.ts index 2a4d75522d010..d9e16105351bd 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/error_schema.test.ts @@ -7,15 +7,15 @@ import { left } from 'fp-ts/lib/Either'; import { pipe } from 'fp-ts/lib/pipeable'; -import { getErrorPayload } from './__mocks__/utils'; import { errorSchema, ErrorSchema } from './error_schema'; import { exactCheck } from '../../../exact_check'; import { foldLeftRight, getPaths } from '../../../test_utils'; +import { getErrorSchemaMock } from './error_schema.mocks'; describe('error_schema', () => { test('it should validate an error with a UUID given for id', () => { - const error = getErrorPayload(); - const decoded = errorSchema.decode(getErrorPayload()); + const error = getErrorSchemaMock(); + const decoded = errorSchema.decode(getErrorSchemaMock()); const checked = exactCheck(error, decoded); const message = pipe(checked, foldLeftRight); @@ -24,7 +24,7 @@ describe('error_schema', () => { }); test('it should validate an error with a plain string given for id since sometimes we echo the user id which might not be a UUID back out to them', () => { - const error = getErrorPayload('fake id'); + const error = getErrorSchemaMock('fake id'); const decoded = errorSchema.decode(error); const checked = exactCheck(error, decoded); const message = pipe(checked, foldLeftRight); @@ -35,7 +35,7 @@ describe('error_schema', () => { test('it should NOT validate an error when it has extra data next to a valid payload element', () => { type InvalidError = ErrorSchema & { invalid_extra_data?: string }; - const error: InvalidError = getErrorPayload(); + const error: InvalidError = getErrorSchemaMock(); error.invalid_extra_data = 'invalid_extra_data'; const decoded = errorSchema.decode(error); const checked = exactCheck(error, decoded); @@ -46,7 +46,7 @@ describe('error_schema', () => { }); test('it should NOT validate an error when it has required elements deleted from it', () => { - const error = getErrorPayload(); + const error = getErrorSchemaMock(); delete error.error; const decoded = errorSchema.decode(error); const checked = exactCheck(error, decoded); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.mocks.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.mocks.ts new file mode 100644 index 0000000000000..28c3eea761b40 --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.mocks.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FindRulesSchema } from './find_rules_schema'; +import { getRulesSchemaMock } from './rules_schema.mocks'; + +export const getFindRulesSchemaMock = (): FindRulesSchema => ({ + page: 1, + perPage: 1, + total: 1, + data: [getRulesSchemaMock()], +}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.test.ts index 51163c3d76ed6..fc1ab9b87795d 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/find_rules_schema.test.ts @@ -6,31 +6,32 @@ import { findRulesSchema, FindRulesSchema } from './find_rules_schema'; import { pipe } from 'fp-ts/lib/pipeable'; -import { getFindResponseSingle, getBaseResponsePayload } from './__mocks__/utils'; import { left } from 'fp-ts/lib/Either'; import { RulesSchema } from './rules_schema'; import { exactCheck } from '../../../exact_check'; import { foldLeftRight, getPaths } from '../../../test_utils'; +import { getRulesSchemaMock } from './rules_schema.mocks'; +import { getFindRulesSchemaMock } from './find_rules_schema.mocks'; describe('find_rules_schema', () => { test('it should validate a typical single find rules response', () => { - const payload = getFindResponseSingle(); + const payload = getFindRulesSchemaMock(); const decoded = findRulesSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(getFindResponseSingle()); + expect(message.schema).toEqual(getFindRulesSchemaMock()); }); test('it should validate an empty find rules response', () => { - const payload = getFindResponseSingle(); + const payload = getFindRulesSchemaMock(); payload.data = []; const decoded = findRulesSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getFindResponseSingle(); + const expected = getFindRulesSchemaMock(); expected.data = []; expect(getPaths(left(message.errors))).toEqual([]); @@ -38,7 +39,7 @@ describe('find_rules_schema', () => { }); test('it should invalidate a typical single find rules response if it is has an extra property on it', () => { - const payload: FindRulesSchema & { invalid_data?: 'invalid' } = getFindResponseSingle(); + const payload: FindRulesSchema & { invalid_data?: 'invalid' } = getFindRulesSchemaMock(); payload.invalid_data = 'invalid'; const decoded = findRulesSchema.decode(payload); const checked = exactCheck(payload, decoded); @@ -49,8 +50,8 @@ describe('find_rules_schema', () => { }); test('it should invalidate a typical single find rules response if the rules are invalid within it', () => { - const payload = getFindResponseSingle(); - const invalidRule: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload = getFindRulesSchemaMock(); + const invalidRule: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); invalidRule.invalid_extra_data = 'invalid_data'; payload.data = [invalidRule]; const decoded = findRulesSchema.decode(payload); @@ -62,8 +63,8 @@ describe('find_rules_schema', () => { }); test('it should invalidate a typical single find rules response if the rule is missing a required field such as name', () => { - const payload = getFindResponseSingle(); - const invalidRule = getBaseResponsePayload(); + const payload = getFindRulesSchemaMock(); + const invalidRule = getRulesSchemaMock(); delete invalidRule.name; payload.data = [invalidRule]; const decoded = findRulesSchema.decode(payload); @@ -77,7 +78,7 @@ describe('find_rules_schema', () => { }); test('it should invalidate a typical single find rules response if it is missing perPage', () => { - const payload = getFindResponseSingle(); + const payload = getFindRulesSchemaMock(); delete payload.perPage; const decoded = findRulesSchema.decode(payload); const checked = exactCheck(payload, decoded); @@ -90,7 +91,7 @@ describe('find_rules_schema', () => { }); test('it should invalidate a typical single find rules response if it has a negative perPage number', () => { - const payload = getFindResponseSingle(); + const payload = getFindRulesSchemaMock(); payload.perPage = -1; const decoded = findRulesSchema.decode(payload); const checked = exactCheck(payload, decoded); @@ -101,7 +102,7 @@ describe('find_rules_schema', () => { }); test('it should invalidate a typical single find rules response if it has a negative page number', () => { - const payload = getFindResponseSingle(); + const payload = getFindRulesSchemaMock(); payload.page = -1; const decoded = findRulesSchema.decode(payload); const checked = exactCheck(payload, decoded); @@ -112,7 +113,7 @@ describe('find_rules_schema', () => { }); test('it should invalidate a typical single find rules response if it has a negative total', () => { - const payload = getFindResponseSingle(); + const payload = getFindRulesSchemaMock(); payload.total = -1; const decoded = findRulesSchema.decode(payload); const checked = exactCheck(payload, decoded); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.mocks.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.mocks.ts new file mode 100644 index 0000000000000..b55809e6b27ea --- /dev/null +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.mocks.ts @@ -0,0 +1,10 @@ +/* + * 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 { RulesBulkSchema } from './rules_bulk_schema'; +import { getRulesSchemaMock } from './rules_schema.mocks'; + +export const getRulesBulkSchemaMock = (): RulesBulkSchema => [getRulesSchemaMock()]; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts index 04cf012f36dba..a169ac3deb9b9 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts @@ -7,46 +7,48 @@ import { left } from 'fp-ts/lib/Either'; import { pipe } from 'fp-ts/lib/pipeable'; -import { getBaseResponsePayload, getErrorPayload } from './__mocks__/utils'; import { RulesBulkSchema, rulesBulkSchema } from './rules_bulk_schema'; import { RulesSchema } from './rules_schema'; import { ErrorSchema } from './error_schema'; import { exactCheck } from '../../../exact_check'; import { foldLeftRight, getPaths } from '../../../test_utils'; +import { getRulesSchemaMock } from './rules_schema.mocks'; +import { getErrorSchemaMock } from './error_schema.mocks'; + describe('prepackaged_rule_schema', () => { test('it should validate a regular message and and error together with a uuid', () => { - const payload: RulesBulkSchema = [getBaseResponsePayload(), getErrorPayload()]; + const payload: RulesBulkSchema = [getRulesSchemaMock(), getErrorSchemaMock()]; const decoded = rulesBulkSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([getBaseResponsePayload(), getErrorPayload()]); + expect(message.schema).toEqual([getRulesSchemaMock(), getErrorSchemaMock()]); }); test('it should validate a regular message and and error together when the error has a non UUID', () => { - const payload: RulesBulkSchema = [getBaseResponsePayload(), getErrorPayload('fake id')]; + const payload: RulesBulkSchema = [getRulesSchemaMock(), getErrorSchemaMock('fake id')]; const decoded = rulesBulkSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([getBaseResponsePayload(), getErrorPayload('fake id')]); + expect(message.schema).toEqual([getRulesSchemaMock(), getErrorSchemaMock('fake id')]); }); test('it should validate an error', () => { - const payload: RulesBulkSchema = [getErrorPayload('fake id')]; + const payload: RulesBulkSchema = [getErrorSchemaMock('fake id')]; const decoded = rulesBulkSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual([getErrorPayload('fake id')]); + expect(message.schema).toEqual([getErrorSchemaMock('fake id')]); }); test('it should NOT validate a rule with a deleted value', () => { - const rule = getBaseResponsePayload(); + const rule = getRulesSchemaMock(); delete rule.name; const payload: RulesBulkSchema = [rule]; const decoded = rulesBulkSchema.decode(payload); @@ -61,7 +63,7 @@ describe('prepackaged_rule_schema', () => { }); test('it should NOT validate an invalid error message with a deleted value', () => { - const error = getErrorPayload('fake id'); + const error = getErrorSchemaMock('fake id'); delete error.error; const payload: RulesBulkSchema = [error]; const decoded = rulesBulkSchema.decode(payload); @@ -76,7 +78,7 @@ describe('prepackaged_rule_schema', () => { }); test('it should NOT validate a type of "query" when it has extra data', () => { - const rule: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const rule: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); rule.invalid_extra_data = 'invalid_extra_data'; const payload: RulesBulkSchema = [rule]; const decoded = rulesBulkSchema.decode(payload); @@ -88,9 +90,9 @@ describe('prepackaged_rule_schema', () => { }); test('it should NOT validate a type of "query" when it has extra data next to a valid error', () => { - const rule: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const rule: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); rule.invalid_extra_data = 'invalid_extra_data'; - const payload: RulesBulkSchema = [getErrorPayload(), rule]; + const payload: RulesBulkSchema = [getErrorSchemaMock(), rule]; const decoded = rulesBulkSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); @@ -101,7 +103,7 @@ describe('prepackaged_rule_schema', () => { test('it should NOT validate an error when it has extra data', () => { type InvalidError = ErrorSchema & { invalid_extra_data?: string }; - const error: InvalidError = getErrorPayload(); + const error: InvalidError = getErrorSchemaMock(); error.invalid_extra_data = 'invalid'; const payload: RulesBulkSchema = [error]; const decoded = rulesBulkSchema.decode(payload); @@ -114,9 +116,9 @@ describe('prepackaged_rule_schema', () => { test('it should NOT validate an error when it has extra data next to a valid payload element', () => { type InvalidError = ErrorSchema & { invalid_extra_data?: string }; - const error: InvalidError = getErrorPayload(); + const error: InvalidError = getErrorSchemaMock(); error.invalid_extra_data = 'invalid'; - const payload: RulesBulkSchema = [getBaseResponsePayload(), error]; + const payload: RulesBulkSchema = [getRulesSchemaMock(), error]; const decoded = rulesBulkSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/__mocks__/utils.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks.ts similarity index 65% rename from x-pack/plugins/security_solution/common/detection_engine/schemas/response/__mocks__/utils.ts rename to x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks.ts index fef6bcf42e49f..ecbf0321cdc67 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/__mocks__/utils.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks.ts @@ -4,14 +4,37 @@ * you may not use this file except in compliance with the Elastic License. */ -import { RulesSchema } from '../rules_schema'; -import { RulesBulkSchema } from '../rules_bulk_schema'; -import { ErrorSchema } from '../error_schema'; -import { FindRulesSchema } from '../find_rules_schema'; +import { RulesSchema } from './rules_schema'; export const ANCHOR_DATE = '2020-02-20T03:57:54.037Z'; -export const getBaseResponsePayload = (anchorDate: string = ANCHOR_DATE): RulesSchema => ({ +export const getPartialRulesSchemaMock = (): Partial => ({ + created_by: 'elastic', + description: 'Detecting root and admin users', + enabled: true, + false_positives: [], + from: 'now-6m', + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + immutable: false, + index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], + interval: '5m', + risk_score: 50, + rule_id: 'rule-1', + language: 'kuery', + max_signals: 100, + name: 'Detect Root/Admin Users', + output_index: '.siem-signals', + query: 'user.name: root or user.name: admin', + references: ['http://www.example.com', 'https://ww.example.com'], + severity: 'high', + updated_by: 'elastic', + tags: ['some fake tag 1', 'some fake tag 2'], + to: 'now', + type: 'query', + note: '', +}); + +export const getRulesSchemaMock = (anchorDate: string = ANCHOR_DATE): RulesSchema => ({ id: '7a7065d7-6e8b-4aae-8d20-c93613dec9f9', created_at: new Date(anchorDate).toISOString(), updated_at: new Date(anchorDate).toISOString(), @@ -75,10 +98,8 @@ export const getBaseResponsePayload = (anchorDate: string = ANCHOR_DATE): RulesS ], }); -export const getRulesBulkPayload = (): RulesBulkSchema => [getBaseResponsePayload()]; - -export const getMlRuleResponsePayload = (anchorDate: string = ANCHOR_DATE): RulesSchema => { - const basePayload = getBaseResponsePayload(anchorDate); +export const getRulesMlSchemaMock = (anchorDate: string = ANCHOR_DATE): RulesSchema => { + const basePayload = getRulesSchemaMock(anchorDate); const { filters, index, query, language, ...rest } = basePayload; return { @@ -88,20 +109,3 @@ export const getMlRuleResponsePayload = (anchorDate: string = ANCHOR_DATE): Rule machine_learning_job_id: 'some_machine_learning_job_id', }; }; - -export const getErrorPayload = ( - id: string = '819eded6-e9c8-445b-a647-519aea39e063' -): ErrorSchema => ({ - id, - error: { - status_code: 404, - message: 'id: "819eded6-e9c8-445b-a647-519aea39e063" not found', - }, -}); - -export const getFindResponseSingle = (): FindRulesSchema => ({ - page: 1, - perPage: 1, - total: 1, - data: [getBaseResponsePayload()], -}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts index 8ed9c30507f4f..90aef656db369 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts @@ -18,28 +18,28 @@ import { addTimelineTitle, addMlFields, } from './rules_schema'; -import { getBaseResponsePayload, getMlRuleResponsePayload } from './__mocks__/utils'; import { exactCheck } from '../../../exact_check'; import { foldLeftRight, getPaths } from '../../../test_utils'; import { TypeAndTimelineOnly } from './type_timeline_only_schema'; +import { getRulesSchemaMock, getRulesMlSchemaMock } from './rules_schema.mocks'; export const ANCHOR_DATE = '2020-02-20T03:57:54.037Z'; describe('rules_schema', () => { test('it should validate a type of "query" without anything extra', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); const decoded = rulesSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expect(getPaths(left(message.errors))).toEqual([]); expect(message.schema).toEqual(expected); }); test('it should NOT validate a type of "query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.invalid_extra_data = 'invalid_extra_data'; const decoded = rulesSchema.decode(payload); @@ -51,7 +51,7 @@ describe('rules_schema', () => { }); test('it should NOT validate invalid_data for the type', () => { - const payload: Omit & { type: string } = getBaseResponsePayload(); + const payload: Omit & { type: string } = getRulesSchemaMock(); payload.type = 'invalid_data'; const decoded = rulesSchema.decode(payload); @@ -65,7 +65,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "query" with a saved_id together', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'query'; payload.saved_id = 'save id 123'; @@ -78,14 +78,14 @@ describe('rules_schema', () => { }); test('it should validate a type of "saved_query" with a "saved_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'saved_query'; payload.saved_id = 'save id 123'; const decoded = rulesSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expected.type = 'saved_query'; expected.saved_id = 'save id 123'; @@ -95,7 +95,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" without a "saved_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'saved_query'; delete payload.saved_id; @@ -110,7 +110,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.type = 'saved_query'; payload.saved_id = 'save id 123'; payload.invalid_extra_data = 'invalid_extra_data'; @@ -124,14 +124,14 @@ describe('rules_schema', () => { }); test('it should validate a type of "timeline_id" if there is a "timeline_title" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; const decoded = rulesSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expected.timeline_id = 'some timeline id'; expected.timeline_title = 'some timeline title'; @@ -140,7 +140,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_id" if there is "timeline_title" dependent when it has extra invalid data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; payload.invalid_extra_data = 'invalid_extra_data'; @@ -154,7 +154,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_id" if there is NOT a "timeline_title" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; const decoded = rulesSchema.decode(payload); @@ -168,7 +168,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_title" if there is NOT a "timeline_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_title = 'some timeline title'; const decoded = rulesSchema.decode(payload); @@ -180,7 +180,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_title" but there is NOT a "timeline_id"', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.saved_id = 'some saved id'; payload.type = 'saved_query'; payload.timeline_title = 'some timeline title'; @@ -194,7 +194,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_id" but there is NOT a "timeline_title"', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.saved_id = 'some saved id'; payload.type = 'saved_query'; payload.timeline_id = 'some timeline id'; @@ -211,19 +211,19 @@ describe('rules_schema', () => { describe('checkTypeDependents', () => { test('it should validate a type of "query" without anything extra', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); const decoded = checkTypeDependents(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expect(getPaths(left(message.errors))).toEqual([]); expect(message.schema).toEqual(expected); }); test('it should NOT validate invalid_data for the type', () => { - const payload: Omit & { type: string } = getBaseResponsePayload(); + const payload: Omit & { type: string } = getRulesSchemaMock(); payload.type = 'invalid_data'; const decoded = checkTypeDependents(payload); @@ -237,7 +237,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "query" with a saved_id together', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'query'; payload.saved_id = 'save id 123'; @@ -250,14 +250,14 @@ describe('rules_schema', () => { }); test('it should validate a type of "saved_query" with a "saved_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'saved_query'; payload.saved_id = 'save id 123'; const decoded = checkTypeDependents(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expected.type = 'saved_query'; expected.saved_id = 'save id 123'; @@ -267,7 +267,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" without a "saved_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'saved_query'; delete payload.saved_id; @@ -282,7 +282,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.type = 'saved_query'; payload.saved_id = 'save id 123'; payload.invalid_extra_data = 'invalid_extra_data'; @@ -296,14 +296,14 @@ describe('rules_schema', () => { }); test('it should validate a type of "timeline_id" if there is a "timeline_title" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; const decoded = checkTypeDependents(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expected.timeline_id = 'some timeline id'; expected.timeline_title = 'some timeline title'; @@ -312,7 +312,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_id" if there is "timeline_title" dependent when it has extra invalid data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; payload.invalid_extra_data = 'invalid_extra_data'; @@ -326,7 +326,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_id" if there is NOT a "timeline_title" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; const decoded = checkTypeDependents(payload); @@ -340,7 +340,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_title" if there is NOT a "timeline_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_title = 'some timeline title'; const decoded = checkTypeDependents(payload); @@ -352,7 +352,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_title" but there is NOT a "timeline_id"', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.saved_id = 'some saved id'; payload.type = 'saved_query'; payload.timeline_title = 'some timeline title'; @@ -366,7 +366,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_id" but there is NOT a "timeline_title"', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.saved_id = 'some saved id'; payload.type = 'saved_query'; payload.timeline_id = 'some timeline id'; @@ -384,20 +384,20 @@ describe('rules_schema', () => { describe('getDependents', () => { test('it should validate a type of "query" without anything extra', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); const dependents = getDependents(payload); const decoded = dependents.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expect(getPaths(left(message.errors))).toEqual([]); expect(message.schema).toEqual(expected); }); test('it should NOT validate invalid_data for the type', () => { - const payload: Omit & { type: string } = getBaseResponsePayload(); + const payload: Omit & { type: string } = getRulesSchemaMock(); payload.type = 'invalid_data'; const dependents = getDependents((payload as unknown) as TypeAndTimelineOnly); @@ -412,7 +412,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "query" with a saved_id together', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'query'; payload.saved_id = 'save id 123'; @@ -426,7 +426,7 @@ describe('rules_schema', () => { }); test('it should validate a type of "saved_query" with a "saved_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'saved_query'; payload.saved_id = 'save id 123'; @@ -434,7 +434,7 @@ describe('rules_schema', () => { const decoded = dependents.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expected.type = 'saved_query'; expected.saved_id = 'save id 123'; @@ -444,7 +444,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" without a "saved_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.type = 'saved_query'; delete payload.saved_id; @@ -460,7 +460,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.type = 'saved_query'; payload.saved_id = 'save id 123'; payload.invalid_extra_data = 'invalid_extra_data'; @@ -475,7 +475,7 @@ describe('rules_schema', () => { }); test('it should validate a type of "timeline_id" if there is a "timeline_title" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; @@ -483,7 +483,7 @@ describe('rules_schema', () => { const decoded = dependents.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getBaseResponsePayload(); + const expected = getRulesSchemaMock(); expected.timeline_id = 'some timeline id'; expected.timeline_title = 'some timeline title'; @@ -492,7 +492,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_id" if there is "timeline_title" dependent when it has extra invalid data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getBaseResponsePayload(); + const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; payload.invalid_extra_data = 'invalid_extra_data'; @@ -507,7 +507,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_id" if there is NOT a "timeline_title" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; const dependents = getDependents(payload); @@ -522,7 +522,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_title" if there is NOT a "timeline_id" dependent', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.timeline_title = 'some timeline title'; const dependents = getDependents(payload); @@ -535,7 +535,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_title" but there is NOT a "timeline_id"', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.saved_id = 'some saved id'; payload.type = 'saved_query'; payload.timeline_title = 'some timeline title'; @@ -549,7 +549,7 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_id" but there is NOT a "timeline_title"', () => { - const payload = getBaseResponsePayload(); + const payload = getRulesSchemaMock(); payload.saved_id = 'some saved id'; payload.type = 'saved_query'; payload.timeline_id = 'some timeline id'; @@ -566,13 +566,13 @@ describe('rules_schema', () => { }); test('it validates an ML rule response', () => { - const payload = getMlRuleResponsePayload(); + const payload = getRulesMlSchemaMock(); const dependents = getDependents(payload); const decoded = dependents.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getMlRuleResponsePayload(); + const expected = getRulesMlSchemaMock(); expect(getPaths(left(message.errors))).toEqual([]); expect(message.schema).toEqual(expected); @@ -580,8 +580,8 @@ describe('rules_schema', () => { test('it rejects a response with both ML and query properties', () => { const payload = { - ...getBaseResponsePayload(), - ...getMlRuleResponsePayload(), + ...getRulesSchemaMock(), + ...getRulesMlSchemaMock(), }; const dependents = getDependents(payload); diff --git a/x-pack/plugins/security_solution/common/exact_check.ts b/x-pack/plugins/security_solution/common/exact_check.ts index 48afc35b56ba1..041d0fb324df7 100644 --- a/x-pack/plugins/security_solution/common/exact_check.ts +++ b/x-pack/plugins/security_solution/common/exact_check.ts @@ -47,7 +47,7 @@ export const exactCheck = ( return pipe(decoded, fold(onLeft, onRight)); }; -export const findDifferencesRecursive = (original: T, decodedValue: T): string[] => { +export const findDifferencesRecursive = (original: unknown, decodedValue: T): string[] => { if (decodedValue === null && original === null) { // both the decodedValue and the original are null which indicates that they are equal // so do not report differences diff --git a/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson b/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson index c2e779feeca77..dcbfa9d0dd16e 100644 --- a/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson +++ b/x-pack/plugins/security_solution/cypress/test_files/expected_rules_export.ndjson @@ -1,2 +1,2 @@ -{"actions":[],"created_at":"2020-03-26T10:09:07.569Z","updated_at":"2020-03-26T10:09:08.021Z","created_by":"elastic","description":"Rule 1","enabled":true,"false_positives":[],"filters":[],"from":"now-360s","id":"49db5bd1-bdd5-4821-be26-bb70a815dedb","immutable":false,"index":["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"0cea4194-03f2-4072-b281-d31b72221d9d","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":50,"name":"Rule 1","query":"host.name:*","references":[],"meta":{"from":"1m","throttle":"no_actions"},"severity":"low","updated_by":"elastic","tags":["rule1"],"to":"now","type":"query","threat":[],"throttle":"no_actions","version":1} +{"actions":[],"created_at":"2020-03-26T10:09:07.569Z","updated_at":"2020-03-26T10:09:08.021Z","created_by":"elastic","description":"Rule 1","enabled":true,"false_positives":[],"filters":[],"from":"now-360s","id":"49db5bd1-bdd5-4821-be26-bb70a815dedb","immutable":false,"index":["apm-*-transaction*","auditbeat-*","endgame-*","filebeat-*","packetbeat-*","winlogbeat-*"],"interval":"5m","rule_id":"0cea4194-03f2-4072-b281-d31b72221d9d","language":"kuery","output_index":".siem-signals-default","max_signals":100,"risk_score":50,"name":"Rule 1","query":"host.name:*","references":[],"meta":{"from":"1m","throttle":"no_actions"},"severity":"low","updated_by":"elastic","tags":["rule1"],"to":"now","type":"query","threat":[],"throttle":"no_actions","version":1,"exceptions_list":[]} {"exported_count":1,"missing_rules":[],"missing_rules_count":0} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts index 5a2a950f21bcf..cf5a6aa01f29e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts @@ -64,7 +64,8 @@ export const rulesNotificationAlertType = ({ from: fromInMs, to: toInMs, id: ruleAlertSavedObject.id, - kibanaSiemAppUrl: ruleAlertParams.meta?.kibana_siem_app_url, + kibanaSiemAppUrl: (ruleAlertParams.meta as { kibana_siem_app_url?: string }) + .kibana_siem_app_url, }); logger.info( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts index 23d5d7eb8d385..fe66496f70dcd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -22,34 +22,11 @@ import { IRuleSavedAttributesSavedObjectAttributes, HapiReadableStream, } from '../../rules/types'; -import { RuleAlertParamsRest } from '../../types'; import { requestMock } from './request'; import { RuleNotificationAlertType } from '../../notifications/types'; import { QuerySignalsSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/query_signals_index_schema'; import { SetSignalsStatusSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/set_signal_status_schema'; - -export const typicalPayload = (): Partial => ({ - rule_id: 'rule-1', - description: 'Detecting root and admin users', - index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - interval: '5m', - name: 'Detect Root/Admin Users', - output_index: '.siem-signals', - risk_score: 50, - type: 'query', - from: 'now-6m', - to: 'now', - severity: 'high', - query: 'user.name: root or user.name: admin', - language: 'kuery', - threat: [ - { - framework: 'fake', - tactic: { id: 'fakeId', name: 'fakeName', reference: 'fakeRef' }, - technique: [{ id: 'techniqueId', name: 'techniqueName', reference: 'techniqueRef' }], - }, - ], -}); +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; export const typicalSetStatusSignalByIdsPayload = (): SetSignalsStatusSchemaDecoded => ({ signal_ids: ['somefakeid1', 'somefakeid2'], @@ -77,14 +54,14 @@ export const getUpdateRequest = () => requestMock.create({ method: 'put', path: DETECTION_ENGINE_RULES_URL, - body: typicalPayload(), + body: getCreateRulesSchemaMock(), }); export const getPatchRequest = () => requestMock.create({ method: 'patch', path: DETECTION_ENGINE_RULES_URL, - body: typicalPayload(), + body: getCreateRulesSchemaMock(), }); export const getReadRequest = () => @@ -104,21 +81,21 @@ export const getReadBulkRequest = () => requestMock.create({ method: 'post', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, - body: [typicalPayload()], + body: [getCreateRulesSchemaMock()], }); export const getUpdateBulkRequest = () => requestMock.create({ method: 'put', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [typicalPayload()], + body: [getCreateRulesSchemaMock()], }); export const getPatchBulkRequest = () => requestMock.create({ method: 'patch', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [typicalPayload()], + body: [getCreateRulesSchemaMock()], }); export const getDeleteBulkRequest = () => @@ -254,11 +231,12 @@ export const getCreateRequest = () => requestMock.create({ method: 'post', path: DETECTION_ENGINE_RULES_URL, - body: typicalPayload(), + body: getCreateRulesSchemaMock(), }); +// TODO: Replace this with the mocks version from the mocks file export const typicalMlRulePayload = () => { - const { query, language, index, ...mlParams } = typicalPayload(); + const { query, language, index, ...mlParams } = getCreateRulesSchemaMock(); return { ...mlParams, @@ -284,8 +262,9 @@ export const createBulkMlRuleRequest = () => { }); }; +// TODO: Replace this with a mocks file version export const createRuleWithActionsRequest = () => { - const payload = typicalPayload(); + const payload = getCreateRulesSchemaMock(); return requestMock.create({ method: 'post', @@ -369,6 +348,7 @@ export const getResult = (): RuleAlertType => ({ falsePositives: [], from: 'now-6m', immutable: false, + savedId: undefined, query: 'user.name: root or user.name: admin', language: 'kuery', machineLearningJobId: undefined, @@ -560,9 +540,9 @@ export const getFindResultStatus = (): SavedObjectsFindResponse< alertId: '1ea5a820-4da1-4e82-92a1-2b43a7bece08', statusDate: '2020-02-18T15:26:49.783Z', status: 'succeeded', - lastFailureAt: null, + lastFailureAt: undefined, lastSuccessAt: '2020-02-18T15:26:49.783Z', - lastFailureMessage: null, + lastFailureMessage: undefined, lastSuccessMessage: 'succeeded', lastLookBackDate: new Date('2020-02-18T15:14:58.806Z').toISOString(), gap: '500.32', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts index 41a28bfe8967d..063c9dffd66dd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts @@ -6,70 +6,8 @@ import { Readable } from 'stream'; -import { OutputRuleAlertRest } from '../../types'; import { HapiReadableStream } from '../../rules/types'; - -/** - * This is a typical simple rule for testing that is easy for most basic testing - * @param ruleId - */ -export const getSimpleRule = (ruleId = 'rule-1'): Partial => ({ - name: 'Simple Rule Query', - description: 'Simple Rule Query', - risk_score: 1, - rule_id: ruleId, - severity: 'high', - type: 'query', - query: 'user.name: root or user.name: admin', -}); - -/** - * This is a typical ML rule for testing - * @param ruleId - */ -export const getSimpleMlRule = (ruleId = 'rule-1'): Partial => ({ - name: 'Simple Rule Query', - description: 'Simple Rule Query', - risk_score: 1, - rule_id: ruleId, - severity: 'high', - type: 'machine_learning', - anomaly_threshold: 44, - machine_learning_job_id: 'some_job_id', -}); - -/** - * 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 rules, builds an NDJSON string of rules - * as we might import/export - * @param rules Array of rule objects with which to generate rule JSON - */ -export const rulesToNdJsonString = (rules: Array>) => { - return rules.map((rule) => JSON.stringify(rule)).join('\r\n'); -}; - -/** - * Given an array of rule IDs, builds an NDJSON string of rules - * as we might import/export - * @param ruleIds Array of ruleIds with which to generate rule JSON - */ -export const ruleIdsToNdJsonString = (ruleIds: string[]) => { - const rules = ruleIds.map((ruleId) => getSimpleRule(ruleId)); - return rulesToNdJsonString(rules); -}; +import { RulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; /** * Given a string, builds a hapi stream as our @@ -94,7 +32,7 @@ export const buildHapiStream = (string: string, filename = 'file.ndjson'): HapiR }; export const getOutputRuleAlertForRest = (): Omit< - OutputRuleAlertRest, + RulesSchema, 'machine_learning_job_id' | 'anomaly_threshold' > => ({ actions: [], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index 1df6070bc33a6..11a4543e2fa12 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -8,7 +8,6 @@ import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { mlServicesMock, mlAuthzMock as mockMlAuthzFactory } from '../../../machine_learning/mocks'; import { buildMlAuthz } from '../../../machine_learning/authz'; import { - typicalPayload, getReadBulkRequest, getEmptyIndex, getNonEmptyIndex, @@ -20,6 +19,7 @@ import { import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { createRulesBulkRoute } from './create_rules_bulk_route'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -98,8 +98,7 @@ describe('create_rules_bulk', () => { expect(response.body).toEqual([ { error: { - message: - 'To create a rule, the index must exist first. Index .siem-signals does not exist', + message: 'To create a rule, the index must exist first. Index undefined does not exist', status_code: 400, }, rule_id: 'rule-1', @@ -143,7 +142,7 @@ describe('create_rules_bulk', () => { const request = requestMock.create({ method: 'post', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, - body: [typicalPayload(), typicalPayload()], + body: [getCreateRulesSchemaMock(), getCreateRulesSchemaMock()], }); const response = await server.inject(request, context); @@ -164,7 +163,7 @@ describe('create_rules_bulk', () => { const request = requestMock.create({ method: 'post', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, - body: [{ ...typicalPayload(), type: 'query' }], + body: [{ ...getCreateRulesSchemaMock(), type: 'query' }], }); const result = server.validate(request); @@ -175,7 +174,7 @@ describe('create_rules_bulk', () => { const request = requestMock.create({ method: 'post', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_create`, - body: [{ ...typicalPayload(), type: 'unexpected_type' }], + body: [{ ...getCreateRulesSchemaMock(), type: 'unexpected_type' }], }); const result = server.validate(request); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts index 5abd7b1e76a76..37500572d1386 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts @@ -9,7 +9,6 @@ import { getEmptyFindResult, getResult, getCreateRequest, - typicalPayload, getFindResultStatus, getNonEmptyIndex, getEmptyIndex, @@ -22,6 +21,7 @@ import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { createRulesRoute } from './create_rules_route'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; import { updateRulesNotifications } from '../../rules/update_rules_notifications'; +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; jest.mock('../../rules/update_rules_notifications'); jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -114,7 +114,7 @@ describe('create_rules', () => { expect(response.status).toEqual(400); expect(response.body).toEqual({ - message: 'To create a rule, the index must exist first. Index .siem-signals does not exist', + message: 'To create a rule, the index must exist first. Index undefined does not exist', status_code: 400, }); }); @@ -149,7 +149,7 @@ describe('create_rules', () => { method: 'post', path: DETECTION_ENGINE_RULES_URL, body: { - ...typicalPayload(), + ...getCreateRulesSchemaMock(), type: 'query', }, }); @@ -163,7 +163,7 @@ describe('create_rules', () => { method: 'post', path: DETECTION_ENGINE_RULES_URL, body: { - ...typicalPayload(), + ...getCreateRulesSchemaMock(), type: 'unexpected_type', }, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts index 0762fbc7dd6e3..84148231431a1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts @@ -4,12 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - buildHapiStream, - ruleIdsToNdJsonString, - rulesToNdJsonString, - getSimpleRuleWithId, -} from '../__mocks__/utils'; +import { buildHapiStream } from '../__mocks__/utils'; import { getImportRulesRequest, getImportRulesRequestOverwriteTrue, @@ -25,6 +20,11 @@ import { buildMlAuthz } from '../../../machine_learning/authz'; import { importRulesRoute } from './import_rules_route'; import * as createRulesStreamFromNdJson from '../../rules/create_rules_stream_from_ndjson'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; +import { + getImportRulesWithIdSchemaMock, + ruleIdsToNdJsonString, + rulesToNdJsonString, +} from '../../../../../common/detection_engine/schemas/request/import_rules_schema.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -239,7 +239,11 @@ describe('import_rules_route', () => { }); test('returns 200 with errors if all rules are missing rule_ids and import fails on validation', async () => { - const rulesWithoutRuleIds = ['rule-1', 'rule-2'].map((ruleId) => getSimpleRuleWithId(ruleId)); + const rulesWithoutRuleIds = ['rule-1', 'rule-2'].map((ruleId) => + getImportRulesWithIdSchemaMock(ruleId) + ); + delete rulesWithoutRuleIds[0].rule_id; + delete rulesWithoutRuleIds[1].rule_id; const badPayload = buildHapiStream(rulesToNdJsonString(rulesWithoutRuleIds)); const badRequest = getImportRulesRequest(badPayload); @@ -251,7 +255,7 @@ describe('import_rules_route', () => { { error: { // TODO: Change the formatter to do better than output [object Object] - message: '[object Object],[object Object]', + message: '[object Object]', status_code: 400, }, rule_id: '(unknown id)', @@ -259,7 +263,7 @@ describe('import_rules_route', () => { { error: { // TODO: Change the formatter to do better than output [object Object] - message: '[object Object],[object Object]', + message: '[object Object]', status_code: 400, }, rule_id: '(unknown id)', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts index d5145e1dceae0..24fd5e151e485 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts @@ -9,7 +9,6 @@ import { mlServicesMock, mlAuthzMock as mockMlAuthzFactory } from '../../../mach import { buildMlAuthz } from '../../../machine_learning/authz'; import { getEmptyFindResult, - typicalPayload, getFindResultWithSingleHit, getPatchBulkRequest, getResult, @@ -18,6 +17,7 @@ import { import { serverMock, requestContextMock, requestMock } from '../__mocks__'; import { patchRulesBulkRoute } from './patch_rules_bulk_route'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -153,7 +153,7 @@ describe('patch_rules_bulk', () => { const request = requestMock.create({ method: 'patch', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [{ ...typicalPayload(), rule_id: undefined }], + body: [{ ...getCreateRulesSchemaMock(), rule_id: undefined }], }); const response = await server.inject(request, context); @@ -173,7 +173,7 @@ describe('patch_rules_bulk', () => { const request = requestMock.create({ method: 'patch', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [{ ...typicalPayload(), type: 'query' }], + body: [{ ...getCreateRulesSchemaMock(), type: 'query' }], }); const result = server.validate(request); @@ -184,7 +184,7 @@ describe('patch_rules_bulk', () => { const request = requestMock.create({ method: 'patch', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [{ ...typicalPayload(), type: 'unknown_type' }], + body: [{ ...getCreateRulesSchemaMock(), type: 'unknown_type' }], }); const result = server.validate(request); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts index 09230d45ee785..1b225f6dd93c3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts @@ -12,7 +12,6 @@ import { getFindResultStatus, getResult, getPatchRequest, - typicalPayload, getFindResultWithSingleHit, nonRuleFindResult, typicalMlRulePayload, @@ -20,6 +19,7 @@ import { import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { patchRulesRoute } from './patch_rules_route'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -165,7 +165,7 @@ describe('patch_rules', () => { const request = requestMock.create({ method: 'patch', path: DETECTION_ENGINE_RULES_URL, - body: { ...typicalPayload(), rule_id: undefined }, + body: { ...getCreateRulesSchemaMock(), rule_id: undefined }, }); const response = await server.inject(request, context); expect(response.body).toEqual({ @@ -178,7 +178,7 @@ describe('patch_rules', () => { const request = requestMock.create({ method: 'patch', path: DETECTION_ENGINE_RULES_URL, - body: { ...typicalPayload(), type: 'query' }, + body: { ...getCreateRulesSchemaMock(), type: 'query' }, }); const result = server.validate(request); @@ -189,7 +189,7 @@ describe('patch_rules', () => { const request = requestMock.create({ method: 'patch', path: DETECTION_ENGINE_RULES_URL, - body: { ...typicalPayload(), type: 'unknown_type' }, + body: { ...getCreateRulesSchemaMock(), type: 'unknown_type' }, }); const result = server.validate(request); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts index 2f331938e3ca8..582bf1a9aa22b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts @@ -10,7 +10,6 @@ import { buildMlAuthz } from '../../../machine_learning/authz'; import { getEmptyFindResult, getResult, - typicalPayload, getFindResultWithSingleHit, getUpdateBulkRequest, getFindResultStatus, @@ -20,6 +19,7 @@ import { serverMock, requestContextMock, requestMock } from '../__mocks__'; import { updateRulesBulkRoute } from './update_rules_bulk_route'; import { BulkError } from '../utils'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); @@ -129,7 +129,7 @@ describe('update_rules_bulk', () => { const noIdRequest = requestMock.create({ method: 'put', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [{ ...typicalPayload(), rule_id: undefined }], + body: [{ ...getCreateRulesSchemaMock(), rule_id: undefined }], }); const response = await server.inject(noIdRequest, context); expect(response.body).toEqual([ @@ -144,7 +144,7 @@ describe('update_rules_bulk', () => { const request = requestMock.create({ method: 'put', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [{ ...typicalPayload(), type: 'query' }], + body: [{ ...getCreateRulesSchemaMock(), type: 'query' }], }); const result = server.validate(request); @@ -155,7 +155,7 @@ describe('update_rules_bulk', () => { const request = requestMock.create({ method: 'put', path: `${DETECTION_ENGINE_RULES_URL}/_bulk_update`, - body: [{ ...typicalPayload(), type: 'unknown_type' }], + body: [{ ...getCreateRulesSchemaMock(), type: 'unknown_type' }], }); const result = server.validate(request); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index f8b7636080b1b..bbe65ff36a3e5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -10,7 +10,6 @@ import { getEmptyFindResult, getResult, getUpdateRequest, - typicalPayload, getFindResultWithSingleHit, getFindResultStatusEmpty, nonRuleFindResult, @@ -21,6 +20,7 @@ import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; import { updateRulesNotifications } from '../../rules/update_rules_notifications'; import { updateRulesRoute } from './update_rules_route'; +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); jest.mock('../../rules/update_rules_notifications'); @@ -139,7 +139,7 @@ describe('update_rules', () => { method: 'put', path: DETECTION_ENGINE_RULES_URL, body: { - ...typicalPayload(), + ...getCreateRulesSchemaMock(), rule_id: undefined, }, }); @@ -154,7 +154,7 @@ describe('update_rules', () => { const request = requestMock.create({ method: 'put', path: DETECTION_ENGINE_RULES_URL, - body: { ...typicalPayload(), type: 'query' }, + body: { ...getCreateRulesSchemaMock(), type: 'query' }, }); const result = await server.validate(request); @@ -165,7 +165,7 @@ describe('update_rules', () => { const request = requestMock.create({ method: 'put', path: DETECTION_ENGINE_RULES_URL, - body: { ...typicalPayload(), type: 'unknown type' }, + body: { ...getCreateRulesSchemaMock(), type: 'unknown type' }, }); const result = await server.validate(request); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts index 3b2750bbbf664..3b514b92e1479 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts @@ -21,7 +21,7 @@ import { getResult } from '../__mocks__/request_responses'; import { INTERNAL_IDENTIFIER } from '../../../../../common/constants'; import { RuleTypeParams } from '../../types'; import { BulkError, ImportSuccessError } from '../utils'; -import { getSimpleRule, getOutputRuleAlertForRest } from '../__mocks__/utils'; +import { getOutputRuleAlertForRest } from '../__mocks__/utils'; import { createPromiseFromStreams } from '../../../../../../../../src/legacy/utils/streams'; import { PartialAlert } from '../../../../../../alerts/server'; import { SanitizedAlert } from '../../../../../../alerts/server/types'; @@ -30,6 +30,7 @@ import { RuleAlertType } from '../../rules/types'; import { setFeatureFlagsForTestsOnly, unSetFeatureFlagsForTestsOnly } from '../../feature_flags'; import { CreateRulesBulkSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/create_rules_bulk_schema'; import { ImportRulesSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/import_rules_schema'; +import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock'; type PromiseFromStreams = ImportRulesSchemaDecoded | Error; @@ -62,14 +63,6 @@ describe('utils', () => { expect(rule).toEqual(expectedWithoutFromWithoutLanguage); }); - test('should omit query if query is null', () => { - const fullRule = getResult(); - fullRule.params.query = null; - const rule = transformAlertToRule(fullRule); - const { query, ...expectedWithoutQuery } = getOutputRuleAlertForRest(); - expect(rule).toEqual(expectedWithoutQuery); - }); - test('should omit query if query is undefined', () => { const fullRule = getResult(); fullRule.params.query = undefined; @@ -81,7 +74,7 @@ describe('utils', () => { test('should omit a mix of undefined, null, and missing fields', () => { const fullRule = getResult(); fullRule.params.query = undefined; - fullRule.params.language = null; + fullRule.params.language = undefined; const { from, ...omitParams } = fullRule.params; fullRule.params = omitParams as RuleTypeParams; const { enabled, ...omitEnabled } = fullRule; @@ -532,8 +525,8 @@ describe('utils', () => { }); test('returns tuple of duplicate conflict error and single rule when rules with matching rule-ids passed in and `overwrite` is false', async () => { - const rule = getSimpleRule('rule-1'); - const rule2 = getSimpleRule('rule-1'); + const rule = getCreateRulesSchemaMock('rule-1'); + const rule2 = getCreateRulesSchemaMock('rule-1'); const ndJsonStream = new Readable({ read() { this.push(`${JSON.stringify(rule)}\n`); @@ -561,9 +554,9 @@ 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'); + const rule = getCreateRulesSchemaMock('rule-1'); delete rule.rule_id; - const rule2 = getSimpleRule('rule-1'); + const rule2 = getCreateRulesSchemaMock('rule-1'); delete rule2.rule_id; const ndJsonStream = new Readable({ read() { @@ -585,8 +578,8 @@ describe('utils', () => { }); 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'); + const rule = getCreateRulesSchemaMock('rule-1'); + const rule2 = getCreateRulesSchemaMock('rule-1'); const ndJsonStream = new Readable({ read() { this.push(`${JSON.stringify(rule)}\n`); @@ -606,7 +599,7 @@ describe('utils', () => { }); test('returns tuple of empty duplicate errors array and single rule when rules without a rule-id is passed in', async () => { - const simpleRule = getSimpleRule(); + const simpleRule = getCreateRulesSchemaMock(); delete simpleRule.rule_id; const multipartPayload = `${JSON.stringify(simpleRule)}\n`; const ndJsonStream = new Readable({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts index 3ed45bd8367fc..9320eba26df0b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts @@ -8,6 +8,7 @@ import { pickBy, countBy } from 'lodash/fp'; import { SavedObject, SavedObjectsFindResponse } from 'kibana/server'; import uuid from 'uuid'; +import { RulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; import { ImportRulesSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/import_rules_schema'; import { CreateRulesBulkSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/create_rules_bulk_schema'; import { PartialAlert, FindResult } from '../../../../../../alerts/server'; @@ -21,7 +22,6 @@ import { isRuleStatusFindTypes, isRuleStatusSavedObjectType, } from '../../rules/types'; -import { OutputRuleAlertRest } from '../../types'; import { createBulkErrorObject, BulkError, @@ -30,7 +30,6 @@ import { createImportErrorObject, OutputError, } from '../utils'; -import { hasListsFeature } from '../../feature_flags'; import { RuleActions } from '../../rule_actions/types'; type PromiseFromStreams = ImportRulesSchemaDecoded | Error; @@ -104,12 +103,12 @@ export const transformAlertToRule = ( alert: RuleAlertType, ruleActions?: RuleActions | null, ruleStatus?: SavedObject -): Partial => { - return pickBy((value: unknown) => value != null, { +): Partial => { + return pickBy((value: unknown) => value != null, { actions: ruleActions?.actions ?? [], created_at: alert.createdAt.toISOString(), updated_at: alert.updatedAt.toISOString(), - created_by: alert.createdBy, + created_by: alert.createdBy ?? 'elastic', description: alert.params.description, enabled: alert.enabled, anomaly_threshold: alert.params.anomalyThreshold, @@ -134,28 +133,25 @@ export const transformAlertToRule = ( timeline_title: alert.params.timelineTitle, meta: alert.params.meta, severity: alert.params.severity, - updated_by: alert.updatedBy, + updated_by: alert.updatedBy ?? 'elastic', tags: transformTags(alert.tags), to: alert.params.to, type: alert.params.type, - threat: alert.params.threat, + threat: alert.params.threat ?? [], throttle: ruleActions?.ruleThrottle || 'no_actions', note: alert.params.note, version: alert.params.version, - status: ruleStatus?.attributes.status, + status: ruleStatus?.attributes.status ?? undefined, status_date: ruleStatus?.attributes.statusDate, - last_failure_at: ruleStatus?.attributes.lastFailureAt, - last_success_at: ruleStatus?.attributes.lastSuccessAt, - last_failure_message: ruleStatus?.attributes.lastFailureMessage, - last_success_message: ruleStatus?.attributes.lastSuccessMessage, - // TODO: (LIST-FEATURE) Remove hasListsFeature() check once we have lists available for a release - exceptions_list: hasListsFeature() ? alert.params.exceptionsList : null, + last_failure_at: ruleStatus?.attributes.lastFailureAt ?? undefined, + last_success_at: ruleStatus?.attributes.lastSuccessAt ?? undefined, + last_failure_message: ruleStatus?.attributes.lastFailureMessage ?? undefined, + last_success_message: ruleStatus?.attributes.lastSuccessMessage ?? undefined, + exceptions_list: alert.params.exceptionsList ?? [], }); }; -export const transformAlertsToRules = ( - alerts: RuleAlertType[] -): Array> => { +export const transformAlertsToRules = (alerts: RuleAlertType[]): Array> => { return alerts.map((alert) => transformAlertToRule(alert)); }; @@ -167,7 +163,7 @@ export const transformFindAlerts = ( page: number; perPage: number; total: number; - data: Array>; + data: Array>; } | null => { if (!ruleStatuses && isAlertTypes(findResults.data)) { return { @@ -194,7 +190,7 @@ export const transform = ( alert: PartialAlert, ruleActions?: RuleActions | null, ruleStatus?: SavedObject -): Partial | null => { +): Partial | null => { if (isAlertType(alert)) { return transformAlertToRule( alert, @@ -211,7 +207,7 @@ export const transformOrBulkError = ( alert: PartialAlert, ruleActions: RuleActions, ruleStatus?: unknown -): Partial | BulkError => { +): Partial | BulkError => { if (isAlertType(alert)) { if (isRuleStatusFindType(ruleStatus) && ruleStatus?.saved_objects.length > 0) { return transformAlertToRule(alert, ruleActions, ruleStatus?.saved_objects[0] ?? ruleStatus); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts index 5fc239ed48263..7b0bf5997d12f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts @@ -22,7 +22,6 @@ import { IRuleSavedAttributesSavedObjectAttributes, isRuleStatusFindType, } from '../../rules/types'; -import { OutputRuleAlertRest } from '../../types'; import { createBulkErrorObject, BulkError } from '../utils'; import { transformFindAlerts, transform, transformAlertToRule } from './utils'; import { RuleActions } from '../../rule_actions/types'; @@ -36,7 +35,7 @@ export const transformValidateFindAlerts = ( page: number; perPage: number; total: number; - data: Array>; + data: Array>; } | null, string | null ] => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts index 1a965842348ac..747cf82510460 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts @@ -4,17 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ +import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; import { AlertsClient } from '../../../../../alerts/server'; import { getExportDetailsNdjson } from './get_export_details_ndjson'; import { isAlertType } from '../rules/types'; import { readRules } from './read_rules'; import { transformAlertToRule } from '../routes/rules/utils'; -import { OutputRuleAlertRest } from '../types'; import { transformDataToNdjson } from '../../../utils/read_stream/create_stream_from_ndjson'; -interface ExportSuccesRule { +interface ExportSuccessRule { statusCode: 200; - rule: Partial; + rule: Partial; } interface ExportFailedRule { @@ -22,12 +22,12 @@ interface ExportFailedRule { missingRuleId: { rule_id: string }; } -type ExportRules = ExportSuccesRule | ExportFailedRule; +type ExportRules = ExportSuccessRule | ExportFailedRule; export interface RulesErrors { exportedCount: number; missingRules: Array<{ rule_id: string }>; - rules: Array>; + rules: Array>; } export const getExportByObjectIds = async ( @@ -80,7 +80,7 @@ export const getRulesFromObjects = async ( ) as ExportFailedRule[]; const exportedRules = alertsAndErrors.filter( (resp) => resp.statusCode === 200 - ) as ExportSuccesRule[]; + ) as ExportSuccessRule[]; return { exportedCount: exportedRules.length, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.test.ts index 431b3776fd9e2..848abc3febf35 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.test.ts @@ -4,18 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { sampleRule } from '../signals/__mocks__/es_results'; import { getExportDetailsNdjson } from './get_export_details_ndjson'; +import { getRulesSchemaMock } from '../../../../common/detection_engine/schemas/response/rules_schema.mocks'; describe('getExportDetailsNdjson', () => { test('it ends with a new line character', () => { - const rule = sampleRule(); + const rule = getRulesSchemaMock(); const details = getExportDetailsNdjson([rule]); expect(details.endsWith('\n')).toEqual(true); }); test('it exports a correct count given a single rule and no missing rules', () => { - const rule = sampleRule(); + const rule = getRulesSchemaMock(); const details = getExportDetailsNdjson([rule]); const reParsed = JSON.parse(details); expect(reParsed).toEqual({ @@ -37,8 +37,8 @@ describe('getExportDetailsNdjson', () => { }); test('it exports a correct count given multiple rules and multiple missing rules', () => { - const rule1 = sampleRule(); - const rule2 = sampleRule(); + const rule1 = getRulesSchemaMock(); + const rule2 = getRulesSchemaMock(); rule2.rule_id = 'some other id'; rule2.id = 'some other id'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts index a39541d044bc3..0a685cab9b450 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { OutputRuleAlertRest } from '../types'; +import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; export const getExportDetailsNdjson = ( - rules: Array>, + rules: Array>, missingRules: Array<{ rule_id: string }> = [] ): string => { const stringified = JSON.stringify({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts index 3796df353abb8..0c103b7176db4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/patch_rules.ts @@ -11,7 +11,6 @@ import { PatchRulesOptions } from './types'; import { addTags } from './add_tags'; import { calculateVersion, calculateName, calculateInterval } from './utils'; import { ruleStatusSavedObjectsClientFactory } from '../signals/rule_status_saved_objects_client'; -import { Meta } from '../types'; export const patchRules = async ({ alertsClient, @@ -60,7 +59,7 @@ export const patchRules = async ({ savedId, timelineId, timelineTitle, - meta: meta as Meta | undefined, // TODO: Remove this cast once we fix the types for calculate version and patch, + meta, filters, from, index, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts index 8bdb1287c6df2..4b84057f6d795 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts @@ -69,11 +69,17 @@ import { QueryFilterOrUndefined, FieldsOrUndefined, SortOrderOrUndefined, + JobStatus, + LastSuccessAt, + StatusDate, + LastSuccessMessage, + LastFailureAt, + LastFailureMessage, } from '../../../../common/detection_engine/schemas/common/schemas'; import { AlertsClient, PartialAlert } from '../../../../../alerts/server'; import { Alert, SanitizedAlert } from '../../../../../alerts/common'; import { SIGNALS_ID } from '../../../../common/constants'; -import { RuleAlertParams, RuleTypeParams, PartialFilter } from '../types'; +import { RuleTypeParams, PartialFilter } from '../types'; export interface RuleAlertType extends Alert { params: RuleTypeParams; @@ -82,12 +88,12 @@ export interface RuleAlertType extends Alert { // eslint-disable-next-line @typescript-eslint/no-explicit-any export interface IRuleStatusAttributes extends Record { alertId: string; // created alert id. - statusDate: string; - lastFailureAt: string | null | undefined; - lastFailureMessage: string | null | undefined; - lastSuccessAt: string | null | undefined; - lastSuccessMessage: string | null | undefined; - status: RuleStatusString | null | undefined; + statusDate: StatusDate; + lastFailureAt: LastFailureAt | null | undefined; + lastFailureMessage: LastFailureMessage | null | undefined; + lastSuccessAt: LastSuccessAt | null | undefined; + lastSuccessMessage: LastSuccessMessage | null | undefined; + status: JobStatus | null | undefined; lastLookBackDate: string | null | undefined; gap: string | null | undefined; bulkCreateTimeDurations: string[] | null | undefined; @@ -121,8 +127,6 @@ export interface IRuleStatusFindType { saved_objects: IRuleStatusSavedObject[]; } -export type RuleStatusString = 'succeeded' | 'failed' | 'going to run'; - export interface HapiReadableStream extends Readable { hapi: { filename: string; @@ -133,12 +137,6 @@ export interface Clients { alertsClient: AlertsClient; } -// TODO: Try and remove this patch -export type PatchRuleParams = Partial> & { - rule: SanitizedAlert | null; - savedObjectsClient: SavedObjectsClientContract; -} & Clients; - export const isAlertTypes = (partialAlert: PartialAlert[]): partialAlert is RuleAlertType[] => { return partialAlert.every((rule) => isAlertType(rule)); }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts index 0236c357988d5..b3f327857dbb3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_rules.ts @@ -12,7 +12,6 @@ import { addTags } from './add_tags'; import { calculateVersion } from './utils'; import { hasListsFeature } from '../feature_flags'; import { ruleStatusSavedObjectsClientFactory } from '../signals/rule_status_saved_objects_client'; -import { Meta } from '../types'; export const updateRules = async ({ alertsClient, @@ -63,7 +62,7 @@ export const updateRules = async ({ savedId, timelineId, timelineTitle, - meta: meta as Meta, // TODO: Remove this cast once we fix the types for calculate version and patch + meta, filters, from, index, @@ -81,6 +80,7 @@ export const updateRules = async ({ note, anomalyThreshold, machineLearningJobId, + exceptionsList, }); // TODO: Remove this and use regular exceptions_list once the feature is stable for a release diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts index b7c36b20f44be..0f65b2a78ec4c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts @@ -5,7 +5,6 @@ */ import { calculateInterval, calculateVersion, calculateName } from './utils'; -import { PatchRuleParams } from './types'; describe('utils', () => { describe('#calculateInterval', () => { @@ -27,24 +26,104 @@ describe('utils', () => { describe('#calculateVersion', () => { test('returning the same version number if given an immutable but no updated version number', () => { - expect(calculateVersion(true, 1, { description: 'some description change' })).toEqual(1); + expect( + calculateVersion(true, 1, { + description: 'some description change', + falsePositives: undefined, + query: undefined, + language: undefined, + outputIndex: undefined, + savedId: undefined, + timelineId: undefined, + timelineTitle: undefined, + meta: undefined, + filters: [], + from: undefined, + index: undefined, + interval: undefined, + maxSignals: undefined, + riskScore: undefined, + name: undefined, + severity: undefined, + tags: undefined, + threat: undefined, + to: undefined, + type: undefined, + references: undefined, + version: undefined, + note: undefined, + anomalyThreshold: undefined, + machineLearningJobId: undefined, + exceptionsList: [], + }) + ).toEqual(1); }); test('returning an updated version number if given an immutable and an updated version number', () => { - expect(calculateVersion(true, 2, { description: 'some description change' })).toEqual(2); + expect( + calculateVersion(true, 2, { + description: 'some description change', + falsePositives: undefined, + query: undefined, + language: undefined, + outputIndex: undefined, + savedId: undefined, + timelineId: undefined, + timelineTitle: undefined, + meta: undefined, + filters: [], + from: undefined, + index: undefined, + interval: undefined, + maxSignals: undefined, + riskScore: undefined, + name: undefined, + severity: undefined, + tags: undefined, + threat: undefined, + to: undefined, + type: undefined, + references: undefined, + version: undefined, + note: undefined, + anomalyThreshold: undefined, + machineLearningJobId: undefined, + exceptionsList: [], + }) + ).toEqual(2); }); test('returning an updated version number if not given an immutable but but an updated description', () => { - expect(calculateVersion(false, 1, { description: 'some description change' })).toEqual(2); - }); - - test('returning the same version number but a undefined description', () => { - expect(calculateVersion(false, 1, { description: undefined })).toEqual(1); - }); - - test('returning an updated version number if not given an immutable but an updated falsy value', () => { expect( - calculateVersion(false, 1, ({ description: false } as unknown) as PatchRuleParams) + calculateVersion(false, 1, { + description: 'some description change', + falsePositives: undefined, + query: undefined, + language: undefined, + outputIndex: undefined, + savedId: undefined, + timelineId: undefined, + timelineTitle: undefined, + meta: undefined, + filters: [], + from: undefined, + index: undefined, + interval: undefined, + maxSignals: undefined, + riskScore: undefined, + name: undefined, + severity: undefined, + tags: undefined, + threat: undefined, + to: undefined, + type: undefined, + references: undefined, + version: undefined, + note: undefined, + anomalyThreshold: undefined, + machineLearningJobId: undefined, + exceptionsList: [], + }) ).toEqual(2); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts index 7d6091f6b97fa..d40cb5d96669b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts @@ -5,7 +5,35 @@ */ import { pickBy, isEmpty } from 'lodash/fp'; -import { PatchRuleParams } from './types'; +import { + DescriptionOrUndefined, + AnomalyThresholdOrUndefined, + QueryOrUndefined, + LanguageOrUndefined, + SavedIdOrUndefined, + TimelineIdOrUndefined, + TimelineTitleOrUndefined, + MachineLearningJobIdOrUndefined, + IndexOrUndefined, + NoteOrUndefined, + MetaOrUndefined, + VersionOrUndefined, + FalsePositivesOrUndefined, + FromOrUndefined, + OutputIndexOrUndefined, + IntervalOrUndefined, + MaxSignalsOrUndefined, + RiskScoreOrUndefined, + NameOrUndefined, + SeverityOrUndefined, + TagsOrUndefined, + ToOrUndefined, + ThreatOrUndefined, + TypeOrUndefined, + ReferencesOrUndefined, + ListAndOrUndefined, +} from '../../../../common/detection_engine/schemas/common/schemas'; +import { PartialFilter } from '../types'; export const calculateInterval = ( interval: string | undefined, @@ -20,10 +48,40 @@ export const calculateInterval = ( } }; +export interface UpdateProperties { + description: DescriptionOrUndefined; + falsePositives: FalsePositivesOrUndefined; + from: FromOrUndefined; + query: QueryOrUndefined; + language: LanguageOrUndefined; + savedId: SavedIdOrUndefined; + timelineId: TimelineIdOrUndefined; + timelineTitle: TimelineTitleOrUndefined; + meta: MetaOrUndefined; + machineLearningJobId: MachineLearningJobIdOrUndefined; + filters: PartialFilter[]; + index: IndexOrUndefined; + interval: IntervalOrUndefined; + maxSignals: MaxSignalsOrUndefined; + riskScore: RiskScoreOrUndefined; + outputIndex: OutputIndexOrUndefined; + name: NameOrUndefined; + severity: SeverityOrUndefined; + tags: TagsOrUndefined; + threat: ThreatOrUndefined; + to: ToOrUndefined; + type: TypeOrUndefined; + references: ReferencesOrUndefined; + note: NoteOrUndefined; + version: VersionOrUndefined; + exceptionsList: ListAndOrUndefined; + anomalyThreshold: AnomalyThresholdOrUndefined; +} + export const calculateVersion = ( immutable: boolean, currentVersion: number, - updateProperties: Partial> + updateProperties: UpdateProperties ): number => { // early return if we are pre-packaged/immutable rule to be safe. We are never responsible // for changing the version number of an immutable. Immutables are only responsible for changing @@ -44,7 +102,7 @@ export const calculateVersion = ( // the version number if only the enabled/disabled flag is being set. Likewise if we get other // properties we are not expecting such as updatedAt we do not to cause a version number bump // on that either. - const removedNullValues = pickBy( + const removedNullValues = pickBy( (value: unknown) => value != null, updateProperties ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts index 46a16e7dca153..6056e692854af 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts @@ -11,7 +11,7 @@ import { SavedObjectsFindResponse, } from '../../../../../../../../src/core/server'; import { loggingServiceMock } from '../../../../../../../../src/core/server/mocks'; -import { RuleTypeParams, OutputRuleAlertRest } from '../../types'; +import { RuleTypeParams } from '../../types'; import { IRuleStatusAttributes } from '../../rules/types'; import { ruleStatusSavedObjectType } from '../../rules/saved_object_mappings'; @@ -364,34 +364,6 @@ export const sampleDocSearchResultsWithSortId = ( export const sampleRuleGuid = '04128c15-0d1b-4716-a4c5-46997ac7f3bd'; export const sampleIdGuid = 'e1e08ddc-5e37-49ff-a258-5393aa44435a'; -export const sampleRule = (): Partial => { - return { - created_by: 'elastic', - description: 'Detecting root and admin users', - enabled: true, - false_positives: [], - from: 'now-6m', - id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', - immutable: false, - index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - interval: '5m', - risk_score: 50, - rule_id: 'rule-1', - language: 'kuery', - max_signals: 100, - name: 'Detect Root/Admin Users', - output_index: '.siem-signals', - query: 'user.name: root or user.name: admin', - references: ['http://www.example.com', 'https://ww.example.com'], - severity: 'high', - updated_by: 'elastic', - tags: ['some fake tag 1', 'some fake tag 2'], - to: 'now', - type: 'query', - note: '', - }; -}; - export const exampleRuleStatus: () => SavedObject = () => ({ type: ruleStatusSavedObjectType, id: '042e6d90-7069-11ea-af8b-0f8ae4fa817e', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts index df9d282b71e5e..80c2441193a0c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_bulk_body.test.ts @@ -18,7 +18,7 @@ describe('buildBulkBody', () => { jest.clearAllMocks(); }); - test('if bulk body builds well-defined body', () => { + test('bulk body builds well-defined body', () => { const sampleParams = sampleRuleAlertParams(); const fakeSignalSourceHit = buildBulkBody({ doc: sampleDocNoSortId(), @@ -80,6 +80,7 @@ describe('buildBulkBody', () => { references: ['http://google.com'], severity: 'high', tags: ['some fake tag 1', 'some fake tag 2'], + threat: [], throttle: 'no_actions', type: 'query', to: 'now', @@ -128,7 +129,7 @@ describe('buildBulkBody', () => { expect(fakeSignalSourceHit).toEqual(expected); }); - test('if bulk body builds original_event if it exists on the event to begin with', () => { + test('bulk body builds original_event if it exists on the event to begin with', () => { const sampleParams = sampleRuleAlertParams(); const doc = sampleDocNoSortId(); doc._source.event = { @@ -216,6 +217,7 @@ describe('buildBulkBody', () => { created_at: fakeSignalSourceHit.signal.rule?.created_at, updated_at: fakeSignalSourceHit.signal.rule?.updated_at, throttle: 'no_actions', + threat: [], exceptions_list: [ { field: 'source.ip', @@ -254,7 +256,7 @@ describe('buildBulkBody', () => { expect(fakeSignalSourceHit).toEqual(expected); }); - test('if bulk body builds original_event if it exists on the event to begin with but no kind information', () => { + test('bulk body builds original_event if it exists on the event to begin with but no kind information', () => { const sampleParams = sampleRuleAlertParams(); const doc = sampleDocNoSortId(); doc._source.event = { @@ -329,6 +331,7 @@ describe('buildBulkBody', () => { query: 'user.name: root or user.name: admin', references: ['http://google.com'], severity: 'high', + threat: [], tags: ['some fake tag 1', 'some fake tag 2'], type: 'query', to: 'now', @@ -378,7 +381,7 @@ describe('buildBulkBody', () => { expect(fakeSignalSourceHit).toEqual(expected); }); - test('if bulk body builds original_event if it exists on the event to begin with with only kind information', () => { + test('bulk body builds original_event if it exists on the event to begin with with only kind information', () => { const sampleParams = sampleRuleAlertParams(); const doc = sampleDocNoSortId(); doc._source.event = { @@ -447,6 +450,7 @@ describe('buildBulkBody', () => { references: ['http://google.com'], severity: 'high', tags: ['some fake tag 1', 'some fake tag 2'], + threat: [], type: 'query', to: 'now', note: '', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.test.ts index 772ebd932698b..07adfde71c1a9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.test.ts @@ -1147,17 +1147,6 @@ describe('build_exceptions_query', () => { }); describe('buildQueryExceptions', () => { - test('it returns original query if no lists exist', () => { - const query = buildQueryExceptions({ - query: 'host.name: *', - language: 'kuery', - lists: undefined, - }); - const expectedQuery = 'host.name: *'; - - expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); - }); - test('it returns original query if lists is empty array', () => { const query = buildQueryExceptions({ query: 'host.name: *', language: 'kuery', lists: [] }); const expectedQuery = 'host.name: *'; @@ -1165,24 +1154,6 @@ describe('build_exceptions_query', () => { expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); }); - test('it returns original query if lists is null', () => { - const query = buildQueryExceptions({ query: 'host.name: *', language: 'kuery', lists: null }); - const expectedQuery = 'host.name: *'; - - expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); - }); - - test('it returns original query if lists is undefined', () => { - const query = buildQueryExceptions({ - query: 'host.name: *', - language: 'kuery', - lists: undefined, - }); - const expectedQuery = 'host.name: *'; - - expect(query).toEqual([{ query: expectedQuery, language: 'kuery' }]); - }); - test('it returns expected query when lists exist and language is "kuery"', () => { // Equal to query && !((b || !c || d) && e) -> ((query AND NOT b AND c AND NOT d) OR (query AND NOT e) // https://www.dcode.fr/boolean-expressions-calculator diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.ts index d4efd9a2e8a1a..233b20792299b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_exceptions_query.ts @@ -3,13 +3,17 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { + ListAndOrUndefined, + Language, + Query, +} from '../../../../common/detection_engine/schemas/common/schemas'; import { ListOperator, ListValues, List, } from '../../../../common/detection_engine/schemas/types/lists_default_array'; -import { Query } from '../../../../../../../src/plugins/data/server'; -import { RuleAlertParams, Language } from '../types'; +import { Query as DataQuery } from '../../../../../../../src/plugins/data/server'; type Operators = 'and' | 'or' | 'not'; type LuceneOperators = 'AND' | 'OR' | 'NOT'; @@ -187,10 +191,10 @@ export const buildQueryExceptions = ({ language, lists, }: { - query: string; + query: Query; language: Language; - lists: RuleAlertParams['exceptionsList']; -}): Query[] => { + lists: ListAndOrUndefined; +}): DataQuery[] => { if (lists && lists !== null) { const exceptions = buildExceptions({ lists, language, query }); const formattedQuery = formatQuery({ exceptions, language, query }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts index b3586c884d0c7..eb87976a6fbab 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts @@ -6,7 +6,7 @@ import { buildRule } from './build_rule'; import { sampleRuleAlertParams, sampleRuleGuid } from './__mocks__/es_results'; -import { OutputRuleAlertRest } from '../types'; +import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; describe('buildRule', () => { beforeEach(() => { @@ -40,7 +40,7 @@ describe('buildRule', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: 'no_actions', }); - const expected: Partial = { + const expected: Partial = { actions: [], created_by: 'elastic', description: 'Detecting root and admin users', @@ -61,6 +61,7 @@ describe('buildRule', () => { rule_id: 'rule-1', severity: 'high', tags: ['some fake tag 1', 'some fake tag 2'], + threat: [], to: 'now', type: 'query', note: '', @@ -133,7 +134,7 @@ describe('buildRule', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: 'no_actions', }); - const expected: Partial = { + const expected: Partial = { actions: [], created_by: 'elastic', description: 'Detecting root and admin users', @@ -154,6 +155,7 @@ describe('buildRule', () => { rule_id: 'rule-1', severity: 'high', tags: ['some fake tag 1', 'some fake tag 2'], + threat: [], to: 'now', type: 'query', note: '', @@ -215,7 +217,7 @@ describe('buildRule', () => { tags: ['some fake tag 1', 'some fake tag 2'], throttle: 'no_actions', }); - const expected: Partial = { + const expected: Partial = { actions: [], created_by: 'elastic', description: 'Detecting root and admin users', @@ -237,6 +239,7 @@ describe('buildRule', () => { rule_id: 'rule-1', severity: 'high', tags: ['some fake tag 1', 'some fake tag 2'], + threat: [], to: 'now', type: 'query', updated_by: 'elastic', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.ts index de8de1bc513e3..bde9c970b0c8c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.ts @@ -5,8 +5,9 @@ */ import { pickBy } from 'lodash/fp'; +import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; import { RuleAlertAction } from '../../../../common/detection_engine/types'; -import { RuleTypeParams, OutputRuleAlertRest } from '../types'; +import { RuleTypeParams } from '../types'; interface BuildRuleParams { ruleParams: RuleTypeParams; @@ -36,10 +37,10 @@ export const buildRule = ({ interval, tags, throttle, -}: BuildRuleParams): Partial => { - return pickBy((value: unknown) => value != null, { +}: BuildRuleParams): Partial => { + return pickBy((value: unknown) => value != null, { id, - rule_id: ruleParams.ruleId, + rule_id: ruleParams.ruleId ?? '(unknown rule_id)', actions, false_positives: ruleParams.falsePositives, saved_id: ruleParams.savedId, @@ -67,12 +68,12 @@ export const buildRule = ({ filters: ruleParams.filters, created_by: createdBy, updated_by: updatedBy, - threat: ruleParams.threat, + threat: ruleParams.threat ?? [], throttle, version: ruleParams.version, created_at: createdAt, updated_at: updatedAt, - exceptions_list: ruleParams.exceptionsList, + exceptions_list: ruleParams.exceptionsList ?? [], machine_learning_job_id: ruleParams.machineLearningJobId, anomaly_threshold: ruleParams.anomalyThreshold, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.test.ts index f3f4ab60e4db6..6aebf8815659a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { sampleDocNoSortId, sampleRule } from './__mocks__/es_results'; +import { sampleDocNoSortId } from './__mocks__/es_results'; import { buildSignal, buildAncestor, @@ -13,6 +13,7 @@ import { } from './build_signal'; import { Signal, Ancestor } from './types'; import { INTERNAL_RULE_ID_KEY, INTERNAL_IMMUTABLE_KEY } from '../../../../common/constants'; +import { getPartialRulesSchemaMock } from '../../../../common/detection_engine/schemas/response/rules_schema.mocks'; describe('buildSignal', () => { beforeEach(() => { @@ -22,7 +23,7 @@ describe('buildSignal', () => { test('it builds a signal as expected without original_event if event does not exist', () => { const doc = sampleDocNoSortId('d5e8eb51-a6a0-456d-8a15-4b79bfec3d71'); delete doc._source.event; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); const signal = buildSignal(doc, rule); const expected: Signal = { parent: { @@ -82,7 +83,7 @@ describe('buildSignal', () => { kind: 'event', module: 'system', }; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); const signal = buildSignal(doc, rule); const expected: Signal = { parent: { @@ -148,7 +149,7 @@ describe('buildSignal', () => { kind: 'event', module: 'system', }; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); rule.tags = [ 'some fake tag 1', 'some fake tag 2', @@ -220,7 +221,7 @@ describe('buildSignal', () => { kind: 'event', module: 'system', }; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); const signal = buildAncestor(doc, rule); const expected: Ancestor = { rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', @@ -258,7 +259,7 @@ describe('buildSignal', () => { }, ], }; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); const signal = buildAncestor(doc, rule); const expected: Ancestor = { rule: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', @@ -296,7 +297,7 @@ describe('buildSignal', () => { }, ], }; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); rule.tags = [ 'some fake tag 1', 'some fake tag 2', @@ -323,7 +324,7 @@ describe('buildSignal', () => { kind: 'event', module: 'system', }; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); const signal = buildAncestorsSignal(doc, rule); const expected: Ancestor[] = [ { @@ -363,7 +364,7 @@ describe('buildSignal', () => { }, ], }; - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); const signal = buildAncestorsSignal(doc, rule); const expected: Ancestor[] = [ { @@ -385,7 +386,7 @@ describe('buildSignal', () => { }); test('it removes internal tags from a typical rule', () => { - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); rule.tags = [ 'some fake tag 1', 'some fake tag 2', @@ -393,29 +394,29 @@ describe('buildSignal', () => { `${INTERNAL_IMMUTABLE_KEY}:true`, ]; const noInternals = removeInternalTagsFromRule(rule); - expect(noInternals).toEqual(sampleRule()); + expect(noInternals).toEqual(getPartialRulesSchemaMock()); }); test('it works with an empty array', () => { - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); rule.tags = []; const noInternals = removeInternalTagsFromRule(rule); - const expected = sampleRule(); + const expected = getPartialRulesSchemaMock(); expected.tags = []; expect(noInternals).toEqual(expected); }); test('it works if tags does not exist', () => { - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); delete rule.tags; const noInternals = removeInternalTagsFromRule(rule); - const expected = sampleRule(); + const expected = getPartialRulesSchemaMock(); delete expected.tags; expect(noInternals).toEqual(expected); }); test('it works if tags contains normal values and no internal values', () => { - const rule = sampleRule(); + const rule = getPartialRulesSchemaMock(); const noInternals = removeInternalTagsFromRule(rule); expect(noInternals).toEqual(rule); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.ts index a0551d75d2750..77a63c63ff97a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_signal.ts @@ -4,14 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; import { INTERNAL_IDENTIFIER } from '../../../../common/constants'; import { SignalSourceHit, Signal, Ancestor } from './types'; -import { OutputRuleAlertRest } from '../types'; -export const buildAncestor = ( - doc: SignalSourceHit, - rule: Partial -): Ancestor => { +export const buildAncestor = (doc: SignalSourceHit, rule: Partial): Ancestor => { const existingSignal = doc._source.signal?.parent; if (existingSignal != null) { return { @@ -34,7 +31,7 @@ export const buildAncestor = ( export const buildAncestorsSignal = ( doc: SignalSourceHit, - rule: Partial + rule: Partial ): Signal['ancestors'] => { const newAncestor = buildAncestor(doc, rule); const existingAncestors = doc._source.signal?.ancestors; @@ -45,7 +42,7 @@ export const buildAncestorsSignal = ( } }; -export const buildSignal = (doc: SignalSourceHit, rule: Partial): Signal => { +export const buildSignal = (doc: SignalSourceHit, rule: Partial): Signal => { const ruleWithoutInternalTags = removeInternalTagsFromRule(rule); const parent = buildAncestor(doc, rule); const ancestors = buildAncestorsSignal(doc, rule); @@ -62,13 +59,11 @@ export const buildSignal = (doc: SignalSourceHit, rule: Partial -): Partial => { +export const removeInternalTagsFromRule = (rule: Partial): Partial => { if (rule.tags == null) { return rule; } else { - const ruleWithoutInternalTags: Partial = { + const ruleWithoutInternalTags: Partial = { ...rule, tags: rule.tags.filter((tag) => !tag.startsWith(INTERNAL_IDENTIFIER)), }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.test.ts index d56e167f59e4c..4e9eb8587484f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.test.ts @@ -21,11 +21,11 @@ describe('filterEventsAgainstList', () => { listClient.getListItemByValues = jest.fn().mockResolvedValue([]); }); - it('should respond with eventSearchResult if exceptionList is empty', async () => { + it('should respond with eventSearchResult if exceptionList is empty array', async () => { const res = await filterEventsAgainstList({ logger: mockLogger, listClient, - exceptionsList: undefined, + exceptionsList: [], eventSearchResult: repeatedSearchResultsWithSortId(4, 4, someGuids.slice(0, 3), [ '1.1.1.1', '2.2.2.2', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.ts index 29b8b54d162df..48b120d1b5806 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filter_events_with_list.ts @@ -6,15 +6,15 @@ import { get } from 'lodash/fp'; import { Logger } from 'src/core/server'; +import { ListAndOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas'; import { List } from '../../../../common/detection_engine/schemas/types/lists_default_array'; import { type } from '../../../../../lists/common/schemas/common'; import { ListClient } from '../../../../../lists/server'; import { SignalSearchResponse, SearchTypes } from './types'; -import { RuleAlertParams } from '../types'; interface FilterEventsAgainstList { listClient: ListClient; - exceptionsList: RuleAlertParams['exceptionsList']; + exceptionsList: ListAndOrUndefined; logger: Logger; eventSearchResult: SignalSearchResponse; } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts index 0930fbdb534f5..b1500e47db843 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.test.ts @@ -449,20 +449,6 @@ describe('get_filter', () => { }); }); - test('it should work when lists has value null', () => { - const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], null); - expect(esQuery).toEqual({ - bool: { - filter: [ - { bool: { minimum_should_match: 1, should: [{ match: { 'host.name': 'linux' } }] } }, - ], - must: [], - must_not: [], - should: [], - }, - }); - }); - test('it should work when lists has value undefined', () => { const esQuery = getQueryFilter('host.name: linux', 'kuery', [], ['auditbeat-*'], undefined); expect(esQuery).toEqual({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts index c464238715afd..3e9f79c67d8ca 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_filter.ts @@ -4,32 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ +import { + LanguageOrUndefined, + QueryOrUndefined, + Type, + SavedIdOrUndefined, + IndexOrUndefined, + ListAndOrUndefined, + Language, + Index, + Query, +} from '../../../../common/detection_engine/schemas/common/schemas'; import { AlertServices } from '../../../../../alerts/server'; import { assertUnreachable } from '../../../utils/build_query'; import { Filter, - Query, + Query as DataQuery, esQuery, esFilters, IIndexPattern, } from '../../../../../../../src/plugins/data/server'; -import { PartialFilter, RuleAlertParams, Language } from '../types'; +import { PartialFilter } from '../types'; import { BadRequestError } from '../errors/bad_request_error'; import { buildQueryExceptions } from './build_exceptions_query'; export const getQueryFilter = ( - query: string, + query: Query, language: Language, filters: PartialFilter[], - index: string[], - lists: RuleAlertParams['exceptionsList'] + index: Index, + lists: ListAndOrUndefined ) => { const indexPattern = { fields: [], title: index.join(), } as IIndexPattern; - const queries: Query[] = buildQueryExceptions({ query, language, lists }); + const queries: DataQuery[] = buildQueryExceptions({ query, language, lists }); const config = { allowLeadingWildcards: true, @@ -46,14 +57,14 @@ export const getQueryFilter = ( }; interface GetFilterArgs { - type: RuleAlertParams['type']; - filters: PartialFilter[] | undefined | null; - language: Language | undefined | null; - query: string | undefined | null; - savedId: string | undefined | null; + type: Type; + filters: PartialFilter[] | undefined; + language: LanguageOrUndefined; + query: QueryOrUndefined; + savedId: SavedIdOrUndefined; services: AlertServices; - index: string[] | undefined | null; - lists: RuleAlertParams['exceptionsList']; + index: IndexOrUndefined; + lists: ListAndOrUndefined; } interface QueryAttributes { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts index 9430dfe7bfe23..0f4b8d1472b3f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/rule_status_service.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ +import { JobStatus } from '../../../../common/detection_engine/schemas/common/schemas'; import { assertUnreachable } from '../../../utils/build_query'; -import { IRuleStatusAttributes, RuleStatusString } from '../rules/types'; +import { IRuleStatusAttributes } from '../rules/types'; import { getOrCreateRuleStatuses } from './get_or_create_rule_statuses'; import { RuleStatusSavedObjectsClient } from './rule_status_saved_objects_client'; @@ -26,7 +27,7 @@ export interface RuleStatusService { } export const buildRuleStatusAttributes: ( - status: RuleStatusString, + status: JobStatus, message?: string, attributes?: Attributes ) => Partial = (status, message, attributes = {}) => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts index b7bea906475db..42893a199a8f1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ListAndOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas'; import { AlertServices } from '../../../../../alerts/server'; import { ListClient } from '../../../../../lists/server'; import { RuleAlertAction } from '../../../../common/detection_engine/types'; -import { RuleTypeParams, RefreshTypes, RuleAlertParams } from '../types'; +import { RuleTypeParams, RefreshTypes } from '../types'; import { Logger } from '../../../../../../../src/core/server'; import { singleSearchAfter } from './single_search_after'; import { singleBulkCreate } from './single_bulk_create'; @@ -18,7 +19,7 @@ interface SearchAfterAndBulkCreateParams { ruleParams: RuleTypeParams; services: AlertServices; listClient: ListClient | undefined; // TODO: undefined is for temporary development, remove before merged - exceptionsList: RuleAlertParams['exceptionsList']; + exceptionsList: ListAndOrUndefined; logger: Logger; id: string; inputIndexPattern: string[]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_params_schema.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_params_schema.ts index d42ba8fe57005..461b2589babcc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_params_schema.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_params_schema.ts @@ -4,40 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ -import { schema } from '@kbn/config-schema'; +import { schema, TypeOf } from '@kbn/config-schema'; import { DEFAULT_MAX_SIGNALS } from '../../../../common/constants'; +const signalSchema = schema.object({ + anomalyThreshold: schema.maybe(schema.number()), + description: schema.string(), + note: schema.nullable(schema.string()), + falsePositives: schema.arrayOf(schema.string(), { defaultValue: [] }), + from: schema.string(), + ruleId: schema.string(), + immutable: schema.boolean({ defaultValue: false }), + index: schema.nullable(schema.arrayOf(schema.string())), + language: schema.nullable(schema.string()), + outputIndex: schema.nullable(schema.string()), + savedId: schema.nullable(schema.string()), + timelineId: schema.nullable(schema.string()), + timelineTitle: schema.nullable(schema.string()), + meta: schema.nullable(schema.object({}, { unknowns: 'allow' })), + machineLearningJobId: schema.maybe(schema.string()), + query: schema.nullable(schema.string()), + filters: schema.nullable(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))), + maxSignals: schema.number({ defaultValue: DEFAULT_MAX_SIGNALS }), + riskScore: schema.number(), + severity: schema.string(), + threat: schema.nullable(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))), + to: schema.string(), + type: schema.string(), + references: schema.arrayOf(schema.string(), { defaultValue: [] }), + version: schema.number({ defaultValue: 1 }), + exceptionsList: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))), +}); + /** * This is the schema for the Alert Rule that represents the SIEM alert for signals * that index into the .siem-signals-${space-id} */ -export const signalParamsSchema = () => - schema.object({ - anomalyThreshold: schema.maybe(schema.number()), - description: schema.string(), - note: schema.nullable(schema.string()), - falsePositives: schema.arrayOf(schema.string(), { defaultValue: [] }), - from: schema.string(), - ruleId: schema.string(), - immutable: schema.boolean({ defaultValue: false }), - index: schema.nullable(schema.arrayOf(schema.string())), - language: schema.nullable(schema.string()), - outputIndex: schema.nullable(schema.string()), - savedId: schema.nullable(schema.string()), - timelineId: schema.nullable(schema.string()), - timelineTitle: schema.nullable(schema.string()), - meta: schema.nullable(schema.object({}, { unknowns: 'allow' })), - machineLearningJobId: schema.maybe(schema.string()), - query: schema.nullable(schema.string()), - filters: schema.nullable(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))), - maxSignals: schema.number({ defaultValue: DEFAULT_MAX_SIGNALS }), - riskScore: schema.number(), - severity: schema.string(), - threat: schema.nullable(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))), - to: schema.string(), - type: schema.string(), - references: schema.arrayOf(schema.string(), { defaultValue: [] }), - version: schema.number({ defaultValue: 1 }), - exceptionsList: schema.maybe(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))), - }); +export const signalParamsSchema = () => signalSchema; + +export type SignalParamsSchema = TypeOf; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts index f94eb7006829e..a2dc33ba1c2bf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts @@ -39,8 +39,6 @@ const getPayload = (ruleAlert: RuleAlertType, services: AlertServicesMock) => ({ name: ruleAlert.name, tags: ruleAlert.tags, throttle: ruleAlert.throttle, - scrollSize: 10, - scrollLock: '0', }, state: {}, spaceId: '', @@ -105,7 +103,7 @@ describe('rules_notification_alert_type', () => { attributes: ruleAlert, }); - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; alert = signalRulesAlertType({ logger, @@ -196,7 +194,7 @@ describe('rules_notification_alert_type', () => { describe('ML rule', () => { it('should throw an error if ML plugin was not available', async () => { const ruleAlert = getMlResult(); - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; alert = signalRulesAlertType({ logger, version, @@ -213,7 +211,7 @@ describe('rules_notification_alert_type', () => { it('should throw an error if machineLearningJobId or anomalyThreshold was not null', async () => { const ruleAlert = getMlResult(); ruleAlert.params.anomalyThreshold = undefined; - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; await alert.executor(payload); expect(logger.error).toHaveBeenCalled(); expect(logger.error.mock.calls[0][0]).toContain( @@ -223,7 +221,7 @@ describe('rules_notification_alert_type', () => { it('should throw an error if Machine learning job summary was null', async () => { const ruleAlert = getMlResult(); - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; jobsSummaryMock.mockResolvedValue([]); await alert.executor(payload); expect(logger.warn).toHaveBeenCalled(); @@ -236,7 +234,7 @@ describe('rules_notification_alert_type', () => { it('should log an error if Machine learning job was not started', async () => { const ruleAlert = getMlResult(); - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; jobsSummaryMock.mockResolvedValue([ { id: 'some_job_id', @@ -260,7 +258,7 @@ describe('rules_notification_alert_type', () => { it('should not call ruleStatusService.success if no anomalies were found', async () => { const ruleAlert = getMlResult(); - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; jobsSummaryMock.mockResolvedValue([]); (findMlSignals as jest.Mock).mockResolvedValue({ hits: { @@ -278,7 +276,7 @@ describe('rules_notification_alert_type', () => { it('should call ruleStatusService.success if signals were created', async () => { const ruleAlert = getMlResult(); - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; jobsSummaryMock.mockResolvedValue([ { id: 'some_job_id', @@ -313,7 +311,7 @@ describe('rules_notification_alert_type', () => { id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', }, ]; - payload = getPayload(ruleAlert, alertServices); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; alertServices.savedObjectsClient.get.mockResolvedValue({ id: 'id', type: 'type', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 567274be6a9f8..091ee54e3174e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -275,7 +275,7 @@ export const signalRulesAlertType = ({ from: fromInMs, to: toInMs, id: savedObject.id, - kibanaSiemAppUrl: meta?.kibana_siem_app_url, + kibanaSiemAppUrl: (meta as { kibana_siem_app_url?: string }).kibana_siem_app_url, }); logger.info( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts index 869c81f640561..082211df28320 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts @@ -4,21 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Status } from '../../../../common/detection_engine/schemas/common/schemas'; +import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; import { AlertType, State, AlertExecutorOptions } from '../../../../../alerts/server'; import { RuleAlertAction } from '../../../../common/detection_engine/types'; -import { RuleAlertParams, OutputRuleAlertRest } from '../types'; +import { RuleTypeParams } from '../types'; import { SearchResponse } from '../../types'; export interface SignalsParams { signalIds: string[] | undefined | null; query: object | undefined | null; - status: 'open' | 'closed'; + status: Status; } export interface SignalsStatusParams { signalIds: string[] | undefined | null; query: object | undefined | null; - status: 'open' | 'closed'; + status: Status; } export type SearchTypes = @@ -91,10 +93,7 @@ export type SignalSearchResponse = SearchResponse; export type SignalSourceHit = SignalSearchResponse['hits']['hits'][number]; export type RuleExecutorOptions = Omit & { - params: RuleAlertParams & { - scrollSize: number; - scrollLock: string; - }; + params: RuleTypeParams; }; // This returns true because by default a RuleAlertTypeDefinition is an AlertType @@ -116,12 +115,12 @@ export interface Ancestor { } export interface Signal { - rule: Partial; + rule: Partial; parent: Ancestor; ancestors: Ancestor[]; original_time: string; original_event?: SearchTypes; - status: 'open' | 'closed'; + status: Status; } export interface SignalHit { @@ -145,12 +144,7 @@ export interface AlertAttributes { } export interface RuleAlertAttributes extends AlertAttributes { - params: Omit< - RuleAlertParams, - 'ruleId' | 'name' | 'enabled' | 'interval' | 'tags' | 'actions' | 'throttle' - > & { - ruleId: string; - }; + params: RuleTypeParams; } export type BulkResponseErrorAggregation = Record; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts index 9062de49fa6ce..6e284908e3358 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/types.ts @@ -4,131 +4,67 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ListsDefaultArraySchema } from '../../../common/detection_engine/schemas/types/lists_default_array'; +import { + AnomalyThresholdOrUndefined, + Description, + NoteOrUndefined, + ThreatOrUndefined, + FalsePositives, + From, + Immutable, + IndexOrUndefined, + LanguageOrUndefined, + MaxSignals, + MachineLearningJobIdOrUndefined, + RiskScore, + OutputIndex, + QueryOrUndefined, + References, + SavedIdOrUndefined, + Severity, + To, + TimelineIdOrUndefined, + TimelineTitleOrUndefined, + Version, + MetaOrUndefined, + RuleId, + ListAndOrUndefined, +} from '../../../common/detection_engine/schemas/common/schemas'; import { CallAPIOptions } from '../../../../../../src/core/server'; import { Filter } from '../../../../../../src/plugins/data/server'; -import { IRuleStatusAttributes } from './rules/types'; -import { RuleAlertAction, RuleType } from '../../../common/detection_engine/types'; +import { RuleType } from '../../../common/detection_engine/types'; export type PartialFilter = Partial; -export interface IMitreAttack { - id: string; - name: string; - reference: string; -} - -export interface ThreatParams { - framework: string; - tactic: IMitreAttack; - technique: IMitreAttack[]; -} - -// Notice below we are using lists: ListsAndArraySchema[]; which is coming directly from the response output section. -// TODO: Eventually this whole RuleAlertParams will be replaced with io-ts. For now we can slowly strangle it out and reduce duplicate types -// We don't have the input types defined through io-ts just yet but as we being introducing types from there we will more and more remove -// types and share them between input and output schema but have an input Rule Schema and an output Rule Schema. - -export interface Meta { - [key: string]: {} | string | undefined | null; - kibana_siem_app_url?: string | undefined; -} - -export type Language = 'kuery' | 'lucene'; - -export interface RuleAlertParams { - actions: RuleAlertAction[]; - anomalyThreshold: number | undefined; - description: string; - note: string | undefined | null; - enabled: boolean; - falsePositives: string[]; - filters: PartialFilter[] | undefined | null; - from: string; - immutable: boolean; - index: string[] | undefined | null; - interval: string; - ruleId: string | undefined | null; - language: Language | undefined | null; - maxSignals: number; - machineLearningJobId: string | undefined; - riskScore: number; - outputIndex: string; - name: string; - query: string | undefined | null; - references: string[]; - savedId?: string | undefined | null; - meta: Meta | undefined | null; - severity: string; - tags: string[]; - to: string; - timelineId: string | undefined | null; - timelineTitle: string | undefined | null; - threat: ThreatParams[] | undefined | null; +export interface RuleTypeParams { + anomalyThreshold: AnomalyThresholdOrUndefined; + description: Description; + note: NoteOrUndefined; + falsePositives: FalsePositives; + from: From; + ruleId: RuleId; + immutable: Immutable; + index: IndexOrUndefined; + language: LanguageOrUndefined; + outputIndex: OutputIndex; + savedId: SavedIdOrUndefined; + timelineId: TimelineIdOrUndefined; + timelineTitle: TimelineTitleOrUndefined; + meta: MetaOrUndefined; + machineLearningJobId: MachineLearningJobIdOrUndefined; + query: QueryOrUndefined; + filters: PartialFilter[] | undefined; + maxSignals: MaxSignals; + riskScore: RiskScore; + severity: Severity; + threat: ThreatOrUndefined; + to: To; type: RuleType; - version: number; - throttle: string | undefined | null; - exceptionsList: ListsDefaultArraySchema | null | undefined; + references: References; + version: Version; + exceptionsList: ListAndOrUndefined; } -export type RuleTypeParams = Omit< - RuleAlertParams, - 'name' | 'enabled' | 'interval' | 'tags' | 'actions' | 'throttle' ->; - -export type RuleAlertParamsRest = Omit< - RuleAlertParams, - | 'anomalyThreshold' - | 'ruleId' - | 'falsePositives' - | 'immutable' - | 'maxSignals' - | 'exceptionsList' - | 'machineLearningJobId' - | 'savedId' - | 'riskScore' - | 'timelineId' - | 'timelineTitle' - | 'outputIndex' -> & - Omit< - IRuleStatusAttributes, - | 'status' - | 'alertId' - | 'statusDate' - | 'lastFailureAt' - | 'lastSuccessAt' - | 'lastSuccessMessage' - | 'lastFailureMessage' - > & { - anomaly_threshold: RuleAlertParams['anomalyThreshold']; - exceptions_list: RuleAlertParams['exceptionsList']; - rule_id: RuleAlertParams['ruleId']; - false_positives: RuleAlertParams['falsePositives']; - saved_id?: RuleAlertParams['savedId']; - timeline_id: RuleAlertParams['timelineId']; - timeline_title: RuleAlertParams['timelineTitle']; - max_signals: RuleAlertParams['maxSignals']; - machine_learning_job_id: RuleAlertParams['machineLearningJobId']; - risk_score: RuleAlertParams['riskScore']; - output_index: RuleAlertParams['outputIndex']; - created_at: string; - updated_at: string; - status?: IRuleStatusAttributes['status'] | undefined; - status_date?: IRuleStatusAttributes['statusDate'] | undefined; - last_failure_at?: IRuleStatusAttributes['lastFailureAt'] | undefined; - last_success_at?: IRuleStatusAttributes['lastSuccessAt'] | undefined; - last_failure_message?: IRuleStatusAttributes['lastFailureMessage'] | undefined; - last_success_message?: IRuleStatusAttributes['lastSuccessMessage'] | undefined; - }; - -export type OutputRuleAlertRest = RuleAlertParamsRest & { - id: string; - created_by: string | undefined | null; - updated_by: string | undefined | null; - immutable: boolean; -}; - // eslint-disable-next-line @typescript-eslint/no-explicit-any export type CallWithRequest, V> = ( endpoint: string, diff --git a/x-pack/plugins/security_solution/server/utils/read_stream/create_stream_from_ndjson.test.ts b/x-pack/plugins/security_solution/server/utils/read_stream/create_stream_from_ndjson.test.ts index ca2f881d6abd8..a1902202d983d 100644 --- a/x-pack/plugins/security_solution/server/utils/read_stream/create_stream_from_ndjson.test.ts +++ b/x-pack/plugins/security_solution/server/utils/read_stream/create_stream_from_ndjson.test.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { transformDataToNdjson } from './create_stream_from_ndjson'; -import { sampleRule } from '../../lib/detection_engine/signals/__mocks__/es_results'; import { ImportRulesSchemaDecoded } from '../../../common/detection_engine/schemas/request/import_rules_schema'; +import { getRulesSchemaMock } from '../../../common/detection_engine/schemas/response/rules_schema.mocks'; export const getOutputSample = (): Partial => ({ rule_id: 'rule-1', @@ -33,14 +33,14 @@ describe('create_rules_stream_from_ndjson', () => { }); test('single rule will transform with new line ending character for ndjson', () => { - const rule = sampleRule(); + const rule = getRulesSchemaMock(); const ruleNdjson = transformDataToNdjson([rule]); expect(ruleNdjson.endsWith('\n')).toBe(true); }); test('multiple rules will transform with two new line ending characters for ndjson', () => { - const result1 = sampleRule(); - const result2 = sampleRule(); + const result1 = getRulesSchemaMock(); + const result2 = getRulesSchemaMock(); result2.id = 'some other id'; result2.rule_id = 'some other id'; result2.name = 'Some other rule'; @@ -52,8 +52,8 @@ describe('create_rules_stream_from_ndjson', () => { }); test('you can parse two rules back out without errors', () => { - const result1 = sampleRule(); - const result2 = sampleRule(); + const result1 = getRulesSchemaMock(); + const result2 = getRulesSchemaMock(); result2.id = 'some other id'; result2.rule_id = 'some other id'; result2.name = 'Some other rule'; diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/update_rules.ts b/x-pack/test/detection_engine_api_integration/basic/tests/update_rules.ts index 127f688dfbc28..9cda6271d427f 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/update_rules.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/update_rules.ts @@ -12,12 +12,12 @@ import { createSignalsIndex, deleteAllAlerts, deleteSignalsIndex, - getSimpleRule, getSimpleRuleOutput, removeServerGeneratedProperties, removeServerGeneratedPropertiesIncludingRuleId, getSimpleRuleOutputWithoutRuleId, - getSimpleMlRule, + getSimpleRuleUpdate, + getSimpleMlRuleUpdate, } from '../../utils'; // eslint-disable-next-line import/no-default-export @@ -41,11 +41,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.rule_id = 'rule-1'; updatedRule.name = 'some other name'; delete updatedRule.id; @@ -68,11 +68,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's type to try to be a machine learning job type - const updatedRule = getSimpleMlRule('rule-1'); + const updatedRule = getSimpleMlRuleUpdate('rule-1'); updatedRule.rule_id = 'rule-1'; updatedRule.name = 'some other name'; delete updatedRule.id; @@ -90,7 +90,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should update a single rule property of name using an auto-generated rule_id', async () => { - const rule = getSimpleRule('rule-1'); + const rule = getSimpleRuleUpdate('rule-1'); delete rule.rule_id; // create a simple rule const { body: createRuleBody } = await supertest @@ -100,7 +100,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); // update a simple rule's name - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.rule_id = createRuleBody.rule_id; updatedRule.name = 'some other name'; delete updatedRule.id; @@ -123,11 +123,11 @@ export default ({ getService }: FtrProviderContext) => { const { body: createdBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.name = 'some other name'; updatedRule.id = createdBody.id; delete updatedRule.rule_id; @@ -150,11 +150,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's enabled to false and another property - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.severity = 'low'; updatedRule.enabled = false; @@ -178,10 +178,10 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.timeline_title = 'some title'; ruleUpdate.timeline_id = 'some id'; @@ -192,7 +192,7 @@ export default ({ getService }: FtrProviderContext) => { .send(ruleUpdate) .expect(200); - const ruleUpdate2 = getSimpleRule('rule-1'); + const ruleUpdate2 = getSimpleRuleUpdate('rule-1'); ruleUpdate2.name = 'some other name'; // update a simple rule's name @@ -211,7 +211,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should give a 404 if it is given a fake id', async () => { - const simpleRule = getSimpleRule(); + const simpleRule = getSimpleRuleUpdate(); simpleRule.id = '5096dec6-b6b9-4d8d-8f93-6c2602079d9d'; delete simpleRule.rule_id; @@ -228,7 +228,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should give a 404 if it is given a fake rule_id', async () => { - const simpleRule = getSimpleRule(); + const simpleRule = getSimpleRuleUpdate(); simpleRule.rule_id = 'fake_id'; delete simpleRule.id; diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts index 54f29939fb6b4..24eee8deaf3d4 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/update_rules_bulk.ts @@ -12,11 +12,11 @@ import { createSignalsIndex, deleteAllAlerts, deleteSignalsIndex, - getSimpleRule, getSimpleRuleOutput, removeServerGeneratedProperties, getSimpleRuleOutputWithoutRuleId, removeServerGeneratedPropertiesIncludingRuleId, + getSimpleRuleUpdate, } from '../../utils'; // eslint-disable-next-line import/no-default-export @@ -40,10 +40,10 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.name = 'some other name'; // update a simple rule's name @@ -65,20 +65,20 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // create a second simple rule await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-2')) + .send(getSimpleRuleUpdate('rule-2')) .expect(200); - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.name = 'some other name'; - const updatedRule2 = getSimpleRule('rule-2'); + const updatedRule2 = getSimpleRuleUpdate('rule-2'); updatedRule2.name = 'some other name'; // update both rule names @@ -107,11 +107,11 @@ export default ({ getService }: FtrProviderContext) => { const { body: createRuleBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.id = createRuleBody.id; updatedRule1.name = 'some other name'; delete updatedRule1.rule_id; @@ -134,23 +134,23 @@ export default ({ getService }: FtrProviderContext) => { const { body: createRule1 } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // create a second simple rule const { body: createRule2 } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-2')) + .send(getSimpleRuleUpdate('rule-2')) .expect(200); // update both rule names - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.id = createRule1.id; updatedRule1.name = 'some other name'; delete updatedRule1.rule_id; - const updatedRule2 = getSimpleRule('rule-1'); + const updatedRule2 = getSimpleRuleUpdate('rule-1'); updatedRule2.id = createRule2.id; updatedRule2.name = 'some other name'; delete updatedRule2.rule_id; @@ -180,11 +180,11 @@ export default ({ getService }: FtrProviderContext) => { const { body: createdBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.id = createdBody.id; updatedRule1.name = 'some other name'; delete updatedRule1.rule_id; @@ -207,11 +207,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's enabled to false and another property - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.severity = 'low'; updatedRule1.enabled = false; @@ -235,11 +235,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's timeline_title - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.timeline_title = 'some title'; ruleUpdate.timeline_id = 'some id'; @@ -250,7 +250,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); // update a simple rule's name - const ruleUpdate2 = getSimpleRule('rule-1'); + const ruleUpdate2 = getSimpleRuleUpdate('rule-1'); ruleUpdate2.name = 'some other name'; const { body } = await supertest @@ -268,7 +268,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return a 200 but give a 404 in the message if it is given a fake id', async () => { - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.id = '1fd52120-d3a9-4e7a-b23c-96c0e1a74ae5'; delete ruleUpdate.rule_id; @@ -290,7 +290,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return a 200 but give a 404 in the message if it is given a fake rule_id', async () => { - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.rule_id = 'fake_id'; delete ruleUpdate.id; @@ -313,14 +313,14 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.name = 'some other name'; delete ruleUpdate.id; - const ruleUpdate2 = getSimpleRule('fake_id'); + const ruleUpdate2 = getSimpleRuleUpdate('fake_id'); ruleUpdate2.name = 'some other name'; delete ruleUpdate.id; @@ -353,16 +353,16 @@ export default ({ getService }: FtrProviderContext) => { const { body: createdBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update one rule name and give a fake id for the second - const rule1 = getSimpleRule(); + const rule1 = getSimpleRuleUpdate(); delete rule1.rule_id; rule1.id = createdBody.id; rule1.name = 'some other name'; - const rule2 = getSimpleRule(); + const rule2 = getSimpleRuleUpdate(); delete rule2.rule_id; rule2.id = 'b3aa019a-656c-4311-b13b-4d9852e24347'; rule2.name = 'some other name'; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules.ts index 0b1b49e379d17..279158f09f273 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules.ts @@ -12,13 +12,14 @@ import { createSignalsIndex, deleteAllAlerts, deleteSignalsIndex, - getSimpleRule, getSimpleRuleOutput, removeServerGeneratedProperties, removeServerGeneratedPropertiesIncludingRuleId, getSimpleRuleOutputWithoutRuleId, getSimpleMlRule, getSimpleMlRuleOutput, + getSimpleRuleUpdate, + getSimpleMlRuleUpdate, } from '../../utils'; // eslint-disable-next-line import/no-default-export @@ -42,11 +43,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.rule_id = 'rule-1'; updatedRule.name = 'some other name'; delete updatedRule.id; @@ -73,7 +74,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); // update a simple rule's name - const updatedRule = getSimpleMlRule('rule-1'); + const updatedRule = getSimpleMlRuleUpdate('rule-1'); updatedRule.rule_id = 'rule-1'; updatedRule.name = 'some other name'; delete updatedRule.id; @@ -92,7 +93,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should update a single rule property of name using an auto-generated rule_id', async () => { - const rule = getSimpleRule('rule-1'); + const rule = getSimpleRuleUpdate('rule-1'); delete rule.rule_id; // create a simple rule const { body: createRuleBody } = await supertest @@ -102,7 +103,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); // update a simple rule's name - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.rule_id = createRuleBody.rule_id; updatedRule.name = 'some other name'; delete updatedRule.id; @@ -125,11 +126,11 @@ export default ({ getService }: FtrProviderContext) => { const { body: createdBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.name = 'some other name'; updatedRule.id = createdBody.id; delete updatedRule.rule_id; @@ -152,11 +153,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's enabled to false and another property - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.severity = 'low'; updatedRule.enabled = false; @@ -180,10 +181,10 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.timeline_title = 'some title'; ruleUpdate.timeline_id = 'some id'; @@ -194,7 +195,7 @@ export default ({ getService }: FtrProviderContext) => { .send(ruleUpdate) .expect(200); - const ruleUpdate2 = getSimpleRule('rule-1'); + const ruleUpdate2 = getSimpleRuleUpdate('rule-1'); ruleUpdate2.name = 'some other name'; // update a simple rule's name @@ -213,7 +214,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should give a 404 if it is given a fake id', async () => { - const simpleRule = getSimpleRule(); + const simpleRule = getSimpleRuleUpdate(); simpleRule.id = '5096dec6-b6b9-4d8d-8f93-6c2602079d9d'; delete simpleRule.rule_id; @@ -230,7 +231,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should give a 404 if it is given a fake rule_id', async () => { - const simpleRule = getSimpleRule(); + const simpleRule = getSimpleRuleUpdate(); simpleRule.rule_id = 'fake_id'; delete simpleRule.id; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts index 54f29939fb6b4..24eee8deaf3d4 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts @@ -12,11 +12,11 @@ import { createSignalsIndex, deleteAllAlerts, deleteSignalsIndex, - getSimpleRule, getSimpleRuleOutput, removeServerGeneratedProperties, getSimpleRuleOutputWithoutRuleId, removeServerGeneratedPropertiesIncludingRuleId, + getSimpleRuleUpdate, } from '../../utils'; // eslint-disable-next-line import/no-default-export @@ -40,10 +40,10 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); - const updatedRule = getSimpleRule('rule-1'); + const updatedRule = getSimpleRuleUpdate('rule-1'); updatedRule.name = 'some other name'; // update a simple rule's name @@ -65,20 +65,20 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // create a second simple rule await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-2')) + .send(getSimpleRuleUpdate('rule-2')) .expect(200); - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.name = 'some other name'; - const updatedRule2 = getSimpleRule('rule-2'); + const updatedRule2 = getSimpleRuleUpdate('rule-2'); updatedRule2.name = 'some other name'; // update both rule names @@ -107,11 +107,11 @@ export default ({ getService }: FtrProviderContext) => { const { body: createRuleBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.id = createRuleBody.id; updatedRule1.name = 'some other name'; delete updatedRule1.rule_id; @@ -134,23 +134,23 @@ export default ({ getService }: FtrProviderContext) => { const { body: createRule1 } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // create a second simple rule const { body: createRule2 } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-2')) + .send(getSimpleRuleUpdate('rule-2')) .expect(200); // update both rule names - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.id = createRule1.id; updatedRule1.name = 'some other name'; delete updatedRule1.rule_id; - const updatedRule2 = getSimpleRule('rule-1'); + const updatedRule2 = getSimpleRuleUpdate('rule-1'); updatedRule2.id = createRule2.id; updatedRule2.name = 'some other name'; delete updatedRule2.rule_id; @@ -180,11 +180,11 @@ export default ({ getService }: FtrProviderContext) => { const { body: createdBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's name - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.id = createdBody.id; updatedRule1.name = 'some other name'; delete updatedRule1.rule_id; @@ -207,11 +207,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's enabled to false and another property - const updatedRule1 = getSimpleRule('rule-1'); + const updatedRule1 = getSimpleRuleUpdate('rule-1'); updatedRule1.severity = 'low'; updatedRule1.enabled = false; @@ -235,11 +235,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update a simple rule's timeline_title - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.timeline_title = 'some title'; ruleUpdate.timeline_id = 'some id'; @@ -250,7 +250,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); // update a simple rule's name - const ruleUpdate2 = getSimpleRule('rule-1'); + const ruleUpdate2 = getSimpleRuleUpdate('rule-1'); ruleUpdate2.name = 'some other name'; const { body } = await supertest @@ -268,7 +268,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return a 200 but give a 404 in the message if it is given a fake id', async () => { - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.id = '1fd52120-d3a9-4e7a-b23c-96c0e1a74ae5'; delete ruleUpdate.rule_id; @@ -290,7 +290,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return a 200 but give a 404 in the message if it is given a fake rule_id', async () => { - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.rule_id = 'fake_id'; delete ruleUpdate.id; @@ -313,14 +313,14 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); - const ruleUpdate = getSimpleRule('rule-1'); + const ruleUpdate = getSimpleRuleUpdate('rule-1'); ruleUpdate.name = 'some other name'; delete ruleUpdate.id; - const ruleUpdate2 = getSimpleRule('fake_id'); + const ruleUpdate2 = getSimpleRuleUpdate('fake_id'); ruleUpdate2.name = 'some other name'; delete ruleUpdate.id; @@ -353,16 +353,16 @@ export default ({ getService }: FtrProviderContext) => { const { body: createdBody } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .send(getSimpleRule('rule-1')) + .send(getSimpleRuleUpdate('rule-1')) .expect(200); // update one rule name and give a fake id for the second - const rule1 = getSimpleRule(); + const rule1 = getSimpleRuleUpdate(); delete rule1.rule_id; rule1.id = createdBody.id; rule1.name = 'some other name'; - const rule2 = getSimpleRule(); + const rule2 = getSimpleRuleUpdate(); delete rule2.rule_id; rule2.id = 'b3aa019a-656c-4311-b13b-4d9852e24347'; rule2.name = 'some other name'; diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts index b4330ce5d3912..5f0a8cd938408 100644 --- a/x-pack/test/detection_engine_api_integration/utils.ts +++ b/x-pack/test/detection_engine_api_integration/utils.ts @@ -7,7 +7,9 @@ import { Client } from '@elastic/elasticsearch'; import { SuperTest } from 'supertest'; import supertestAsPromised from 'supertest-as-promised'; -import { OutputRuleAlertRest } from '../../plugins/security_solution/server/lib/detection_engine/types'; +import { CreateRulesSchema } from '../../plugins/security_solution/common/detection_engine/schemas/request/create_rules_schema'; +import { UpdateRulesSchema } from '../../plugins/security_solution/common/detection_engine/schemas/request/update_rules_schema'; +import { RulesSchema } from '../../plugins/security_solution/common/detection_engine/schemas/response/rules_schema'; import { DETECTION_ENGINE_INDEX_URL } from '../../plugins/security_solution/common/constants'; /** @@ -15,8 +17,8 @@ import { DETECTION_ENGINE_INDEX_URL } from '../../plugins/security_solution/comm * @param rule Rule to pass in to remove typical server generated properties */ export const removeServerGeneratedProperties = ( - rule: Partial -): Partial => { + rule: Partial +): Partial => { const { created_at, updated_at, @@ -37,8 +39,8 @@ export const removeServerGeneratedProperties = ( * @param rule Rule to pass in to remove typical server generated properties */ export const removeServerGeneratedPropertiesIncludingRuleId = ( - rule: Partial -): Partial => { + rule: Partial +): Partial => { const ruleWithRemovedProperties = removeServerGeneratedProperties(rule); const { rule_id, ...additionalRuledIdRemoved } = ruleWithRemovedProperties; return additionalRuledIdRemoved; @@ -48,7 +50,22 @@ export const removeServerGeneratedPropertiesIncludingRuleId = ( * This is a typical simple rule for testing that is easy for most basic testing * @param ruleId */ -export const getSimpleRule = (ruleId = 'rule-1'): Partial => ({ +export const getSimpleRule = (ruleId = 'rule-1'): CreateRulesSchema => ({ + name: 'Simple Rule Query', + description: 'Simple Rule Query', + risk_score: 1, + rule_id: ruleId, + severity: 'high', + index: ['auditbeat-*'], + type: 'query', + 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 getSimpleRuleUpdate = (ruleId = 'rule-1'): UpdateRulesSchema => ({ name: 'Simple Rule Query', description: 'Simple Rule Query', risk_score: 1, @@ -63,7 +80,18 @@ export const getSimpleRule = (ruleId = 'rule-1'): Partial = * This is a representative ML rule payload as expected by the server * @param ruleId */ -export const getSimpleMlRule = (ruleId = 'rule-1'): Partial => ({ +export const getSimpleMlRule = (ruleId = 'rule-1'): CreateRulesSchema => ({ + name: 'Simple ML Rule', + description: 'Simple Machine Learning Rule', + anomaly_threshold: 44, + risk_score: 1, + rule_id: ruleId, + severity: 'high', + machine_learning_job_id: 'some_job_id', + type: 'machine_learning', +}); + +export const getSimpleMlRuleUpdate = (ruleId = 'rule-1'): UpdateRulesSchema => ({ name: 'Simple ML Rule', description: 'Simple Machine Learning Rule', anomaly_threshold: 44, @@ -107,7 +135,7 @@ export const getSignalStatusEmptyResponse = () => ({ /** * This is a typical simple rule for testing that is easy for most basic testing */ -export const getSimpleRuleWithoutRuleId = (): Partial => { +export const getSimpleRuleWithoutRuleId = (): CreateRulesSchema => { const simpleRule = getSimpleRule(); const { rule_id, ...ruleWithoutId } = simpleRule; return ruleWithoutId; @@ -130,9 +158,10 @@ export const binaryToString = (res: any, callback: any): void => { }; /** - * This is the typical output of a simple rule that Kibana will output with all the defaults. + * This is the typical output of a simple rule that Kibana will output with all the defaults + * except for the server generated properties. Useful for testing end to end tests. */ -export const getSimpleRuleOutput = (ruleId = 'rule-1'): Partial => ({ +export const getSimpleRuleOutput = (ruleId = 'rule-1'): Partial => ({ actions: [], created_by: 'elastic', description: 'Simple Rule Query', @@ -162,17 +191,16 @@ export const getSimpleRuleOutput = (ruleId = 'rule-1'): Partial => { +export const getSimpleRuleOutputWithoutRuleId = (ruleId = 'rule-1'): Partial => { const rule = getSimpleRuleOutput(ruleId); const { rule_id, ...ruleWithoutRuleId } = rule; return ruleWithoutRuleId; }; -export const getSimpleMlRuleOutput = (ruleId = 'rule-1'): Partial => { +export const getSimpleMlRuleOutput = (ruleId = 'rule-1'): Partial => { const rule = getSimpleRuleOutput(ruleId); const { query, language, index, ...rest } = rule; @@ -252,7 +280,7 @@ export const getSimpleRuleAsNdjson = (ruleIds: string[]): Buffer => { * testing upload features. * @param rule The rule to convert to ndjson */ -export const ruleToNdjson = (rule: Partial): Buffer => { +export const ruleToNdjson = (rule: Partial): Buffer => { const stringified = JSON.stringify(rule); return Buffer.from(`${stringified}\n`); }; @@ -261,7 +289,7 @@ export const ruleToNdjson = (rule: Partial): Buffer => { * This will return a complex rule with all the outputs possible * @param ruleId The ruleId to set which is optional and defaults to rule-1 */ -export const getComplexRule = (ruleId = 'rule-1'): Partial => ({ +export const getComplexRule = (ruleId = 'rule-1'): Partial => ({ actions: [], name: 'Complex Rule Query', description: 'Complex Rule Query', @@ -345,7 +373,7 @@ export const getComplexRule = (ruleId = 'rule-1'): Partial * This will return a complex rule with all the outputs possible * @param ruleId The ruleId to set which is optional and defaults to rule-1 */ -export const getComplexRuleOutput = (ruleId = 'rule-1'): Partial => ({ +export const getComplexRuleOutput = (ruleId = 'rule-1'): Partial => ({ actions: [], created_by: 'elastic', name: 'Complex Rule Query', From 9bc093631143a647b3c3346aadc195c38e9caf89 Mon Sep 17 00:00:00 2001 From: Quynh Nguyen <43350163+qn895@users.noreply.github.com> Date: Wed, 10 Jun 2020 10:11:46 -0500 Subject: [PATCH 33/53] [ML] Transforms: Add ability to delete dest index & index pattern when deleting transform job (#67922) --- x-pack/plugins/ml/common/util/errors.test.ts | 78 +++++ x-pack/plugins/ml/common/util/errors.ts | 75 +++++ .../analytics_list/action_delete.tsx | 2 +- .../analytics_service/delete_analytics.ts | 2 +- .../ml/public/application/util/error_utils.ts | 32 -- x-pack/plugins/ml/public/shared.ts | 1 + x-pack/plugins/transform/common/index.ts | 17 + .../components/toast_notification_text.tsx | 12 +- .../transform/public/app/hooks/index.ts | 2 +- .../transform/public/app/hooks/use_api.ts | 15 +- .../public/app/hooks/use_delete_transform.tsx | 255 ++++++++++++-- .../transform_list/action_delete.tsx | 128 ++++++- .../public/app/services/es_index_service.ts | 33 ++ .../transform/public/shared_imports.ts | 1 + .../server/routes/api/error_utils.ts | 10 +- .../transform/server/routes/api/schema.ts | 14 + .../transform/server/routes/api/transforms.ts | 154 ++++++++- x-pack/test/api_integration/apis/index.js | 1 + .../apis/ml/data_frame_analytics/delete.ts | 2 +- .../apis/transform/delete_transforms.ts | 318 ++++++++++++++++++ .../api_integration/apis/transform/index.ts | 32 ++ x-pack/test/api_integration/services/index.ts | 2 + .../api_integration/services/transform.ts | 23 ++ .../test/functional/services/transform/api.ts | 63 +++- 24 files changed, 1165 insertions(+), 107 deletions(-) create mode 100644 x-pack/plugins/ml/common/util/errors.test.ts delete mode 100644 x-pack/plugins/ml/public/application/util/error_utils.ts create mode 100644 x-pack/plugins/transform/public/app/services/es_index_service.ts create mode 100644 x-pack/test/api_integration/apis/transform/delete_transforms.ts create mode 100644 x-pack/test/api_integration/apis/transform/index.ts create mode 100644 x-pack/test/api_integration/services/transform.ts diff --git a/x-pack/plugins/ml/common/util/errors.test.ts b/x-pack/plugins/ml/common/util/errors.test.ts new file mode 100644 index 0000000000000..00af27248ccce --- /dev/null +++ b/x-pack/plugins/ml/common/util/errors.test.ts @@ -0,0 +1,78 @@ +/* + * 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 { + BoomResponse, + extractErrorMessage, + MLCustomHttpResponseOptions, + MLResponseError, +} from './errors'; +import { ResponseError } from 'kibana/server'; + +describe('ML - error message utils', () => { + describe('extractErrorMessage', () => { + test('returns just the error message', () => { + const testMsg = 'Saved object [index-pattern/blahblahblah] not found'; + + const bodyWithNestedErrorMsg: MLCustomHttpResponseOptions = { + body: { + message: { + msg: testMsg, + }, + }, + statusCode: 404, + }; + expect(extractErrorMessage(bodyWithNestedErrorMsg)).toBe(testMsg); + + const bodyWithStringMsg: MLCustomHttpResponseOptions = { + body: { + msg: testMsg, + }, + statusCode: 404, + }; + expect(extractErrorMessage(bodyWithStringMsg)).toBe(testMsg); + + const bodyWithStringMessage: MLCustomHttpResponseOptions = { + body: { + message: testMsg, + }, + statusCode: 404, + }; + expect(extractErrorMessage(bodyWithStringMessage)).toBe(testMsg); + + const bodyWithString: MLCustomHttpResponseOptions = { + body: testMsg, + statusCode: 404, + }; + expect(extractErrorMessage(bodyWithString)).toBe(testMsg); + + const bodyWithError: MLCustomHttpResponseOptions = { + body: new Error(testMsg), + statusCode: 404, + }; + expect(extractErrorMessage(bodyWithError)).toBe(testMsg); + + const bodyWithBoomError: MLCustomHttpResponseOptions = { + statusCode: 404, + body: { + data: [], + isBoom: true, + isServer: false, + output: { + statusCode: 404, + payload: { + statusCode: 404, + error: testMsg, + message: testMsg, + }, + headers: {}, + }, + }, + }; + expect(extractErrorMessage(bodyWithBoomError)).toBe(testMsg); + }); + }); +}); diff --git a/x-pack/plugins/ml/common/util/errors.ts b/x-pack/plugins/ml/common/util/errors.ts index 4446624bf2e7f..e165e15d7c64e 100644 --- a/x-pack/plugins/ml/common/util/errors.ts +++ b/x-pack/plugins/ml/common/util/errors.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { ResponseError, ResponseHeaders } from 'kibana/server'; import { isErrorResponse } from '../types/errors'; export function getErrorMessage(error: any) { @@ -17,3 +18,77 @@ export function getErrorMessage(error: any) { return JSON.stringify(error); } + +// Adding temporary types until Kibana ResponseError is updated + +export interface BoomResponse { + data: any; + isBoom: boolean; + isServer: boolean; + output: { + statusCode: number; + payload: { + statusCode: number; + error: string; + message: string; + }; + headers: {}; + }; +} +export type MLResponseError = + | { + message: { + msg: string; + }; + } + | { msg: string }; + +export interface MLCustomHttpResponseOptions< + T extends ResponseError | MLResponseError | BoomResponse +> { + /** HTTP message to send to the client */ + body?: T; + /** HTTP Headers with additional information about response */ + headers?: ResponseHeaders; + statusCode: number; +} + +export const extractErrorMessage = ( + error: + | MLCustomHttpResponseOptions + | undefined + | string +): string => { + // extract only the error message within the response error coming from Kibana, Elasticsearch, and our own ML messages + + if (typeof error === 'string') { + return error; + } + if (error?.body === undefined) return ''; + + if (typeof error.body === 'string') { + return error.body; + } + if ( + typeof error.body === 'object' && + 'output' in error.body && + error.body.output.payload.message + ) { + return error.body.output.payload.message; + } + + if (typeof error.body === 'object' && 'msg' in error.body && typeof error.body.msg === 'string') { + return error.body.msg; + } + + if (typeof error.body === 'object' && 'message' in error.body) { + if (typeof error.body.message === 'string') { + return error.body.message; + } + if (!(error.body.message instanceof Error) && typeof (error.body.message.msg === 'string')) { + return error.body.message.msg; + } + } + // If all else fail return an empty message instead of JSON.stringify + return ''; +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx index 2d433f6b18484..38ef00914e8fb 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx @@ -18,6 +18,7 @@ import { } from '@elastic/eui'; import { IIndexPattern } from 'src/plugins/data/common'; import { FormattedMessage } from '@kbn/i18n/react'; +import { extractErrorMessage } from '../../../../../../../common/util/errors'; import { deleteAnalytics, deleteAnalyticsAndDestIndex, @@ -29,7 +30,6 @@ import { } from '../../../../../capabilities/check_capabilities'; import { useMlKibana } from '../../../../../contexts/kibana'; import { isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common'; -import { extractErrorMessage } from '../../../../../util/error_utils'; interface DeleteActionProps { item: DataFrameAnalyticsListRow; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts index 26cefff0a3f59..ebd3fa8982604 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; +import { extractErrorMessage } from '../../../../../../../common/util/errors'; import { getToastNotifications } from '../../../../../util/dependency_cache'; import { ml } from '../../../../../services/ml_api_service'; import { refreshAnalyticsList$, REFRESH_ANALYTICS_LIST_STATE } from '../../../../common'; @@ -11,7 +12,6 @@ import { isDataFrameAnalyticsFailed, DataFrameAnalyticsListRow, } from '../../components/analytics_list/common'; -import { extractErrorMessage } from '../../../../../util/error_utils'; export const deleteAnalytics = async (d: DataFrameAnalyticsListRow) => { const toastNotifications = getToastNotifications(); diff --git a/x-pack/plugins/ml/public/application/util/error_utils.ts b/x-pack/plugins/ml/public/application/util/error_utils.ts deleted file mode 100644 index 2ce8f4ffc583a..0000000000000 --- a/x-pack/plugins/ml/public/application/util/error_utils.ts +++ /dev/null @@ -1,32 +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 { CustomHttpResponseOptions, ResponseError } from 'kibana/server'; - -export const extractErrorMessage = ( - error: CustomHttpResponseOptions | undefined | string -): string | undefined => { - if (typeof error === 'string') { - return error; - } - - if (error?.body) { - if (typeof error.body === 'string') { - return error.body; - } - if (typeof error.body === 'object' && 'message' in error.body) { - if (typeof error.body.message === 'string') { - return error.body.message; - } - // @ts-ignore - if (typeof (error.body.message?.msg === 'string')) { - // @ts-ignore - return error.body.message?.msg; - } - } - } - return undefined; -}; diff --git a/x-pack/plugins/ml/public/shared.ts b/x-pack/plugins/ml/public/shared.ts index 6821cb7ef0f94..ff83d79adff67 100644 --- a/x-pack/plugins/ml/public/shared.ts +++ b/x-pack/plugins/ml/public/shared.ts @@ -14,6 +14,7 @@ export * from '../common/types/audit_message'; export * from '../common/util/anomaly_utils'; export * from '../common/util/errors'; + export * from '../common/util/validators'; export * from './application/formatters/metric_change_description'; diff --git a/x-pack/plugins/transform/common/index.ts b/x-pack/plugins/transform/common/index.ts index d7a791e78b3ab..79ff6298a2ca2 100644 --- a/x-pack/plugins/transform/common/index.ts +++ b/x-pack/plugins/transform/common/index.ts @@ -38,3 +38,20 @@ export interface ResultData { export interface TransformEndpointResult { [key: string]: ResultData; } + +export interface DeleteTransformEndpointRequest { + transformsInfo: TransformEndpointRequest[]; + deleteDestIndex?: boolean; + deleteDestIndexPattern?: boolean; +} + +export interface DeleteTransformStatus { + transformDeleted: ResultData; + destIndexDeleted?: ResultData; + destIndexPatternDeleted?: ResultData; + destinationIndex?: string | undefined; +} + +export interface DeleteTransformEndpointResult { + [key: string]: DeleteTransformStatus; +} diff --git a/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx b/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx index 1044081670523..3f664cf8bb09b 100644 --- a/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx +++ b/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx @@ -29,9 +29,14 @@ const MAX_SIMPLE_MESSAGE_LENGTH = 140; interface ToastNotificationTextProps { overlays: CoreStart['overlays']; text: any; + previewTextLength?: number; } -export const ToastNotificationText: FC = ({ overlays, text }) => { +export const ToastNotificationText: FC = ({ + overlays, + text, + previewTextLength, +}) => { if (typeof text === 'string' && text.length <= MAX_SIMPLE_MESSAGE_LENGTH) { return text; } @@ -46,8 +51,9 @@ export const ToastNotificationText: FC = ({ overlays const unformattedText = text.message ? text.message : text; const formattedText = typeof unformattedText === 'object' ? JSON.stringify(text, null, 2) : text; - const previewText = `${formattedText.substring(0, 140)}${ - formattedText.length > 140 ? ' ...' : '' + const textLength = previewTextLength ?? 140; + const previewText = `${formattedText.substring(0, textLength)}${ + formattedText.length > textLength ? ' ...' : '' }`; const openModal = () => { diff --git a/x-pack/plugins/transform/public/app/hooks/index.ts b/x-pack/plugins/transform/public/app/hooks/index.ts index a36550bcd8e57..b439afe2b2165 100644 --- a/x-pack/plugins/transform/public/app/hooks/index.ts +++ b/x-pack/plugins/transform/public/app/hooks/index.ts @@ -6,7 +6,7 @@ export { useApi } from './use_api'; export { useGetTransforms } from './use_get_transforms'; -export { useDeleteTransforms } from './use_delete_transform'; +export { useDeleteTransforms, useDeleteIndexAndTargetIndex } from './use_delete_transform'; export { useStartTransforms } from './use_start_transform'; export { useStopTransforms } from './use_stop_transform'; export { useRequest } from './use_request'; diff --git a/x-pack/plugins/transform/public/app/hooks/use_api.ts b/x-pack/plugins/transform/public/app/hooks/use_api.ts index f3c35d358f1f2..5d7839cf5fba7 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_api.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_api.ts @@ -5,7 +5,12 @@ */ import { useMemo } from 'react'; -import { TransformEndpointRequest, TransformEndpointResult, TransformId } from '../../../common'; +import { + TransformId, + TransformEndpointRequest, + TransformEndpointResult, + DeleteTransformEndpointResult, +} from '../../../common'; import { API_BASE_PATH } from '../../../common/constants'; import { useAppDependencies } from '../app_dependencies'; @@ -40,10 +45,12 @@ export const useApi = () => { }); }, deleteTransforms( - transformsInfo: TransformEndpointRequest[] - ): Promise { + transformsInfo: TransformEndpointRequest[], + deleteDestIndex: boolean | undefined, + deleteDestIndexPattern: boolean | undefined + ): Promise { return http.post(`${API_BASE_PATH}delete_transforms`, { - body: JSON.stringify(transformsInfo), + body: JSON.stringify({ transformsInfo, deleteDestIndex, deleteDestIndexPattern }), }); }, getTransformsPreview(obj: PreviewRequestBody): Promise { diff --git a/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx b/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx index 0215d723188b1..1f395e67b7d31 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx +++ b/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx @@ -4,52 +4,257 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; - +import React, { useCallback, useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; - -import { TransformEndpointRequest, TransformEndpointResult } from '../../../common'; - -import { getErrorMessage } from '../../shared_imports'; - +import { + TransformEndpointRequest, + DeleteTransformEndpointResult, + DeleteTransformStatus, +} from '../../../common'; +import { getErrorMessage, extractErrorMessage } from '../../shared_imports'; import { useAppDependencies, useToastNotifications } from '../app_dependencies'; import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common'; import { ToastNotificationText } from '../components'; - import { useApi } from './use_api'; +import { indexService } from '../services/es_index_service'; + +export const useDeleteIndexAndTargetIndex = (items: TransformListRow[]) => { + const { http, savedObjects } = useAppDependencies(); + const toastNotifications = useToastNotifications(); + + const [deleteDestIndex, setDeleteDestIndex] = useState(true); + const [deleteIndexPattern, setDeleteIndexPattern] = useState(true); + const [userCanDeleteIndex, setUserCanDeleteIndex] = useState(false); + const [indexPatternExists, setIndexPatternExists] = useState(false); + const toggleDeleteIndex = useCallback(() => setDeleteDestIndex(!deleteDestIndex), [ + deleteDestIndex, + ]); + const toggleDeleteIndexPattern = useCallback(() => setDeleteIndexPattern(!deleteIndexPattern), [ + deleteIndexPattern, + ]); + + const checkIndexPatternExists = useCallback( + async (indexName: string) => { + try { + if (await indexService.indexPatternExists(savedObjects.client, indexName)) { + setIndexPatternExists(true); + } + } catch (e) { + const error = extractErrorMessage(e); + + toastNotifications.addDanger( + i18n.translate( + 'xpack.transform.deleteTransform.errorWithCheckingIfIndexPatternExistsNotificationErrorMessage', + { + defaultMessage: + 'An error occurred checking if index pattern {indexPattern} exists: {error}', + values: { indexPattern: indexName, error }, + } + ) + ); + } + }, + [savedObjects.client, toastNotifications] + ); + + const checkUserIndexPermission = useCallback(async () => { + try { + const userCanDelete = await indexService.canDeleteIndex(http); + if (userCanDelete) { + setUserCanDeleteIndex(true); + } + } catch (e) { + toastNotifications.addDanger( + i18n.translate( + 'xpack.transform.transformList.errorWithCheckingIfUserCanDeleteIndexNotificationErrorMessage', + { + defaultMessage: 'An error occurred checking if user can delete destination index', + } + ) + ); + } + }, [http, toastNotifications]); + + useEffect(() => { + checkUserIndexPermission(); + + if (items.length === 1) { + const config = items[0].config; + const destinationIndex = Array.isArray(config.dest.index) + ? config.dest.index[0] + : config.dest.index; + checkIndexPatternExists(destinationIndex); + } else { + setIndexPatternExists(true); + } + }, [checkIndexPatternExists, checkUserIndexPermission, items]); + + return { + userCanDeleteIndex, + deleteDestIndex, + indexPatternExists, + deleteIndexPattern, + toggleDeleteIndex, + toggleDeleteIndexPattern, + }; +}; + +type SuccessCountField = keyof Omit; export const useDeleteTransforms = () => { const { overlays } = useAppDependencies(); const toastNotifications = useToastNotifications(); const api = useApi(); - return async (transforms: TransformListRow[]) => { + return async ( + transforms: TransformListRow[], + shouldDeleteDestIndex: boolean, + shouldDeleteDestIndexPattern: boolean + ) => { const transformsInfo: TransformEndpointRequest[] = transforms.map((tf) => ({ id: tf.config.id, state: tf.stats.state, })); try { - const results: TransformEndpointResult = await api.deleteTransforms(transformsInfo); + const results: DeleteTransformEndpointResult = await api.deleteTransforms( + transformsInfo, + shouldDeleteDestIndex, + shouldDeleteDestIndexPattern + ); + const isBulk = Object.keys(results).length > 1; + const successCount: Record = { + transformDeleted: 0, + destIndexDeleted: 0, + destIndexPatternDeleted: 0, + }; for (const transformId in results) { // hasOwnProperty check to ensure only properties on object itself, and not its prototypes if (results.hasOwnProperty(transformId)) { - if (results[transformId].success === true) { - toastNotifications.addSuccess( - i18n.translate('xpack.transform.transformList.deleteTransformSuccessMessage', { - defaultMessage: 'Request to delete transform {transformId} acknowledged.', - values: { transformId }, - }) - ); + const status = results[transformId]; + const destinationIndex = status.destinationIndex; + + // if we are only deleting one transform, show the success toast messages + if (!isBulk && status.transformDeleted) { + if (status.transformDeleted?.success) { + toastNotifications.addSuccess( + i18n.translate('xpack.transform.transformList.deleteTransformSuccessMessage', { + defaultMessage: 'Request to delete transform {transformId} acknowledged.', + values: { transformId }, + }) + ); + } + if (status.destIndexDeleted?.success) { + toastNotifications.addSuccess( + i18n.translate( + 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexSuccessMessage', + { + defaultMessage: + 'Request to delete destination index {destinationIndex} acknowledged.', + values: { destinationIndex }, + } + ) + ); + } + if (status.destIndexPatternDeleted?.success) { + toastNotifications.addSuccess( + i18n.translate( + 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexPatternSuccessMessage', + { + defaultMessage: + 'Request to delete index pattern {destinationIndex} acknowledged.', + values: { destinationIndex }, + } + ) + ); + } } else { - toastNotifications.addDanger( - i18n.translate('xpack.transform.transformList.deleteTransformErrorMessage', { + (Object.keys(successCount) as SuccessCountField[]).forEach((key) => { + if (status[key]?.success) { + successCount[key] = successCount[key] + 1; + } + }); + } + if (status.transformDeleted?.error) { + const error = extractErrorMessage(status.transformDeleted.error); + toastNotifications.addDanger({ + title: i18n.translate('xpack.transform.transformList.deleteTransformErrorMessage', { defaultMessage: 'An error occurred deleting the transform {transformId}', values: { transformId }, - }) - ); + }), + text: toMountPoint( + + ), + }); } + + if (status.destIndexDeleted?.error) { + const error = extractErrorMessage(status.destIndexDeleted.error); + toastNotifications.addDanger({ + title: i18n.translate( + 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexErrorMessage', + { + defaultMessage: 'An error occurred deleting destination index {destinationIndex}', + values: { destinationIndex }, + } + ), + text: toMountPoint( + + ), + }); + } + + if (status.destIndexPatternDeleted?.error) { + const error = extractErrorMessage(status.destIndexPatternDeleted.error); + toastNotifications.addDanger({ + title: i18n.translate( + 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexPatternErrorMessage', + { + defaultMessage: 'An error occurred deleting index pattern {destinationIndex}', + values: { destinationIndex }, + } + ), + text: toMountPoint( + + ), + }); + } + } + } + + // if we are deleting multiple transforms, combine the success messages + if (isBulk) { + if (successCount.transformDeleted > 0) { + toastNotifications.addSuccess( + i18n.translate('xpack.transform.transformList.bulkDeleteTransformSuccessMessage', { + defaultMessage: + 'Successfully deleted {count} {count, plural, one {transform} other {transforms}}.', + values: { count: successCount.transformDeleted }, + }) + ); + } + + if (successCount.destIndexDeleted > 0) { + toastNotifications.addSuccess( + i18n.translate('xpack.transform.transformList.bulkDeleteDestIndexSuccessMessage', { + defaultMessage: + 'Successfully deleted {count} destination {count, plural, one {index} other {indices}}.', + values: { count: successCount.destIndexDeleted }, + }) + ); + } + if (successCount.destIndexPatternDeleted > 0) { + toastNotifications.addSuccess( + i18n.translate( + 'xpack.transform.transformList.bulkDeleteDestIndexPatternSuccessMessage', + { + defaultMessage: + 'Successfully deleted {count} destination index {count, plural, one {pattern} other {patterns}}.', + values: { count: successCount.destIndexPatternDeleted }, + } + ) + ); } } @@ -59,7 +264,13 @@ export const useDeleteTransforms = () => { title: i18n.translate('xpack.transform.transformList.deleteTransformGenericErrorMessage', { defaultMessage: 'An error occurred calling the API endpoint to delete transforms.', }), - text: toMountPoint(), + text: toMountPoint( + + ), }); } }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx index c20feba29f582..d7db55990d333 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx @@ -12,11 +12,14 @@ import { EuiOverlayMask, EuiToolTip, EUI_MODAL_CONFIRM_BUTTON, + EuiFlexGroup, + EuiFlexItem, + EuiSwitch, + EuiSpacer, } from '@elastic/eui'; - +import { FormattedMessage } from '@kbn/i18n/react'; import { TRANSFORM_STATE } from '../../../../../../common'; - -import { useDeleteTransforms } from '../../../../hooks'; +import { useDeleteTransforms, useDeleteIndexAndTargetIndex } from '../../../../hooks'; import { createCapabilityFailureMessage, AuthorizationContext, @@ -35,13 +38,25 @@ export const DeleteAction: FC = ({ items, forceDisable }) => const { canDeleteTransform } = useContext(AuthorizationContext).capabilities; const deleteTransforms = useDeleteTransforms(); + const { + userCanDeleteIndex, + deleteDestIndex, + indexPatternExists, + deleteIndexPattern, + toggleDeleteIndex, + toggleDeleteIndexPattern, + } = useDeleteIndexAndTargetIndex(items); const [isModalVisible, setModalVisible] = useState(false); const closeModal = () => setModalVisible(false); const deleteAndCloseModal = () => { setModalVisible(false); - deleteTransforms(items); + + const shouldDeleteDestIndex = userCanDeleteIndex && deleteDestIndex; + const shouldDeleteDestIndexPattern = + userCanDeleteIndex && indexPatternExists && deleteIndexPattern; + deleteTransforms(items, shouldDeleteDestIndex, shouldDeleteDestIndexPattern); }; const openModal = () => setModalVisible(true); @@ -71,17 +86,96 @@ export const DeleteAction: FC = ({ items, forceDisable }) => defaultMessage: 'Delete {transformId}', values: { transformId: items[0] && items[0].config.id }, }); - const bulkDeleteModalMessage = i18n.translate( - 'xpack.transform.transformList.bulkDeleteModalBody', - { - defaultMessage: - "Are you sure you want to delete {count, plural, one {this} other {these}} {count} {count, plural, one {transform} other {transforms}}? The transform's destination index and optional Kibana index pattern will not be deleted.", - values: { count: items.length }, - } + const bulkDeleteModalContent = ( + <> +

+ +

+ + + { + + } + + + + { + + } + + + + ); + + const deleteModalContent = ( + <> +

+ +

+ + + {userCanDeleteIndex && ( + + )} + + {userCanDeleteIndex && indexPatternExists && ( + + + + + )} + + ); - const deleteModalMessage = i18n.translate('xpack.transform.transformList.deleteModalBody', { - defaultMessage: `Are you sure you want to delete this transform? The transform's destination index and optional Kibana index pattern will not be deleted.`, - }); let deleteButton = ( = ({ items, forceDisable }) => if (disabled || !canDeleteTransform) { let content; if (disabled) { - content = isBulkAction === true ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; + content = isBulkAction ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; } else { content = createCapabilityFailureMessage('canDeleteTransform'); } @@ -117,7 +211,7 @@ export const DeleteAction: FC = ({ items, forceDisable }) => {isModalVisible && ( = ({ items, forceDisable }) => defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON} buttonColor="danger" > -

{isBulkAction === true ? bulkDeleteModalMessage : deleteModalMessage}

+ {isBulkAction ? bulkDeleteModalContent : deleteModalContent}
)} diff --git a/x-pack/plugins/transform/public/app/services/es_index_service.ts b/x-pack/plugins/transform/public/app/services/es_index_service.ts new file mode 100644 index 0000000000000..491213d0ddbe7 --- /dev/null +++ b/x-pack/plugins/transform/public/app/services/es_index_service.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpSetup, SavedObjectsClientContract } from 'kibana/public'; +import { API_BASE_PATH } from '../../../common/constants'; +import { IIndexPattern } from '../../../../../../src/plugins/data/common/index_patterns'; + +export class IndexService { + async canDeleteIndex(http: HttpSetup) { + const privilege = await http.get(`${API_BASE_PATH}privileges`); + if (!privilege) { + return false; + } + return privilege.hasAllPrivileges; + } + + async indexPatternExists(savedObjectsClient: SavedObjectsClientContract, indexName: string) { + const response = await savedObjectsClient.find({ + type: 'index-pattern', + perPage: 1, + search: `"${indexName}"`, + searchFields: ['title'], + fields: ['title'], + }); + const ip = response.savedObjects.find((obj) => obj.attributes.title === indexName); + return ip !== undefined; + } +} + +export const indexService = new IndexService(); diff --git a/x-pack/plugins/transform/public/shared_imports.ts b/x-pack/plugins/transform/public/shared_imports.ts index 56be8d7bb7de7..ca3fb52cc02c3 100644 --- a/x-pack/plugins/transform/public/shared_imports.ts +++ b/x-pack/plugins/transform/public/shared_imports.ts @@ -15,6 +15,7 @@ export { export { getErrorMessage, + extractErrorMessage, getDataGridSchemaFromKibanaFieldType, getFieldsFromKibanaIndexPattern, multiColumnSortFactory, diff --git a/x-pack/plugins/transform/server/routes/api/error_utils.ts b/x-pack/plugins/transform/server/routes/api/error_utils.ts index 295375794c04e..5a479e4f429f6 100644 --- a/x-pack/plugins/transform/server/routes/api/error_utils.ts +++ b/x-pack/plugins/transform/server/routes/api/error_utils.ts @@ -10,7 +10,11 @@ import { i18n } from '@kbn/i18n'; import { ResponseError, CustomHttpResponseOptions } from 'src/core/server'; -import { TransformEndpointRequest, TransformEndpointResult } from '../../../common'; +import { + TransformEndpointRequest, + TransformEndpointResult, + DeleteTransformEndpointResult, +} from '../../../common'; const REQUEST_TIMEOUT = 'RequestTimeout'; @@ -19,7 +23,7 @@ export function isRequestTimeout(error: any) { } interface Params { - results: TransformEndpointResult; + results: TransformEndpointResult | DeleteTransformEndpointResult; id: string; items: TransformEndpointRequest[]; action: string; @@ -59,7 +63,7 @@ export function fillResultsWithTimeouts({ results, id, items, action }: Params) }, }; - const newResults: TransformEndpointResult = {}; + const newResults: TransformEndpointResult | DeleteTransformEndpointResult = {}; return items.reduce((accumResults, currentVal) => { if (results[currentVal.id] === undefined) { diff --git a/x-pack/plugins/transform/server/routes/api/schema.ts b/x-pack/plugins/transform/server/routes/api/schema.ts index 0b994406d324d..cf39f2e3829ea 100644 --- a/x-pack/plugins/transform/server/routes/api/schema.ts +++ b/x-pack/plugins/transform/server/routes/api/schema.ts @@ -14,3 +14,17 @@ export const schemaTransformId = { export interface SchemaTransformId { transformId: string; } + +export const deleteTransformSchema = schema.object({ + /** + * Delete Transform & Destination Index + */ + transformsInfo: schema.arrayOf( + schema.object({ + id: schema.string(), + state: schema.maybe(schema.string()), + }) + ), + deleteDestIndex: schema.maybe(schema.boolean()), + deleteDestIndexPattern: schema.maybe(schema.boolean()), +}); diff --git a/x-pack/plugins/transform/server/routes/api/transforms.ts b/x-pack/plugins/transform/server/routes/api/transforms.ts index 55b2469a7f3a7..93fda56d319ad 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms.ts @@ -5,7 +5,12 @@ */ import { schema } from '@kbn/config-schema'; -import { RequestHandler } from 'kibana/server'; +import { + KibanaResponseFactory, + RequestHandler, + RequestHandlerContext, + SavedObjectsClientContract, +} from 'kibana/server'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; import { wrapEsError } from '../../../../../legacy/server/lib/create_router/error_wrappers'; @@ -14,6 +19,9 @@ import { TransformEndpointResult, TransformId, TRANSFORM_STATE, + DeleteTransformEndpointRequest, + DeleteTransformStatus, + ResultData, } from '../../../common'; import { RouteDependencies } from '../../types'; @@ -21,8 +29,9 @@ import { RouteDependencies } from '../../types'; import { addBasePath } from '../index'; import { isRequestTimeout, fillResultsWithTimeouts, wrapError } from './error_utils'; -import { schemaTransformId, SchemaTransformId } from './schema'; +import { deleteTransformSchema, schemaTransformId, SchemaTransformId } from './schema'; import { registerTransformsAuditMessagesRoutes } from './transforms_audit_messages'; +import { IIndexPattern } from '../../../../../../src/plugins/data/common/index_patterns'; enum TRANSFORM_ACTIONS { STOP = 'stop', @@ -173,15 +182,37 @@ export function registerTransformsRoutes(routeDependencies: RouteDependencies) { { path: addBasePath('delete_transforms'), validate: { - body: schema.maybe(schema.any()), + body: deleteTransformSchema, }, }, license.guardApiRoute(async (ctx, req, res) => { - const transformsInfo = req.body as TransformEndpointRequest[]; + const { + transformsInfo, + deleteDestIndex, + deleteDestIndexPattern, + } = req.body as DeleteTransformEndpointRequest; try { + const body = await deleteTransforms( + transformsInfo, + deleteDestIndex, + deleteDestIndexPattern, + ctx, + license, + res + ); + + if (body && body.status) { + if (body.status === 404) { + return res.notFound(); + } + if (body.status === 403) { + return res.forbidden(); + } + } + return res.ok({ - body: await deleteTransforms(transformsInfo, ctx.transform!.dataClient.callAsCurrentUser), + body, }); } catch (e) { return res.customError(wrapError(wrapEsError(e))); @@ -238,18 +269,51 @@ const getTransforms = async (options: { transformId?: string }, callAsCurrentUse return await callAsCurrentUser('transform.getTransforms', options); }; +async function getIndexPatternId( + indexName: string, + savedObjectsClient: SavedObjectsClientContract +) { + const response = await savedObjectsClient.find({ + type: 'index-pattern', + perPage: 1, + search: `"${indexName}"`, + searchFields: ['title'], + fields: ['title'], + }); + const ip = response.saved_objects.find((obj) => obj.attributes.title === indexName); + return ip?.id; +} + +async function deleteDestIndexPatternById( + indexPatternId: string, + savedObjectsClient: SavedObjectsClientContract +) { + return await savedObjectsClient.delete('index-pattern', indexPatternId); +} + async function deleteTransforms( transformsInfo: TransformEndpointRequest[], - callAsCurrentUser: CallCluster + deleteDestIndex: boolean | undefined, + deleteDestIndexPattern: boolean | undefined, + ctx: RequestHandlerContext, + license: RouteDependencies['license'], + response: KibanaResponseFactory ) { - const results: TransformEndpointResult = {}; + const tempResults: TransformEndpointResult = {}; + const results: Record = {}; for (const transformInfo of transformsInfo) { + let destinationIndex: string | undefined; + const transformDeleted: ResultData = { success: false }; + const destIndexDeleted: ResultData = { success: false }; + const destIndexPatternDeleted: ResultData = { + success: false, + }; const transformId = transformInfo.id; try { if (transformInfo.state === TRANSFORM_STATE.FAILED) { try { - await callAsCurrentUser('transform.stopTransform', { + await ctx.transform!.dataClient.callAsCurrentUser('transform.stopTransform', { transformId, force: true, waitForCompletion: true, @@ -257,7 +321,7 @@ async function deleteTransforms( } catch (e) { if (isRequestTimeout(e)) { return fillResultsWithTimeouts({ - results, + results: tempResults, id: transformId, items: transformsInfo, action: TRANSFORM_ACTIONS.DELETE, @@ -265,9 +329,75 @@ async function deleteTransforms( } } } + // Grab destination index info to delete + try { + const transformConfigs = await getTransforms( + { transformId }, + ctx.transform!.dataClient.callAsCurrentUser + ); + const transformConfig = transformConfigs.transforms[0]; + destinationIndex = Array.isArray(transformConfig.dest.index) + ? transformConfig.dest.index[0] + : transformConfig.dest.index; + } catch (getTransformConfigError) { + transformDeleted.error = wrapError(getTransformConfigError); + results[transformId] = { + transformDeleted, + destIndexDeleted, + destIndexPatternDeleted, + destinationIndex, + }; + continue; + } + + // If user checks box to delete the destinationIndex associated with the job + if (destinationIndex && deleteDestIndex) { + try { + // If user does have privilege to delete the index, then delete the index + // if no permission then return 403 forbidden + await ctx.transform!.dataClient.callAsCurrentUser('indices.delete', { + index: destinationIndex, + }); + destIndexDeleted.success = true; + } catch (deleteIndexError) { + destIndexDeleted.error = wrapError(deleteIndexError); + } + } + + // Delete the index pattern if there's an index pattern that matches the name of dest index + if (destinationIndex && deleteDestIndexPattern) { + try { + const indexPatternId = await getIndexPatternId( + destinationIndex, + ctx.core.savedObjects.client + ); + if (indexPatternId) { + await deleteDestIndexPatternById(indexPatternId, ctx.core.savedObjects.client); + destIndexPatternDeleted.success = true; + } + } catch (deleteDestIndexPatternError) { + destIndexPatternDeleted.error = wrapError(deleteDestIndexPatternError); + } + } - await callAsCurrentUser('transform.deleteTransform', { transformId }); - results[transformId] = { success: true }; + try { + await ctx.transform!.dataClient.callAsCurrentUser('transform.deleteTransform', { + transformId, + }); + transformDeleted.success = true; + } catch (deleteTransformJobError) { + transformDeleted.error = wrapError(deleteTransformJobError); + if (transformDeleted.error.statusCode === 403) { + return response.forbidden(); + } + } + + results[transformId] = { + transformDeleted, + destIndexDeleted, + destIndexPatternDeleted, + destinationIndex, + }; } catch (e) { if (isRequestTimeout(e)) { return fillResultsWithTimeouts({ @@ -277,7 +407,7 @@ async function deleteTransforms( action: TRANSFORM_ACTIONS.DELETE, }); } - results[transformId] = { success: false, error: JSON.stringify(e) }; + results[transformId] = { transformDeleted: { success: false, error: JSON.stringify(e) } }; } } return results; diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js index 2719486d0c502..b79dc3f3ffe59 100644 --- a/x-pack/test/api_integration/apis/index.js +++ b/x-pack/test/api_integration/apis/index.js @@ -30,5 +30,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./ingest_manager')); loadTestFile(require.resolve('./endpoint')); loadTestFile(require.resolve('./ml')); + loadTestFile(require.resolve('./transform')); }); } diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts index 23bff0d0c2855..dc0ccfdc53a18 100644 --- a/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts @@ -197,7 +197,7 @@ export default ({ getService }: FtrProviderContext) => { await ml.testResources.deleteIndexPattern(destinationIndex); }); - it('deletes job, target index, and index pattern by id', async () => { + it('should delete job, target index, and index pattern by id', async () => { const { body } = await supertest .delete(`/api/ml/data_frame/analytics/${analyticsId}`) .query({ deleteDestIndex: true, deleteDestIndexPattern: true }) diff --git a/x-pack/test/api_integration/apis/transform/delete_transforms.ts b/x-pack/test/api_integration/apis/transform/delete_transforms.ts new file mode 100644 index 0000000000000..40300c981ee2e --- /dev/null +++ b/x-pack/test/api_integration/apis/transform/delete_transforms.ts @@ -0,0 +1,318 @@ +/* + * 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 expect from '@kbn/expect'; +import { TransformEndpointRequest } from '../../../../plugins/transform/common'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { COMMON_REQUEST_HEADERS } from '../../../functional/services/ml/common'; +import { USER } from '../../../functional/services/transform/security_common'; + +async function asyncForEach(array: any[], callback: Function) { + for (let index = 0; index < array.length; index++) { + await callback(array[index], index, array); + } +} + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertestWithoutAuth'); + const transform = getService('transform'); + + function generateDestIndex(transformId: string): string { + return `user-${transformId}`; + } + + async function createTransform(transformId: string, destinationIndex: string) { + const config = { + id: transformId, + source: { index: ['farequote-*'] }, + pivot: { + group_by: { airline: { terms: { field: 'airline' } } }, + aggregations: { '@timestamp.value_count': { value_count: { field: '@timestamp' } } }, + }, + dest: { index: destinationIndex }, + }; + + await transform.api.createTransform(config); + } + + describe('delete_transforms', function () { + before(async () => { + await esArchiver.loadIfNeeded('ml/farequote'); + await transform.testResources.setKibanaTimeZoneToUTC(); + }); + + after(async () => { + await transform.api.cleanTransformIndices(); + }); + + describe('single transform deletion', function () { + const transformId = 'test1'; + const destinationIndex = generateDestIndex(transformId); + + beforeEach(async () => { + await createTransform(transformId, destinationIndex); + await transform.api.createIndices(destinationIndex); + }); + + afterEach(async () => { + await transform.api.deleteIndices(destinationIndex); + }); + + it('should delete transform by transformId', async () => { + const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; + const { body } = await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo, + }) + .expect(200); + + expect(body[transformId].transformDeleted.success).to.eql(true); + expect(body[transformId].destIndexDeleted.success).to.eql(false); + expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); + await transform.api.waitForTransformNotToExist(transformId); + await transform.api.waitForIndicesToExist(destinationIndex); + }); + + it('should return 403 for unauthorized user', async () => { + const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; + await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_VIEWER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_VIEWER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo, + }) + .expect(403); + await transform.api.waitForTransformToExist(transformId); + await transform.api.waitForIndicesToExist(destinationIndex); + }); + }); + + describe('single transform deletion with invalid transformId', function () { + it('should return 200 with error in response if invalid transformId', async () => { + const transformsInfo: TransformEndpointRequest[] = [{ id: 'invalid_transform_id' }]; + const { body } = await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo, + }) + .expect(200); + expect(body.invalid_transform_id.transformDeleted.success).to.eql(false); + expect(body.invalid_transform_id.transformDeleted).to.have.property('error'); + }); + }); + + describe('bulk deletion', function () { + const transformsInfo: TransformEndpointRequest[] = [ + { id: 'bulk_delete_test_1' }, + { id: 'bulk_delete_test_2' }, + ]; + const destinationIndices = transformsInfo.map((d) => generateDestIndex(d.id)); + + beforeEach(async () => { + await asyncForEach(transformsInfo, async ({ id }: { id: string }, idx: number) => { + await createTransform(id, destinationIndices[idx]); + await transform.api.createIndices(destinationIndices[idx]); + }); + }); + + afterEach(async () => { + await asyncForEach(destinationIndices, async (destinationIndex: string) => { + await transform.api.deleteIndices(destinationIndex); + }); + }); + + it('should delete multiple transforms by transformIds', async () => { + const { body } = await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo, + }) + .expect(200); + + await asyncForEach( + transformsInfo, + async ({ id: transformId }: { id: string }, idx: number) => { + expect(body[transformId].transformDeleted.success).to.eql(true); + expect(body[transformId].destIndexDeleted.success).to.eql(false); + expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); + await transform.api.waitForTransformNotToExist(transformId); + await transform.api.waitForIndicesToExist(destinationIndices[idx]); + } + ); + }); + + it('should delete multiple transforms by transformIds, even if one of the transformIds is invalid', async () => { + const invalidTransformId = 'invalid_transform_id'; + const { body } = await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo: [ + { id: transformsInfo[0].id }, + { id: invalidTransformId }, + { id: transformsInfo[1].id }, + ], + }) + .expect(200); + + await asyncForEach( + transformsInfo, + async ({ id: transformId }: { id: string }, idx: number) => { + expect(body[transformId].transformDeleted.success).to.eql(true); + expect(body[transformId].destIndexDeleted.success).to.eql(false); + expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); + await transform.api.waitForTransformNotToExist(transformId); + await transform.api.waitForIndicesToExist(destinationIndices[idx]); + } + ); + + expect(body[invalidTransformId].transformDeleted.success).to.eql(false); + expect(body[invalidTransformId].transformDeleted).to.have.property('error'); + }); + }); + + describe('with deleteDestIndex setting', function () { + const transformId = 'test2'; + const destinationIndex = generateDestIndex(transformId); + + before(async () => { + await createTransform(transformId, destinationIndex); + await transform.api.createIndices(destinationIndex); + }); + + after(async () => { + await transform.api.deleteIndices(destinationIndex); + }); + + it('should delete transform and destination index', async () => { + const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; + const { body } = await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo, + deleteDestIndex: true, + }) + .expect(200); + + expect(body[transformId].transformDeleted.success).to.eql(true); + expect(body[transformId].destIndexDeleted.success).to.eql(true); + expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); + await transform.api.waitForTransformNotToExist(transformId); + await transform.api.waitForIndicesNotToExist(destinationIndex); + }); + }); + + describe('with deleteDestIndexPattern setting', function () { + const transformId = 'test3'; + const destinationIndex = generateDestIndex(transformId); + + before(async () => { + await createTransform(transformId, destinationIndex); + await transform.api.createIndices(destinationIndex); + await transform.testResources.createIndexPatternIfNeeded(destinationIndex); + }); + + after(async () => { + await transform.api.deleteIndices(destinationIndex); + await transform.testResources.deleteIndexPattern(destinationIndex); + }); + + it('should delete transform and destination index pattern', async () => { + const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; + const { body } = await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo, + deleteDestIndex: false, + deleteDestIndexPattern: true, + }) + .expect(200); + + expect(body[transformId].transformDeleted.success).to.eql(true); + expect(body[transformId].destIndexDeleted.success).to.eql(false); + expect(body[transformId].destIndexPatternDeleted.success).to.eql(true); + await transform.api.waitForTransformNotToExist(transformId); + await transform.api.waitForIndicesToExist(destinationIndex); + await transform.testResources.assertIndexPatternNotExist(destinationIndex); + }); + }); + + describe('with deleteDestIndex & deleteDestIndexPattern setting', function () { + const transformId = 'test4'; + const destinationIndex = generateDestIndex(transformId); + + before(async () => { + await createTransform(transformId, destinationIndex); + await transform.api.createIndices(destinationIndex); + await transform.testResources.createIndexPatternIfNeeded(destinationIndex); + }); + + after(async () => { + await transform.api.deleteIndices(destinationIndex); + await transform.testResources.deleteIndexPattern(destinationIndex); + }); + + it('should delete transform, destination index, & destination index pattern', async () => { + const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; + const { body } = await supertest + .post(`/api/transform/delete_transforms`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(COMMON_REQUEST_HEADERS) + .send({ + transformsInfo, + deleteDestIndex: true, + deleteDestIndexPattern: true, + }) + .expect(200); + + expect(body[transformId].transformDeleted.success).to.eql(true); + expect(body[transformId].destIndexDeleted.success).to.eql(true); + expect(body[transformId].destIndexPatternDeleted.success).to.eql(true); + await transform.api.waitForTransformNotToExist(transformId); + await transform.api.waitForIndicesNotToExist(destinationIndex); + await transform.testResources.assertIndexPatternNotExist(destinationIndex); + }); + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/transform/index.ts b/x-pack/test/api_integration/apis/transform/index.ts new file mode 100644 index 0000000000000..93a951a55ece1 --- /dev/null +++ b/x-pack/test/api_integration/apis/transform/index.ts @@ -0,0 +1,32 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const transform = getService('transform'); + + describe('Machine Learning', function () { + this.tags(['transform']); + + before(async () => { + await transform.securityCommon.createTransformRoles(); + await transform.securityCommon.createTransformUsers(); + }); + + after(async () => { + await transform.securityCommon.cleanTransformUsers(); + await transform.securityCommon.cleanTransformRoles(); + + await esArchiver.unload('ml/farequote'); + + await transform.testResources.resetKibanaTimeZone(); + }); + + loadTestFile(require.resolve('./delete_transforms')); + }); +} diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index e7e166237c602..2a0327ff57104 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -28,6 +28,7 @@ import { InfraLogSourceConfigurationProvider } from './infra_log_source_configur import { MachineLearningProvider } from './ml'; import { IngestManagerProvider } from './ingest_manager'; import { ResolverGeneratorProvider } from './resolver'; +import { TransformProvider } from './transform'; export const services = { ...commonServices, @@ -48,4 +49,5 @@ export const services = { ml: MachineLearningProvider, ingestManager: IngestManagerProvider, resolverGenerator: ResolverGeneratorProvider, + transform: TransformProvider, }; diff --git a/x-pack/test/api_integration/services/transform.ts b/x-pack/test/api_integration/services/transform.ts new file mode 100644 index 0000000000000..1403d5d2d67f0 --- /dev/null +++ b/x-pack/test/api_integration/services/transform.ts @@ -0,0 +1,23 @@ +/* + * 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 { FtrProviderContext } from '../../functional/ftr_provider_context'; + +import { TransformAPIProvider } from '../../functional/services/transform/api'; +import { TransformSecurityCommonProvider } from '../../functional/services/transform/security_common'; +import { MachineLearningTestResourcesProvider } from '../../functional/services/ml/test_resources'; + +export function TransformProvider(context: FtrProviderContext) { + const api = TransformAPIProvider(context); + const securityCommon = TransformSecurityCommonProvider(context); + const testResources = MachineLearningTestResourcesProvider(context); + + return { + api, + securityCommon, + testResources, + }; +} diff --git a/x-pack/test/functional/services/transform/api.ts b/x-pack/test/functional/services/transform/api.ts index a805f5a3b6013..697020fafb196 100644 --- a/x-pack/test/functional/services/transform/api.ts +++ b/x-pack/test/functional/services/transform/api.ts @@ -20,6 +20,21 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { const esSupertest = getService('esSupertest'); return { + async createIndices(indices: string) { + log.debug(`Creating indices: '${indices}'...`); + if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === true) { + log.debug(`Indices '${indices}' already exist. Nothing to create.`); + return; + } + + const createResponse = await es.indices.create({ index: indices }); + expect(createResponse) + .to.have.property('acknowledged') + .eql(true, 'Response for create request indices should be acknowledged.'); + + await this.waitForIndicesToExist(indices, `expected ${indices} to be created`); + }, + async deleteIndices(indices: string) { log.debug(`Deleting indices: '${indices}'...`); if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === false) { @@ -34,11 +49,25 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { .to.have.property('acknowledged') .eql(true, 'Response for delete request should be acknowledged'); - await retry.waitForWithTimeout(`'${indices}' indices to be deleted`, 30 * 1000, async () => { + await this.waitForIndicesNotToExist(indices, `expected indices '${indices}' to be deleted`); + }, + + async waitForIndicesToExist(indices: string, errorMsg?: string) { + await retry.tryForTime(30 * 1000, async () => { + if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === true) { + return true; + } else { + throw new Error(errorMsg || `indices '${indices}' should exist`); + } + }); + }, + + async waitForIndicesNotToExist(indices: string, errorMsg?: string) { + await retry.tryForTime(30 * 1000, async () => { if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === false) { return true; } else { - throw new Error(`expected indices '${indices}' to be deleted`); + throw new Error(errorMsg || `indices '${indices}' should not exist`); } }); }, @@ -63,9 +92,7 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { async getTransformState(transformId: string): Promise { const stats = await this.getTransformStats(transformId); - const state: TRANSFORM_STATE = stats.state; - - return state; + return stats.state; }, async waitForTransformState(transformId: string, expectedState: TRANSFORM_STATE) { @@ -96,8 +123,8 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { }); }, - async getTransform(transformId: string) { - return await esSupertest.get(`/_transform/${transformId}`).expect(200); + async getTransform(transformId: string, expectedCode = 200) { + return await esSupertest.get(`/_transform/${transformId}`).expect(expectedCode); }, async createTransform(transformConfig: TransformPivotConfig) { @@ -105,11 +132,27 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { log.debug(`Creating transform with id '${transformId}'...`); await esSupertest.put(`/_transform/${transformId}`).send(transformConfig).expect(200); - await retry.waitForWithTimeout(`'${transformId}' to be created`, 5 * 1000, async () => { - if (await this.getTransform(transformId)) { + await this.waitForTransformToExist( + transformId, + `expected transform '${transformId}' to be created` + ); + }, + + async waitForTransformToExist(transformId: string, errorMsg?: string) { + await retry.waitForWithTimeout(`'${transformId}' to exist`, 5 * 1000, async () => { + if (await this.getTransform(transformId, 200)) { + return true; + } else { + throw new Error(errorMsg || `expected transform '${transformId}' to exist`); + } + }); + }, + async waitForTransformNotToExist(transformId: string, errorMsg?: string) { + await retry.waitForWithTimeout(`'${transformId}' to exist`, 5 * 1000, async () => { + if (await this.getTransform(transformId, 404)) { return true; } else { - throw new Error(`expected transform '${transformId}' to be created`); + throw new Error(errorMsg || `expected transform '${transformId}' to not exist`); } }); }, From 3c6aabcf354cd83942a02b4eba89894a4912d944 Mon Sep 17 00:00:00 2001 From: EamonnTP Date: Wed, 10 Jun 2020 16:14:46 +0100 Subject: [PATCH 34/53] [DOCS] Move Logs app content to Logs monitoring guide (#68644) * Move content to Logs guide * Add redirects to Logs monitoring guide * Update urls --- docs/infrastructure/infra-ui.asciidoc | 2 +- docs/logs/configuring.asciidoc | 46 -------- docs/logs/getting-started.asciidoc | 11 -- docs/logs/images/alert-actions-menu.png | Bin 32575 -> 0 bytes docs/logs/images/alert-flyout.png | Bin 171358 -> 0 bytes .../images/analysis-tab-create-ml-job.png | Bin 241031 -> 0 bytes docs/logs/images/log-rate-anomalies.png | Bin 305676 -> 0 bytes docs/logs/images/log-rate-entries.png | Bin 235595 -> 0 bytes docs/logs/images/log-time-filter.png | Bin 51802 -> 0 bytes docs/logs/images/logs-action-menu.png | Bin 531 -> 0 bytes docs/logs/images/logs-add-data.png | Bin 399007 -> 0 bytes ...ure-source-dialog-remove-column-button.png | Bin 378 -> 0 bytes docs/logs/images/logs-time-selector.png | Bin 5793 -> 0 bytes .../images/logs-view-event-with-filter.png | Bin 929 -> 0 bytes docs/logs/images/logs-view-event.png | Bin 555 -> 0 bytes docs/logs/images/logs-view-in-context.png | Bin 388396 -> 0 bytes docs/logs/index.asciidoc | 24 +---- docs/logs/log-rate.asciidoc | 94 ---------------- docs/logs/logs-alerting.asciidoc | 27 ----- docs/logs/using.asciidoc | 100 ------------------ docs/redirects.asciidoc | 27 ++++- 21 files changed, 32 insertions(+), 299 deletions(-) delete mode 100644 docs/logs/configuring.asciidoc delete mode 100644 docs/logs/getting-started.asciidoc delete mode 100644 docs/logs/images/alert-actions-menu.png delete mode 100644 docs/logs/images/alert-flyout.png delete mode 100644 docs/logs/images/analysis-tab-create-ml-job.png delete mode 100644 docs/logs/images/log-rate-anomalies.png delete mode 100644 docs/logs/images/log-rate-entries.png delete mode 100644 docs/logs/images/log-time-filter.png delete mode 100644 docs/logs/images/logs-action-menu.png delete mode 100644 docs/logs/images/logs-add-data.png delete mode 100644 docs/logs/images/logs-configure-source-dialog-remove-column-button.png delete mode 100644 docs/logs/images/logs-time-selector.png delete mode 100644 docs/logs/images/logs-view-event-with-filter.png delete mode 100644 docs/logs/images/logs-view-event.png delete mode 100644 docs/logs/images/logs-view-in-context.png delete mode 100644 docs/logs/log-rate.asciidoc delete mode 100644 docs/logs/logs-alerting.asciidoc delete mode 100644 docs/logs/using.asciidoc diff --git a/docs/infrastructure/infra-ui.asciidoc b/docs/infrastructure/infra-ui.asciidoc index 96550b4ed5758..9e7459da743a4 100644 --- a/docs/infrastructure/infra-ui.asciidoc +++ b/docs/infrastructure/infra-ui.asciidoc @@ -103,7 +103,7 @@ You can: * Select *View Metrics* to <>. -* Select *View Logs* to <> in the *Logs* app. +* Select *View Logs* to {logs-guide}/inspect-log-events.html[view the logs] in the *Logs* app. Depending on the features you have installed and configured, you may also be able to: diff --git a/docs/logs/configuring.asciidoc b/docs/logs/configuring.asciidoc deleted file mode 100644 index 6b54721f92e89..0000000000000 --- a/docs/logs/configuring.asciidoc +++ /dev/null @@ -1,46 +0,0 @@ -[role="xpack"] -[[xpack-logs-configuring]] - -:ecs-base-link: {ecs-ref}/ecs-base.html[base] - -== Configuring the Logs data - -The default source configuration for logs is specified in the {kibana-ref}/logs-ui-settings-kb.html[Logs app settings] in the {kibana-ref}/settings.html[Kibana configuration file]. -The default configuration uses the `filebeat-*` index pattern to query the data. -The default configuration also defines field settings for things like timestamps and container names, and the default columns to show in the logs stream. - -If your logs have custom index patterns, use non-default field settings, or contain parsed fields which you want to expose as individual columns, you can override the default configuration settings. - -To change the configuration settings, click the *Settings* tab. - -NOTE: These settings are shared with metrics. Changes you make here may also affect the settings used by the *Metrics* app. - -In the *Settings* tab, you can change the values in these sections: - -* *Name*: the name of the source configuration -* *Indices*: the index pattern or patterns in the Elasticsearch indices to read metrics data and log data from -* *Fields*: the names of specific fields in the indices that are used to query and interpret the data correctly -* *Log columns*: the columns that are shown in the logs stream - -By default the logs stream shows following columns: - -* *Timestamp*: The timestamp of the log entry from the `timestamp` field. -* *Message*: The message extracted from the document. -The content of this field depends on the type of log message. -If no special log message type is detected, the Elastic Common Schema (ECS) {ecs-base-link} field, `message`, is used. - -To add a new column to the logs stream, in the *Settings* tab, click *Add column*. -In the list of available fields, select the field you want to add. -You can start typing a field name in the search box to filter the field list by that name. - -To remove an existing column, click the *Remove this column* icon -image:logs/images/logs-configure-source-dialog-remove-column-button.png[Remove column]. - -When you have completed your changes, click *Apply*. - -If the fields are greyed out and cannot be edited, you may not have sufficient privileges to change the source configuration. -For more information see <>. - -TIP: If <> are enabled in your Kibana instance, any configuration changes you make here are specific to the current space. -You can make different subsets of data available by creating multiple spaces with different data source configurations. - diff --git a/docs/logs/getting-started.asciidoc b/docs/logs/getting-started.asciidoc deleted file mode 100644 index ca09bb34c0e56..0000000000000 --- a/docs/logs/getting-started.asciidoc +++ /dev/null @@ -1,11 +0,0 @@ -[role="xpack"] -[[xpack-logs-getting-started]] -== Getting started with logs monitoring - -To get started with the Logs app in Kibana, you need to start collecting logs data for your infrastructure. - -Kibana provides step-by-step instructions to help you add logs data. -The {logs-guide}[Logs Monitoring Guide] is a good source for more detailed information and instructions. - -[role="screenshot"] -image::logs/images/logs-add-data.png[Screenshot showing Add logging data in Kibana] diff --git a/docs/logs/images/alert-actions-menu.png b/docs/logs/images/alert-actions-menu.png deleted file mode 100644 index 3f96a700a0ac129d60f1bd3548ddb4b554e2f5b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32575 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 Au>b%7 diff --git a/docs/logs/images/alert-flyout.png b/docs/logs/images/alert-flyout.png deleted file mode 100644 index 30c8857758a8b4d39b448e5f4fd892b02270cfc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171358 zcmbSzby!u~);A#Ch=8Po2nZVlq&uZSK)R$G>23k(E=fs|?hXSs-CbMh-qH=<;+%8O z<-B*Fe?FgwaIZDz9CP#-^EU}qQh0@hPJ#{x2ZtpsC9Vtyhd2!fha!cF41Ds7+a(7M z4pYiPOiW2yOpH>=!Oqme+5`?xDl}0YMMI^BFjHGu+T0&i3avGiS}OUWXgDS1n+m)* zVbM@lst?n6ufNuYqfQUM!IPLm=+>%CmZ&@pK}t+?t~3x^l}F#$I$gY6Ja20}9ZGe) zQDHk>B!+YP;;w9g{RKm~?5QFl5k)^qT3j!+06Z!s{PV{Mm~LK;3FM@tNZCh_TL!4D zuob=6eQ)pN|NNG!Z*RhY}ne%+C%Y0OV4)| zpI70}klbifQ`KkP+I*s?(#&9&93Y~T5G%oARmmiOQdIZV8eJlN!-q7LS|PO^>qncY zv|Gi;Cuu2E7~x~neGaSF$A%aZhPE}x>T977sbBK*o%6rBk;LUfquu%8L-EPWTGbbX z@K)+`lgmz(QrzbvBCF&zB(Q~-zO17m#|ihF6#TMrZ4v9|L(x-bOYrXRM82Hwn_K8v z2k;G#MFvIF8p}%m~4*GpxOtrDfGJAu`FD2ng+g<7 zC+`d2bAF@w<}Awh>*T3@>`sV>hQUko5WH_MISPIC*=vw_`*2e5>h-7y0*23?sveK z<0Iet_DdTM>fsfa?ua+smCD7%1-AE?#MgDFTSvIhx)7%mXSm^LxOXms`c!@D+wWF` z;Mx^JfkX0U_1DU#vHVK#H~stw_R044WDp>nKI)KA^T= ztysvXMS9Xmar|L4^JlzBAo1`KT5}|=z&&x&;pGjaBi`AlHet^feim=#`X4%eZDGYG z49qtqPQgqIN;F*6z*39m_L{CIzjqfI zqcwieQCJia6m1jrk=)DQP_|}hOL!dS#}-+YP!%*P*C@W3eWZN+`9#&%5`iO}H(5)h zv@kPgF}H1GbhK*pV1y)>cJgEHn@_c`wo4|(N~2$Tf5eXzBUMxxP8zNoi5jsTTO8hW z;`6{2NX&etFIt|Tl`WL*J8Wu>GqGlgQDbJMZoy@)KjKp)Hc~n9c3Wkw&eT}v5g#s%t<_F{xWSu~!K(;_#);%wkL&(mHn50`mC2 z{EK(_{23 z7B8kQUQjzNEt*`MB%UlT(JpDWVX~H->#r!PZZwjuJgy^{DXSDPx?CJwWS+70*UepU z^rZ1D^Zw+WaV>z-B$oaCQ3y$hRh0NEJFqp_IVw3ri4KP@RwZ$a)@*!cOmnAYu+awf z?S~=Uo|unRT)O7W*2!MUyvZSAsbaaogjhCY7Y-={72|LFLNbU?CMLdffStp)7k*uQ ze}%+i?Al^waA%i)E|h5glw z)nk2Kj0459+XeOht|h02&}u=%EQ72W!4NOO3y+Jn^S$HixuH&$IlB>_6LeYUPg)#kjn8KX68>0lx>ya_}Q`A|Kqln$^K|`oYiB7{#8v*9V(rUIfpAzq#glPyE7yKit zh~)64t=oJ=1N(l≠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∈*P`=OiFq!S}$wF0)W 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 z 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

9o*Y+=KPU`rI z;{VJ#2N!h+{qSschw2)HM|vi9pb>qgV0)xqPWfnly2>Q{qJ$qL291>u!aH0$tQOE{ zv0YA8S$^_z18oL6|G0M*8j?Zv`G>F5WxYw+N3$hnj=smSyD|M~%=%F&Bc_yo;%+Cq z@eg^bBpd_-D%?D!zDfldz6El}rBY}^SJiu{oOfqETi>*XJVwxyKG~jQ48SIhd?!7t zmv3-O{Z*s(d^T3_h7B{r@omz<1U-Tcx&5LKx3`&`Yj1yEL_)>-zF%%6^RQW@i8m|PvB9*zi~gCL^}Q?(ue7X>Jy zDcr6~7!25hM98s|Zc^!>&*(ii9zafkbiN*Sv4tJ?8#dW(w8a!er1dN1>$UzQuEj%< zx2<~yP6RF&ybh9~nCg2kCIOIC(qY_7O>x?u1TKJ18Qa5mA^#Atq!)NX_A)7jOWu0# zXliNPQD@GJLQ5!XsDiPKDYGfxf7czYZd-UWYQ=;4<5tRL6R9*2d7um0PEkE5b6 zuGlIcyOp$&yO85f!#=mhy<+#kADeml*{WM%ymyUj$#`A|>R}(DE`;gTu4mP87WI@HsrfWF0&AgJ|uW4N~SkPKX9JZLUqCSjHmbK*RyEDwuB zH9zCE7U6CotW!b?3Y~D{9yc3VR}?p^INK_m2egtOcO8Tqi&Puswd%~t?DT`5CVTyi zLCK_q4u_uu7eHK_ooJ?+%dexkXF1>YNfJKx$ab|fAR1ghtM{xNg(?bi^UL; z>CJ|UP+UV($V%eTXUg~m!5ZgP0}G!9kzM1t$4g=fVGYvs+oLIuaQPR&?i(hpm*P57 zG_zJ&2WqV}PFfK%iuqV^I7KJQsl!z|aac)Ou-Si_4l*4EAVNbvo;|`^lEjZN2q5%a8}&%F2U_2)Z~zi^nG$Wde%6?|`g-9x7Z6H|>gJJ(XBkQ`)8kTO$s=?$B30k@(vhppb-*Ll~VlVIe zY>{$V!R|v@tjxsDZMwq<1axX_M53l!9d{PlJ0yw<iL->{-=RM*Z@%qxV5mY zX>e6muL8urripzm>Z&dwh$aCA2aeKJ*9#c6w7Df67`}d@5>60_Z_aXD)_V1nC`3nr zN5{L0luJY={cI5v8OaKpT(J1|I1VE!o_b^KEjo>!Fj8eXo2TIg$}DvaQHBXUw{VgR z=~0Ev)wH;cFeYx{9HaVPowU7*T27F*+USc_j>Yu?g3{yOuY~yw+9E3yYbf?c(NvlL zs|LZMC_Z;?XBrOGwJY?Kk&+yn%)KwPQ!$Y!;DNFbA zLGe>LP5K=S44qlP;XWikgxv((yXO`gO-Dm3G0zzLbZ}FWL&YagmADb>VSI>mUL3Pq zx3{Rgi|f_OS390!jTPb+;h~V}Dtm6d;*2*PHb!aYCRjQ0jgP(5Dw@jz%nd*7#{=~u z-J$cC6}*1mmnOBz_aaOdE?%^X1w;$xWcOy4ig6JrW1)@-2W~^^YE@In0kb$0justZ z$Eh-HM(Az(H&H^dVMh{U-Fr?C$0y#|P6x4Bt028&`GK(UO<#Jl1xOk{IN4tWjoS9f znVHe6$lsFKUKq)PsW<`#r5x*>rU_#+>|}=YO;(%NN@!z-^QQNSqT2lL6&g;T>3N`h zSszS;3=P>C2K1NI#q680^B%zii0(7#WOgvly48gc3k=ZR<%07q3LQjtlV(chp@fx> z56NovQx8RjvHMCBqeK=vrIcgyQvDlfo`1L(2e_4FQA%Fp!@pTvrnY6Bm$1#Ic>SqW z%W6-A1O^n;P^oBgPGbBSy_xSPwt#Y=iV8VIq6qsqzECmW(~j&E$eBPLHXAYN0}K+NCDA~*_pvvLEBxT1TwkqJ zt0cFPU&wz59(LJaA>%e;?+>37<)g35!^a0J@~xkY6S>syzF_o>wa|HsWm#bCajG|X zg}61DQIp!u!BZD+MFre<=@avE@pV)9qKoC(cS8>0#(@r}l7hh>(iXzdmsfVB$=uQIIWtzDV+f0SMUf3mQ||oPc*=ozuTbAyBKcef zk@8+4-H3ksa8^(Dfd}>(a93CcBHN08FX$s*TA+-nuP7||&_LfbgExQZ4YXl7%8 zA#i2+;ul=8Y=;6o+Q2^&i~|GPu8_QXk+8>|2SdtR9pd7tOZ>+YrQu6VF!V_Tyrd**bwj@2TJ`1eyKeFzWaKEVeCv-W;LSacMs>mS zHSg5VXB$Fc-}9qxSIN}A+^o)n&B*BN!m6zgbRjYrW6Uspgd3>vQ~+G7FB*)dXI;yOCW=!-FVB8{_#jLg_o`%Fh%xY;=N-2?gxLL8>C6ddJE`!*|%Sp$_D|NUIiQB zeS2>-FoWL1PvSF$tMn@2PH71@Xb&L2-+xgbfiI+F`5VrF_ru8TZ!9UBAJ~|@Cd2Og z(ZbchAmMQohja|Uz|r@dqf}pHfTA*tpWm3+jmJOcsXX4Eqag5xl)3g-H5ASaK)?VJ z;0T%sVQDJi43IS6>v$J829;KBF9ZNLl6zv^p8xaE`}1y@p z`aCVWG!E7kDO@0`nbWST-dTZiU-myjPZ%*C1=vmHal73A!}eVBJBaFe+K@CC>QlEO zxhQ*8D=9KWu&+F?l$gEy+iHGY*`MuCw(#}YZsRMn1H_Wi&3^-37!m=5WH|j^u|plf z4d)7BB=)+(h&V+y7faq3wHx%ew+Nx!;>sMzkgh|MNZ=?d8wq+wkr;myvu_|e6VR77 zi&EQTp!Y?Jil7_AveE!xeQ8(8f+vX!M=0EYpit`Hcjm8af&ay45qKSYh_1d%DL-{K z3~fg2cYx#A00Z|VvGmjVtiom4s`JZ9%KrsMe~uKG06+qlsxh4y09g7DO`hK|q3t$> zaK_nf@1e(1i-`E?3YUoF2x{`b5B@8m{L-!fz63GR)9Mlf@Flev7ytdM2!1qxd+~=M zX^S9ANda@t&K_*I0nUH_NFfIRBOHH{n?NQ5l-yRS@%uu3jAY=_+|6{71uu{Uz`K?A zakp=9oPP<>UxlggH#iw@YV>5%VvHGzM83K4S~fMD^s=+MYNLcLf!ULhgfaag;{W|T zf8l{o>EUdY{wk0WsFCp6Xy6wx!BHgQGn|uu#->P;M+}04jWV6}&hH!X>pXvHQ**(w zw~h+0N#I@~>PE*+SOkXy+e^5>x<(c$Ob@&oK-uZ?JGlM_^pm^=N6=fSz2=nuko%aW zzlkXXbR9h4->uYG?9Nfh?f@uueSJx8Ap5_6j9`N=wK9wZppY$>ikcg54dVyKDqPm4 zGOlgcUuW9j$N*Rx$msK|K)Kgsg)E}lOi89tA0&>{BJFW;#Lv>2F}pc zR=Et&fzS)fN52DC*b==Hu&=oNaI0KttC-{r%K^;8oyo#LfsnP5yvK_9WcHOz5&sMA z|A_=qaC(x$4bxN;d)JN-$xFoe2R;pJr4b^b)|m>I zN_@~+{lBp&pFeh%VJiV(2$f-k+A_aW7mk3>cYnxr?^Kn^T9rPwlR+ebhT*2N&eo=4Ltq%XaKN+x!lN$iEuJLh93Fk zsHXZVy6f&r{~Oy$je~>;81@w}>+PlUJ$I8Y+|H^owV|O*=MK)8T3wU?%$7yc$9MdV z09P)xM}tEYt)sbA3NO}U$1z)ga_x>ZXn)_TUvU3d>g0ywAVL%(XE;L!Xg!2jNmyp; zFSrqyDm*IcxW;ult4X6GWdA}g^-R5C@Jv+j`cmQOt|2-wc~%9A%6=GX3>c<8r+z~Zpd*sl2Ewf(Cbi0WIi|`_k;8m zoo%w4tc|wjt^FuaX4@?xU)y0mp)KS$rUWowz~=$iMs#Y8j7%;jF}2v4L)25N2RpI? z1pbhUfI+-})A=t<=O0{&q5#flRkAg){{l(jXULhrRZ7L4D0*Y^X~VB!_e|?S zjoQb(b$nNG9$wdsCb0=AK>gl`XUN~OUcSc?kji{=%FY>wo_ zR`(?VEr1&h?i)P0i3dM1=hp@fAtFS(Ia!r_3!E%KWfJSmSMeC002z^W;8ow--TU zV3$q^wDf9kb7XpicRqL@tN5Cx<-s~2bJ0YEQ`Yrv@eWzI$jPTYO}U?M5ed?wQIb#6 z(nnJ2=}qGOm>`|9y}g5BS5EZ5sW*SFb{G%({pg1bQCEln1W{)T^ z5pl{N-!2kP29CYB#bN^=Y)Q#q@K{TQppoj00I(?P+RTe}b_^T`=ZnmkjCt=|vl#F# zJxRb&71g9iVHu{CX8-GDhe-iKUJ5kv8 zFq)gX_OC?queR_cGC%ot?4bjUhK$m2k5llgase5q1npmylfZWf{Dmt*O!%D;jgLF@ z(&L&|6%8iFtTYPhsiWXjUj>2oBwhl@@M~jFJT$2`dp*D{;U%3=ijrmO)1XD`FG+eA zNXlD%^&0VSFgbt%NN<&K>w3gYkgeh&Lq-dF!dPVh!nmO&p}lO|Vx42u2v3om8#V8Q zY#a$&VUDX^U#)msbp*)Z1p?Pdou;r*(8MMRw6iC@!>#CPB>jiN^q0*p>Mi&3 zfD~s6iNppZT&}-v>9TYim3jc7BawJf1?Lkri43Cr5ppe&9?GrAh~z55%Rv z9ww=C2{$wRx4%FhpTnx) zt|rs_fUH=gzzOKZd&q&j0BkBZdG}vw^kU2h?|uARU&6M4 zzVla==)YLE4;rAekUe6d{aNqkzlI)~9I(7accL5O`d6;_H`_Rm0F{yoxqJ0*vD*LG zX*+y*$=HT}3m1RI%fGZK;paxbwuI!rB_sb0rvL1bf*V+#@8K(^zX+}WD=G;4!H)|# zMA83-bpDThA;Zu1wt^uv{{<5L{z+g2K>xUihHw9SLi`5~{^MvEQ1Snd2e@z(gs8#G zpEdOUBi8(<@oXP)X0{{R39Q7V=0002VP)t-sAyuFM z|NkRapCMMCC0L*$R-YtRpYihd5m22(Xs0AspB7P_J!GXSTA^o&yE|&DPj9O6^Z5S% z|J~;B|Nj19gt)ZD-6~n3+T-u;@b-O~!vI2GCUKrXEtA zH)p9NSfIAY-X2<`BUPT>=JBbz)&N78gPq0)Oq%cU_9j`OD_NnYxz+$hm^@>pHejOw zM3?|aoBjU&07{xAUZo~jpdVA6BwnQ;Q=J@AogY)47gC-8OPc=v{_@6Z0ssI31xZ9f zRCr!>Qq_(GF$_y-n3kEDnfdZ+NoA1pOi(z*^1#1A3GYOdSsb#v9CJR(p? zXUV8sugq!ywOOTJ9+7NX3P}0W+9+_rnBWCtea#ar0yeJp7hf=Vg9-n(Uttjrq~BD_k$kT7A)Ut!O6S_Y(*LeL51HUiP4FTU{LB2RW`2^H>$gO^SHA*b VCJhtj8HxY^002ovPDHLkV1j5E_D28! diff --git a/docs/logs/images/logs-add-data.png b/docs/logs/images/logs-add-data.png deleted file mode 100644 index 176c71466aa38585c24af0869bbd0ab413af2d46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 399007 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%0DnTph*pZ-%^DxiLJBQQb-q#Oc1ba&4T0`+M5U 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

6HOH2Iec#%8Zs?dBw$@(5kob%H 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�lCb(bsAC05jNSS;1Ih@vq{=OKJ zOVSdo^u$=F_tuh{rI8Z|Cjn-Bxmcm86+g^h*2@5GkjcP8Mj}0x^9KWnUz-5|_k#Vm z8T5j-YKJ))F^qGh*(gjvcx0;E@||!>-bQ=-+cG|*C9*UyquaLvH%I^UMBm{a{n&gHD)KklyM$y5 zbn6D&9tkye3N0di+{e`U%heq559e1=6vGwLH07$PrwX&Rj>Z{FJ%HZSR_r!m{{XL%{()-9o+oMm zP+XjD=@w`e{|GaP!Qc0&%i89$N&Au3zAR$1J?QarxG>)g-8twbvt4L>6nozki{qg2 z%>G)n{ut57iTl;JP8OSSWQ)k!>&|x9Y{5&rOqWFh(a1kB>owbPQp;s{{}K~?JXd1O z(EQMbyX>_yV!D=u(QBkTKF!H2eW-r3^G170;ef4h8G0FqARz+T5Xo#i@e?rljF$#L zyE^B=+GV9`+8*tLTC%>)qU&8MpLm%fq+;LaF6zh&>n}MFLH2oZS9j4wFHBW0p4i5^ zti%jpM^9Z{l-Z@)X6 z;X6nzRiGU=PUqU@k7qo01E*Lc1GoK}S|Kx>_QQ~&shv>XV{pGMeIco=Z}BSGNn^V7 ztnx2wO3o8C11a3Tq|7R-#V*~^t9^pKW00-d*r+bAJQ|5nCVwwvJ@3YW4eu(O*r-@* zNwv#=$zu11vfO{5pY5feDSylNj?FO4)JECi#e#%YIc%d?8jI=dhtKfe34P#$AU0^H zSIN+}A>fO@4*iaHDZt~cnNy#T^(BV@Ldg)#9%sGOQ4qQOjQ$oxc9R_JcM9P!1e)hC zb(4hQKNgQZ%92;UuriM%P%lI|&KfT<0jVkck4MV@tLfl0X(P-xruIwEN8|e~#Y=)x zOer4?!@TF$mBsdbsPi=pvYu2l3}TaZhc!`iO>IklI=(!tBL(V7sDy8yAZ(82&^=pm zF-O_IJa23g;2If6h3Gl!t1i|j*q`sr%qajnhNU|eg@4AzNbZZg@YB=#uKFz@KHn#n z5g>HwX|K@`_IQSlY;u=jE`@ggcA#W_=m=XZemO69sbl=5LROOKO{R$JNWv8(Hj9ut89U9U~321{hWL;L$+XgRPv#S(SVp z)4|_`l-je?)rdeaEJFB>S3NzE^Rq}SpMCX?gUw8_S&->v-@Nyxc*SD9>t*@G!Aa$y zo+D1KS(sJe4~suT6hY!A>&(!-$&y;vn`VSug~}8Y?(QU_OreEDFmtNEk-u-1I^6DL zeMV4?c3f^E!u@(ibfy)a%kB>Of+W5TKt#hcHN|tTxjtG9k~(#|_4qpc(~)MV7EMJb z9xjiL=SiDUKwbC2f@t1ww$@VHJs>Vvump6)oHp<-lG-^|3UMeed=soqI1J!krh_?ry(t8RY!FetByV#e2F%t zVi$q0fNx&G;uK+h=swZB$LY%!s;T~wy^ty*Jh^2w|CD+)IWt1a9 z9qDMO`+wTJtG=Dmj$Botj~2+~3v}6tOtW9>N}x#ZQFq>Bn{nH#$u>1rxQWS@aOiK9 z3gI!d_Y9vqrc-BQFFzsfJo)wJar*A`FG=T~#Bm%O)+&|Wj8rT$)|Ch$K?pfQyYXF;E>+q@D-)KQ z(hhhjbG#9&!WxUBW-wk%cb@PeO<7YfPA)FGCmW+BTd(yXm$0RM!tb#&7pqgt0@M@0 zRvWXI8brI+nP1=^rAXh2_>Qc&E zE=E|aq)i&jH#2h7#erUi)&^`_YAVn5b89uv-Aq14Cz?|wbxc{=wbfrJ_8QP$uS2uM zOPfiFZ})>rL{W>!yfqA;vjDbAQG7OYY?)EYRbwzvgMd%Iz+3yiU|a)!0!5wOJea9< zd2^<+VOq=~x{DuwtZ?61{b?L2tL)Xt{3#5EJ@(9HN!%_y7qYoISH%MTV>2TdQ^MZo7!gt{1=^mTVbIbk zr*~W)Jo4tdISZ4C=P=>?*hz7C`k-$PNMvS8^-(PJ;@s9ly{v6sTJSPVE(+sprTmF@ z<8YN?hnj*a3)H#&FiZ3E6Hh8P0@RsHAMylF5l99<9{W&tXxtI%gtdYPY3Fq9PskWR z<<1p7GK=Pd{r!G-VvO zhG6r*GY#%ZFb=Vn_tcBxhd)znrNw1ntb~LK#ALtOv81Wda0?t-&XY*lTpNUxht2I1 z$hv)U+!#hSUY+fncnDgwTY4T*OvU?hfXM{#LXJT;Z={N*+WvDdiOs=sBs%Tlt`GUO zeR1=ea}#OGm$4(xl`xm?byuZUT;LCfJ)3s!g3bV z8avW$``TGRn6dS{ag24uQgEcmgK2vlByury?fO2FK71FMTQ_2?!X-xX`niC(GRAyl z#z^L!!}P`s$tc?iwI*!hy)ov(8cMrIGIvyZphQqj_|mPon(wVX55j)?`P}W5M3C~w*$F4%Fy&rREpS~?E zZmLUvI$#>07U*4F%G2@fQ?0S9ll{=w?jr4ac|?L!C`vX_PRGNvAX~#}ZIJdN^!@qt z#G!zC^c1C3m728u`DOhE%qEj+@kUj|KUy2m-{{Zb0wlOxZ=Ome zx$W*pEylt`^Z>T4$+T2@=xj-ZTA8`oyWgK}6(}IGhxs@orB%7gJsa2*G6WNgtFv{N zbgMO0Z!5tc?a_8S7uMqF(5IRFZMO#c%_UCe-cy)H5XWLF0R~IB?)B^D%9R#mJ4QPG z30aLS^JDivY*WUNsgk$j4SwTn=d_+N4g*WdB-Ea!=1cx!bgo|LU>5`FD+QRKV1lRH z#0VIpBa+A=WkfV zW%+nSIpmA!h3g%)1_r*iM<7Y4-sH>H6DZ}#%UP#Q3&+8HO$~{TGs4AKmiOv*Y@nE> z{4N6H%fa3?aPCNrVh#P^i}a=pP~;E*DmyqF=EqM`FIg0v0?AXPdp8^vzzRn5=fo&` zm7B5R-jNy#i7>Vv7jaZs4XrfuzZ|grc@Y2Mdd1Izs-!i4^5Y-kw+;_jp`*V6w7RHS zklKid{EhUkv#|hBo2K)7K!+(O^4M#sX(;hZJX>K3ET1cQ>v&tPp0nnvN0z&DJMli2 z)2w19cf@+S4dHM__U6iQgnO}Vxm#rk!Mx3jrOmpF7m}(`Z|$}6C!x@wvjO&$Z9z7; zt*9`Q;+OYjZ(uEdWq1QfvKDD>S)aw~xgBRC@ykD5lPg*FvLSje>N7z&NI|dv+z)c; zN*|AgchUOFl*BP);di3+=BOE^KZmXo!yHoD9vO^4A?`C%%2Dnf9zLCO55fU9zM!w? zH9?tv_-|ceU>mf~BF-KOb276~qgW{MbigU|Z7=@kbKn<}i>nAxm+d$%7A*n}CNqYB zf4e-u@QL|{s`l4!=^AW$p|hFed5W#Wc-b=FX}{ATtrm2A@imtWVBoF!YWh?0(_oob zrw(TM*OpOi+7IthA7=7=0vsAs-gw94q5l;3IR_XS#Yr2zA6?Q%eN;hggDo>?g{RE_ znUYPW9z^7Gm>>o2i?UXFl|Nf?3MX`DEVMo8YSP>`j-oU=KLYnvd9tqlRh8Xt_N1dMV3y8tv}5ysy-~J$w#d2HS~OfCT*KqqMtkAXsACb?Zs8{44H^sirUnCQ zTtI<*;;yl^0Jt3?ms|5NZk|6-RAP8ryUcsx{`BoQ-!e2hiFaf%IZ!-?Q?_~JU2~PJ ziLch+me$$g4W#v}mz$v3f9B}%`VLLo72s!lZnd8>R$$Fh52GQUuoFAdnbGdqeLury zZhLaHcG^JK*BAems5NY3_4jhYtg8U$Anz%yrB?NhK9zR(fyDfyudjXXgyA73e9m$k zv-y4m)T0jd*>s7ZzTtiH&B&EUR7DAR*+?Hch-xO%cl@GQKBwAn-<8U8_t?_d-7QuS67meqmPb z@^;`hCB>hF$}hZ_-=-7-@!cn$U^h4qW)O zRql~TFF3)psv{yx_jLO=URWdF;B7W$k9i7k-L+)w1X zMa#A~?|4I4nVZrg;-qoa`?-ZVQ#!JN6X3)7=XP}EyZx%euHD>3r*UshJUit)mLGG# zG=xX@o>+G)RElfwBb%s_yRux zWa-4>KOrcbg}R-iRW}J-N?g|jF8j-tu^i&Wb7x1L$VnrswV}2^srgorhLV5{=q@sc z)2#%%efkfc=XJeCk9g-#B1krOHdSkguVB6%H#ou-bnjSGURyY?dz`~uuKKDmpV%ABrfCfO1*0!m^VkAx2xF@U3 zyOMLVqkMM_g|RDWC}y{dN6b{zBYNJSza>vb4GVIh%cGNJa!1*idleVo+Dw~wNKxJ= z>bvKIpy2wEFiV^;$%|(>j7y4J03+&mbHR0*gc$=~kwpj(8Rl-$gL3)h4c_vwxwOtO zim18M49SRaidztJQ+>~N?W&(bH&6kIl@L*j5=pJV&*P0$I<7E;53NmE!DDwi*^ngY zg@~Jr67W{3OdOwA^0#DGqyJHJmQchyJ*+$RTNkQi&V)qPVfuD`PV7)Rzj3Xhw9Qpi z&Wb*8O#XqC8cD0UBDd8C=gudl5un95K7~+&8f5PKrzXDcE4^m5XQoV2%3_8E9G}ru zJWNt;%U{T|V}ieH4Y9F&3hxP8bYN+W${vRUp+Le+6`srK4~P1~47C!qT+hpqZ1b4x zDT#XjZAyz}sI!|k{fDZK1J};EK#L4}y@;*|N-&bAE2qLu6}k4hW_PVC!VG`|ao7qd z%yD#6>Vx(M%3ZO?(oW~gQOiyaDN#V3gL?v0S^20b==TY#0|Sts1eNBiy*wuF;H>6PW5;Yr@!US0~`JJ&*7(77Kr*}SNADooN&)WM{9UZJvGaFJh# z7J}`g=(RJ4vfP8e3Azu`Ff<5I$&*GkFD@%;SB03odO`^sT?E0L37szIbvX;xa^GfE z_4$Kk-5Dx8OGbk>tXXBr|4Dg))Q8H@7aRMHh<^vmkWDWbic0F7Q2qMZgA%JYEx%B5 zagrzEE`+j6UBBkGV!qtgyuo{;K@16IT9m?LRzq=>dd6%}q>_XmI_?!fPGoQeyosc! zRLf3bm$A3s-;>2L7mlNShPuUCkd#=?)A(u*k2s1P29~+ zOxr@qjJ`aQj>?w)Wdw&+ON;^%0foE+hEC1a%{7wE=81)4Y9zw04<>o&HZ@LZyAPHq z(R*su>UfiWqvI|^#pK4%a>?pTPKPSa zd-SKcs>4qn)x)G*T%|hizEU(hSbMZTKHI(ciiEZXVqDmqpilblWhH4-FyJ^|UF@|J zyNh8Nk7X2l8i5{KIhe!|<$NZLT1ldTJ;&rw8B7+ouilKmoKNqU%#!a&S`_VKg;~sD z5&Z(_7!mq-T#nX?moU~-u}!z5r?YG29qMUgnB{663K1c1(i|lnQbyN@j0`Tr+XchO zoCT|qVhrOLs%>}_FJ6dUs*{d)U)#~ERoa!ew|^m2oDQ$Yb-P#(rwLi8=2Z+QfHE`=ba+oH^_(Jk*^QkXj=k5h^(Z0*Zk%<$Rij2BI9k?JNnmY!#j`+2B%(GwC48-4g zVP3R=TcNfiTRQcm=)!{&|O1A zh2gs7aVM^W|JK;YH8~tD^&hp43I{~cgvqds$wP^y0g{_#y51Qz~H7~~fs$sLT zx@7@7KL8m9dgs3}jXM7VoDht>5e&DQ8*B@ZgWYt6g{0VK{pnA64tb zpi%WLvoD&A9jGCcWkJy3X1j`Gos;(t)U+|QUikyVMh2F3k?xco58z1zLEmVQJx>6h zPWDwJk;>^d*Za?_49Q^hPIqE+g}EAqqpQT<;&WHN9nr(|qUlKkileFuZWs^I3=Byp z*zgMT#~LY>ce|_%o?h!J#5aPmJ?3NDFXzf$>oXGl#lD1w_xV#U$$rpYLokm{Q?1@6 zrI_QS<;&eWqurpvkw4B3GVVr$m#@SnZQ z=gG)T;aJ#mNFW#&VKmlokMAH)!u@mXnd31y9t9EcgbF$rc?;@yf#U@jU_Qg%cyX;S zpAT200i*B)R-%7UoaMWhhA?n{m%7`G57GC$z}D3^PN4tMHdhu9F72A5t{JHyS(dfBUOsU}($;Ze#%8*M^kQt=S-@owCMN zI-Ua~U!(rp+mC;APO-z`z(x>+5k%-xUh^$p^sqYlJtNlNh^G80xA)$tg!{i@i0w=v zV03jlFda3mezp=gx*Od9PluctpZwz;*aMy+4`!E}98~(r(TgAet#nnU#N&n!OyUri zjw{D5&^jHKK%F}s$;MF3(Q|~ff;!`$jY9%94uuBgQxGye;e}F)w{6~7#ImqBpV)MT za+W46P{M(KX}d3vQ5LJ!ie8H5^{*#B#K1bb~55aDE?3)b-&eiziznVl__Q>0C51GO1|482PnC=nnB#-kB zw`L6xdTG{6L6UegaJBvE+$G7SqQ6+Lbnrv#W4!c!|G-cq6g0bMG6lW^3MTlMk})On zmoISeZr8^u@7!-lH0!Nn3N&k8PfRfM1EGSTxif`y?6-rJPQe`c44c0a*^j_ihzB}Y z234kdSl&PryTCj&%K>lhSOSu6K=>3`^vxBePyd9YK51R%SLI&$T zqO5ay|K~v-iQJ*Ir~-`3@WQZccE4a?xyKb`u!LRzy{7XbAQ@H7SRLK#4#C2JRk@1< zoUW^~|9Ozcd;K&2zYo*>n#IGSzDeqTy}N0cgsYM(@aBHv8(0_)>HD~zwM+0{5Ax!! z5PbLVNd52S)`4(JWB=#feZvP|dETyl;GTYfEkqW~(#+4ee3T&gp9gvP<_;J^`rjt} z-zI$ZzfJhRNcc}S`ClabCw2TkoQ^ZYRQDb{ARiJJ;#d4%YQ9g^4<7w5HUHn#hjL_l zi$PIT{GMmwjJlrL%3g4rqjXvi&T~z1^EIEPRc2DRVt%`EggM8i8-GV1v5@Kz!Di5^Wu)-j@y5R^h^k-}TWkMMxD&;{J5wQVL`_<|Sgqk=S$KZ1GX924GE zWMET;=CyB|$8))Rto%{U#<^Zv)H?FD0Yk@REzo(U9%I(Z0OBPzp0h-*JU4>UWRTRZ zMwfbZUAs3o-dN&5H1tr2MQ%)Ew z1Y!Pj`%kfJQ1UjFXiE{?9`v~hC87; zvxM&`>rA3JvoKCarC8qs-V=x3EXFr4SX=BN`&uhvs%1^y7JQ4Egaa^3W=WXwPi@EtnG(U0EqNy zSIBk#gUYssDB?HL==2(8QuQ4bbY`!{_ZdDZY-{&vy${Rc#(G}xfp@O(k;qUhfF}6g z-xbpZ_pc@oyqcxm7_5_F--x;XqIvx#5&su#KLGjvlWlDwC@NbwO?jifGN3a|L;+ai zrCa@vS)ijoz%Vxp>QyTJ#^jW;Pc!7@9hm`nl>Ap`u#dhkYuYK*tdx1SG5xD9a>KHi>@Ryq6KIdpJiR@jW;tNTI5A$Dn3tME)~Rh}*Pu+|cZgXEP<5H{Cf8ViG1RAAJUq?z4s0}3+ZsOnBii{EC z#6BZt>o?M^%Yr_fK`7FXYYfjRH69&1Tslx74@#+ZoE=S2-G`=dTNk`;)R8vpWN z1L`K!6c2*Gl@qp2W#O9(q-zH%_~txQ4Y%~pe_k?K|D4R14}GvI`Q%}sT1U}52mrF! zH308$zx62VCktfUdIPV(`^8^GSQm1>`*HFj&S(F55PRce=f*_@&$U-=DxPZ}lc`?m zggt;)VB`1VXBt<~wG0z1^8*Xywx|;%lJMHJNc6#>>j_7S;{P$11P?87EO$ug*-(F$ zy-Kc9X{_OlQD0&f+B+MC?$5@x@Q=5=(TabbHNYj3i@%CK5a~-;e9`~eyL3cJ=e=qO zzgyLvy~>l~pNTb~jr^Px{~{PXqr`e=|9qOsau@5t&VrY=0)QmL1xYcb>Jn&>q?6dR z==95Bu40Ob*?_f`o~ddQ8RX2X0YvSjZ7_CGt{u%eJF)r$V{0>2P3KVMmzj66z3h+B zrOw-Es>8nnPdL~5=A4v&;g8*~SSMeqR{nOko=NP@V3i@m*J6Nef}gU-iRw)4vSUkm zjD3>LZ2tuOAdvI3e-yoY*o#b-%6<=lq@I4pUY-R5q@prqoN;^$O(Rf_)+y@hMmeFg zdN28`ay1GBFGq)KRo~2W+GiAzgBenp#0;95T=qM10^%Pc-q})9t5jeEr!~JrV3s&0 zmuC*ZBBSc(YLZY1IHW*23oQ&`(s$~LWqlGsD;KWU=1)~y5SqhtyOKYJElGX55~sRU zb##8PoB}l0l)~#t?l&po3LpDHrV&)H+B0NY!LK zkizphjwG?F?u`>ssge!RF2zrwk%%h!dg#|gw zgTy{817=CPSk8OK9MmY&QI2ystRdT86lJadzyccA;dM5lm5JFpBZlL(bDwF^3a%*H zSUTv`c@hYr+vg$Yz5R)OeQP^Bmj+x%nMXaz<2B}AKSph7ru9&w2=*GvB;D{=puyy` z(Ap41oKdBa`W(#Pl?};DV0vY!Xep=lA-FF~h~Q#6di-z#$mW*KD=5?}O-*S@b`R|d zrzQ!ALK}uSOfCn1stW$HFbC$H3JKnV@#9+LOo8*a)>^>ik*&~Palm%lXY5Wc6aGU+ zY>wKc0p@nLBHLBEa#i6s<(i5YYl7j=?mKb@Hy`y}mM7{O&rsS_9x>IYUQ1d^IA!gI zn8Oiy*U$ub{0_Q(XZR;r>m?kO_X+GPEqKWh)M%?xlTZ$fC?N{dPIAxc-mnS*e&oN&O!g=}a{$JZwDF`dTs* z0&R#Tn&nnQ%ADV*7~cMP6VRF&E)W|T+-7^Y1WKrLB~BHy-93l7hTEGrQ&boj?HNq% zrGr(bm=nr5Y8fPTCu-cwEc1nLXFFbJLFaCKVD7X9%OS%IBadw!5a=d%$!ZqI+KT54 zptY|9+=)Zmn$SA*)9}()%OeclWXeQ@juy^Itukn&3;AHmhqWCq7jqJ=&d^-rGK)N= zRxNoklB20P=Du?ZqTY{Nx}yA!>y`aJAmZ|#rTXx`V}@f?{liNd9!x7KA_ZQjEqF4C z=-`d9JYfWsr4db<>aE5^UwZquPRDR3**9*cx3hZxAA4`vlt}2@u@f zg1fsD+-?Gdpn+h)-Ccsa2Dou|cXzilSuk%_BF|C3BYjf`x8&Nrka&sLH=ONQ=2|@5j!s>WlJ*!+rXOxE3c_`V=#zV=Dun=uPz@)v~ za`=_iyaVpS zDe~9aD1f@2ym&yj@RGI;h`{EM#I&F*oj^z}5k99et;tG<~hHmS32!_W}iodrmJ=i_NYl(I2}>?*KwVBVKd>ce7F5BlT z!91S3wp5%6D#fytx!0Z$^wYGuwMjN?RX?g-hm@2PPjY*ZY_jPrm*%%9@uI0Ni>54y zv1rsTeQ-&9>Ks1IMFgP|Q9RdHN!y^E%(lw&m6RHHG~=*u4n#SNYo(A#FCWT|ed=>c z2aJ{%=E%X7NG=pCat;2=T4m+&cs&}E4hGO=$m5eO zB8}~aXD^`cg*L`{A2BgG;|tj3SVrYct7$eELAV@EOAwq)r;W(MpdQ}59O}Y5t4?9G z)F18}1Widf)=Zlgis=$m=L%y8DVi`-vla|Oqru?3g(qHxrY4buBhJo(fxyWjr+$m` z&3|%UiC$XOEC;hvjUJ9X=lbUG!RuJyjKAca>P|qm%GB~no=wLBw;Rf}lQRq^o z=xPQfT>q~Eah=)SN zpT)g|aV1}iC2fdX6F3`XVA2T*6(+;<op*6L$S(9Ds}`p;XZyJS0xD zo87p%_0|-X&4*;=BJhGw{Hv0mzvEhM7JmZNQ1VCB02uKfzN=ExJl0=5koTPkD%CrT zeJ_65<_SDTRDN^uh__p={KkpP(Y=Wu&7MnA$Ff4Z!8<<4l8Vg|i82u)GvMEQhBI5Yom! zk@eCTXa(Dzk|F11=xEjNzP)&WAwx5O5r7c)n}C3>U&XqN)C}mvmQ__F=p3}IQ0e@N z$Lg*qF!e)2J?4Fg$YIT!^B_%gVgYQ~FXH?b;fwEJWGyyyLtJc{2PPl;5QXOH%1ab9 z4t{ocv}YPjL!u~%6M{A!f6p~|TauKfGM2<^WFDhPZezqrLl|kFipTL zqZ4r0*+f_+k7=zu7)o$S02!x(y%)R^0u@m+bs;~{FG9tBby!3EIdvH>-q55Yj?~Ai zr*|tQA)b>PGM)Dj4bn|%&4C*Y*!~(X@*~mg(&BD^zx!X(&g_tRSXY#XkGZ3TxBc#Z0rgsxf zlTCWQK4ft(-5Zq1cI0Y?sbu#T`{^$#ald|9O_L3OJ)IJh*$DUD}RBZdGN7oW8xqSI3fS;_~6s=v}rV62U~=skjn7Dt2E}DYc3EOoAy-qtgfVm z`AJy`^OH*>`+0ecIjQ~0o#0FM4``~7&9D|{1b3=kcvo#0Ol8ti*2|vObu?(E8w5%y zguLjMGp)a+lvSF=#U+BvX1Ys3dv$5`&rrt`j&;>mJMj5En%`y}Wce4-7n+h zwzehYQ@KsYA@ES~p1;x{TGLTYHNoPiNk83wyEB8CqC9kC8snVWQ#V?%&espwe`}o$ zG6mda+jWSIV7FzDNC$mcCQ*qK&-J4=)m6b~0!u`X{v$|((Y?n(7_6dET*td5Hq>paj_|$r9|D&7v z8kDwh5_ZCb6%FE3RCNcl$mW)h>F)mOH?GUulv9zjt7mjhob!Rf8L@Jw*pNihwqeQx zu&k2EMsw=Ik5q@3Sxz;gkdzHd_XLPNbD(EaDaYPhg2MUE;n4dl$Rl&!)Lf*@O{|~C z$Ho>7>#`wxeI0^qUsgTMi0W0JwMF&JQ%LdL_(2egBzfs*#wENVqknItbI!PQJVq~2 zixqRoIcYcr?jbazKo<@35<|crDl(b5h*5|rR7b zXDG@$_+)m?HBO|LbzT^ZWyF7A$(wAV%ZyTP_ng|fSbEbn;7v1T*(F|M;nBo6Z6**s zJ#V0z3^f0|;o>u~o4ZF@Qa|0)uC&S2m6P+5!_!L2E$m00!GrP3Ph(WM*cQm1fMuaw zE!p6icVj_PU#Kfp-$^IB7!CDGg!^gx(D@6+<7OhG7QlJ>L8LMZ5Yi201D@ZPTl5psxE zkoY6FUvI}FDQ8O{t8;#|mzF3JV_|9@bv!I#Fi0fN#sVsE%ITCw`0J=Ckd)(8Um5hM zrOXj=2|0tkH)^~;xV!pVi};XxgNW!wc`0dZOa-bpG$3&bbCqlL6K06pOo@lsn0QnK zIG5vNcI_N%sR8C%C!&h6k-(b^71l4&8uWHnV`@}yV>+uJr6}>5pLv`Q^U~*>h%`VG z->3F@jj98`l4PGD*X?@YclmE&F!Q35PeJM!&&Tlsd;5=pPQingR#*og?XN&ZD-2gOqA+22}St@fhly?DdI&V zgJXSTqI$-~GsqS_;%6JI8sU|_HJ=Twj2qN z&?U@uK%+)^3Nphi&GO#c86@60nHQYAl`#l$2HpuPg% z%drz4sFv$31w*vLt54}{Ma@+)MF|?k!627?Rv30Cm0!78PHRb$g5R@U{2iFEX^DpQ z8Nr=U0|DtmDP!hv!9IA*Yk(zc&;PjVFY6~b^i&BO_1`C*9NgkX_7S_XcS|i=-@vbv zY+@HF6d3#h^@Gh1Jab$5l6YEPPEJ)kBkkpEQoFLJBm}muAB=p3fZKW+3*`2ptNw|< zjqr=%-ZGTx_x$0&PaQ0zIq89E`eD1Xj2k#2VT^6$7zjL`mkBgXO(zDCy&<~qaBLE) zMOo~#a{tZf99`(m({sk+p3@1!FK$q%U*xG0OIJyT)&SFTV%RLL<5pCqJL%)W;T$Vk zL~;d^a$4sH-cv6{eNEUo`;g{aA`jI)(a)I^=OAzqS|?W4rG$4eW1ANu9U#trs0M67u5v`d!^!NHxDTXyQL0>uDxPn)Wcx_d>yTZF^l+Sx<-;P?_1 z1L(@PdgqUf+z4_K`O$_5Z}S>a40kx{unsf(L%XZLF#HU4fpLJJf!Dhhg0$)0bBJ@t za`N9$8p>j~=z~+PH4$|`>mfx$nN|k9@SGg8$jzSZaLU~}1%}CS*#WdqwSFFLnjlOB z9bzNW$c6xYB_s#$=1zM>hH;&2IYW)H(vo3MyS#Nt$HIrw8X(_hG}6B7)Oeu&sC|SS z=exk;_S_>H?HGA?M6p4IX1DT2LNGqqHySzJMSiqRvczx)_5kDj*>q-sQhNP8v)o&F z2l@jK8&_$Nz_zcLv)=hq;U8h4qg99g+nUwHK>U*O4<}z6*d#NGMUp!>D8#C!Hu!`{ z6Bp>f%ou9E3~hS`5;Ej~imBc4jfk8Vm02MtZC0LXfg#Z|x2!Jf$*?V(lAniH6-|Pn z<$&Jz_aaC?cC7E{W(m8a8SX>f3f3fBr9<7y4nUy4JC;<%QB^R~z91>@*?D4R`2dBydpD$`cvar4T-e!K7f^=euGR@I2%yiG`$f%Ky#2>n14ddm)`m-lM9X1iG$sxmJ78<^j<~PY3qOCud>Bq4Ox_ZH69Q4znXK zF>0Z+FE~fm5sZfs#1| z%Rj8527H&R&Va~@z+9CIJ`w&*;Sp(x~nWIMgto~&X* zPxMAPF;1NBG4l1#lHF?L+SX@a4RUxrFGa+95sQJYnlxXS*$-FGZ#4H+f6;4Y>`yff zmUFEz_tWEa?{6fZ`TCtNDd+R%F}Bv*8Js^j{jtzZ9Qy9e$j#K8!&>=s32wC?^_h?$ zOe6@!TJ2T2+%-vTX)JnvGAhyea6;ZmJGf|m@GH>~C6Ee$7br<{O`pH2OZRB`cIpIJ zclO*G4hv?YESXP)ys$nSrdpp+GqJvbm?d*s(Gr}OQy^1S_B|J>TgCVu6`l2o3sRgB z0SU4sUcFt{yEe9;n_gueyKv(4;B%eQ{=1tw+E99(4`9L>Cq{Z*&y1qeShfV|cpPQ; zquJV{8>`tT)ZOUHjE+vqaP;!$(j;cbDn`=XUT8At@*yB?NF~sqimHZq)3-y$VU%2Fokn$4zlbSQpBN%1LgMNYh~(g8z(#aJe!|8Z1uNOUV!% znKyS;?! zP7T!I;|IY8&;&0+N4ZO{LxuP$*)qrNbAL-*IEOn9wMm06eXCSCjLl=$%)kHksoL?$ zio0{Oxc({*K60yYef=Z%@SmoEU*+uLC#-A{nbz|;l~zJruy__27$N2EAZgh_i9IC3 zr0ifzVZ7#xKbR2*9hH2{(B6gai91t5vr%ZOlLpeXr}ap!;30K$=AITMzVcU=(E0zf zgnc>B6BtGn?}{$rEd@ocNkX$+scxN+u^_%17Wue=^uEF7BRrU{3l;DHMskTH*xr&& zyj>b_gUvld^!0h5bjmqy*ln&K1a}IL;(b61=BIo={L>p6zfE252t6DzkDM{NSAVrWwo`qHUVL&-aXAAE^zBSEkrdU0~G(125pEP zaZE$yHdK(j)&3oe;JQVA6uWTP7v zt)#&7WtjYn^AZ9$n&S810V-$AY-}N$#p5>`R;!NYIiQS)aqncj6suJKrQy>4_R+YJ z)mZ#@LS);@*UW17voAPx+c7=PLmy{ub9mmKqR{ANHOn#rVR2;K*^c+|a&JPp(V6@?OrWzcA1UXYXggoY;|-|_--Ys6kHS!L zTQC5BMI+(6yV|PKcxmiO`FP!QJ3S@yI6YOWoIGD=T{uyarrUHqdf|c#wm6kpO^#*T zb3U1lN-It4n*d_7(aVQC8fIQKBG#U3cS+*{+o>V!K7Ss@U#|N)E-lU^a(u@(Z!E?) zEyvrewjdk%wK?|OE~q}(!kODKX*T-bU*nNBL8d`A2jcB?Pk2@i?@m7sk=uPm5}FRfNeyC#0VPQp&@8zUEKZP1*zx##N=~o}C(p~50@dUQ z=+=>8jK%|bZl7(WqopPV%1DqGH3prU%Do)UU_73BSj`@WE4j^v?A+%8Ou2$JnJb%% zPhv?fJiwAyPUmPF&%tyqN)@b3x{B`2+kuQa^^*42c%sE>r7Xo`pi^;=i_OgP)@AyQ zlE++ay|>;Nw{%o<=TNBVc_AA|rV&Lft4%<^dN@Ontgn4mD9Wu0uX=m9IE*sr=p@w+ zJxVX%tvPWdB?t%#WX0ogGRMT+;WbZ&gYNIti4J8onM`hfZuQ0(gJ{#lc{uLDj~34T z`R;8@dv0A1K2jPQKJvWb{U>ju4bMR77^*0}A0VUF^T#VYRp{ly`f4%4#;EA{$uJy< z2mhFTO@7OdDH6~_*%^XHMWbDNP$07-DpnjRpee(re?rG|rWGlFDO*DuL2xfc{mgEW zP+;=;MJ&@{jC<_F{%ogu)~nV`cfRcv1^^$y;l(V}odD2bwc~*OsT%EFro*3ZSHI@TiV;FgZ85nk zmhLU@cTm>ytE^=@bv+Rc$~0na@zaSV1!EKU%F8MlE(`1DsKZi2sNKq5!dx<8MU7l5 zhQt=F8t~+A3G=2bR+K?dOkQd3io7A1z8+|u6oLm@pi?iKM)2)3w!=*}ogIO@6(Lqa zif!YlmopBesgvw+<=@WF3QF&kJ(o5_sBWL}ZwmyRN`$5(pnyvr8oJa^PQTKMl$1dS z6@_dkU7F4SJWP>F!}oBglLq%SSfw$vZ%V?3-~kTkq=nl*kpw(aM$uPAC6f)t+Td84 z7$gx#Bm@(Ojb)E8LeGNWOW6C3YRprkRKxQz#GR46#RfD~l-Zg>+XqGfe}R*=pQ!C& zq|!KgWUkg0wp8!8e3=wFpAEZf5TL z5M%>slwp3GjNyZ$Hnwxbp-&T8%W*#zeXe5+0gpk1?wR~PzR8QoFD`G;%D=l1Y_)J} z?<*Y~h^SR>9-Xvg>w)NXbHNyyDicCQOv`IOs*|#DteA+^_9$h}HR(!#eMad_!fWlI zl`Z71kcSfk9d%P#k0M1TEvWS{lZC0=D^<+^1%b*d{CqMi5FX?=4Bx{3ni17LH=`y!B-HG3h+79DidLaFDaRm)lSL;3y zGOCF`V^Iz0Tv;qNjyNZ_J_YTvt^obzH&$?2#CsP!ewE*9>|lWLxWlAGQe4yr!EG zAAZXYXdtAMGTJCdC5L!{gW{v)V>40a#7wTcZ5-~k7dAPS%38QtZK#9kvK{zgwjN6|Z{!|e5kc4lWL)W$a zw>*?s1um53vlFh@6Vs*FCr%lp7(fVY2iYEoS8n1OBbSLbK+;>2Jlh>&x~#aM#=G&m z9+*IRmc2p!3eny!sK$M-`ytL1$^>4f-9)?f982yK042?s^6jNW5whR5>kCAeGZ73D zKIOs>5FJu`%-se}34zPH<PYqgM5xRt-vk{^w@$`?X&yZ<%WLH$FC=tmgZ> z@VGt}3@~ZblV{4e{9(1(N<;VYIQ_hRbhI- z)h3--34b|UT^tAS&}YLt=`XS+EcE)7q#wLBs1pzD)vj<|@b6|mIqmFu3nyx+n}F~* zZElr%n*iXX?0e*-Mw<1Q-q@q3(=L>Bb|y%9)^fq>uC+kfxnl(ZDsW-R6^Y&%gKz_w zY7QTj2P9#tc6A%WfH+`G>s3W%QOp4VZx-3b!m4#}#}L(m2TQACOBUu8*ofSnr{Z_? z-1}vvw}DKkufvFQ)nB%o3PzFxRGb%i6VpSJGb0KkSOsti&S{oUE}rI2LFr6{W_=++ zEE^teBckC?mdJjRXUgbcabo+^+?u`ZMIvSDNU?Du-$U17dL?2-MSrhNPOM6e)8e7G zyf55eCVydKnrNsLiOrSiO1a!?KYn7kHXD2toY1PZiL*@&M%NmIN5o=~t6)qqA4)48 zFx~+7ha4P!NaC=kd(nQ#gZA82rVi7iE~epCE7vn$_=boTjak*_1%M}{ju6>#$DAez zV<;OUB!4XeU5*u^t{3s7qTVgp5oaQAlj54jGt?2$IdaokYV*Cb zGA!v)^_?bfGtB2dT)c}ZQ`hkQf-e%@gli2a&&&vJ8T0xo?=&x2ZAYqwk@uAjnp5Am zMJ(#dLwHPK3N@3QN1Rv#nzTnSuv0*DfLQ?JaQBZL=wczj4gW&9uuH)Z#-otg^qiox zswgevIX13+rsxD8EaIUZSStOQCYO236c2L9_F(=^GukcUl=dVQ(R&i#k08FDetVx6u*>tP9HLojUs%RmCCuR50gvrc?gjNZ|# z$OWPzN1ao`i=u_N$7vk+slq3p@jyZ9?U!z#rkf(8H1CiKKT%!!OgJ?CEdQGc*uFO+ zIcN2!LS1vHl2#S%2Y5tv+=(-^yxUO@sO>d4U)zrZ)V}rS)>QnOW1Q*otj=txkK4TL zJNX~eD@cpZ{FK_h7^IpHBT_B{5K3caG zEQD|*;7Rr)Xpjzyv4f4W!7B4gb1WPPGT~Hzjuxl(Lr? zkcp52n||ZyyR>er?LtJ}QN1P^5y79bEV6w82>nH^?=-RB{4xJSyqa<8!tlR4RVuRa z7VhK-;Z6j%^P}lm3!~&LK?qmwnaqJF6!aNI_DON+r}@l*9Moy5alI4A$?-}E%6fGq zql>lYAB$F288VUHgad0XCUC>G^ zvtC?zO^A6jg3I^S6pE)fn)OwZJVUJ!ZKZh5B4~eWL9MoIk&7aWii{Zr(gccL3II1q z0}Jbl>L6-`_uCT-K$X!fjHJ9nK+m7zM3?^TiW1bJLdYu@NK=di!~1PYNIbXoH#KTv z=$CC63X@V->FETXB9Li6+E#~t!nr2?pWjXuqJ`k(U*ug;9=YgD&~!%@bj!)EYP608 z?=6c2^yp+0L$3;;cnhZzy=l*(i@twhWBNOvjho(Itgb{awzzGh{G#89RDyO$XFTRuY4ypsBRM8xQmGF8DxyB$e8+>Me;Adek}uC7 zv_r}5aZb*l+Zu|=q{lcRXgnY5=)Cb`&J^3XTO9YJ^|IP`ua@OFhnI#g&&T>J^^Rz- z-6>6T^W<;=cLu_Qs=BV&`X+`?l_$X(zYf=;L>r(GHf|>syF4>-`pB)T)SwKUqb@7N z_oPU)VbSYI=PRWD+B;gP$!T=4I%qx(Mn>4b^VG))YT8XN))l$8p7#D;Hkk1F{^{v` zGMdVIC6x>2sBislKrC7B&?QjxGDc-R{r=vf@#^50@-)4sNvy!)Aggf5_iiZ~oEn2= z8)5CZhsz1%$%caiT1fyJET_s;=JT`mMbs>Ij#SJ_%+109Qs-~LlL6UlJxDDfuuK9p z$G(y3)u^^zNV?YCfoVJO3CS+v5-v6?tPM< zno3p@S3oZT`_o>Ud24v8jj<=3k~S$(iaGfwbx#>>6Mc{WwpFX}pA(!L-3}y2)XIw{ zR^R($?*nd$^!omoKZd47rwfKsjk}QTsP+-#rFSJ=^VvQ@c8#-7{*g)K73@oU zY~}^Bb6~SrGX3L7H)ua05%E!=O$Pd#i38wv z`?8cfev6|E$1D){Wn=9owf`LBS9yhZV3t&?5ts=Ke}}cn@3!p7bF@&GPTZ!r!hZD! z`{`N{D77d+KxjQXrd0_s!fXrpxlT1#5Z)(0vqDe!+*1HUKfLIdkYGkw0JlE)T9U3?M1 zL6X>xQ)(VPyb;KWvX6{Aq9Zr?rXZlJ*%y7Bi`J_!UQ1Lvafw4@!H=AX`>{lVLC=!( zVk1&pFIQ{;g}h8E+Iz7GBZN1M)c<}Ah3m8mgDy5(DKZ|tYO6#^4_PyPZ*+L?M2Yw`HZcd-8A3w8Oi^IZ+IFetgHB(t)sr0fP0MxWi>;jW%QW<^1AgFLX)h9yL>Y1uk)R@DXO`Zb*51xg_N?) z)~D~cqrVYlv2Qpq-h)-t%PCsgXie^^acir|40SOP+$6&&}I_owWmWi$I|M^9-? z;OVuR!|zeC%|fn_g}F#e-t_k=%#>!(YqH9;2`tJYJfr9RL_9 z!_wM;nTOM5wus=L9XEA3<9GdliS~{L23+`Tu&!xHi(Ne~uD6}0%{k^~2`ZJ|f z$q(qT!T-}?d#M3sZ9rY4wevhKXT>;Yi;m};cd6<@1b--(RH@V@->INssfDd-f-uU3 zL3&LIf(XakRsa(TPbJnHVdK~2!4J^+yF3Md3Io+;_5M!(x?e*DTuu2)9V3dSdNe(V zYpeP^nUlu~@)i+d8{$`cfKS=QZRwmAAcSwGD*N*-@hTh>-xvs~d!8sz5LYuCs1cNj zcNDhG)Xd}bVb^1Zs{BlL&Gh=1R}ML6cMJ*=%O0QZTjep*==1&0Ey13^7vKXLckA_4 zN)1%WCDx)k6uvXKQ=$Eu23GwKgIqkl|7)tzq6Y`9J@E&k3rx^LMnx+CzC^85A(~Mp z`k%EnbJAQ4IrQBHRvD|86qXMf~Yi$KxRRYAk->v*h(FwtE`&N$$XEBu-*&y)MD6Mf(RBcr2g zGCx5i7gtKP*Hg{#7GHP zg#35Z{!xl*Z7TQ5acMc%N7~WM7mOI!ou3mR1M0EObAUfb)LqE?69p`*r7lJ$6jZI)V0N(=C6Z zTT0nZJ4HaF7;|% zYJB1o)hq`KyJ0nk5qjK`SYixRGaJy#`oTbt0C|p?IBYxQ8)6;3YDKr?A3Yj`+OMML z2#ecf>hwJ2AO_yf{`}pDx;;qdI293oyjVyuRi?U>B=&vjG~!+R6;{xPK{;>(k?cf} z_Ts3ZX$i9_5AMs`Uky z4$~f(A}Rx0OC`gX*9AO-a=Lfu;^{XJlFMHJC;jjVBOA5if#0H{i|Z)BM%lz#q0WlLT;xmgR} zFv=9=^P6nTb@>h6Tr3Bn5dErO0zKF|Z^fz4o4OF}R0sdTf4JLOfx}b()Xh7&ZQ$`EqtWQ*gTu3CA61axQX8co{I=~Jof2J z?1dt!EBY;*PfV%n$9>TKfh~8s1r!^-SBKZdn#72DZ%wSei32&P-~p3MC%nxQvqeX* z4|v?1!Rqbm?f09XGO>~0?xuWlLTFHk?s4K2aP2!MmT3a4sMQ}On7NN*?Oy9Zqhx0t zjiV9byU+#yXuJ;pZHUh|{W1C77+=&wMC>^mo___=UP#mE!8rq+mgr2SI9Hs}wg%i} z6g6(U=4^4x{P~G*wN~NvI9C`vbO#`orv1Fv`pN?edu{cc2&F%j{R&5i#_)0q&>n=#k%CS^&l@)} zH?CKHxFL$ozr*G99Q%y@8h_pAG$=SUtz#sBQ>O!j4{4xa4mLH@eHUP8XY{dSLx>Yk zztaF>e7L+O-)vmpJN_8T@bk&aL*zoQa9I05t8t3rulj~3NUm}J<31P)or}E^bi~?Z z1B5rb*@5Hixjc2;z=80fE^-e!{}AHd3=@|BhO8Zq8FK9F8z8R9jIanJ{`I{i12hoP zs`-gprnh{8h{7~X-~l+fUN4@_-e1-x(AW@o&OYDx)1<+m z^mNv1XSJ9USBuYLd@tH-4WC`&wV1;0|92y+fHlvgXo4I5I;nd=`>PcdQ?Fz`k!PQy zI=X!``!S$1dbWX zRE+$-)Ax8mK`yD5G9fsyD=ykpT7a@Vp@F>YYN2vNLJPPEmmHQwClxEG{DBwvooC6E zFmJsLl??!1femr;4x1CiDwoP3g9go{T%ah_f3Zs22%w~XkYAzUbOCcU-lPfB_9=)H z5B*&j3EYo4UKfq=y67nf2jka8cLD|lu3@`KLB!32@S7iDqWJ%&n6u0+ z1RMzQb`%J+j6=nc)_MSF_w&TI?bb*3XRVnG5P@f|hcWmkNkE%T${#rQh`*|DGZV2>;`9WuU%BU)%1uqTUCq0@NEi6}92Y1{nee*fHjif2pA` z5}<}c0hmR|S8CvU6`_2G0fmV-5B@@77kM!MR@Fa>#~%RH;AaA-)0!ff+Vhdx0hRCa z4G{n4(IkurMuCnX5)cZ*WXk?%Es(p^bOS!PsWKY^nh`FOl&v%cNb~7M6M}9#b}i`Z zNRQtE0%q%N#s6{2?`O}C)Bt;x#&)GuSvwXS&%}h$tbEEXELCLo!+dwYxct1;D6bDr z6#n%z`vo1?u>Ib>H@K4yZg*q>mTmyeEBf`02DQUP2_U(5POrzzBl73Lr;<(WY|qdKf$*>{di3LxfG+jO!2cY)3@|+H zvUtkF!0R{smo(EO`fY}>v;Jqf;a_L|C8TJ|B_j4%{`*+4=ZhEmlTi$%?f{J$AbaUr(zo5f@QIk=ew z5Rc72xNhSAvn~VZW^rPrM|9x(@O_bu{NH0GAmYQKsOS6>u;v7T&c*+o5m*Sbz}CmC ze-2(p2Ig9~?QUrMANc{4^VeDjA4D1dgDQVo{YzE`{67-@zlVhJ-_<+seR#UOD0lYq zTcCE@mPKjcN&<+b6Yx|csc_kRlJ&sO?c-Ug33@2vwCLIY_Wz2>6JoTMo} z%Q*p%Oc40qzO2MFiR*B?xa!sr2H1v_1A&D=ZNk5PK3U{JR*NfVE zx}@6RnI1@|s^m#?LG)}vJJho z(@ui2=&CO9<)@UAjmJUoCN8|(#uygbcqueCrem0RDN#xgR+KN_nvkXL>a z{}y$^uQGMi;X)nZAe!GECF^2m1ZYGrwwGw7`e?etE>3I%EgqRD2w-w&EjBoPK2RId znUIm;CBC&kU2`DNw-uTDy|RiM1ZwT{3@AmTRZWy~|q6uP2fYY7`0zxN4r;`3UG3P(Sbl5}(n1kb0I} z7fL6qr9^Zm)5C#etnwVZo^7jE?ep=CTlWTi=hMg+C zsT!Qm^r0&v<50*Rilb2vluzeBYSfGiymmX`Y&>`bG83aa--`}DSWqrSb4JR`$c@wz zx%Tasw_M|beXUzfNAMtw9wwfEAD>%^wA)_%l0MqgU93HAyP|c;i5U6i zJ4{4cte-7b$6x&GN=JS@v?uD*#%?d!>>s2k--R6CmaV3`anaU^7A=j;SW=_fysB@! zXh!#Bg(Kp8!$rP9*udirR%;}s9DeBl?W4;#B83Hx^3kxXw40cK7;FfA;8Hv92@nYv zB!3@Fsj1j}cr$m#x}EUyI8d(ACKUa_x5g@N5Aak{>oz)@)&6_}vSMT26HItsvFWCoAr&(&-aqq|5n@Cx&7+3J4i+|jos$!9b>8=e}in-_kOQZyT|kB zVN(;sbm$VRS8Zm$B0HrrXeA~|gvQ6&dS`j#;Eui^FX?S{gc#Xa`L+QadU1WY%(;ac zLUqBU?RaQ3VfO4wk$}P_w({>!_q|~b0z#OQWcOz09KqD!is9_$$smx%mzpw93@s9? zz9!|b^6$4R2&iKxy?!$k%f`62=;m!NBtL*$7@KL>-}y>@kax;8A(py^v_FwxR$o6( z3bwRiuU*WTj>s&HEMPJy<5SD>nm{B0P*J%L$1M^zNP2RB?VG0{uuxFk`F$;T4XRKw zs*{`XXRmc&;akM`asRhrF{)m|8qh)h82Iyv3K|PlPABq&GB|8z8K6$u7p6}CZ&Mvr zzqm6zE`~VAkcABg_7O0fMYIl-&JcXRm9m1ndi^NXHO*&1I}rp7-3+GzT4 zqA~Q;de;w!?l>P0u8#x+nWpWF+9tMo2({Wcy~Z)rbuz2IJ$+;K0rKo9Qeg?HWdR>x z?DzkVy|)gls{7hT6;VpMq(K^_yF&p9sZBRZigb5_ba%I;NH>zwEl5a7cXynL;O~3S zb>4H%zu$LV??2CTvA1ilwdR^*tTFF#-}gk6PUCv5TCNwd|Lr@TA0jlm4)n;2hgCty zJNzAKBe2TC#5K!^mT!f1e;zGRH{3H;gF2p}4TFTAjn8Fv5{+}@uiTKg-}&aM-{Y0`S=n0d`zUuC}Dkia5mhz5^EMk35ctjCHe;i+$oF*N0tE_R%;ne4#)}ZGb+#5xS zy|71EQfd9CK`Gv<0DU5OqUbnN%B{*t5$xiX1yO3=2c8?*9G6J3ju(ONeg$Hp6^C5X zE+M-|dqa(n=ocD+4Ym@Wm(r`RSP~c@lg|5qLQ%TQf|oS>;O}tGV&>l5ToO6e8q*fz zYc`y9^|a}IlCE_HYJkl?$u0@B|?>zh#9oPii8pN?<-_qG48sS04{ zGSWrSXXwQTr0CS{%*^g4pR2_}vQ*1gCFF0Sz3H{3)5lGDfUOe34TkEc()5Y)H9*r^_ zbtl>$6f+F$aTzkU|&k@3IGESce=`d z;3`i~xidmjufo7|oOer$QUab?ncx0Uj^+f#8677cAH^|NK3A@mHvOIIv}op3-$cM= zrI5;a@nM2qcjW?hc_1drjKKmghWhZuZ!1YH&Dn16I*Wt#>bV=@p}O^4y!8k%!b}Ow zv}_i`LD>$8!Jf?H&1OMUH8%T~QLkn(45(O!=iE;DTramz(MF+3s9M+r^hJ1xoW8t0 zILPEP!q&K}5{4JU$a=G0_U(&IOY*8ok)OL>pg%jOJJZg@%YAlewA}L(YHkj0g@4#w z=V~o0Z0Ju|OnP4e3zw2D=-*siZ1(%`#JFGW8*)3J;4h>7QLou+R1iv*W?`Gt-TnX? zn`Cs1dKME1QF9W`1bHWF)e_wM)h_2hj(Wc~4=XDFr2+I@jSHY;n_s<0cRl`TFvYND zh+-hVTUVIQiWtho;?6K$b{66aTFV!zjOk}-Lh&?%Q9RXahgnu`=k>_kkKr zX7BTnQs4u^-{ner>qCaPy2}urqo-}ftqN2wk~O@(mD&+k13qnkRHyrO|E7vX)W501 zw%#^ClkQB*?P?!)s)*|>ilP&imvzPdZp(Wl5^EO; zs_#oZ39m!rM$;@-W6(A4Ll{uD(VLGM$R;Zb;{r|2N~{Wmd)}}1OE$po=EQBt-}T+& zC!`oBo`lC#nNN&J*&PX}mzP9$3-ecf6v^!CV=909*#H4zQ2)~$e&U)=GxF9RoXd@TIp?Vl{^fEU-rLD*fm{5j^Qj86 zol^oXw^j@iN!JW zb3UZU2C%ZNRBGe^v^3uz8*EnzN~eikMU) zV`2%Y)Nt%BvK%z3ot<}sQ{G^|(UfjDyY-30aZ7UwJc!#S|DBh_9saL5yA^ECj5t z^lQKI_77&wa=DWAam*JYxYIefE-HQ>vr)3#P+cqG$)DK#{beU8KuVSq9)hBm%xM`p zo5HLaaq5Ugr{)7ZuU=1RM75{u>}y?~KVv4^OJrpl_Q{cHxrNG|H(2zMJNkZoTizS{ zY9Nh~O4T3<)>^9{RKKbTxWR*KOy~rwsL8)j zzXG*V@ubZQYZt(R;0|t}`a{O*ReNOcwIW8?ShH)-BOjkVJI!>OfNtfPI2Et&WXoH3 zL*eE9KKAmoJBY*6;SMg_6`QN0Uq5!5(2Ie-&=S_#8;GxN$GzFm(?|6z%+fNBu<@Es z%m;ReK9Jcz?JZ0-Y-z7fB4CKkT3T~hEru){OjD-5e0z6SNLwy_u@HyGTSE`FsGWfJPr- z?eOT7Lam(3uWk7;u*1HK?`W>RM5crbWPDK|6W5!zzoH;vDYahcqvdfjNEX0JXl85Q zG(U=hkrpy3a$pebT&-kTg`$;0J>FrF?d^=CyY5or-)4Qb(4hX>RXg6K!&7*i?ZbGo z-l2P9_{1OLFOlbM8$U>q1@xv7@h=n)KK60+@r?S`fnd~ZC%uGNccd^6t~@PyA<1f%iV_M z4-QcN7=F*4)p4H=C%j5^vQ5jfGgVi4&(#HBfQ*;-n4K^|1}6>2gBYsr$JyR*ClmgQ zKVg~`_PhK9w@!ofM>aq6Y<^vx2@1WTwo2!XkF(O3M3*l4z7VbQ8$0O?);YbwV>Eoj zhwwmmAG!m6GvGTa>0HLCz!|J+g?C3*aBJ%Thp>W4HBFj88fY=v;12YrCl7V7@Na(dio)N(mehjx&N z6sWSC=AtH=k=lW<3eCG-&_nyIQ!ia1F)5GhYmrpHQ`?)W%%?1AT-GzMWJYLshgK3s zDaHHEV~}eUO4QT`G28F7fy-TvET)qODNP@6B)CvmzYD1_>Mmle-yW5R9KaR*G;Z8# zJx~M9Bt706Dw0PBDl(G`9FKE^t(&s8e<{p0eaO4H)){#BLLhR7#vv~^2t5aET|T0_ zL`_m;tgA8MUMF;#ZxVN+Q116Not@3ixgcXj1u9Bs7IlrZ$gRaGo;&AJ-PyI^i)1!Q zEY*-&Cf#w*T4WOw&Zi!h3P@1$_5BDj1A}W~clsObx21OwX6G|R_ap){r}?96M&Eh6 zB;JL+yCD9;`}86fcP>HJftTaYcgMd-@MrA16{TBtziq(p#3xuv8yrTt6J}>8vvjXs zrl4=Oze{QwMr_4BrXv~kC~C7QE%}vW!eDCo%vj}ihFp(ox@vpKh6Ey~{9Xk!w(7%7l5N||3kR?_uMzdwt8Hj*Q=dN}<^i)bK$ekrB;d!c5{p#-|s-dR+{x%%rq zj2;F~PI&((VNYO=a`8-yZg~_oX{I!gIlH;GVRIA_Ae=e@c<}T5s+FHh>UY%Ek&h^o z?M*m$5e_wVd)oHun}l45=7|MZIQ$C*ATdrhyGGMF0MOZZT?@7x8yY{3;7Yd5Q`=mu zHg3w>-{F2`X5?^PNq+Kh{`{uEkEU#7!jJ#g};TAlDeG{C+mUB8S=-_EzxU7)DXiB)}b{49hKJoKR;~iP}an6fq5?4$8k5gRm?ycIKWID zKKBuC^T8_SUbAWOSz~o*Ki20)JpPPq;>CzubcoM);SM+0xEDF_#7Sx5=BF8Rqs?T` zI2i%fN*x>G7%9I8|Mm5PKLMO#YDw`S@uxb_*4ki=PGhleLM8-I%3jN3N6`=*^GMjW z+vDmv*NsPrmJ)B{+Rk8o@zd<26R%RG{eR$FlX&clLmm%7n_gjK6)98{QZkBi1&dP+ zBrCUWHByj7XP{x2{-n1QNs$(?-_dBrYlK;|`>NF_o!3%su${+k3Ra-}*0S+OQfrfi zU!}E=_i@w8V5xY0(6q`}F*8<}+-P&_ZPv?>ukE($FZvMsRz1DvMr_lGa`AvjK)UT$ zeDiCPnUe%%VU({yxhLj>_>%LhSD|~`ZGf=qazXXVo4jFc4Kt)=k-XQIXg^i%gEwXA zT*ER?3Q`!#&E*oRmsy$(Qact@ATk%d1KJ+NyxjLfswQ%kR7&zg76D9kYue;-JM_6{ z$MhGMY3^PW%SYE|W}EEquz3^KTbI=v=Bec`d7kjj>^V@FZ5iI<$8U$M2*C0_32~(^ z8>m-YV1v9#;lit_w1n_g4pnz`G%r8?Amna5O?rY(9LALLD|%>M1^){V}97T;7WOXjo&njiDrKq}Y@9dpoR&*{CCl zaw3~^N$1(=oPEMlrGUmP?6vG4pZ&FIa|^Fu;bTXG$y`Y~2Ps{UW+6z*PUoMe$VQ=# z5?wJv$ZSN{-8x0g{=is+4EW_sv^{bRIG^^K`C+p#KpPbsrQQ8)OHXe_MQs8Fyu6z- zEFPt-kIu=UOvrL8V%jutVeeg9ZjN2{(Og>5AWx=l{P6H>OD=mF%%ML9+*b-M8@znS7X7ReI zeJ=1=o!eGzq=|8)k54~OTe-&BIepU)o5S(7wK?jg$Oey39%pG}QGP3m-+=cV(zxV? zdSKt8gkai{9yF&HD7l1%@48It@$lNUbp7%k`6p$|g=;s(4{A>WCBjiMrXr4(K=kDN zVuZumHouedMx;*%^`pj%+4*Hs4?tp^+adB!v1^s6rm5#j5Mr9F-}3-U8eidP*6kXr zWy-PAg`n1JZ6b?*UI12#)a74}+?y5)|&o{Q+7C!qwKKb%oirVTEv?H(-k!n4FAk zC1I*-@YLE&N=!o6Z$?TdbCP_0@1vOYgNQ-A)@o(Xcn4Sl^e{@T{!!!L$&-F3R5)9~ zsGk_~qx(Cs8lWi8^t<_)Kk-(*j(J*TKi_cK{0Sw6Kq3#R>Q6>4Wc2Bd_Vs!B%xz`O z7>6m=N_XcKl?!Jv*c|>uR>#CG<+iwuZs)Axl$lBsWIpY@j9_+|A^4WSrby%f>6MNj zGV#KYT#EM`4ns)_N*cOd^z5jg<2!3%_DX%Jkp+WM(N@;?fHrfKtrf~6s?EOEw$OmT z8&u|pW2HY^6>40995eAl;C%DmZtp&y+V=bLn&0lBeJBoK?ie3mWqxbT_mzxK9buai zETlKZzwN)NOfyf{e;Gv?G8`Kc2Al9Url8UWg58&7>g+XL1e5R%0djdll#a``DULfR zpzO`vG$lF;N$rqS8e(X^5)Fe_{gKt0Y44<)K^YzttpTT$pPG*k^Rp0z%RJx^(0Ds;@?O#mmD7@w52!6*|57QGO}$Zy+p)BwJ!r3R-ykUBiTa zNx8?VvX-BHdU5I03x-vnfto~Fc=~sjj#R=EJ%>L(LZ#Tv-*F`?=A!L1ShfBNR%T}A zq1{@+ZH<1Me^9gW1(;V~G^Q^OBX_9~q93RpP485vA6z&mT0gcb0_3^N-jY$EB7LI< zU)IxP^DGDk>*V9OlU%2;Ux2L`6%sRF*U9`v(Z)6U$%IAJpOU(TtMqgB+aHS2ic^Db;*#dJD<*;!wLfv{Jye?bpoGIE9U8Jb+Y#O!POGSxV={XpKyV#wuH* zo$j*@)ynt$`aOEugL~DYQKeSo;;J~<5Goe?0q1CKjg~L?CGWhwkno`yWC;;E0UOjb z0Wr;8O4*?AOL@|v1QQ!KlZTj*%V-vPT6k?B7M<{i9}PK@&vCdT`4g+(`supiLWS!j zBUQc!OD1LJILqzY5LPZj0Hw+recYYbbUliJhQ*&qK>+w<@f%9O4B(JZP(iM zAU0w81TBN0_6B+8GFgn=p)T}A_!sy$YNZzWgSG|*X)oGV`f=q#4AbnQkqa8e^J)o8 zb8F$$^|ht-GZl3uRMgNWf`~Fjg5uVnl&(EN;^J3Xa?9H}YyVFu;f;Nb+L8^Ol-0$Q z!5{hbDr;+LHdp?8js0wOahpa zS(rqoAsE_NJD0uvM$n7BP~BeOg}V>Lh*Z>C6x0;m$`6(>;;6c3SKHg3MR-~>ONig9 zKQ~J2t3a_{ZOf7Hg|kf0>)DW^AWGlWM%wq`6V0%L&y2#j%k1Vpj!_3N$KbK=T4`Z} z{w$x^%z&&;WI6S%f)w@1Te**O^!pWo1jlr9Zj>0gqP=81v~mVGRF>P=K~ru1x0#@3 z4X+Un@mUv3$dPMv5;iUfNZ^|{z%8O~DL}*TQFbV6ka1)IdxgAGtNa)eED!ZI`I&2` zFdL4)TPU!jdA0aw4)C%*4wrccBZvWcsLyf!8)*I;J-TC;#;?Iu@QUw(G*F5fW;n%F zk%Z$tz0rKXt*jKqG(mppr4xTfTuPtMEYc?VI@o|F)elTzI3qnQo=AxL-(E=a`*JB8 zi$8x#tm5M#SIcHHj?P{Y$!f$a%*lcGrh(vv;R# zu>5&PLbzx$_C-{YRykYP7yhH7ALUUcw!{87S_p%QoWnwO{vWm zo`lW~UcpG<;UpK1bE8Pp)uL_Kk$N-fBb6ISQQ#j`SbO^gr=K5U_mbgjczk+BPredE z_UTFv#1s%&PwAk?=%z@uJa0WL>Iop$UWocbz z^9J-%x!@j;#W;<#Pb%r5J8u1I9$Q<+x~Su4LBMF%VJA>lOl(avI@^AVD|z%`FjZjr zC;FcHD)k~1S6&F530M4u?;}_s3NKn~SK_<_XukXdXn@{(hdV^D(c;1_Uf2SnOQX^B zbQ>-%@3Y_T^9$6sZ~b_;9;kXQsDR~%jm#h{y@_Vs_{Rn_RaF4VQ4pu4A~nccR#w9k zK`$li-dO73_JIE6+pLM&?--n$OK-%3NOH7^m@xi}&$CnIO=O$3)mtRrl{LcIKomtpFLDaxKb z`An5j5x#YPH7;D9RlC2$iQF5MRJ0^3UWM7|(9d%Zg3ZF2Wy|&IY6)SVZ?aIM2(haDFjmMho^KPthg{qdN zTD_mG8=sdc4H3** zp|lb=3fW43lz-EOQ@PZ~nJ@f}BfP_Xr9F6`J-s}HRIBCnXLv1_@k-oSF4uRRUJvow ztT7ZQT|0{N;{z$RK9z~Ht|OfAb55R?AD<(3hc1a+$VLsN(%#ww8m`)w(?vpi6`$g| z_{J#DKKG-9?q#A5!AUspneaW1uYDbjF<8)SHM#Hljj4ndj*8cb6+rydHWbLJlCg{~ z5V2PX#5gthuua934v531L%Vtwg^?GIeg58E4J0l@S5JdXF`s3e`BfEeV)kiZ6SKR=@CHq(zdKF z`?XdG4PHjKsaa8AhPUx*AiYVDH#LdflJLG=c*k*UAhOJ}4LEOne$*&Z82uClf|{Xz z%5l^}*WG*&7ji{g;KW~B=zr`^-`kuL#nO`4%(DUg-xzLf46226$YJ+1(v z00n}sKjR69J@0VbnaeCDP`(f;oz@51w*%sup0!Q~()iX4r!}7rC5KHWY7ji+7nLi3 z+W9rT6z8`%G#D@xtb=IR2rVk+cOYFPC|mVEgHC-%)rKu9SkUN!<1^GrNiUIrkVzi2!l^cH3DtIW#z`%; z(8HVK@dPp#g4?+EW`Odh&g5&3$=7#RHPR{UQJo>~%6S6H_0RZTMMuMbriIo;T$A|r zoo$y4Nkq4Ym1VY4(%I>aM&WAbZyn*GMF@ox#* zu9XQ>6`QX{w=v}UoYS>G%EqZxev%;SOAs>;c|qFibJ222`P}MLQN%p!*DAB$qNQ#* z_*kdPm-mfz+C(eHzwlYTt$0JpNZ+5q z-3lgMIv@d2dh?zGA1pr*d{pj;(SU1KlSBZP+>|5^pcIj1`~NFNM(f%&b`^?L?sk4! zS0O+;!(fn;&P~GdlhP0KJv4;u%+%r=SD4QEvYTFr=1x;f<$KjYefTkuw&qV{H{^$? zJ#so-RhX?eF}(?mCj+MZmvIe97}|t(jb(yQ41sM&{QZ;%NxL9TcE^L9j1mT6s)O)d zGVKDDlyB>kL{kZBP>9I(NZsgtGSfp!*T3{ z-FzgUS$bet$#D#5AZOe9=F1}6*0l`x{WAcF4O4DyI4BTk2#OO?`x&9wB`g;Fmyxe}-988nbu-9qj0^(kl?3B_R z=GFuv&dkI~fjPs;3Do}L3j|PHczSwXJ452kzHTO|msZc@f56jww=#AL4>#X|H|Fkn zV?WmzE#S`IlL}ICPWw=Pp*K(k5(S zmkFkMJzr`Y4{ME{t*>f-Dks%C7NJrm?;ZVzRd~B}kZ61u~HJc~>(9Tvt**pN= zBWnx*;f5(V48>)cHPmE^f6Qo4I>PCYkgNcj_2*E&4J?*|Xzu+@&%DrC20LZ%8IQJ8u z$FvIlkU@nKqswOQvVp7X+Zouw*S5*NQ`)NU2i$O&$KvZygjDDTI0uY9nm}{7*j4fF zDT{oP(I#&e#p)7*e6`5$(4mWay6(hRDD(X6>1}?Kb&8mYIg7KC32woyG8!Y zcuDLH`GC2_&82PmKrLhIjR1SmCZOX>sAu8yP|94GRQ(zoZ+<#oyC3w9n-{cF^h6r}CjKZzEN@iM z`<+kE*{4XF>i_^TsJj#9=48*AXLo}_ulb8O3V1cu-6eAeOXt*&-iZ#P5Q70gN#7Htu=Nmlt5sE|E?91#v7l7^33J>7%R;I^N|5OLf_*;h;jU&G$>tk z1_lG7a=9?EpZ|V-t$ry3wnr*~x0tb(KDc`MGqp>(D$Zx6H@eljKf$jy-|F zLIUTt6ZgaZ>Tx}sXGkc~i<&;Q>B*y=J`&0@z_{;i`wa`=-cwygRXztbroi0H$@eQ! z5#T(C(9|(Q+`>VR@fW{&kp`-mX{IHYzxYi%`W+)*VCrU^e8uTUbiRr@Nzwe8?XZ`x zINn6P{qE2GU*Q&!%JG}dF4Mp&r;7nl^VxMf`;gm(ybs3<^c_Z)vR_LqDm0lAn&@SN zlBQZMib1`qXX-ft7FHt~zL!VR^9W&BSCUV2>;LwoVZeX?2_6HZe*92rOV{) zVa4p}0c*(FW$~MB#NW0?zIm1aVdqjk5HFID05_;AJZGzU?WW6}OFaRBs8u+9b7bg# zE?s+v$BxMkuea7|X5nQDGYO*$73!M#)FIE-D`0}{O7E0Yr+1afBJFvF9K(qUD#~aK zaElObzCQ7n@}d@wCu2=f0Y1TFz0L!u$WcMHR?E?Oc9ug#BqgB&8k1u0CV${A2s69*({|p#e%9!?kSU>u9*!>vNFF#f@?{%R+F+ zv#`FhGL;V{xx(C;f9TI_C3u|>1XT1(wfTj`+Lx1-3?Ni~F-=mga1@UjWVH@C`R=k0 zSh^%pzRXC++Z=B$?rd!O9o=#Dd+kzaXwq^g-@fs&CMW8lT;!6ScVzRLN?1{jFdS(g z=I%ej=RU$#EWByJA-~=oOcbsTqD6jfdD9nCpRvmN)dwZi=Vct&j{RQE$iKv>JYBK< zCLY-$m)iJ{n>~2i%ds5xgC6%4(nix+S#ZIX!qbgwQG1pI8vf&=D*}}tzx%TL?7U9y z%#9L%b#Nn0~ zZJaGf;L|*&UYFUPOC427H1)qNA8aPJ^imUTle&nPYg@}rGCS&~fc7AJ^}4&pu<%dG zR_MsC&9SeHE-K@yAZT!)mgFl)gYDSCy5-I7%_T$Qo(r8Y-Y*dbC{&i=^~caIG%Eg_7hf*gT`s7$=pIiI4zy_4b!ok zb$a$hj?xpEOWR z2VUEYQ<-lj8v`MO785DbCYmBdgDNq-Oal6$FE6tm1IR{yp{coHzIUeU0Zm;jI{DH2 z#WAcAGsA_>TV+=V8EfJfHTJ-4YNqZ^@q0c+;AR_>op$5UHoPm9j>Ezq?r7OK-?tuh zbh8aq$LrtZG4<8DBRh=S_uiyxqhk?nF?^V%Hf)S!P-@mM5V+EVmItKMJJoiK8Yw>M zv2f|WeAbE@34GwonkbH>vo8Uo{uS?+DV;pcu4T_I&s6FK>}K>5Pi9}?gdiIn8ieHQ zwD7F8o+AkVDh~lRt|hw>bZQl_A(#>*Jqbj@uwJQdb3EYPoOAt4S+8LYuqc6A4voVd%b7ly zquJD=^&xMCiY+lrlm(mlBx@v9rMMoz(0(c(QGAZ!6K|wU9Cz)vnGf7{xsyg4n0LK8 z@ttmJaTO|nQ5U}^_tg2HL00pdmwd`XeG2iyH6QXO)(#Q1ztfHuz~y8DL;2_Wx#sN} z+Q4lpRqS<#W^az90L5W}KrR~YicxJ@j_-jMR;#%vm%FeBa1oE6FF-Ou8edd5ll>S*TK4gc8u6 z^VP43{G}+t{zJh2QIz&5p^@XvnK<4m;Jsd;mOte2wyR&*AOGC19UNgbZk`jkN(l;l zMyP!+AOM&Rvq`rNsGaqc%1lt%73>N-p3nW-lwtWNYMl7bkC1Gbpqbs#u5!ac@tm|` zVfqaGrs)YS>kt*}n~aH|J1Iz`^J(|1+}1G}foowzTy|xV<%Qx*WXue_a>F=y&NR3j zdUCNxn)r{bH(!z~11StJX^Xch6)(vT!pJQwsSEV!puEsK=9WJbB>V>a*<5S-5Nacj zi7}!Fm<@ZR^n3WFtC#w-7U2Ckpdx@j6nO*_n;yz^p^eVaSTb$3@VG>}g|S~T=U_O#Is5!eh|VyES|ho__9}j>c?X~Pnrb@5h@DzgRL{ci+ z@=B@68=j9^K59Notlgfn9}awLr%&XNUWygWW~Pv)Wjy*-n z%92$559~KDXns1J7-Lqr3R6qR>x>(x@Kk0^RTgYoloECb*3ubb?r`gz;^v(o_hCSx->5-c(?V*wQu!iFOcp ztefQ0grhu?(De2vQ}dEvE|y95*#4D)sNWZ_(5&cTNSD>x=xm$UBP>2>lYc&KjVoF1 z+QVR0n5_jUsd#fV13TvresA2=L!CZ7Ycje$7(2qmjTe7Jx;wRp7YsLm0{dA{Q0iah z@_(WI!ID8E``^V>>)(ia^6B@UgX|Os2liYNcj`{lB|XRMwtE8L+o->CxYB28ar4gS z2F)#cgm&LdM4FqvLVPKEC&}R)JK&6k#8u&{4ZJXC!9Fk__3?mdtRvVSSV|@9+?un2 z`Jh-x$er>ITdwbqy1BVv(w&)BctZuD291BX3LR=GQ)ud`6;H}`-!{CAhML8oI=fww z#YALiQvxKjYulyIGkf296h0xmhyYRXOx*F;h-59A5$H^UYW55gFRYm{KpTy?6dn9Z z#g}^MdN0eDtOWhJg0GahY;$Nub_&0%lk#~)cQOJ{>EKrB;j}qc`yDpHRwzl0%aUdS zv-C=7TqNxH#%)&WlNo>Hnee+Lyv!4;t4^Q$r9vCL^%YAWrOe?(yK+gtup;9J| zqDeQ|;pSMq z_QeBQO2rGkSl@Y6gXv!QO+jGV7$+_boM98(Ao0UuRG$_Ct5O>;jP;pfu*YL8mVW_y zb9N?vTIomVTrn;Ua{ns74IqlDYEb;vJ=Xw5igcLLl~u%)@040_L{@1&C$BXKTfVGR z*9Bv}Ihxxq#m@fLTc1SZ=L%V}Xlk1KdCUbu4xQ~b(c+35W5@x*rj~`7&!b*t7b!^l zm3*F?zR*5QD@(lUS5?wlRrjS9bDN%MoDtj@nyl1#n6*pIr@IPr{DWf`+vj+aY0qx3 zzhlC)7z{-0!fl={CVIruC0@Wb%Dn>NQt%_Kbxc{?6bovdV=1`|zFyJMO%(awOM&U3 zZU2_empUDtW^R#OCPHlvhm8kn-vMQO9xue4K{@~tH(t+FVtD@H^>e2`n+>Z^SWT?s1y~FrHjCVB8bq-yVn{?m+|st5aMO*>Uw`5AN<3H-1r=IR@WG~@ z5OE5sG8o2 z4B^6l=gl-VA%znYeFDoRjUV^&>e<-6Z3*9lZHXBwY@E5=u}|CG%B+(p3}$v=sXJ=% zW9m}idBH9y*g;p4SnE#NYAZISu{%GV@VX1$OSSFN#1+}{>GsDAS?FrF-&Q?|XR|vV65nD_BrI4fr7_7OuFtklhBQzSElFI-IZs~@zbWx1X8?bk6a>B%UMFS)JWC^HUuoIYg2yu75&->|Ai_ew4ccj?*j- z!Wt5v=&BIaIIJ^YJMNjQb^t5llT4cb>Sz+|VREPVL{uEpYhMWUMTnDa@v?tw(qo6% z<_7@|_&F~zkd}(H>-*^OelS6$l76=$A0*NDxIn6w#|p{`VOdTv%XYhQ&{mWQCov97@xvqmT+IUf@yLTDg_m)_rp)1F0pV4+oo* z#AIi@zDQ67&Su%LP_LB#Irp?b0ti~icVbI)98XT*+EB)cXR$+18vYE3{O_D~jCIN^ zuwOi8K=oK3)@r;2*2wxf3{7W&IMlSV;StJ`;TF^*1K9B|3U)**SpS7e5oB-Q_PH|jz!{&n&PPGjaQLBJ0OT5!JbD?0?}Z(OZ} zesLS=5Y;UP(z+~i-K|=J1uO2|W!%dDU)*I_nU8?JEQLZUd84|F*U@VD`(xKHLz?y% z{XYVN1vz0$HK_5AYF>dgP&U|qBTa&qwEJ2I`aK?awC|m-YL3A^L=TU4(KXld7UwYn z)SauuAIb*W59W326ix*rQFmKm-FdQ-Q^Nd3G zm8sC=;+PLi5{5MYmnl@BhIdVF&E0rea&65RgSk-(T)03-7YSJI2o?~3cTp|)J`e-` z@DRIiK~jf33+@JEa&I3LEckybU;i899ah^l;A0Q~Y@)>0!S-7z&n$}nb1X0?yHdbM z=C@C|Q={EmBHfvO|MlTv){ye~Ums@zXah*!k7EAEhv$EPE2-LB!(IMIUvY0?Lfxm} zQQ;7onI%vqRAaCZX>sVf2fApI^x`n-ROM8=CFHKDm~r1`L{2i}o+h-9y+HEx)S!he)Jd`Mevd5OLSOT59WOjGN}aF?B{nM zfzKJ~1bOw5=LPvhv8Vx7X z^Y>T4e@3C&A-N*d$bZlE7#jYaheN^8$K+L!`?G`Zbvq#7)FoX1b3uOx`+r90f9BBt zMA`q@c}SmC_v4?=cV%aBbEZMul?93H8UM1RAaRMH%43C@q_+n;MLyJv`DBl|5Fe6b z*-Js*7)&Mjhur81g+`o8lisr;hkBn)iD~bXrGCx@6~@Ccfx^T^k9yk6BN+9CBbXo3 z_4kTL`_aa7|H-Jr=-`Jca9154e&~CJpvpc593CI5nNPYoV{aO=}7)wkcXfa9Jq}H$@r;HN|zLIkwcGQYcw0T z*Rgv9YOb4sPkvuPYT>^}spVaCMhvWO;!MGo1v;KRv z@`7=1EwoO3@t^O(1>=avkI*;K!9kLWsn3;EM|(ey&AQ8&TqL0xC{q2KQz)NF(zDq5 zFL$t=FB%(9W)vl2Xmn+|^LUa!lTEyjG9{H-e~l{B@kPy!^kFdGf;%G-I%K;aJYv~T zPe11cn*Kb{dH4V&QZRmBVFeBn_}*65Y^p*P81j2g55FpIUXV5W#<@BQ}y2|fmQ zkExS$*!6Hm9R&}E9x6)Te~;@iybq3yemG+e+XqDQoLd{)z2d76Ay<_<0{I%oFq4f| zBA1-E{|XT3GP=F#o}Xn0VU=aB=VkJaaRfQhYy{dnlv4Td`wCTah&^HtmCzC>aw4r4 zUpLTanZ7-vt^# zNmtdzmQ9!NsE9+Bx7N=jVySR&6hBVCg(SGfbr%*VTbo#-<$lhSnv%zQm_gYTU{WSx z8~*2HZjTqKn_;IP#=t}HBb4qBh%u$q`iI)Qh{*u-a^69c9RkNhH%J-Jvw?^|* z>?^>>^yfdED;yI{x1v&cs)tL%2nXZvSdl#}@F9RyQK>*QfCu*x$Z4oe;(dT?LC?jp z(#RN*d$+sNK{P!#pLPd9Z?B!cq|j$vGWRg3G*2?udXYlldi?gu;^KZ!-0n(0b2z58PM zeyn6?zzhX*^pa=b@cs#en|fx3<}pjf%cs(fcByzv281$KTK=J!EVcCJ>uK9yyX|UL zI>12q7rf!`Jgt->6*>s2%f+f+X%uf>%r^xDBl*^iT~$OTij3D^PC|Ef=A_s-{&|>xrf(%_&~@kW}xM=Ppy| zHl38`5@;pgj}GAQ`j_pA6~W_D=-?#!mwfg>{5bOc68`t2@|aXTf0GgaPOKEw_SUqX zzKE$!2y10aVyt=Ajac4RdFVQof>V`iN0oc_$IkPAH)I4gj^WI$6Mdal3@4XUG$=o= z;F5DJpe`0W;+puX(iFaFhCs6?U-*;?(hdoQPkT5{M+4--6Y4(8<#Oj3#E^d>6Slv zqIOH1YDIST=3yMNz(v^AV{Ai2=V;*XS3l{cAmqWyW;0~f_&#D78N##nqa%E%e_G{6 zT5@07u;#zx9*M5}P);FjI?LTUHVy`&F(R9~xym)ro$_CJ%5FV<86YPl^O0ywF1IT9 zg+8SexT>ropL}_x^h#4)e#1A^t1MqiXJ*8BW0H5M@zRDR?4rxaZwtGPR*e-!&ChzIgh9wywCfb^O2#1Rzg!v{y6AOeeO?RX%HHYtTLxc4vr~KTe8~I2u4L0)E4p_u(HE+*n|@HDw$5BVhdEJ zw5O~2=DZ7cI%j_{jEQOYG|3UB@!#;L(>y^Dgjh`h(3C-WECG4_pMB>4@Hb)h$1Pet z+QdS^|CdHM{`T1aOT%nJSV;+Y0sOx-~M(bFw1&GB}1;e^0-budatJcgvyPbd5Q^u&5^fdDW zPHFm@#xT?=>dKvi$DQZ}Jw1RBFLS;955&WlLcKUOaFwdkcb}h@EP=IP;4-iGc`rM@ z5DJjSvvr_MR!zK2bHUW$YbEz>+lk~K^J9O?%if+&=ED7%u+N5tH^Zu`7I6NL_c9(y zi!Bst2ofOG!!x?q7Jv+tC4Gxu-dm858EH$Hq~+NXrp_u`ahAlL1_+X!>{ zdEQVe)^3QiVriBmn^^OxM?50@Xb&l=w>=_R-h(x4HqHJ{?Zx@fu;c^*{uB6y{1?Yx zP-L+#)NpZ$IyR@-Tlr&y3jNZcQC(iV0j0^j^k@zrBEu#yEuWoJTF^|2670LV~4vt*up@i=HaP~G!IK&o9A6h!5u z3z=OT%5#e&l{Ws8)#;N@Qk^2d`I6UcHxIX`FX}n4T9zJ|75iu3=uC(!(B@ol=)bH=DRxWZP=}m z{w%jpP(+J!$?v&Xgqa~WPru3Z@!Z+fBO@L~$llWS9*~ygGM5RPdG;orWWZBsn5kiD(fy-6jHDiRm2o%SA2S|d&OsES zdTJBx$*(V}OWrd!O)&9~QYbg7D=&$Lx_c9!`%!$-V%lGMxT8*R`r}9d`WK$ReIzV3T4C5}^zMiIab`|8YEBuk2UM@hd%A#``f5)Msl<=R-;Ha?R`Qlj zxRcJgSjrI9bm0&P@b!+7YQ%(`=ic-{l9~rCW zixV#nq)&CGcNtGfA@l`bGG&I!Zo~I~q=z|WtTf1XeA1!&LkK|F3YI zg^86ub|koe7%2Y>+6!OPo>FjuVpNwNrYne=c0Tm~F!U{N?za7SrF?*4dH-UmW}$7m z?zx(%)3~t5_6J=fIZ@N-6w#@XWiD?Q%YkXvSVvEK@y)^}^NH5ao^Dh%SXPIM7yq%G za1Euw;6OqW@D>D6g?0Ht%6T;jM+L=nNq63?pqqg~-+!J(Ix zBhVR3%D3>rD=8fRfTnOpKY|mn083S{|4!g}UO&duv0fr{rz>^lJjE6KV5z(d=@K%s ziCCL4&i&w_?XOlxz5vMMmCwaT-aL z5Pt3dQpYrjUCCkjcZF=ixHYR1xBhN}gA{1S>b@b+`ApHTgpAzOC8y)e%un3)&!QKzNakdt&5`-lr2TQ133>Xy=Ruedj61i%U z_qn?lP7Q(&1n5q!kE?{@`WG1Q@*&C09wDV@27Z}^RZ>6&ozetl7&Y=f^`VqgipimZ z&xtjgKk~-eEVzoFj+DcGjW}}`d{zPJfqxDk_n+DXk1_&VzlPNiIsNE$2>9<=lQu#W zzhth9e-6WzSe1@EW~FG}ID}A8KVc5g$6Ehrx6qgtJabg(pi1Ng!L`Csm{2kQ1_A%= z+|L?9i(wO=bKve>F$8OUbkhELtC`_Ppe}=%K=UJ&1H67LjX&3d zzw+7uaOcJU66VYFu^#O2ilyOyY;5g?masgzM3=$}0<+-Fjc<9J4Grd?42vav4hq&& zDO`hr@Z8DZXFd-->Lpb6(379xGjfeR2}b{%l|F8r%$|`?{NItJFZ98DD(@~3p6N4i z&H6hkDs+u0j>TYxBV8h<6=Xtm`yu_ z?^qBP%?5B@16lt)$y>mQXj=>PY@hznYa3up928Kc5xV~#BpL*q$4Op~!C&uc{O9%{ za`1605GJo?4dU@zojEa{(-|k;yu_7$$F$R}Tm8S4O*) zco}D6Fbu6I)A261*9itvQI2_Cr^d?$TaA|?=W+&B(78G24nj+L?>GWJ;b5eI>fowW zN*E7Pm68Q?IUP-mX@*KzxoH?U>5~Qdq#hF>!N(xr*uu{_CMixGdmi6&4$vAQ0 zHl(ef?YJn~!bW(idVFjm4)Fshs&vkxze!oM4&4~J%dDC#EGzQ?qH6hbzh}x(D=+>k z%D+q;8%s<{5P}6}QGslR6`3JDZBj5bgN))*bJXfD+@lhY-QJKq=j4LCEIJ{tiCV2D z6YEhqg$kEsK}HA*hTTHz+1A8sc;E_)vRPlI{_99U{{qLlv)(i^V$C*8qqgnyZ25@w z!UuiT7TA$1xxF*dyYDqcv`tXSL#Uu3&k1RoVd1Yd(FO71mxrpko)h4%A2|RJ3CXjB z3Z6+9Kfh8-OYUUWY^#X)z2+X(l||C2xfjcmnHBt_4N@9NSHgBD-Z+lqoGMLmlV#Ph z;xjTF>K-GHteh{M!V?$iW0}VG;?tJFuL*5k*=B6dv*nCfifI^Dyw`>x#W4-()XdvA zx#RXExwq*CB6LVrI_ex!3lDN3D`BDpfym@_Fy}NMJuFg#TEI0{N$(MB zaf+?SC}?a!v{@0mi^yh`#h_ymHuqTG^hK^bROWK zYajP6pKi+CVc-zbCQT`VPM?sLV(dJA*f-HB!pL^loC$SAj(O-Ona=EMryqWQVs=^w zK3}3%)}$VQj%kY zihu;4!}OtegG_`*oSSLt`_qa7k1yWJbW;)V#sfU48V^f*1j+i4F03D5u$|IJJLcbp z$aVeJ(~q4Qmg&mnCCuw2J9Capyi$cB^cBVqOG(9A33k~|a%^|1DLllQ*rFJ4?naU5 zY65V_Xk)8tW$dQ=INYkW*-CXak1DNi=Wbn{udGapg8oO!6Et|q1Z<|CE1dk)Lc$V& z-}Vh6CoNnp28-1Btd>)YroMh2B8$6EQZLtJi!R5CUq3A>Z{zC?fGt}LbgFfnIJE2Z zF6+MHJay7w4m^CDP1@oxRmiC6%|x1S<+=Wl6qxQ`D9q`ws0oc^a+j%)3FH^io@PA^ znHbm^D$!Gx!89f3z#emWoRU2|$NNV#d4}NnHDG$R=o%N4g16(ME1&b!ceUnPaAQt? zv8fQO@#%tEa{|waFJ)dkfmsT_9XQn;$;Q_ID;?N@IkaP5Z+hIricK`GxXIXIF8Z@T2&~6b`CZ^ zSJ?1Y2-9^YVC3N2#|x;p#SIp)ZU9BrRUQXv-w)cCCa+xek7^W{f#x3`(Tivdjbf}m z@-Kv(w#fqN@F65RY(|jaa84kEl$*F~QmIr?=EfhCvFw|~e-|3e*ZQWCYU}fOfTd@V zP6c-)@{uQl+h$ z>bu>#M?+o01pcC&39RG=tuR9A`Uc4GI*r}gV|WF&CZjbh+BlKSrQ_;%hThuFtBLX zGPqMprGSK=D^~yPBcCmj6j2Lf)}f!?*3sL>h}7*(lJ;jKh}o?FljiXO@k!@DQHrN- z_0Jha5KnwdrTB<7DS0w(xu08RQARsV=+bNqjB4uCAnQAv3L)ET+fE;O|7+|94xai! zlVgtg+oqh!&)@oMKPeK-H|4D91vR$x+a{FIoiTw9m`t2eaSp7I5BiGYOJyd82otlS zQ+MxlC)C{V5yPrih|tE~#81#z9Gb$L>ltg?Klpm!B0h|Xk!3S$vnIz!1#^(;=?D!M z=`qhuB{ON}!Fd296}^j^=!_Iy`#7|b^9mn^17Dp6lRODU?T=d|Ci2M6#s{Xy|WJ(?7-P$SAW8lK?!B+PGwFYz2#`Hl`j#L9#gi_`$eXxz=DOi>)B!A zJ?6XV{aakx1uRs05Xy%}f(ASTUuB6pnsG;~90lNfn~QcSm)L&G)blczTyTPQ$hJ0_ zO%k_NanGn;sq%r{h>=H}`0l9DF2a-1rf>GV@KLQ%acm{W!jt0A&y4P)<5x8cP`dT2M~7hgs!L?(tOS{ zUHcdJuQn;lYr+%aWTl3v4`~;roKlhs*Sw-P6CunKiYB~^G2o}&nfVL3V&STc3dyWx(6zs27XOZ$rrv0v3xe0p4|Ig3qp-h zx_O^8EHAaxdjk>bGIORXwYyS6a?iXz)!8yH-_CQ?6rAlost*30Pg!1T2JS&{>GeNn z{xh*m9@2&OFNq1~5i#NKlbaO9y0px zgr<6XSXm7mH5MURT?Qij#rDg~$gj&rcwvcc#>&0_58F`W_2R&ww97QaNA|wlA}ML{ z^kbb8!yCfdICyuGI9GXh=gmOysxs|Jd#}onx!LghA154}Ix3<_PSA)FUJ^RE6CY>O z5*r_H->>DYn8@k42`_jq`i-rKE5;0=j)PZA3g zWHyZjPe}dcmOr{mPi{J&PbEf0=l$$ZEhbFN#PJpL-B*AFVd9m({rWY4-2ZfL=h`^V z`vP^K2R=zJD@T69hka;Ebys@8s(9W0SlJI3aN`q+26l(ac=RcD%A-s0J^%3iW$(8i zDr9uFc%0X0v&*7G|piNJ5$oxtFJ zzX-X+JEol7y6k`W(pDA{=aRi6m#>R7l{So5@GuI!IV(f~-6~_NvpTLywd)o4v_wC6I`-2TPI+TRw!=w|h{RiO8XS1zkk5FkH*_LWog1}zW6lJiuZi&gW4CU!PUC9yNX<0=JI!>9NWH6B2I1rp8J+wHGk zDglvLU+5?3WmZ!K?yUz5h+5}tx}m?1`n-Deb|+oQl8!d{IgILKD+-?nTtqiS^J?EK zOb&UHnR%KCwgs3?L9xYelJ>Q0EBEt*KZ}%WS1(V>B`UmbH9db#&Hz{jCyLh1C~*Uz zf%j?^vSLg(YE&Jbou>-28cJF$4HB@`#&tD#M=os3G?HrgmxO?eZmiP0W%Q#SS^wd! z!@!RMN8Y9J0>$4T%-3tC$vQ|oWI#2JM!>c`QgofE3u18FBmf=v!5@wOx-AeWPnqSs=IR%^05AVBr)K}+Wlzs?+MdPk6duWgKW0C-P5c6K=sYJM1h&a1UN$!c z(x>ZYcq7ts%<_6H``q5;z*!ywdKVq)zz0$(Pqey;pc>#?UB1tq77Saki|^W9s7^q2 zId0tVG>%H(*Omh!=V+(R{HcoF;s~0dtohRs!LXM` z3u1IixyLOS(?zKTj2*f;c?BW5t9H%_pJ4`u{Kb3 z&o>_z)G$BQ#CiZu%CQ^nTL<)uGEd!PiZx7PLZ7p(aK-RZxPM%UeYK$^CtlsJ9v^A_ zOAa46ynIdBmBj!4dhEUQJ5U|d5AHc!3;u#XA4tCsZeyHZG{AOFY$$yY5!^&MyR_eS z&)V%xMkl5E`26Ajhz)Pw_H`q(r`tEjUZv)nckWaFauBZ4i}`mD*P$YcnwMl@QId}S z0`zZTbpZK$a6VEO%Y=kaW$+0vDfk7Ph?~K^nd)t|O3Mjl{MZzrGJO5AxDQrqCC$f1gX+5li;_i6GH~7! zo?PaSiYL%Rc$yOGCITNQj?VN+8yh|^n{!q9d-B0Dc>h|PU~5;TpL{!4C~!KD)+k?P zQqi?vvFmFH&pf%Bb!1y3+gdOzJIaPL{3g%tWbf-Ej6$Ak&lW&HMJCP0KB*9AtvdrG zBba!u`^|%{SQE%0H@87mD3(EdxsF^_etU6>BT}5ofHtKVH*5293iX;oYsK-ZH z2AXSC8Nsl-6dp{kA3p%RMyJXJc1p5T7Z+b@zDFW^kCr0k5-)3nPRX`tRTBFi!>Mu} z04l}j+$fD{wt)lFxfF2M60c3Vdxz<|no8=2UDH(zTzB=R z`Y36H9Iube01Oj7X7aP_uu}ccMl&v+Q`;j34|hl5p6p(E8)b4DMgxp;?0fRrn>h<8FGjg;?ONg)vB24SQ#qp_>5i|pXith z*>ALm$0Q9W?Mvv%GEE;BP_^@}ErTn~!}9oyc7hyWta~iwDM#oh%afj&;@#8xK^y#n z2$QUh?!`@W5xHLBeI@S~U;Q}{@7NS=`n8IFWPs46&TUxx%he}WA#Q#qh-_;uyy`RY zlqBw;0{Nv?W1%Y{0nAr*cdXYSG646++cgGjz`$=iXp@(IFNneS`?i0t9<$7pbp+kA zNh^FSi(jPRGsN>JO7@}z+c^fWM=Q0Fe7Tx?bqRjTiTY+gDoymuid%d20cYIM#&y3iOeI~d*2T-9fZerX!( z;z=dqPMY9N^<4suaXh@PY9 z_SYMtVz~{5g}b+54$L%pHU{Ap*0=?Aoe8auPpoN1ff?f&wf|x_Gb_Mx1RWawM=fJY zD-ZLhxyLy6ta%i|5@W7CW+FN*N-D}hb1Q*2mqg7e(pNFvXN9`Kl|?7c`jtz^52`RW z3I|}}Wh&ciBa#QIlG{aBsj;oR%sw~m zgBaWKv-Lh)Z#0mR#AR7EL$YmR<`%-Zd}Q2bBN%bjhHf1eM+0+?JlIWxhRq$+G@p11p=Ma_LDHc5&TvaQ0#m??0bqXX9aLe4SEs5#a&eo~K$x zdA-)AMeEx;lKC>Jr{+sven05aZP?#vm{3va_f_zeXE#;ILwT>j$OARc3u8Xh|4U`! z7U;I@7a5nR^J9!2^Dt#22PP7}{}0_WprytiAL9l76&o|iU+=_YqlNs3k}jQ31ab7` zXClU^jM{>8jI`g|q?@r{i&==KY7|L_fas1@>NM#cSpJ+r|y)tB}9gE!=VT1{$+xdQY+DcL2K_gkf}kWB9B!Z zr+daKCEYnCluKNAfZ9Fn(9v^4p%!lX?V?>yL3R0`3GR;7o(ujyCd^GGjg#QB+uWur zZH$mlRx)Djs^a1;+jK`H%KZb&S7MYC2OiDEm6hsmPN?nu4q-g}F*ZR%C9(INSNP9s zeUB%}Y|y%d3)_pM#A@sQJ=lFlr5IYLMuAs5yhu9#Jf7yFJh# zBCJkvok<<7=dc^~unpyE$om_m2U?U+rApdF+qU*fan|&3+;b6PO&kV-v#LRhNgQ+} zYBH{3tW(~$-VT+ib(@Z1%d``1&+p@@_4FOCidaZ4EUl#M$4F*IA`>IwuF=bBepn>)=1Q}s@N4H2YmSAl!xR+sd=ve@}pAlX1zd|d!*hwU+{mvs-mU{r}Q_U+it&WPjk zF`6TetUR|2iD7$YltmIjWjy)N(n@{s!f+(5(~_C{A43XZ^McRLIdOM$iKSro#)XGB zA}3xNZy_@vo!TQi@f|VK5#Euw$6fK=3mw0oW`BadIa@=O!N`%F4w0Jj;Tj({DRGoU z&+`hGxff`Al}u zY8->xZK_Iu zn!w(DGj}SOr}x}N`$^B@UoV@HabySCC154`6 zvuyl%pLi__5MQ5(z6;&GUZb6b1{S_^RPQFLx>IjXg>q{^t_M7jWqQ@wH=6Amb;az+ z`lqm}qyX`1bO^)8dQcnF*6w@?pN~&*dX-^Y8kO-U($LjmBd62jzDLv%YHbco0aQC5 zK(#~NmZ_lxNQt@*7G=cLq6bX3I2|d7Z5)Prcb^mw~>(@tjCF20%=QeJ+j*^Bgx!ea3KJ0|yvl#|Q)qpI=rfmY2mqv}z zoi8hp4T=;p_GMix{T;B660&iB*^s}s{(NCMpj&K2I`6)7eCCV-e~07J^x?NC`+3;8CY_iCfs1bO zpv`l6%Q^japH-vhug;4|`O!%x5;Ui_|O8Azl*>HAXX=nSJNas=A@pCYRUp)w{tX^TFn7ipg)e z(LBC+OvzM$P--cT$W2m6?B}CoRgU{eQSP+hk1*l+!EMU+Ckzfq zmSfK}?^G6ga|*whOUetGcv$n7ENuX0F!=h~2&PV_q;ZxH2cy_wzIb?MZnYGi`by>& z#8m3gv5W$0&9k*y22Mxs-8n5Voz5TI+H&d2n@^Vf)C#hc<7QC^iyvWeeC{hmf%4ik za*cw!3tu@_b`sF*q)$BsGTdI;*)h!7mV5P4>@Cej&0Ul}no$sSPZn^xA;1?DU&{Q1 z-}+TB;!(AEhlV$H*(!V8K=i(3iU4Are=xYrG)j^K^zzC#EM{{$)+esh%NI(0V;0|c zY}#v;o7w4ZaassoEEaD|BSC#F(%rb``z(Z2F}-crBbFOI*?zH8~Nu7^EyQ;&TL`2d$DvgAe}ps6i-Whkp- z8oZS;j8lH%U8MM;H7HZ=hEwsx5j!>0kH%l;I-{4zWbgB&>nkJFrV)zb7Tsv9_?goD z^(ckP{agwCQ7|lXR7G{9TEHQ%K)W#Bz8X4Y^r!oY_iRUA*7|;;8BJFgPo#(cxx(Xa z0~-)6D&4)9V9IBz(0tptU+WkB^|oM`eQUODVmF)|!WY}Ds@gmaiClN(p^4dOo`#p( z4sCc$N3}X0Nl#R}J=+4w)tB_}@0_a3+GZa!3Uai}o*r-~%^}Y;+bsL#16veK8Zad1lXFWdLhZAAQ$! z!H8q_RTCzh8uWH(Fk4fxu>L9oGR%EnBig`=5(k+G8zkMNJz7Un(E7djg_Mfk!)3A( zHKZkJX2pVpS>o1q;K)o-z_h1x1aGa9f6MJ!+#I?ENw^j8Io`Vd=H{u z$8C0-t36gDg0U$Xd6|;g4F2^}?LbY`#F;*2z<01xr+ydZ!+iP47qGNW@}L&9Nb~V& z%l|&@m3_rJC_2)5!MKuACFZMQ!u=a##mKZ@S?(`nv(s}%+{Chj`0d8OC!hVp+dGYu zyX~y=<`e3WM9uj=nb`GMzs0B_7je@S(A9}qz+Skm3FDo%VB^9Rx8IqlCwWjy$h zbGU!IYP0m^kFe;0gwp4?(PWaG<*1_XoT55@^M**(#QsDCV}`LOO4|jkJ#`y}#%8L^ z??~{Em4fC|kM18(3tR-&dzIbDO?u%?ID z5aE>htDddub5&uodQs6#{@r}b6b5^J_HoI)ZIBNY|gupksU)C8|<}XCW zmLplzANXk-VyZLVA znJ9EIua0M6Fl(Gv{C2VALnnP>1DO{EMit3!PQGv4tdsSUs1a((R7CC{ZCkXOMIB?b zVqUwsy5k*M{Z80FI3CNeyVY=zuf)LC07vo znQ0kN)DBOl$3Q*ZN{3RCJv&4$<=*$G+OetLWxrS`H`ULI>Z>G(z)+B(l#)M?p8s)f zJ(z=jYzc%y8Pyx<@vZKZaguW}7_lFXHW7XgkJ_BX_B9Y*jXyYG#-GsJlmbh+uIHu$ zFlqb_!<;MqsuBSvy9MgZw#^lQ5Ip+wju(JJ+kZ!OjbmkG1u9hsOlF5f{#-+TYPTvP z|CCC}|Bvm|Y)-z(_&z1n*w5yJp)Ug6W3ij35;$-;S(5I*9swBPAEfn@&BLCIBWNvJ z8pKGcL5&I=YnvX+VZdg4{tU*uetjdhKl4@3nqKq(D8s8ARAPTek%gwtne>_HtoTy! zlcc57f^z5SOJOwzkr_RU`~?jeE*qm7H-qV{rNp- z`j>Y@ELs~k)=;v=eb7Z7eM?qNL=sT`W5uH)%Q`D$lKZ7)OZ&<5wm6(Q@20x|FAlKr z{Dy8?xLi2LX5Gp#UqKHMs6^G0^29lpuyb4}Nlt^Y;NGpRV&8Zm!kmFQ{@1wWsB zmbw~x+`y^fDQIHrco1_1(NhG*~ z1|MFQ=HK9@d-2%Cnmo4VJyGVi5aGGDCbkg0Q10~~xD7QN4(^#@SC06~AvEOi!M-Z* z5r%U0A!uOq^)`by1U7eQ1`l`F3bnQ#q~x&UyH4URdB`VrW+zNW%?BC*v&DOTeNu?< zqox7U^5>|#KI^5;N48a(bSU^wV+^|zx_(99+hWZweS7wYjZfBann!;emu`K0dw*Np;KrI@ixZi49# z^PhH2Z&E)0QuT0YBoZG@T6rCoXl#|!vY)2sHRO!{O6WtCf~^8zv>VfYd$NGHvKy?YE8D>eVWdF{>_j85X}Era02+>VDYXRfM} zk2~*U3(ds#-w49>{uZNG&p5p(CN|ZaO0mvJM|twmy5HPMU35&zv7L2=1QBLCDB5BB?E8Ma2#W5X<7rauSc_Z)!S-~tT8^KBA2Cpb}FO2W6+29V8-x;#? zl1=(B@?b4CVd>%Bi`zo4FC2153AE^BZ78C>)aVu*{~7o_gc;k&%zxQ@xL6q6tnnd^ zR{|5RYB6HuNscm{#=RC%x4`{D90b!Bh2P|k&yI4SaW9rMT}f3z%m>*p`t%G$3-gZ^ zf-IbV2sDL{y+AcTRt8F+Nl06o)6jQ%Cqa zpm9y5-I3)cAf^()t@5x;F%e0jOlfFsKislg_SWO^{pSqE`A|Lm=+)PzN~dX^cY6L| zN%tzLEVA0FKw-y&SK?fV;YI%r$!M=?auU?Rf%bF;ulpg1P#2(+y;fQfiSxoU6Tg;` z;~D+`R@7K@EoRZn)}Ln`tEDUuqrwWl31~uYTr+I)siHGP@=nJY2nxtU{r3f3K>t8v z<5zw89I5E}bgD{#qFOWgCimk3HtveQPf3qZz-^DMjqzD@YW3z{?b!o)8{rA)$@v&n zsAvdt#yH0q+{i$9cQhMydt&a8g3l$oisE|h@?FH5NTbz{_v_LqvMOl(mE>Ka zxbmQtE>PgNe{D1WdXB82S)#mz25XMUZO+^<+Bm`l_FO~&uoC=ApdxatAj;pPj+rN3!b{2 zv{tS-JCFGM?Om6V=QMK9!?Wmm>`tsb?P$u})F(w><7JKsFp-WOY8RO{S25%x+HsiY z%T*m0(D74r;0om&z7*NB=XWeC{tqNg0Q>ge`~>xZk7~kA_L^|jViQEDfR9(#mXs5B zQ`Mf)nzm(|?nL~ZU;xF10!os7jB#d9Rs={ru)CLX$_jXfqsS(a><|0%_Ya=00+wu@ zakS6)x?wI? z@Wr}pbAxz-1n-Q5FmmmoI0&O}C`{hGDYVLy}EI+yxqNY_MhHD+8i<$+|?LrvKs zkq(;bol&#M$gw~1cVC60FSsrSa5#*o&kCo4Lyc`Ak{qDt*S2lc0T=R757%+XlIeXV za{ika;Bk|P-jJN%Qo<8i=M|mhKn11?RZ3V5`A{jpzA>iVV?BJgWx(o}Yq|Zx#_lDp z=(Kk__;V{4;Ro>ovx8c83Sag4DltE(RdH5J!&za(wjW)9lF0;axWZW0t$gKIbD4-( zjqfI|sZS<;ETjAV2f=6s&}!9e`WCtK{VKj=s^p6^!svE_QkB!G`C(th#&%;`?sH!=Yh*HmS8+PP1a8Ul^1t9skm#Hs}M=!fq zF*O$tU&}>FN@DeFfc|F}1{j4Td!b*na(VR3v?vZinN$di0=V|^!om<{yjSx{V~%TY z=x{6U2$P=bJ9Qx)Aj^@Iorv6ad~G#Wymf=*eHhB=mis-MenO%*q$% z$eDNAZUr=fgpnvTMr;@K7`|G8Rw+p_AY3T#aK)2i{3n$LNK|@elcY^sEle zEC=}VXpUf$_mpQxUkI~n}x>rDVyWHdlH)MR( zp)H2s)O6kP86sYA=OqlhCMfm>mo7ET!1lhQ!1W*3s&dLT~#-?Zb0|H*0{qE@H`r)y>h|m!u*Q!)cbfaaSLL3j!*5 z<1mYz#v`NIDRmkD%AdVDmo~UT;sQuGh`4duUatjhpdSUkF=476>cn47I!b zzA#+*y~Zgi{<$X<$U=~IXKOtS>k~lfCJlA!Bfn27Qk%a2h2O!Y@dJZEO9c;tgd5VI zgVU4m^6ct-eG8FsmwpGcn?~#u<{_BZU_F@+DMWM~Vi4R$B2Kh0yv4o|u_@hfEjIN2 z5zoPg=)F;S)Dq4U9_jbnI5lSz168^~AK2NHqv7%EJq=hMZUf3@p8CIhdX-*f`-QV5 ztCgW682CGz{aH@uYk@mJ%+OyG?rEVWc8$wap{vhk*sWdwlZ9g3P))jrXGZ^uzM6Dk zUbibBa{Q6ru-kX^=7O|u)b<~ z#GF-OH;K>hqpz*~{TGsZDQ2+ApOaMtrG5mk}{@vP2)OC9Z zlct??(|Uudp1AK4koA?@CCiERXE4ln9p$7NG7o>NYaC#_Gm_A8?}*g4Y4ID`RE+;F zjKdTj16@(t$hZ*b2Tp^5hMVSHz(2SnADZPnt!UL#wCwMLu9w5jz-b&*Uy-c=v3_0U zdH0W?^ZX0;f@8IZ>+UjaHh$XsaO6^b+cQF zs15JcV&dKR7uI>`#jG<^eH3P+?;=K6^hZ?Sb|tIKG3>swHMWR?+@)B79*P}|h&7EA z^1xi8SFEAJ`bn&>_wrly-Rs|b;D#!RJ{SZ?7PD?`f|im@gwK=;+|y)3Y5OmDVYyse zMPswin)|{+7V|6Cit`a3r{u*a*Ul@93Zpu#^PaGso{H6o7qZFte zFBDx@0cc~ERp}5j4e4)HsP2O~Ai`DjMC{wmi393WB?Ql?@wx zP49Q_Ae-hW1O4#F!Z`DTVPujA&q`4K715YC!LS`lXg#Kux8Ug-0@uV$MDO*urM{2! zI*G<)cthZW`~j;|_OXtK*wEw@M)#I^feD6+MD+M-P9=cX@cnc=zYoMFX-@+)zA-Z1 zahOP55{|chnr#VV?8{XDNy@6cV-xU1(>M8BvH&LDA2Zg*u(wR8XyBrt7K}Sm2&fCJz_C+RvAxQjrn&pQ+>=%$5e3;) zEEW8spR25&R{HAkIz_J4&P8fm-!O-|F9whfleY^Up8~r77MOvt2!$3ZS>S_miqJ-0 zF5ld$lSNgW_3wMkY)WOFrA%|!Y3nuL)bfXWS67(Opzr3!DsTwa8@bHu z2V3HfRS7uSqvAt-BP$-oZU;*${lem==ZR$k(v~OB0ieP3L@X|?hUqTDs~W5G{;NQO zCAS^VE=}KmesN-dce|4KuWVwcM}rh#Bh|@FQM`TW6j~*|CTbs?H>IiC9creo3m5B0 zaA(Ur66L=Ljw2-WSWc>@)j!YU_25ZBH$HQ$FN9mG-}44X}GiK7Z`hUf)@XUcHgX20Tfdassq(;cupWeJlIDQ#=Hi?}txG;g+qB zvaLOZCL2Dx2^WOZJzw~m)fD~OiAern|g z#{jE(GcBH$x4=d^i=W~RHGntDfY|4@bJ;@Gc1R?x9WWjHGw;8=6tr5ACC=Pcep>zzGmE*eo*ZuCmxDq}t|Kn^;- z&Szy_>;udp5-7a64Qe8=SR%$+6a6at+YM_JVv{+MhM$?A*Cqgc(YmYqA>bR!@-EPr zD*w)ARz1&c(tUW3Pg()Q?j;`tl_luSil>8mM_kOmXy0|W6zG3#*J%$W1L#H!z1TI2 zA0o&8K4W4$mavUp*KdhUw)v!qMtCTTCdtcw@^Sm=l_X|Ya?fZz&9ZLXvEjMJ#vN`N zI!>$S*?QWO@WxPEJ`EYQpjb)Jja*71@9p5O*+u&yKmL2pVyIwxVR&Nw&l;o1yt;6m zzi6)nB*c&}&7VwMOpU?MIx{ad3aT897tHDt`Q+7$R?Jav{dqdIyqbC?!*7MU59#*5 zvG>+rQN7*!I2|e=pn$Z5NO!j=-9vYXba#VDmvj#uLpRbPNOyO4*U<1e_hgjYn# zx=V&-ku~}~ssIM>KF!4K^k6to^He@goV!AW*wZ3tVfhJmc$N2V(dsEt+8L>f;9s>6 zr&`$6nc2z9uG7t65x_5XWhm!hi}L9B;rw;vXQpp2=m>%FsRl?`1%P+XbE!L6lSWlW zn@d@A5T8=&Q7yX9NS(J%G#7s?R~Xk6D7q~66w5;lBzndxYmw{UZ!e;`sd_jjG4t|< z6RC-YxOfXb4!8VMOLJ0N=OQa^Kwco%&rhi<|4Q0j0jvDED4ClQNW@UKK?PYiaqAq_ zU$uwPru;Pl-$l8KR!E(x!K>mY?(@hgQl~xT}nVIf(ygGPJJIxE?wl z+an^Xp7x!PjCV2}7N0YQdTE(NUT+-8)nqakEPR$Q4#sj%b(h#=HF0riULrc7e6e8Q zsS7A>;aTXM%>(qB6Uzx@FG$m}#1v~GRMwm8v1IyCyB;e00c3n+tWV_Y@prPzs$vk3 zEYh(1Q913-O5%w7*Ee=kQ%W%+<@|WI!Wfs>KIvB8n0-I|9DpFGju{b*Rsxvlp0j0@ zo~*7=^16()9GpX(-a4%^l;&VHaK zDvt8~#tXzC5%!OFfJ|&RXxBVf*7<`P;G>k)66PbHqSy@&Ih7H$RnoM z7suicF&Q}^xXUB^>~rNPx%`8kh&L*a$4`&L_%i!%hP`nw?3}T*UUb<4rO};0ATz`- zrad#mg)|AsI3?!aPc2mt^g3G(5!9!dKSYAm8eSiBjyjDz?6W@t$<3PxjyN{}@E83Q z8Ta$>NgxehRqVSR<56oI&th=|+lo#!#M$z0&V=K`z7*xDRJB?Zt9pJP5PgtjsdcuG(E^!k>kbQMio#@Q$_Tt@eu(ekK8nl0#0E$t^?|6|3yrj? zPC@qYBWKZ1W0#w>DlTBT<0t6+nw;V6`hDngVv(EcS672;c~g5ub9Y{a6`cB>I;?LU zu~U|Q*%85JLDFpW=^PwjyS;Y`N&st@%>hk@lYmh>93Az zBi+Q4r5vBpsf89PXr&r5?CTR*7`Hy&A{#rNU06n6R*$f>MyFAL3&g#!f%-tyZqU9` zcAOe^j-`|BuS0h!^~{DAB6n_}X>=c6;CvKHe<2vhPpUb1v1=>^xdD|-$cTEem#2xn zsEM5EL7c#Zp+kDqOyYR(+#6#zniEPALrXMBA5>YDi=I}5g7~335kZg9ul4>U3V4}cmVoOrKtqN$Gff40NN7E6c z)~^F@Y}dWWSv7v~l8(g>2Bq^YkiMt%2}#;=smUK~VwF})zpy0MrnCVI8kjSE1Lq}P za~*R7n@wrs<@NiaqB{jkuv~H6ae6ba#=NDHPn>}N8{OsZyzbyPx^t06@M0q(AHupm zOZsbTgt@?~?N4THZv^kD6%TMiwVhH+o~+P}fGp)o?b2V(^{s|?)()e<5G}&A?>*m} zSErA|eJ`fw4L9_|q;`7g!tgDJ;G{v!~JeCEw<>#AIm?m(Q<7^$-i`sD)mlh zb;TMT4kMn+ruoS4624k3t}iY~%%q$O3=JSsfOcY}iM6t`tTY_5Av879mC2=Z1k)_3 zzSmQ2LY6Mkx{1q-IehDFK7mqrmEl-Tmt=goR|Z+l4&N-ix!LN`S9;1s9&{vT4|8nf zU-Z1v?#xb^%lF-)_6A$sNVgT}R5sx=bv1-uCL|vSZ|@1{c)4HjPSh>K^l$0#H;%HF zXlm5zBO(Zq^1zLNMo;Z&i3Z_mYPsE^T4u}4OnMr`!^BK)X3aoUP0Ggn2{#dXYT5f>e>0NVy0i2m4(>u~y_+Q47ydTs#wF9VDu3sE zla_AYrORtE?p(NcILiV9>?&3HevO*Gz;bkRjE9V$sAVq zQ3p|rER5cTu%MZR?$(e0t1HQCwpv))(Y`)vIn<^K?-A(a>H~SWyCN9p zo`c`MCdA__Xf=AnN~~@ckZAVDwBd^Y$xV|Ih;F!7?IKCTna)p0gM1~yXRI9&78C{A z$bc9lMKFsd8_-Vn$7aAC zSu@YlT-&D-WZMV~gmwzA(1WdHuNFM(xFz9PSM~d-WRpLE@(0UtnWq->U^euJ%qKj2 zYVV;bhV^&mQ%nJT+op(B#>2Ai(4$=AxoZ336tE+t3q~vAxTve73F8^eKZLN$7p{w zsyGJa5WB5`_oah@uTo?g8+-2orE2b@Xms@ASDxT>DO&RgM5N8+rxu1+QbbY#@ieBG?_s&h-~fw_ZjmlexNalc$P@(d5e5R*t)xiC-3mg|_x*2l(-6 zrg~ixtzC+dEYWHL1p0S6-!q#w^fjRylzJf#Z)K7>FkH}k+zxU}(_~`q2@k^`r?y4! zS>}*g^VN}lFunYt=F|G|-Rt`=?`7W{Ao;S%wlVU@mBWHOyrh$ETTq~Q1f!7X9#{}2 zEVlnd8)5A#8(~iM;HUT2;QgI8U%!jZK4rVA&2a&vpoa7Ln*E*3+au5>#C4N}7nd7F z94)Z|P>UKh$;6fupK&TY1Qu4_(CYDAbhJun$j(C-_-D-Ta+07>%JqglT z6R1HU0?Bv23K4$pM|7UfK4?oL#ioW0TggSc1ui0IDb_7$W-;eQ4{J~r%5B4?x+S|% zJXku`!^OIEf%_Bkm$XB_dj%dMa988C#%^1efwef~>t7p{T>r@o3W5sSu2FbiJzT+} zOAK{yzixfI!WJi8JoJ2CELa7EN$Igpq=a_${Cprg)Us+P+~N0nm_*pEgM4!nJ3}R% zN}e}aoW-->V?=1w+G0UW#l?!{yP5~S^n^_3`;3BpS;B%T!J`}r^qNPB-KBwqtij>3 z5+)}h3SWGI$2my z#5)m-4Gx(U9_G&s`&MNXtN8Swco-yx)=^HXtV33bo#T_bWziZIXvb zUY4ud!%R(;%;&sY2caddp-#t|{mq4M)Zt$aFKrC)_M@`h+&BIi7WpjlaM+dYSLBzF}e814k4K>m3 zY`z>_vw81j!^K!^l4+vnCJj3rlG{oS27xIH&(pfHc$Yv+8=8v%hGwc^L zi%&%ay{@;}2h&(%c$^L_FzIA5P;^~OFv1CNx%k5p)=zd2e+RsB@VKtC88tAQyq(SX zR{Kzq1Qg0zY}lrJVkm$OOoMu42`5DP9La`(`Q?{zO{1NhhQ>wIqp21 znO_|J2!`(c&@x8etEP@AaMWf~`3o7bYyn;yZ%OhOyKfx=+rj2+%V?7 za_bURu}_yw#4GJ520gSbg92K<(jtaK5`z48L9ok@F>q*TiXi ztHzLNQVpI^a zlPUm6q3!ITLG@=Zi6Ma(*)iI8wSjw+xvReee(hDi#AO&s$zI|Rm9I;1)Y$gfW;PTZ zeOTM%VV{N1bD0SEBa?1}wx-z6Lw_DL7f$^0*k6Q-cLwRN($%Ac;WyfhN;YqdILLx5 z%jRxsrs`t7RIcmmq5;KJ%6!y~xONw2R9ZZ|1BpcT@%%DXt6zTHy>w0c3uX?ww=d;k zL1K}_xs}dw7=#h&kg8Xf17c<~62)QGM=Y{cDTd_Ob#XGdP=2PoR5<6+O- z({$nb*3+N-Z3Q>mC+%LOH|n?CpN5ExP%;OV4l)iy84MfkeyM zqY1`yK^-AWu;)@V1=bg;-iuSt*r#j(Swi8a*>aXu}p*H>dDVDWBih?8t>9v zQ}g^$#yhXmuX|eyoS=1c%#yO3;YNUj*=cQrnO(=+K|DPnc8OI9Vow-Z@2 zmN0w4-r%y&aTuhlp@fZ5&E&B|>ImvFqCz7+s3!mrK@=H0ijNQ>U=Zcr>+Q7;ZR=5k z!Pe~^U0~V3&!~w!&PRN2>9i)WWAu`)S0&1+^irx|iC6Cw_!pK`NQ|&H8eU z6~@ClhGwnWjZWi7i|%12hihHdd23{9h2l|UTLeC9#LCvdLcc zyNjWjQ`k%S`F6N+byjBUI+J{motr&rqD>5k1CsQmyCG@wB^1we?t0;3{VG1HoQ}7v z4|?d0Z{R$4@vii6TfmYMZq+66u2{WlP6k0cvWpv1H2htKkXM*=2=$sW!$D7|Efzh* zm&0qRB~)}sONc*(Gb|+o0^nQ4%zf)>B@U&wiEqpu!jooKDMo6blj^eeJgEvf=K)`# z{T6M@Ih2}_3Q&Si+n#&`F=xv5a5`>-8zvfw0F55aJNI{9ZT-_@-Ncq3^CIlg=PDB_ z%Ff?>VKw&D+mY~M+KYFgplVhCP-8`>si-G;bzNDziy0u81<(H_2TaH~6I@tK(9Ty!7@ zJbS*4rfERfIFMUBuSY%b`M+6=2=SuRtspn@A=VH&vZpqXGotwTZ~`*F#O0sT-`m>3 zNIdAad<*ml(|)8cWyp)Xv+qV{ZPaXgV;lrv24X&~e<9|*?I?1wo%s1;a^dr8S3Xa$ zrokal)Mw1*)!{De_cJ+Ue-wLdxTsZ(pO{s%)eF8NeGhP}3|=hWJM`0c1()R_o^5kh z^2ikJykY7}az&t>;^ZT1n4fS@jl9%vM&4K4pQ7K{D=J-+`PacwR72knOEiUQ2;?H=k(#rsQ9XR-_{;Ughw)3jACCQxA!Xv z;7@I_hhaCSW1sJfmo_x z$5=t#mh!-yS9KAx22uGxR_osT895#BGGR zbvnFQN{#juzFnKFEx^yvZlg!vgclu#R;4<~Fe6&^4(h?z2Z!8qUUSzImA$5>iid%4 zzCCPAm_YKK!{g%A2RVb^z3D4L{rq9>q$9e9p?0(Lv5tt`Spjan-4+X*bo+NivZ(?c z*OQ5vgEkO$t5AEpw^i`vv2doRy6Q2eH()07fc7~HcX`x?ggCqhR4Co;*& zS5!l(OyBc>UN-1nQE{g7mA;sCarE|Qp+a`N0uNNLcdIa;%#)!JDBcQl`>Ydq2v~7G zx^6FEK@7$-w#)~YszuXypu~sAJC#+!S>vWt$|`a_$>^YCIVTJ4Uq8Qc`G1;pn6Eul zdTgPIw}=Wu&|~&_`??&njoTFdyYlN1={82#-0V4%w^4hPH?^dXnzBxoK)dZp76pE=&W&pJ7;(?Y#E9P-d`bjc&M!s#2a4%7nY0)Y zJo`**F)$ZO9?+L&aZacwJvuLO>GOhP@C4$L8%ygGd?c2pV(!R_SVf%4CuRgr?Py}WSvgX5iHM4Z027$_d3K?+E4Hu@q62sW~!Flb+dNIwA> zs{p0Qm^#3R`XzdC4w-KpZEF@z2^ba6vR6t^nnr~n5bE1jjPVWBEjyKf?2=Q^;;EAz zNT8OFvbJ{;yOr+U^4*0;zvI1YZe8(rsp@6^8BW*FwC||fW1DAtVtL9 z-r6HK$AyDJ!SK&kV_gwS)zL4X{1z?L&IcRb&AfM%I!%E9@WA0{fqSmjk^u0?a4J~) zz(8E$3(4R^Tg$tB($^fYsWJNGBCxN65`pceS$jc)2yA#;TUHrD1Tnv4mo>cv;>$M~ zp)A^;HS4Tia(U&3T#Z&ku;FVBMGP>xoDLG1jcQ_4TGpXhN_oAq12CxkX9B0g-V9i0=PObBC^I<+fbD_(&*1@x9i?M9B~n?Gm09sr zhaX#JZMr${J`VW8pm6;Iw)!vyIr1FgtRwIbxeQ{bowOY%`(haLf1L}uy@6HgZ zeC%1cNDdHTwf{POd!atmL~r!TvEV`l)IR}@!%#IGdZ|dpOX`-e*f5+vAo(g6sf=fb zCx4!tu{9I}mE18;>MOlgz(eq$fZ^XHw;-f>kCMvk3{DoDj0WH+*&6iB;n#S+Ox8hy zHckcF8w5bR0kM}zn2T8NV%wZ+Dj#F=(`B)!iPw)=;su$n0I}vmxE}+dB)-U3{mChV zX@ie7CI#6r5+SGOl*K=`JyG9OA43w22brGt}Qf8 zmqm2Ofp;gi7rP(??+^wRfx?%B<57GN?9ykeq>|LV8zVM^$Mf~|WU2DFDQ7M4x;m+W zcgb~#r$j4*y`nJW-g=KO0~CrJIF&QF-yKGw#J@-(eDU|p?P26z||$tt>azW>H42tj7g>KLb2*h zd2wFllE8UCc_!w`rZ7}re(pXOv!q6rWH+Dt0k#}}W(grj&)Pu<9{?|LNIa;@(p3m5 zrS~C!nt6TW={1Qf(Kh?yGo23SNPqHEP=EbvYp$QA(cAMoey#v;up}M?g1(@wFoqy1 z&j6dH_m3V~^^ih=d-g}^HNEmJ=j%ozh#Ef{{(03YlC|9z7gJilW!6yjRRYM3w*FKu zM856^Gt_&%gFHd@fcZ>=kp})-tlXgoxoCnGIq=BnBSr~2lJ%tnU;JOb&Fb)f`NaU; z2rH~DiPhNTyiC)iJDt~Lzt+-WtrPVb=s4`=&c3qroG+;x3+KeacH=et9wlrqO#1K| z*bqU_;P_5P-)8r#QJ_(q@O+(hJ`l|V#nUCo1O8BF4IA#}U`*iip;y(i{c_I%!w&yf z4pAflv+|MnK-vb*g(F%(4(2*^%(yj6ne=D!KSC%usPm`dpTGp5f~x;=dIfB7c@FYF z(EeKL=bu>w%$WnWKmWfk_eR$#ip9{gFz*CO85gsD`eQ03QMq~hb)!&DDkstZLw?RbzT5I2bto1)i z6Zq=@1XRXk-a!9z0V^C(q*<3-b1(mL6@V9*k@62{XmCgW?`?|Ve{CQ9Keq2#`2T)) zKEUwjrhGgAPR&0TDDZ)^^LgL48uwXCKYxWd|2YQ^SA_q)EeHQu!XuE#o>`@tXTkgX z9gzVr6{o_?Kl=e(6K4aQgW#!k6TngU=U@0({Ud|BN8JDCHuk?H0NUqgN2(n5zbgS0 zi&a)R^1mnY}a4?GPY>{e{M7TtN!qV{>mx*|5?cn_2OrJjDKGs z9Yqn6qtuAZZvM~iG(1O<04}0&TkpTOO`<%zd2Fv?K|CKjkp9m~MnDb09mM~>Ae8m2 zPO6E;-2WqE4uC=f++<1T;r9RDR`~Z6nE*QOe}eZv!TXnN|4;D#r}3V3_y08B|4i-w zOzr=VO>M%^VVZzvvVdkoYKvBVGJxJ?02rMOcXO^7j8&(2nqr+bFS+pP=6o~!oqyU| zVzyW$=Yb$}=C{&Xt>%EC44B1_!+PnHs;=i-$Aging$P7%R64a^i7I6}hJ@9s!=vWlZfB)k#Nk|qQ*k^m z(v?2IgPH7PtH9ahc**mbjhra8EW#tA6d1S#5KuMFGXlz!As7LfRxRHbvtPufSKAg} zNWv^<_qgM@(bzey#{M8i2~;uI>N-~2gWeS?>yBs139!?Q9_Gr%^1DMPN?u2ROHn_c zd!}=Gzb{d*iU0zh(q&Bx^xF24QsI7JNvYxA3T-MO`O!f4yrS~4a0bK z*DsKQ5vVvIE@pgv5=E|*y(JQWiEiRnYPrAjYEDwMP;vgcq(J_W7@y@=nI)sj!-o@- zY%0_FTEX2sg3z%I3Bw10rn2sHz+Ex{Xe$SKX?Ko{e6nNK9Z1h?CIt!w8SFyB=cWA- zP*l~q29{eJEu_t31m0J=oRR}!DTOOsG*ZIL)PCpy!t5!`#zF5hDUZPM_^Y?a?q+iq zBHs>|S=sI2&DM~s8L0})ad<2G(DLxjReB$FeF<;_ZP?Aw-=cA)nxD|%ltrh` zP+<}2L|K9)?dXw7;CVU833Mgq&^W#6Fk$X=yfLvlS#QwaEw)2Rlr$#7&*I*dAoVw) zxuMMXH2J&V3qjg7Gq&YSNbbvY`g3NQi0QLG@QX3HsXH^D%y>JO;=%`4^2jv1kjn@8U77Neoo@_dW_VxWp>@ScyI zSS~7`7H}tUduL|b{eovICQaV~N7D39Ysm%0&rhRJDIx#Dz=Q`NCj5!obHf)rHXdms zzPpM-OZxL8f{iYgtDK13mmvlfCQj8*- z=8X^L(AxtjgNw;MYm>ob$7=Iw;&nXE1^Gm)1_+)q#Dhc|$SjTMjw6^nYrHzhl_q-v zNP}#Ejg|zOo96&=xt?N&$9q>d_W>6k?;}3?x92_f?%e!K1(`s??7G-45C~$MZl<## zYPmn7z13fr%R+11-4X2G0eTZ>X0B1=^N{#Pqp^Xs_P)TiuuCsEvQ<)=@fz4K{BA+#qg2}iAT}(2y2h!HgYhBy z^G4f@E%xqnSo$miOR2)Z6{u}3xwzz99vg1GmwY0=Q%4p;7wc_oY(9M4D3NSJY`c9p@A7I=xi`zx8&%z%ZzNn%Pu=D3x4V4n8{xi!{6C zEgt`LZB4fNWh%xtF9;%ONp2IZj`40G;ql%+|8((gH$Q#1XEghd1334n$*(ZPp5eR; z7nx9#pTz3Ta@n1^%FCYL1hv*rF#^d6e1n@Jm&6(05zl#n;R>lD_s~~zByL*+?;38l z2zG1dLqI@gQeNwmfW?j1oBH;ftM1VgZ-T31K_Q@8m=c`jaCOui`{f>IW6+*R8K;$& z^7vO8%ePm27zf+){x7$Kz1N?s!EJ}EahCUs!k0T5FebA48Hb4vPAG<*w;G*~1sXP@ zrGjn%i|Jq548@lOj`~NGig8BRw}r$yP;$M#m$?^F$Zmaek$W|WZZF(Ih9g|2Kv6sF zckBX*d0N#wpt-a8V+SB#qrfz#duN)y^&O9U&Bz?C(SW#ep;Ar&#&nfOFj;+M1I#oxIg#nOEtUBtP&@xoi&%h}&fqU=p}7(%p3icscAE^Z7of*bQYbh3hJ#e*a@* zP9p5bnNJ<98ad+ntC1y=vsJoVYNA$QlUHen^Z6URZWkmPr(KeB)uybLPxgVfvN*IV zKlUa{B>;x6zBu}Z+w{zV$KyJv;!&${O4zg1a4Cs&r~(8&OGXwSLEM2L9A0x-b6gbE z_+^M?ij9w*x1@7Cd@54$wB$?RC#?oW5US$2K>}QmI+H1s6debW#*IHG!Tn)fjHa~4 zxJl*Fk})X@bvv+OS7N(DIY^(U_;q@&=@rmD+*jJ#@|vG?jmT~*$fF#W52O0Z=3wd{ zE2>SB_p%>DaBKpFY2}Yc!!`LjGMCct$A>GfNyuFgCS4TgvE#*R>Mrb;t${Q#cqDX; z83xXYGF`y59=*0%Cz5GZ$GvHZ<^;`A_Y}`hzW8KsbN}q6Zl1`^UL}o24>U?2#6|a8@g*KZ4;^nj zf|wQC!C)ZUTzb`)Em+>r$&-?x5zH-L`l6@n0wD+U2#0UfbSg8LEM5mG-*kH)3Rw@D zQL`bIjkt6ifJBK(2_%^#WZS%JnQ=NA8wW~PdCy|*^xFu^kW#yw(z|3Dw{@y#5;m`6 z{HA%FEN~SI3XCR?J))uZ}LU_?I?J4eK=9lnU$xW}HRQ65USP=PnGkiDi{D z%}eW(143J>ktGVZ;dve0uJ-oSz<#kCt}M4DnW8IM{NztlC)}&CGw)RzozSuwU7pI{ zTaPqfEp5h5+7fsVyV5A`TG;n>`Z@t|X~Nez`Cx1NZRu=uqQ>ObxV- z6!+r^-=xE*k=kOQV>?J~rrsBe*g#H7J_?Av!0?^oec0ix@ zwF3~_*n~k$QA~rmFpScG-L?X~cc#&(__cHYmj?YvFT z!JumRnPi8|TPh`Xn9rbiZPS*2V+xhd`o^BmF`Qs!?#bv{l$koTyVLL znZ^ZonJ*)l0?X>5?`k|?(@>$Nuojij;ON~|UZt`S)^DiPbgW~j84&gkl7cd_mSV;j zELLK=Q0;FT*l#0*KMiy@tX2P>cp!K|!^!ZwmTU3-64am@DUyY9zk8l4%)7t5zn{hS z4P&Gt`7+nqp_Vi8gYo(wnQyM>-_{g7xV`|zA{bIedIYS^GS#*zcoIR&4KcxW!*1SL zm^S2fr`sWKX(6G9!q}{R^kjiIYc!VS<0g9>w(+Dwlkfgm##nCNo^Z?O+I?B$Ea5s8 z7m%wlF{eBC)=GEp+)+MgQ$OvZi3uEMi@)cXUzaKN?9GNf<<15h5-xOL%zg^bGg4V= zMI@Fv7*y!ZZtC@1mV5o+j_NUjTrY$W9*>f@ zRS=VDlk;?foA^TMh4T(%BPtdE=KzQoErU$ED8J-3m3+t4HEpgOdCub<{pq~_eJ;Gc#wch6p1K*0ABO*@$~|yi7pV2j zI(tUhEN|(~H@>yLjKr&V+~*k2@8Vr1WDe?!qqW?Mc`18!?z9}fS5|&!rN%i?I6jg^ z(icZBGyNic%Xztk)6<)9rn7x)m7)>dAgzO3<#gxJyhYnM*a9 z7hj}7x#u1Fslg%JIPPs6UON~b*=Wt<0DHF4I^F+$lZ zT0AMu$E$2=blGk8Dss3Z`N z&y;(6_m#AXUwny}t&5eJZ@Q&Q;m{3ZD)VSjhbjK>>6Gpb9}il-s_w2;M4!=c;N@2! z_QQp}1_Y=~BqN0)|2*F2n8Do~___O(UAineEA;i^8SD+9d&{P9yM+M|E!^m9Qnrp@xCknOUw#wE2UvmwGaT zRYMkw4T~N~{f1xm#)A`XE)#h*f{Z6*}vRKxAiJLC!(h~Yxn7*hI zYhptS%Pk_R_9Tp{g5K{T#>dn2cTYFlB&@>#N{e2?W13hPh8{vh@)N=y-qKE29-mbY zIl5%sux>H)I3LDQN)i zikC?7UX1Rv;6B~n=w%&vs3fMLYUICbNbF$BxZhzu#=kdOTK0M(-%a8m8t@npmLbEV z34YhV9-4AZv6{$KWusfP-7%KiKj_)SwAu{$rd~T*x4c48gQg`0WOWdmZoLIbeF)a0 zs;8A`O8W`;so3^UL)wjlo=^Ao1C??J^Au@Zwqpy70b^{pVzt5u_lb8+bST>~u3EM4 zmo}=Z^{|4nbRhae+(nO}T%zkQ>&dTz%K_*FaSmr+C0&n-M8nfr`t7~gPj8CB#`i>T;id*U zYIXJ=L)5|hJ+u3rP0$2Cho&ZzYJt2MH9Ca(c?fHfz|4YANn%+gfm354Y~@?jC_YqA7RW%klKB zntfI2;+H8w3PtoS1TA%{52zNuj~dmXH@I8Oz_>xvQ~ET1_o=mht+QR0{!_n_auVrF z_9lL}REW&4RJ_T)wd~X<+mK_G%T1fKS+U03efF(YrRH|8FTFnnZ=4k`ODdp{2O$ww zjI#bWCB#uq8>d|_%j`gH+hXT9iH<7*3YXZ%TTm(91)a&ro;$+_&uzmQPr>5zPN|Hh ze(?ijW0Im`s&sd65&=4Af`$5{ru3_d)?Tn$OyNU&%h#M0AY%Ldyj|xBRVeZUYap@A z*6aQK7;WqmcBJ7u8cP4WCb?H(dOEE)v-OEyvo1~_yoEa*?BgHo8t+p9x+eai^{GYq zh~-}9K2>`UehRJ-CsY*sOgL*&KI-t z-29Kx$i6OZ`E^z6llaKKJtS{W|Afbzokhk}a~luwiKRdTVa;H^<6p0{>xKAz++gmi z){7_csDUH&AU}t2u9{Eh#ctmg;l5G_!(&efF<$1yocFZ7ZrKf^IF+GBcDGpxO8hg3 zrIa}r)BYBkff7eBE!=DxzsYSP*32D0e-mR}OiA!q&HMeUj#E~_&4Daj((vv$L&kxy zZeUPE!J8<|3tuH;;IZK{c5#$W;@RCHjH{E`H=p3-$x1Gc%8VN4r zR!N8NpKyA-KmW#>?k4aV(BM4R0=kd6rkdLF)^F-tRuQBtPOz+F@P)+>3LGSLOYi$O z^y*5$*7xN~0-8i&*oakndb?e7XEmcrW;yfl(;~9$@*r|m?||R^ikqmzb{^nfWE!oT`G=SzU3ixV zvTxrh0Z>=wvTP2m#^RyL)DWO_4jRK9C#kYn!c-!A{3N`byh9hf@2_pEA`Y&M1b>1Q z;die66_f5y^3N(Je5ldQ6g_t<83v?p^XnH6h81IOh2lNcp%mXtnA8!@$7lN~&v-7B z$gaFRYKh#~>UE#J(6pA!(?T)V*QhO`=jZ9bP(~i*MHd_z_VB&^)$M3IUhhf^;_E6E^*7{E+>3rs;HAzd9}I=Iw>OBKi(N=@L8@3Uz=)Oa5*(`kViFzdz3AOwnQ+ zEtqGJxKps->U``qPQ3hv7ZJI~FU-R}EJ+n@N)g_>2}v3vi*lzabmnpoS^7~#u6aqq zG*H~%a6DD?g|44(4I7!=7AAlv1kE^_GY7!9>gaF2ejyILlPU4*3wQlRIXT~plRXOLTpHHKKVpdPEEC`-)weMxeNA(k)eCVGO8&gcvC!{B& zgTUGyd^}73`Wi#`;KmZEE{8|cW#S`aa4Sgh^GW?5*soR+4-vCzR-<0V*NH&+qj%i` z)=QjO5(9Au))Y4Z1pCfk;Y?lGlM;=DAK%eIvg;tHf@g$aR z6_WFRwCYlnI~~ogDbraOF_i>PzgVrEWW#ax%q-4+Z2Ym5!Qcn_nLzN^veXECuXHAI z26AeP_UVr9s$1c-{qybS(T_-8BWnN|(|)zWQufNsK=$`2hI=;2*b`m33vAp5PUwW;_nE&oCeL;~!;lw@yq958vzh?zYs0wiNK zhJUgNQpC@!#p<|o9bM6?+`l!kw)^c*CCWmUN=Z6ry!+Ljq@&q1n#_u-XzCxB&0R19p%`;R_4w_2M^%rO5r|2TC6Vrq z=)$9k#S8{n>g#IfWv@BL$LsTanbwho`tv~x+IYsSXV|YiVa`RRFrX*# zS1VQA&!0J!Z*++aLG_in5Rp6M$;J51;}%^xzrZF_3j&S}w1%stM!LH+l}-_kTiwfs zKMb``TRpSs!*!ufm3q1~#oaXGq%(zkj&KTt+5^ zZ%b)m<^x=k$p9~Qm{D2rVi=(6!kmt0#SHqS=2{-)up*SOey8HkrU=d^&hd?R&=rEM z$MeGSv%Xj}T|r*bYw{Zp6s58nqbqvP6I-8Eo4Q{X4r>kbg0~wy{PzMRz(uZSKsVhR zhq{CL)Iaz=!g8iQiAd5ya>BqTm!3aY1n}Ih<&(z_iA5h=$300Vi;QvIGKL=Z-e+mZ zT3=Brw2M>u1D3{_;sOTv2+fVb-_z>VgNMPAK$Ml;i}3Sn>}Ll^&CB=#g+{&dN5#QK zdb0Dy{O^K^H0Pgq+##P&BBLI_js2r1`VVO#`14a`%i<;T)tvE%Eh$F*D)M#2Wywaf z))zJp$l@p=OxM&(XJrnY#koT0@<{u`4#48}XThd3I_>IT6DhZbk~}Jv zqNF2x2-qZNrxyJ|n)k+FcUdT)vVMf7Y{oYirb}GXvd(Kb5`SPe^j+P)`?^X9ggCQv z=~Uo=$RHw1d;A1Y&-eoPBttI>#>@V+i+GPNHTMo@bc*Lwz*UEvvu%6YcaqYmmR2iB zPcpOS$z%{%eLVO&WUE=7EYI&mfgeKqwwG0np?kQWq&VS>uUtH8A2Mo)LBNczs_jT= zJQ{z(Cr==$D)Kj4Tkizx6cnXWFdn*y_S(a*pR-{!=Z3`lljkiuoAj%lCw%2nrS{1M zFuyxQ=b=0N0j+b;Ynp*5%!vJ@+q_LF{Emc$5vLTn`cRJw9$D5V8Ys?VuO$;!bwrd7 z=JXZ+j2MF#9^iGmyPeUkWNqPR3komrB{yqRDoeOa910$eAIJt;#%R%hQ};T&gslcb z9EO@qVgb27)fCcb%vQqqNy_YPG;i+A@ETK7rCOgV;&2#sBxzgJBzT<;>{#?Is;(d@ ztOLC;yuXqK7ymf06u4gBLo{;9fVfmTCI!_MP)!qx&*p&fCidnaolx!4B|88*2)jT3 zv>^Qd*n8`yIJ&6qH$Z>@0RjZq1b25C5-hk3!7UKn-912X4{pIFxNC5C_uy`W%fQ>@ zzVGL$I)9vVKEPYkHAN^Y-Fv3@?zOLVt>20ixcgR-c8-YBx6okD&FNAf96fvN5WC~? z8^+H>j7YdhAhI83 zwsN!!+!$ELov=P#f0K8^V?$5CiKHP{4+h*$q(L;-17ii02KFbyuU-_MG!oCuG2JUW zF2OTK1v)?H?#X~!B(#t-Yd9dEA;p)InGf4mc2x#Uph3Uw?Xy^De^ekl7TL5T7Z&~53UNcENaWL z&R9`C@{X4b(-4jnTv?i1EiolGo2`vEcbx{AT`!k|#KOWv^*4`wAV9VH(rJ@QnaXqa zCD{jRMF=F3s5w12ZgW33p?CfYYg{g7mKY)sF1wbz!YJMnVLX?PJmim|RT6wZ7=)at zbg%K_401cXKPo1yhyW3JviAgFB=NcodD2V`T{X$fj_&gU#>%U#xQUnTTIXBC+@j@L zpD{RkB|Z0Ibj`LCQldWsHd^H2SG*7ZI~8c2q@MX60Q3d>><q3IZRIz)0 z|2IwQshg{bqHkho-$lu3LOX#_3{o%%l;Cg=G#u7wq z78S%mYSu-9$i7WQ3t9^}OD0QJ>=%z4@eRijxnJ#hC@H_gWMQ5M= z8TY9w2kuBb-1A}@bj$c{JPcNq5~F5pKr*b+b}Md z?g%8;T+qW49wk{8kkeisjtA@u*|f1LaYSx*(oVg45OBMML+87&yjYz{ondmAJZl=H3g~#2sfYEJ?(S0xblQBbU(ZZ{ zNRatNaY_8&yS-t5kn&lShiu%BTq?rlO(BNMIc_B+@#1An#&nY^jS%q;SrGa3kW1Ps z=^7n@Y!Z2k+Y#BR!R>yx!)$6c06Jl71i@V?=*0yM@G5WzqHg*P#Yjj^!;wAnSgoZu z-=odxc{&!gd@`Iw0Sve(;`XjM7s$Kg@-Emc;QgXfjy(FhYMC;nVCP-$`F`+>dh`>g z>|RlMe_epTIn)k;R0?N&MMQ zl!Iud@L6(K@Y+C7!N$kCk4D;uD9p`s{=h$7U#$RuxNAJP#-YHIfCy9r$0rmc&K8Od~r1XSaC8NnXUqCvOSwt%nEWh!TT zI99?X=5|S_tp35S@c}XhCM>%8%p~VDO-SMXJI-xH0+P12(GP4S2~q^jL%`T!mJBXD z%+#0f8da%N2=H>{`t#9bpZ4jOfvU6VFasWFugKo{o2=9hq(nFCb!FB7gMmJ|NRASD z!*3hMZmiX`ZSDQO0RjSMM^CA;jc|EiK>^A8U{n^--+LI(m0A6G_aCEos zZ1jpCn-=6&gm)t%bd`veqQFRoJ;Xx8Ce9Z@;O zX5ug|;x8Vy5=x6#R03XxPUh}bFo|Otl#wkQPw01IplE56XVGKr-Q~fAv^HO(q2to= zbV9ZnVfyDxi}}q$1EO#`!m`$Vx`CK2OoN;NlZTv%uLVA|HD%N-+<{DkUP%lD7qOl- z50yVOgj9e~=sN*RjY+!&GS~7@EC8j<@LsW)THRYKy!c{|aCM*)Ly7XaOmUPa%|1%Fv7ACVNjJrUD4@3p(lfApOn$}q#1CYn!Rkzvl`aWj_6aq5= z?bc;ws9c;lTm`GBH$qfo-kYjrg?w)C>~0OfD}*=OZcwqhPudNZe0Z>X(MIv-e2?R5?Dk!><$anofk?>oAN;d}OCRK3S56 z1E1L*MfLphaTo!mMt%FT6>gaAfZKwj4xN~5VClG;EU=dA9C^ntNv!5wpfy+B`Nx!6 z;&8TU^O-6O?>t$=$r%7^#co#p&_4exqCMrmMuJo;LperPjl9=Aol2c-wKQqGyrt z1oY&x(`~rb(31*`$AH_qG!(;qsJY_|*rOcKu9ULZ6{8GA9GzDrgPq zr{l^)6l24a6{zG`Exxd8J2~lC+t}EShfewovo)5CrtXa*wr$~6%yx)S_-5;ib0OsCA>zh)~)L1 zBr?+_YXaB$aN}kjCY*8euM*(v++QXfZX3<4NegKkLG&4qIs11UN*YcD#^`Hy|5uj9 z^+e3aMoEdwgnPu8YjkuUD>_Ga$?lO)0&(p}B0T*bAVYo>usMy&W^{UcD%;RJzF5n+ zmAKyt3z%YnexB9~8ud288?3I`-xFo;Oji6T+%t!&_o{{<2EDQljLdme(q{8_t{bB( zTtGU{(hkMRj+4R3raXDGox4d}mI{rYVcNGYG5{ z4M~v)Zvg69f_8mhLm5w$_*S9L?q|ey&=V0j#fYhR=K^augSGD5kB;nc$2U28aWsMn zZ2*Y#>lz2Obgq}(V#S_dI){#k9?0+Q7Oz0Vz$|j=ve6|K^5|-%-)$r)$PFQ{dBd*U zmhY6WS-pxc^y8t_UUNEAqK2fo1VO;F@`ioT3ddI~-7<~OaiB6%^``ElU<8od^-E0y zWvQ_nCk26~&uRbo)S^P>+Ec&ppY$$f_o_3v2(IS5sp78^6>U<#W<8O4zR!6I6lz)3 zw5QojUFQLpQ?OTMf^WLips|LFqiUJpgXgz&Kj0jEc)yA#HC{>OTeEG20%o>kb<3))Vlc{nHXXUYxGXBiHAL z`B9RW0YfQu3Rblqc4M&@{N=<=CxK9vLqbQCs5M;Lt+V;IbFo~ES`fF{MU6vUutiyCuzh+d)jPGNZNH_x5Q&>)S;1`Mo{P3Q_kvk+KU;5fZt7lJ0R7@4 zrvu4f-S*?PSjUb6Y3(_>pQbR(lM4tkhqWE~`svSHtXZgaMm`l+=)-gLDUy6v%)y5BPxTNaCvKgC@jhi5r5q zlwn2|ez#2=$?{cRB7&&qknn# zfgU-Z?7SwGUf2<`N3K_5UPuM7Uq7KEHuuwa_JXN?a8sYGN`uk@=q_%CKgF~2qfJL= z)dLJm!xOktf2gJKNZCxRWj(aDLeM>?*O*X?)O|hZcai5Ztm*v~v5~I*^6m9_`qZk- z2$syy{9xX+BT#B6ctacG_);c!x{9IFt(f4uH{p_(b!L8ygccCpZ~tyvzB(`{XCFI` z0&ZiH&vCqg+0Q8mD|EHAyOAT3o^(|x>bNJVAxNeC@_Bilc@&*T6vS>yS7{p@gF7ud zy+nG9k5k;=7;am460B?c*2Ao@fCbw8l7W8B`qaWca~BhP_agM#e(ddHyy<9q3l5Nh zQ1s+R3_zD#*j|kR%!&-5$r<}1Txf1*$x{jM=0^`M-UN?ox;}VW=e%4g(BM$>!I(81 z`xBjqO7dZn) zcZ8;MbRac`FZQ)PfLl9Ej+gjZN$q7scljp47?lp}kj%n|nrrsk<^*GEXG*U9Nq`(J zBXUW{s_AY?v37Y6YZNZ6pvx;o*NqMi^asURyqzLj)Q;8H&qdqgY{4B-Z0i8%CMbne-%Yfoy0-+KR zcEg&RJt1={ulo-^heIi#-vW1S0+#(0x7kH`xjiTJ{-mv1ZyYlj-FXL46(Iu1z(!W)^Xrm84KorzdXttE zZJaQcPM8ctB@BlOpfil_Bx@%nJRVrLQl8aD*F2=vO~Tub*f)V5Ong}r_>FhR9@X8N z6-C&YnLPlpdYO25T?+=pdwHIhyXlbWAqI;!nLYk+UgJ88 z+cY7p^HMv)>1zGk_X9sTiz{gHxNE{}AW?XQJ#)`yK#CoXZB&4_7XqaA4UNiNR$G)C zAfCzvdN7#inI=m&l3nKuMZr6bqkziX*zcI+EpptLUt|cn?mj=#09O!(#?&iJLa^zB zcQ)etz0giwY5X$7mOV%W?ml_aG4dD=MfrN++&>!*7i*!kpKm6=czr$BdJ;YfV=np!TU44Vy+bSZr}k5A;Y&x-!2oQ2?j$=wEm@Zq*c zqpw>hibopLd&fh^?t!&j+0;$O6WZ7Z2tnHIPAIAuHtvgUjz9O5w zO7QFf=lHSZ4Vcc+WRoDRT9n(-K;cTyEyd_8EIj17wmnRsGqCx?^@@8!5@@dD0-rSM z)h1iz62-_kB1wT5B~WeC`*@qc^>~9Ni_;tLxFIu~VIgCgE}4Wre{egqJs&|4m_nVu z$|WQ;>yK4cpxA=Eth%Oiw)jIfRT_kuVQ#kWCYR2kvK)8(!!u=44UTu07WK_!6w)s3 z`{$hKB|YJ&8<5=#*Ex3!-`RNC6to6q>xKwPk#r6kzh6plS&RDX`zr-}f0>9khko9a zTl_eqZe(+psh(N#$WO5@lEWr4KsA8UaPm{Obhqd2BNWkOA`U+oR?+lDN2uVCrH8z(@{Q&buhYPz@ls(#i9cr%=5Zt1hLl)* zRe>7u`tyzEy}vf?O97a31qlKCjwUgny-**fT z!x;VrS`8DJynt{eEWmDQInMeZz#innM2qm2<-*s)XdpSh>>99AVO55ka6CJO^?L|0 zeY3>b)p{ZJy+Bhek*-RLB+DP8aJTCGpvmhPAm~M*gu4Dyp}y+8H}O8S05DI=ucHFE z{-%Rcwu`%B!MzZACg&md!@0JppP%{9w^wPgba|-dTvCv+=}hK{8BVFEIuS5TrOU4I zO)7S(AtSpO%1ST6^H_+Bukm=6TIVZu+Pt*gvNr4;&bpHr7Q3Umr|L~ZeSF?e7wXae zDQB~O{D|2}$$uz0-!%e%_9MAs?LPr=OK(X@3hSAz=RqXX?Ye}?Z%6mJgbY^92v7Yz zpsS#8>7E*nMNXcPnBKf;8QbIC=+Qkk#+b=JAq(9QKaS1N>J0niLr^%5$h%SjtBy);=< zk3>G(aW@{`zc;n9X)>ZOmsKWGy>q zfGyD9Kw}E91&+aa9CxKKvt_{!$`XFYmhkW6%@EqH9uZjI{0iB|{?8 zikaY1l*#yd`Ea2nDBWs&#^Z%i9pmh+VFzG;&5}tfX_abN-HY|4ZP7h8XnwI@t!s5K z4i)QUCZC-K9B}}}FbvnS^L9@DW`KT~kvUB~TVjqXA1EJr&x)xA34uJ#>N3{c6m*$r z8-Zx%VR6!Qes0NBJhWDM0=pz2EOIYL3n#uNv38Pqz~s0mn8xKl!f$vw07Tpi`pOKi zz5MeIzMw-cEL&nXIt+KgqiTG&w{CHxGio{+%CbH?p8aj8(E=xn6zSKsme+pxFHbJ$ zvxWRC0YjgcV#0Z?C&UnT4!h zb}*<{4k>+;XmPtMH2N{#J@win-R?IIf9=$`C(kI9vsf_*Z8Qe2WBk=zC>0RIR~Q&} ze53s_KJCI!-8u)UNF6a)8MW>V-op+*iS_6Vt+QW0ncUFdLJSpRUIG`i*v^Gb|DP zI(Fdu_1R*AfS-EPjxGmm-rJx1?Lv>>UqXNiN6~^d+UMc zr!gAfTC#mqTau_)wgJ1fG9x93xecKUV&Cfokob`Nsd^0r@+TSs`!LM2_FmsPt(HV3 z+TPqF&3kvZM(PDiq4VT07ehnp8#-^HS^pnaOKAm%M~nU zM)JMw5A2lP6v%DM}wmycaO2`=+x96${w zjF4?@dp4N$pwdw4tjHh)sEI+(Ly%!i1ceGELNNe1W&I0M#Yw72B#69%UaUrmAdMP`jPiQ;DE-iGWb*;$>JcB?XHi5OTA(5psaAI?BVTwUy4+6J`PadsjuRG< z;-DqSVK++An55!6oK`cHQJwoJ$v`q?D61eIdN`5Q`im6H#V3xyHw+BoYsgnB3iY)u zo5lzNsq3xKdsM6EqCudb_%OG?oTSMoMh;u37vRJ>uNQ8YV(+Mv*hb6+u{yI2_<7eQ z_E=w+3OcA?4HnpB!G5`njg_sl6!62V;<3A-*}}kGY}Oy(rk02RyISG$*Yo@i9)&+1 zTmo>^EK*5eb>_t`kLI4+o*h0QA0J8~cAgg9YY<&|JImN}9pTOHVkW@sNjqpyEQb_C zEDyg=weoevM#%NXkt8rJHYM}5VPsnJV%^CbbXIhHa2Sw5)YT*n(j?6?Ru5w?H3hm>6U{J%0wc|pKPBV0hn(xJ&iHiHCdg3{y>*t2lYT} zf;4lB^2>T{VvaVAQMDWJ=lgxOgW1)mIkOu&*Xr-huIGvD7zMXWKURq@BX}v- zbzeEsM;?g+PI8n9Oqg9o;58m+ZPC21cm?-NLgZuQz(Ry>j-)Nd%1N23Lue$IW^udx zgAeR<30Z!|CC|1J{h|sJ7ZF>aeps@~aN+gMcW><*s|XN)k62u^((OGL=8vBH^-sFC zN$8s)P?yW{3P`C2e1TQ}K<4v%p=LGoPaj+Es*YzT-qE)NW0@3Tq8H!eoc{7( z-~3IjKVyqB0a&$?sUAK+4^sltFVQg~yl=jv!;Zn7jiYCoRk&a47*y})Cv)3+&YM0y zh)w0Ml66i2X%Hpoouf!nx7VBR$uAK9EbBJ;p8ez)En>0n=_;_K`uU7xI&`cC{##*8 zACh>AQzW1h0O~(jrk{J1aR5nbO#B6`6rmK}UF2^bRtFyRcO!*Wi8!Zg2p$Y9?4FNBFv zWy$qD$TP;TShXzcq;*yA*!wJCXBXI+4?8mC$o?IG!!t_yy#>IVDgeC4$^>c%01Ge< zP_}b670_O;`vVRjj|-7{vMFAy5*^!6 z?31Ph1XLNX`Ow*DfQ01>kAgc1a0K?s+8*;bS4-K40P)d(+w(@qu-`8DxRdgm;BMi! zT_X-mpn*idi;DsjJPY9LuR{MJa(!_``P-!@`_Ycza~N|G}$-ft*$D#P4SiTn;dx_mn|)WN%1cW+JX;n%p@0QAG`Qj0bDv;KmdHky+1`QtokPFCpjaK7UlQH%PvqrzJ^J zuM1XB=x|-NDKE9ftWD>>r-&rq7D)-${##+z?Z zOy_rW$F7d}!}hM93k$nLu(JreSAo=dE}P-;g+8*YFqu9qfJx3bUU0~KW_o8!#@8RI zn9Y=6VAH9Q>8H?qdMOxC1+dG=qMu#ob|=|KWSNowjP363^^bqZX6vahP%cq$M>d9s zcuw+7igprwLh>Ri8DR7NA+G-eEbGDoW}nMG>eO?Go# z`IG>BCliKsKNW$`@}EQKUtD9aTzA&L5VaRC^`-yv+_3*I&+Y&6-2N{}@PDvx|6d?M z-=`{Ps#88?Ya;Ks5EaHs?C5HGOXUz6_c+gfm8(k1`xs95?{6xNRs(1jCiCL1FfkhF=t20M-kR8f(k<~?Ng@qO}n`Oon{CG0w2{j((U z-+zAsn1Tub1Q5g6Tk?PZ<_)832m;tElIVaO29xaX!DIOHC#CT1_y+=++Yix>|C|MQ zzmfHU#I1^|lm2_+D1a)MDG+Z$KJpmz-^JX>l4(HR0#`!9J0tOT7{Ewu240Cu`#`e& zIT9iM?+^Yt3-ErL@?wj&Ex1zX-xHGoKucj)x^eMTDCK__bDAPty-5pPiJ)DHJeJG# z^0nb5ec3+rcsV`pe1xBQyC0xAtF}U~-20QxG56-y&Js`1`J)<;O0;Ukxh!rJxGMqF zPK=;??RP=}vy1ae=aUn=BTiN6&Ok?UCfr|PDQ!1W+ryeU^0S#Ah#MXo&3`(YrBlE5 zr7&z~cj>Ew0A08T8S9o9IL(z&!0*o~C7wsJ^E?uLkJ%5dbgjJ!ErTwwXAJV5kbWxl z=C1*PE?4vOxf0j;o7IzY(%4f#8^ZoY>$dzs0J@>MAT-YQc?%qif1;Qov{ zdU|T6{ej{Qt#4WDql(dJdRY~>nVNiQL*AzxvF@3&8q-NFroja6^~xk#1A*P2Y*?c% zmePN}x9$UMhmd=K(qWOr!m3`c*1SvE@KEWIUoW-?@=T#lj|(T{?hnA-j;bkRko68I zc?ZVeaXHPjxV25O!g?#t%iM4iS8IKdc*bUY{Bb$(vh3HV`0+1$Z1M4!`?9CXUNrclX$+a85eHPoROkEzM=k4l*;y`czg7Y_~tv1ReBSw;fH3 zA>%NRo$ts+R=acoIybjuo@@psvrIBhrA!0jz^6zO`2Y@wk15nL9*U>$qzh~S*thh( z)32?yprV(h)h>3R$qv6PgtYpvUa`@K@yv3$=Bgz&cps= z8rzH!`{KLIFC90EU(WNX;DoB@p$8<|Ieni4C^c)Vl)$O3|1*dE-ed}3zkHo7NfwKF z1DIlRfYQE3$3(2&B_0tEz`$@xeS4qbebH;gt>t}0d$go!-9n$%bTwm%$7xr-N1E_AQx5YExhh~0vW?v^WoO9jSru~f4nfXmp%|e&6|*7vK>%N zmrAXONJuxTHP-ss2Q7~`;R++jZsu3hVuP^H`X z<>zs0AIBaS?!=HyL3R=c#hEBOZhv6GOaIxfjDV{5Q&k#X_opsQ#jH2o%};KlT6h7} zJh>LzbV0}&S&q20Ph~@{V+I1)lrn*53s~?+)Ow}mY30SNDJ)$FQXRW1Z)5ncbGKPG zYbU{iaAA>b9eQRf58aT%0^3I7+jCtiIK+!+^U_wjOzp+Gr;_lZR_HMzG3ij}R@9g5 zul?TAZ{8a;)&9!Sn3jUkQM*38mEA5f%m`0V**utN@ZZ7gtX)G!%@d|$QAkJLT$_#d zTu$Q4Z{^YH@LZPhrxgj+{C9EwP7E8DuWwv3r-b-~Y9ppzAa!GJTMu@0Nmr0KO!39Xh+Kb~q#IPhgh+ z%{$x<^iSDrH*>s%kdelxgMe$T)IiSM{!&8`!5mUr(st){G0 zRa}j_#nLrxkxMJ9JuW5l)mCAg%)|GJGJY`WaVRgdY&>AQNh)}&Ng$Ie-0|w)A@^MX zE281uJAF7wGM^Wyd9XHJTQIK;VCtxcm4`@YCtm$&MN7s&(7F4$w=A ziI-{U-7RE0dLVwFm=YT~hetXGS;#}O*=m`va$_g0()%eRhT55l*2C~!q1qWt!)8n< z+&++6_Wn8$%I=^Q{XQU9soM@_kLPA5!=KG{z=7ENxM4@Cs+VBT^Ev~UN;X!+Og)Hw zQ~l6=9r2V2EuZPBaO zk6Bu(MzaGU=B2dnyRDd#e;!j9qOt(MoMD1J%Fl%5hdsc6DW0E$38Mv?`GHGb_lz+4 z4}cqNtLD~n|T`VFb4Gb zR@z?Y=c4+tFPk0U3r2YB3yWZIwP@{bxO~U$Nbr_L%(_|U1eZ=(p-4!LHS;x^P5L#L z2N|hXy<#NidTDcIrVexckmof5jce348qHIw-4hay$vg*|Tlq8!qAY84wr<%n0(wbTr@Hpw!^l>hWC6`yrG6!&!{;m_dOw_jcHBhMYRm;K zs1cXzus!xz6GLk58Gp?Z95(^GYubQ~$V&TJ=9mlXm`&x`i!|qztmA{GkB_B9{7zaz zcP7~$*HCo7RUC%!SZaAIT8#@gTGdjEkTb+dOy~G%17iV!#MLKxZqL%={I)4;4V}-A z2(+4c)jOEn9}tD4kp9MmXwNYro~C2seK6$h7VQAI|C(uw76Y_NdoKO`Ixe0bX8>R7 z5gq%K>0*5<2}XSh0bJI0R%@XG;rJL%Fue&Ggurjsp{ta6eQtgF5*ksY*ixkBb!+H% z?X&LuW8C(Xj?=z}qUloz6lmYG$Ltn8R%VUPd%a|zD)4L3!Qsd8!M%g?=(RBQxi`N- zdJ0+94#Sv)T5_4lJr|6+MJG0a41DG|VqCrw+ZlOJ>#>yzV4f;;*8i5gPvXyAt@jSo zzi_IR{kH+(_LtVXeM0DQnEeKnWj2@BkzHz8QwiXO5RBzawQ9b6yAAX2a!r8;GXO^7 z`olW6T)nF|)U?`-t4o1OT3Ec3nzcHY`IzCgV5*cSL;FjEVIte3#NjRJ zKCjiT774hK|6Y*&mpwGPmUiilm>CPa;KaVFPCRLyRV+Y>91z-D$Iq38=+ssXw^R*JzW3E$Q_G~z0r<4Bi}oB%Q$Z@~(?K$-y4s@d zA+47)`atvT`b8AMZ?l|Vt_@CBRt>j`YAPKy**cr0bZv7RsiYE^3e^`}TdvxVfqqi6 zZZ)gQ+PrpJnS%+;s^SNjM{GceT+|s>eqZngb@e0qMv#vyEEWMr0XeVsok>n^U0Qwb z=?7eg7H`^?f%yHq`l_2Fr6Og?GkeL_;?hQ?6_0abPg!4(!v=g=U)i?YfV3}cLW&jN z;>E}{54P)J&bHvBwRYUEww@rrKQ{6DUH}k3$EEJlgfE+o*4LyT%#k>dgDY%gHZx&J zZ+IFN{UK$lqH{y3%xc)@!Uh3+^X?F&SAfF+i>!g@>E?`0b13Wcp&z?eZQL}Cq!BA)G z3;=sd8i*jv0+AjLUaU(%2sTO7K>Q%Tu4*I!ui9~Ilc?~_u&xJXTGK_0=lvC8SBn3{ z0G{#gA1~V1DKc&ajNjgP%zK{x`7mmcsC6`*U6pD-GB4K%{cS#1UP>frr@YOqww_~v zIDkT)`cVA(!yP&v=0&3q=5Bw4yvZ7SX3P_sUKppv&2FZFk40zTg{t4IpxjwM*oa5m zNiL_x-wT!Gq8ghVvXkL08LD#RmyRfvWu=`l6(|n_|HS{>?p?iHoyGiqJi~IM!&L07 z5pOgQ(!Nr&>Z*#uR&SIs6qIAhD^&SaDKOoTAMa*|dp*8u9Q0Bv_6-^R=fXWLk+L#P z{LFGbb&ap%>s!g(>l$@tRI(`?<+1+9_g`4BL$5V8N;%63_^p)2?$NGada0f&ZKJ)} zb-y^=p%Gr%!+YXoZlM7#E=yU<8@wgo(#?e1T{a`$O9rTV< zz`p@CPo+eS5iSG2w76Y@hB2A@vSh+bLL{(m#ict*l#`8iU8Fzm6FSb-<71GrN+m7q z*F*eC-S4~F+hbXsN)>jf`59#;8YQn=(cS;z&>qfoNEDH9{->&c22Cqiv!wIJ+N0^qvvKEQC^uuQ0nkI*A{qJgWJ)35>75H;$T&-Pq=FAcK zFzYHb-4>7}@Zb6r`f%{%W&lQ(@B9maLbuG!w^L%@4ASmrO8(k3EYg&z$E^6k zWyu2h0a-Wb07@t}_us1~i69xX7gXx#IovroKG@~0jZWsgHvJCvwI@k-;uS71~0}Z zHhW7Ys1Ri)(L9FHbGm?@VTRf<&ya9Tkn zl6f67ty~Ix^Hb143%gU%peMt-gR`nC<5}A)ICM{LB85j}!?lM=dH%0^>+=!q-Ss=v z{X^>ZX?Hd)?R!Flqv*c!zI|dBrqy|Hf_9hja(_#sUT}1RyeH|H>c-Wk&@EssM;%aMNMUZUM~vY7 z_QZFY%)_8SVo|DM(ByiqD(71MZHxD#25R2YP+8Nl8FbpOAzgvHN57{!80LE7rJ-%4 zJ6`(%$pq3qdMUS-^Q*xhL*wbi7atNqwZc1`KfZ*RGfP&uwB=rDbgIH=YcZ$Qr`s2= zqCb=-mc6sdXy&l5e2nQR?{rivlw#a*`{;4TZxySx@Aj}6D?4HxvPi}rhoqShn%6f}85Ifa=IwR~-jx?M*?IXKOntkk##*W67n)yALSc3MIE&)X zn>|@^>20N5MvG-(elTkzKkvBRpT_S4zwh&oG?gRqPp?O0;b4pGuzQ|vBTd~Sfn`S% zV-E>EMv{-aSu)#{fVQig0kH2=jLnZA;g616c#?=n|HNl^QUB3Iufg6cwPSh`?*32I0r8(UoVa+Iz=ODPTV!e6}V{nY8b2?hzt-A$P?^O_C} zH(^B*Z++>L6ybHg<3F*mnNYmGUbVIbc1x3~)$k|@d}l`a5dWG~fHBc{!cNsc?{vJd z*q^<`$#=Hqqybt{OrTd?%kn81AeUFFBk@e*o9^V6Y*2N85DB_5NV@*8oiLxZESW&( z*_%^Dkd@<8qwf~O97sAHm&n*zzgjGi+ zX{}gRh;lg>CZBr4or#KPP(z_Fd@B~3z`GTMMu;612v_sgH@4NKKjiJ+cLj7CPuV1= zKX*#UhH1@!y= ztlIiO8Fh=GNIWbSBfZ77ek-|jm0$ckmclJkHue)yqx6Rhm!YwUTVSli3I(i(LfYiF z=+~MQv&ootaL2AS7IHCcwf1Uj8l9KMJ?i*SUeh`Cr#nr#h40a$l*9rqeUc!jLp7x` zA-Gfr!@jK?*X1fg(EMhOfkX=tpP{YSbqhh%?OP%|-c4r8SYa;TFj)2OKE}d$S2i}# zRw3BNH}xktd531JFoyz&7%JJf3S&oEfS+bX-8O0atOl|R&OKB}DPKZsI$gsaGMm$> zIL#lw2?ahJp$WQQIzx)eE|>c6)I2%&Hg7K`N8um^!L-zzR~h#ez%HZ%TB-HMy7%h&p=NP z2Gj?huR^xJgf+7pjUe?IJY^PN8o*5q`FfH}t$BS<7RqKSd*KVy@j9&V@sZzq2TE+BbV?5O)$XsJMyezT8&xKnHnCVTV zni_bfS3){4;tt!%?F~~(3^4P*`>NZegTJn3D|qBm&B1D$q2?Xllc}84eJbVD>a15i zyXOXc?efhmnQR6ZOZCApt~Shx9A#&noB`%=%r#eoN%!gS)@3YT)?Os*Q17hS% z8nDV5o7B$u1K{!c_i|8P8hQ8#n61JI$+&zP`J|=}W>@4&p08id57DXkf8%v*DoRuD z8hv8}YH>Re<-E%HSZ&QVfKt7iRuyTN~x zh2nX#m{uEPm+eirXC@fQAwmi@5Ex8)EjP$_$^7=X9}*8Dt7ShB-s}1;8`ZVPxmt_2 z;WFzSt7BgXi(B>LoD5RUMUZ7WSD>26kTlD4ThEUacK+%dph%wf-3ta$-`2b`xa2R$_iHE-~2J#5xwsi^lD+2%K}g z_K$9h!I9%KgiEAWN%jlp+*(6ygk5vu#(n7+1XI)+kO_voC8C z7+$?@_w)Rf`75j5efkStR*9wh@d%0tZYMNA5)2oE%fz=AJ!mcyc7{KY-}3^Ux&pp& z3ea>rp*a0DI4pP{&`u%xJ?L%nPCmGtv9%8KgHB3)p7-h9Eu;){B;-?U$?cVCF*hbi z3RWBW)kKqe`*B+D6+yIHg~FT9x2a+}pR4>0rTmAhUiKxAa3u9HFL^fOYQZdmY!mjg zgRL(EKU&VvzS+;UU-1P?7U{u|lr8BF67a%nrV^4k56|{F2_{alySBWpJZwJp#4|{$ zJe@H`WbVY~7aYH)l{Xy1eskF9kH~HRYyGhXWFjmrlMF;!F)D#>#=^Iss46G#tS}_+ z6NCQEe6Gj8*eY}(o}W8PAmzhj&xgC6Y6%IE?coygieTZ4r5XCIO^_QIC(F-P{Lf5hAf3U)p)(sN$8;*j5nJfQLt%fU)C5VQ7mP$-*QmCe(_^xKZ_5fr7M`FIBf>Eo+7{kdUTImK6YD zw@@>XQ|n-=l*w=~4yU9nnNs>kCSy96XRS;kk61pl&P9xtm%31kby?&?$2V4`61DM6 z$2nK(Fw)#vA~7R(&zTB?KLj5;=I_XA4#pR#)xQyuMBJ$F9yo`Nl#V2=eKAgxW3CKOCZdGlGXMcWnH$K`2 z^qi>Y%(RJ)^G6_0d8sjUY(AZaZceCLnB4q>ea3=B$Rab=5Ga>aYF+QV!#jYklW=?i znjtK1RHQ2ejHac_1z8#-w4GKahCIgCy!U~Ak<_+Ey{|)1C-xyXGl|cpDpm}xs z@KWXJTpfJs@@{@N{$Xg&&4-J#K zdhM_pBj1{XUo;Rx>W~I}q=1_JEW<89^6py?sM@NYto(G2V=0FJ@c>fLOKfrL2(ZNL zq$^TV8Cu-X-)wDblP;ck$RW&*{2%t-GN|gd4d0ax5d@^9q&o!ZRFLitDFKm|X3>ob zf^;L@-JJpw(%lG1cS-Mi3D5KXXZGxw_x-kK&;H_!48vOMx9&Wz^E@u#hFt}1UdIj} z&d=D9UoP~p6-kjv-^|7#KyV}qR`l23h)+HSNl8Ji(i5Gl6-<(X!r8JkGy|K(EHM{nGX3to+ zQ06BeT+cvUy~1eBWL+M_E=w}?mHN8-rM%Vx(>8C7{JmM>lbF|`O4=9a-+RTRys`Rr zyu0(B0BAa#X3R%CSFer-DUm8G>Q5R-CY9)YBeWS*A-ii=AG*VNwlN3#D-@-aPwqt( zY6;SZa$2r4ZxZFNPGpF58Rg-I& z=xkTdcp!N}wD28ekAb&vvA_OS$WI8Xkkr2U1W@{+58-~iSoB7L6 z9tDtf&N)RXbSh`A^z-d~pgxr81cxp6%SX7Y*ODgMw5F`sR)EXNUY=1Y1Ml-r=2B5jC zb@^YWR>jpE+9j^ZnXXqoZPQdJC3zqjgw@sj0{pfKkO}*tytq^LR5ZNAi#izg>s6|0I$7t zG(Ej)+lsJ;L`O9Y+!va)W?$qmXz=S8o+B!A;WWOamY2eXorQcr^PRZtQ5*WqUfud= z_zNca>CcnT?%J`0T#kOTHkXATL%8own0@%)53i%2`sOkTSw(?5Qg?!N<1&7+i??Ga zX{Q>*_VMa##@DBWRyA_F%AE?UB(xN@wmMJ0l57YBxfUu##n&-{LgwSFO)o^{+%}w% zI6CrUj2*un_r75wudJ!iE`6hh>nWImC{ zEbm~pMU-D0_PSPeqDvZY02AN!^-~4(Rm|Cl<5V6B#!UaW(Km@`uf&6`6YVnl* z!79#l@PiJVCmN6Y@+T}(9v$g(*Sf5xrRa$|Ct=uB3CC#p(y=3k9W#~BTZg?dUo?7H z&RqpJ*)9@y(EorUCs#SSx||lnTJrF)XDn^@%jQC_*Y{iWSs&MoGcY?E-e(CiM?Z1P z-6NK+fvSeouOOcRVkEkLFHE5e6f1{ISLqB{{oh<8qJ^pEk8i^Md5RNJfc!gOal6>n z!9UT{qwH)L)WCjN3-Wr)JWBU;?yg*rb~#yR1WM?u@fQfI9=a|k1nWOGteb1a%8dD> zCyeFGrbvfGZOOIC7L)POjBBtY=MIu-w6K*tJ_J)i=w}^FJWJp?_uG()Cx1JQY!TBo z?xCFu;P$mYnGTP3dKhVV@2c|_r2-Z@MRCES(-{n6nGzmir($0M(%K{caJxB3i%$ycVHcr=J;eH`dxYHqGaPX7o|ldXVF0D;|-!bP96K z&SjQ#h3!`p1QZVT=o7-dBt3ARkqgOYW=NPvCZb=LYHCX@>$Fb>diS%zS~;LP9`|NeYpIYz!CQQ=hML6&SRNZ zclJTHZm+Ia?E5(T>YL_WERhDN)Rm?7z9?2(%U}bkx@<-`GVyyc8^>oI7W_2H;(?d( zv{ZD%NTM9Id|c{{{6rUPtk%IHz40iAw!Y|oPaf6u)}Z{1lf({hw~z}fa~s~o?|ie% zms=`N-_cC^E+DhE&T>zWwGmUyvXSFc;Lk)+qYcojNjTP;#;{+qoBYH<4nWpLRHi14 zPH$Jw+Apg(h!{v*rIvBw-qWT2*0_xu{by^OYKrz}M&OLtMN4^c5Wxs_PwiR~VUbyq zhh|fQi>ZW0^ny0;)N6VyR6J%%458x`sM*hlA6n8qn(4*O>d@~A=4i6;lw(37kmQyo zuy0K#@R=J>h#2~@jX+BfDZiS5j4VF8OU|t3FLZbO4FPH3{$X*S(NNmYEY4=M#7^Nq$*`EMk?gfN z#p*iPzqAT1Zw$* z7d4wVmq{|63UPBR;5-!5yrjU=K4r|0-X`4EA}88CUdlvGl?ZF=M_5ayZ}ua1&Jk$vC2eU(M_m;I}4=aG1X1^mwk0vUAUtxHsLwf7B zXD(x8Id??Y_LtLD!wCD$7p{57UyY84XitBSrt-rf7@cqCTPIdz_Ug*zO)M(92eUcm zTIH|gDyz3gq|cF2m5Cs;xFiO2X7f^XMjm>A{roqbC=$(8pUorM3%*RG~4Toz5t zukX;cDt8wnF&xn&Cd~O(I|$^?Pl}sYqh5D;C%6}0olNMxJaVC0e9Co}d6C!35EP=^ z!%m}Da-g`&o5WueGge03e^6y9giy$*(w5fIo5&l9m#?6yoN=d}ywhXo5m7-!|JcIu zzO!z_(31bi`8B<@t7Ljtuv2Ht&0O$t@?8CyQ})%-GL37}@5l~<{|6o2G0rFtTNw~z zLY)7&V>lWpCZke{KzckOW?SRJaeWPhFG;Spis2+rU2*0Gwo{_@CI*hD9SCQJU@m*s z2Ozs5@2-vpniH3G-4WqeIDiSP;`v6c4fcuWRlonkDz}{ICyr&yNgJt~Cy7VympY5C zOQ|A(5rd8tm-G`?bp;nKou9V$jkvM}%SU#aokSup7n%n5K4i&|TSE1h_u{s5OYznV zsrh!-c^FxV?pGeut)Wfkn|-y7A16S06#H5-nweNL(v z9Z`qNj?0QTj<7dtfRm3cOABB@wuurhj$JjM+MDP67{x4-?U(f3hBq%K#t<;fdC-^u z;Zj8>ODu4v;W(J_nBM(f?-Utdv22O!~OzpWol)T30PIezoJ_ffvUP4`g5Kz28QX`?HW?7I`85#gZ^qcn-YO<0VPys!+ovG55Zc zu!GQbMLQ2(KMKK*M8X-69>(|)3a32|yt=6T{ed4|2+Ma<3p@|gb!yHH#qPWEcV`0X z?e@j+VZT??@?ej@KQ`u>@I+AZWe8PxL zbqgmOsxhl^Z<^^)VP=->E@xe+ZzVyUB1MAXL(Msc7D>4I+AmjDo)%4R9cDCwkt6Vz zjWgFb$>8=OfEYn7f3_JP;%kM>%XC#uAZja1Yki3>vQGYih*6&zhE(4`aLkX?uO` zAfZ3?LAb07GHRmH5O8d8*FkU{I2OS(t`>;3A_m4K?1}Lv_sgAkwnB(dH}kJ>x46z+ zjo;=U8yS5j;*&Q8!;>2?dh1TCH#=E$xuuz#uh<$%EhGgaO$STja!AdRiXHO1GE5_c zxgeY3N~5AFyttjZ!Tef zk@K)Jla_9OYxE0l>_gowjrq!Yl82O{g_TxXjy7IXO0g0$W6jZB_Wr<@fYYr)Q0$r_ z5Ce;`)VPi2n?<->k}J=g6`CD|6)TqG$S90EK99*YxN4%; zuomj3d&`|^?ZTndd(Kgek>uqcwd|}Nn_??5GJML6*2>#bCvezs)98HMoBAw;7<5~D ze4;Sk6EiptaxI zwaVouV!thQ7J9uNHS=)c4%>@L>BIZYiKUsxauXh!ae>{>E2hn`tj~t;9eox{g5k7B>#G$>5|zGALL3KqF>l2AjbgyBZWeY2^2?H1?)(t=Y95Hb zoBd|*Tcq_^AbXnNBJ1l!OV(P!@XVn^sW*IPZ&jn2wdr~uOOvQb6UAqK(V2RC@f9R1 z(DclT_*{8VMxLI9yKO*BSRIOVuk&(>6HW|b`iV0DF91~SEo+4;ft>JQkN60eFtCN>k<|Qsm;?A*<(hY@J zNEC2Ktn+S;719Cwm(=qZ{Vkq@U6>@C--IB3Oi#7PRNOo7?u1fEIEFO-Eh>Lp;uc0E z3BQ=?{A-9CvYoDrVhMa5Uq*IPPQG<>Ya0KT4KwM;8XYkqzEK1JAL(5ok_$}(+%68^ zr|NWx0w03%1f;dxy`Iy1O|dUN2l6C62qVix{Cu?kEJdc~@vZ>&>h<7jI&rGu!po65 zo|?U6;`87{r+Em>Ph~l=41;vs5D)i$3yxFuETT)VR{)W9A1N6@gFqLPd1kE%g+dh9 znZgd>foH)*#;|U_PNtRCoBJT6WtcYa2X1^4fkToJS%pODVNb{MCH+y)dU-ZsJ_a5I zYuc@r4{&bf?e7ylx6uELM1#fEaGPqsJ}JA_PFnrgrv{o2*|?-Pm;mKzkwmnYj;{p% zEZim<| zWCqyuu~*Af*L>e*WU}cq*q*4?>GWJoVX}QSsAJppIzW7tfx*8r*LbOZ{eY`el=YXF zfp*cGm`y?2pbv_=U%#pbO0w|Na4p!U&j$|wDhkKAiXm5O)@AxhYTSJ55!6t1^T_)k zkr=qPCD^w(3~y7-R3l;Z1#5Sw^Ht9;V zkaM>aFTsf?G1c=f>VWsQLljeYW>ve_jTRmdZ7kz-81uxoM_bzVbhs{gjHyKD(!s=ot*PHo4evI)n z^31skf{-06qu{_xrrFBVpIi%{4tY~+7nAdq>+5E-Je1{>o9XoOU$D+rS=P7zvJi1X&kG-31NEkfIDbE7s5^YVn*N; zq2n2;KacbEEIHh%8+1njK)$m@zM?1o@jMKTEBChgXaUgnz-gJfY8|yilPcTM3v|B;`)RJr=E>_*D;<7-X zkgff47+B4^9o0BFLTy8#r8*%oK~|LK}&O0x{dLh>0XI{(~dpB zM-qCHI^i3#9WKp`&W#|L=20-U9HRT=le39{ECGC6=-$D6h*xNeg)iOrOot{?<8}mB zw6E%04WoSf%``V-E*fsEew<{WS|GNyaO{17P3O7Jnku5&JHC-NsQJP|L7Z8cx2CcA znz^SvCI?4XrgFGWm3`HMVyYE}eCI|a8~%Dt)xS70$&C5I1^OyMH(d}hi!a>_D{_Ed zrMc>au~|;2Snz?C%gp&!akJ!D;3l`_OQBu?1+gtQo7>h>e*=9suzF$RnE~6IjNpDw zfqfoc{?;z&Um6C|m^>F0>oL)c@rCxW-4ii%hE;!$_rB2M{joG2!W@--EV7p8+%H8s zrHm3HJ{OrOHj8K+mSRVuSF?`V&k2fuf5LxzFUWTEbJ$2}@f!Sk;(ef;<3*Y>G=Lsv z9%b+e1=th6uGQ~(4&o+JH&5WgwtoL)xB@DTjo}Dt6KByyix~*)qGmHi<%W|{$)xQc zFm7;In#n=yWV`9*O1R~cA{}05D!Sz~%2fnYKMIXncGW^H$z4W|`s7*h_)D@)HU8S( z1Vgtuom?dzJNzMB%dMkhVM|k@JmEVHBPxk8OmJTYW>rhs^%;9tYn4?h+Ie)b29<9z z0cOF+kiZXb{RV*eO6A}79t6tL##7OA+I!#X)P_aDz=?!%&>tLf1~^wABHK868NAt0 zIzw*47n8_uRaxy>J%O*mT-mXUb;r+Yo$-n>c@Tjl=8B;zw1M&vcH{Ahs;8E3j4)mv zb1EWgy6Dd#KD)0*rkGyq%lE z1A=K{a*o(nwcZ107|!Y_r?0bkkmku;P6Ri?Cch)ipnGH$M=~kXYn0vWBSwr?4LJ|? z(UXme!&EIv6SZEi0A&| zjFsBs^Ick~m1Z$+_>;^ts(qORtw`+h5aRQM5Iv_|JvAW`%rP2vm2I~5+ekbU z-g%qt7x)b?H4Ruy-eiEIv+V-LpX%=s_5-Dx@?`1?AkR6 z9gTj)gxin*3c3ke(`SZ~tud#%Wf^2(XvV=qLt(#@TcQtDrdR2HI1ZqZ0($jp}jL2_Vj#fN8(9Od{sR2;-Y80h&-)MWV1Yth?3d$F!;^ zO#omP=ekcH9`mBPJYzGLI#b|cbh{#+QCg+>1mDyS(6Yzz^XL^ia6SF5kLtF4*>B0}e|+4;o`TNk$^-mz7v?5M^NLMw zngoNzc;OBbz4ZvFPvJxw)RzUY-1YyNexlF7XT%iaalDLGBbK4G<4wWp|MMg0jn>)) zg=NG9&rXfRbOW@I-V?cze6%wdQ}KR?vf$>?A*a2_pAymlp0#|c{Nl!}kFyTyDBZaY zaAUa>-$(ROEoJj%tj^d+1*5}#W8ODxO~V`^3{JI?`SE2$3*pNtuX$xtIkoV)FN>XI zZu&+=_HVv$DjSbGg}8im%T;qJg|pY0s~4oxR3X6Mc;-wXL*{XNBNVm#IV?n%z(%0X zX_%p3e*x;}c3327=SNoSFNOQ9w4dxC452n3Doc_>9apPQY_#5*h-QjQcZdUZD4Pb_ zxCT~!^V|j||6%3$hErD)v)`^VkYdZ4GZ`TVMGb%Cx~8YGd{J zj1sgY*IZ0fpJASurm&8SHRYz4!rel8!|lrAO& zT#ar4xu6(}?T{`@7gkJb+ID-=<{Zeat1MJ~#y?%^p3rNswxsbhIk-f%PE<70;zfDh zUWe-LG6ULyK@217iGFT~rP&mE@at9v)C{xpm&#qFo>%hU_)PkPPOzw{=NmiROU38# zKI}PrV_DhduP*yQUfacVsGogk|5W-aj-i;57FvVkOJM1$0auJ&*SY@LT9&ahP3~oZ z%kLm#EK}@+w)CsAvX|YcZ|CTB9VxI)gMG_=HnYKPXZk!SF+bXgF~`I6IeHjkjmotu zf&7kYvt*6fL)-@P#jRk8txr*I(A4E(YJeKTwfL>>5X?qZ@(_`4=-%! z$HOF%7d^80ai;XYx9_>;Br7GOW{5!Ozly&TC~FRP%TwkPFo=(@di&NHNZ(q_-i*pM zA6o5Y)n0Z^rLU|ncgaiiC&s+zLE35UqM54`Doj8OO)P&Wb9#M^)vT!DLZ(YILo1*8 zyQiNBGIH7PrJE9>H##d5eh~w@ng}eM4E{{5^|?Vj!-+zHg#s8To0 zdLj7Xbl-z)1n)|tl{X5Dal=mb`-5auTzk>&QvDr0k06IDj`QLp>g6BL@dYQvS8{}y z*dQ4@KK-aJ`s-XnTn)4Q{4gNe%%Y2_!u75W+an`;py0?)>YX;nr5;#;2EDd z+>LFVlhjod$(Do`Flh47tUa)uX;5)5P6-)H4#i^mT=O_fP@-cFC>QZyoPEtN-ka;_ zl&rqF;#IHMT)M_(8XgjouYji&a>=q+q6dLAjOYSicr=)sCPJ*)cbu>X&*UApM|Dcj zxZC2#q=%0cUsZG(_t{}5o>9A{q7p=t*#g5Xxk*RjzaSUN#n*tPf``)?Cj1M_D{MfT zn+`{f!?t27INHHEdY$if1>>cUi#+l2gmxtD~WhD@8za;Gz?Kb#yA`m zC-o!;br>nbpb6vkG>ELxshwhS&o;&P(|G(DfEC)CrP`Tx8kf#$ zwHwtpMn))Bacntsvs6tk9_!jd26mAA243~*@(;M{jMWHvAv?L32Hh`PlhDXnfyWwL1KTvg`eDhR2bwh_D0`AT@?e+p1x)`L@Jr6#j9a*VA7dGvzsI~g>%IR%J0Jp!`MBk2hjdIM8yp5J z(twSA^9SVBzn_X5N)qZvjGQBbAw`BJ>c;^WufStf^?bLU6i{@o>&5{zL+W$RE!2dy z@qponX}0mfl0|_Jybt!GoBRh(neI3DN|oIgK5Y?LbZ^gF*>KNW0W!_UcTr7ZSL3pSFJIOBe} z-tVSf3qUVEmyP@nq>J(?RF&cUwaxMmRR;XdU$jooUYOy3K1p`4FmxpGO5Bg6`;#n8 zGw>lDCeZ!|(k1Z%yk{)S?^AmJj;m&9K{Bm1a)F}jKc7U7z#G`~J?y^%$d`f<@xPDE z1Nb>sxfK5c>H7b1W6%frf8xgeUq28#G~JOfh{Jb;cE08pGm~d0MN{>=&_K}x-JM^) z^>8hCu-snRDIBhJQ{gZ~Mf4cljH8i>%58gDftc1kbvnge4+e-!MgBB+&W;?usvQ^1c7PJ zT(wHu&%kythcVnFf;Uxd?I}Fnx54s*W8w+Q$K^Ychp+`O6+c)-dISw4|2Gsm62fbp zrngbhy>xC8mnpsn*b&7?_ix|=dY0M)Gl8vWIK!r_pEb<~)5yhgj&QhK-7~2iQcexT z)n#OP;i99_b9kF&P~81V6&g3Ev#l#+osM{JtEWj{UeM*>l;Cp&ohFaXgVt6 z-sotk8}?maEH2QXL%>L&EO-{FU;-q-Bc_l`@ z(GZf4w>Ou?(7=P0c2o~ehWuWUTz#qC)gPPM<~JP1l^%nigf6$sS7+@8Fpt@#qyHRb zt=dQOL8t!XF0kkbpL_q;t3j8TXZ_hW4G4PY61pa_?f(NQvsm8y3n|-T;_CG~NN@Ws zFN;_&dw#eYmKii+wI30Gl*LtCC`2r1?-fa}%4QKYn5*Vd65X#ZS!h3Uwz2C%>e4f8 zti4WT)L^D|K?YdHoUi?eEW@_K%d`;)NLd($(+Sy=z`C=uMcU=$VfIEK1>R;K~4t z2NWFn-!2{}Kpkasw$qKLpDH(bIQ=P@GZxk5mrNqSoJIJu19T*t(>yux5a{5Zd!gSE z@o5$c%=|lG0FpD;9!;qMPgW^@Rx%>Hm#k7|Zmj2Z`axTTQ8((;!I2!)Cbx3*Q_lqEum`M{VQgn}4B6j2>P+IGSf~S4diAe@jS&+&?jBc0 zJXy2ah~}4HxZcpLKfEgt30nZ67Caf^|KZ61iO#C2HplIB>fPLaJV%}+sGj>ck^@nE z{a_w)<_@{_4K<1xUM3ducw?n-Q3WnwL%j`_H@_Gl*C*A-JX)1*GEkTE-t9rxtr74? z9p79_aRstb7l3lS+ig2;?Vn#k$4c(5QR3;qkrN|7b_?CppxCboJIgBX?TRA%7+?3HWSs;ofWX&LyvMv?{}o zH;2xR-uk)L2&PnD%Q3yIF&VIiE~-j7gE)sNY)z9A#t#c>|Pmv;FiDV0z*C3tW!3@hZ^X2=_xaUh~{u9m!ytT;9`# zj6iBkF0s+K(y>0*!2w`Ip7Lq=R5sej_0WxvRX!XqIw|2F%S|HgaKBsK@X4X)Uku9s zVUB|WFjFj-j#kxfN{p$a;G`X*>Z{{5cdX=k3tol1$slg;s;4Hp#Nkf3U>DT z%3T6ZdK}5)E;&^uhaQ5l_@LE~Q=XrWkjn~d9me%^oAD80C95Qib_NFVupXZ&D+*Na z8_hZSIMO^-4m#Yb>zIb0oK`QKN=4;WCUG;WBDot=dLt@(NA`t#LcxbYxP7QHXg2oX zPytbc?JL}e&gj9KTBc29{g(KhE{{Df;fTb_IqZ`(J z3Ge_*}4v7^-f)QhQv7 zpAs*R`)W z(4}0isPWWn3J_1bP>`mB&5r=v%kj_vX;op~uY5pI+p1|p3~*G7VdS_QrmfMk6cAl3 zus_@g^n5L<*3x=Rk_7dCWXVZ$KG<3)&IVn)n!BHtxK~UqA7&0~Q`~Pt>1Wr&b_rXg zQE5Nb--PLHY&iWG?kGQLOqK5xqI?{9KcCTANSf=O^sWCG6$0E^0)cl8f{9!v@s6SI zhx<-XxaOm+<{}=Yg7yT=mRej+u6afW&bKRe zW%^4>b1*Djh!Vg*h(Me=G-5y%3k58btK*CZNDdzTOfDBrCggkmKtT&UH5h&c)gqPo z=Pqr-ZcvLXeuIq55|1UT;WxAk$#ptR3*wBODb!9C?5@!05jj3n8RLniN_nu0s(8%T zN}G+kiHc{u!}+!lHAKkIO*X4?j7Y#%^G(-7Q9MVeY6A4M$(O2TCYBA?M-iA=o&-)m z_z;1<;b2zX&GGc&mLU8#P%=hhJbRCpCF2idLmyF{?s3^ z`c(W2k;P~389k3FCJfc$;?SW0lx6V^ccGKnoX29ytY!7(--+uy)?4M3dy&9&=D&k$ z=Q=li9-iV73J$T@GSMigpNJRuu;_(G%&GMmw^0``IIX%P_+qR$8ssZIt|WoKeZKz0 zcbI>D+sZ-F3Tpvi^@xpy_OIU8yOZofk0K9Hz9as1!AwRg|jjh)w69BGO1loqa1GJ+yd4SpAhryK1xG;o3kXv``u3KUWPl z`I;r(MhpF#S4bEns2{K}F-WrXpNxWQl4kXd?A*12ZtScZ6a{&4D$gn07XJAxs;MjK zHQx^RTB2P>2Ai7C8XdM)h1p(#+zW8=^Bzjzn-o(8Jq(!#zL5MjDt(kSU2V?vXmi4G zc$QC=#B#@({b<;(`Gsqf;giYg&^k|gss$mB&DtSqZKPc*icraCx_63(N`vl8!Q) zyPF!q|HIS(-h%h%>Sm_(Sv|DyFum?Sli0^>th{P~7Y!)8ktT?tqPX6H$ze6OhIJT{$N;kwU{}X1$Lvghr zl=1($9Y!`Dv*ODhyu;^cW>|wE_($XHF`}uRiM)dv>fySh@TiNik-s?>;ER^ArRW_V zeu9bPN4F4Z{ID84@~FachoL)pR3Q^A>^GG$s|`o}C)~=mqv2ExMn6i7iWLQ1`KiY8 z)X;xu--dM&E!T667u!aoA1e=h$%HlOkA3n%m*lH3`TZSKv?hLdQXGu_Z6uO-m>7SK zDDC#Q9iPow88k+o(rsClCm$qEu}I;b3^3@MHg(EsZ)5~K+LD^-(%y6jPu)SV^R6CX zWcBx{r~EHZ9S~#&U7WpqXlUUX8BVWi!uoCXz|Xc<|Fl7xP3N-G-3~WQ>TW9VW!#Tj z3F`_jG3@=IcE|K31(*;VV8$(|v>1~UT(~k8RswKNqu@)H*q0{7@GFKc`x2 z2ws-ye6;6D3o0igfq=I76_98-B&x3nTO5*M z$<-!kfNFCt=z5E^{onDlBR0w>}jTQZS75yp+W(i=@ zU;YoLI>H|P%|8dr!v(LkO*Tr=cV;BOwadQChd}0JQ$SePea9h*CNU-%IB8;V7}RcK zocs^h?ULtj@A2X;%|LTd0x{z_n8fGsm{%ZLhw4(SA{-ZHG@uN7Yr0 z>L!;nqlKW+k8ihZ1iUrPZy?649}j2Za2emEMXL~*gT;JQb8|lY&}*2qzH5Cos`!VO zH%-ihv?8~}_v2jbmAb8>q1>=H+KwEcQo6HVt9~B=rCpEI_PP9B1o7>SQg;pdA7gv?t(_S4qUiI7(cD%jbA=?&-M-Gc4(P~LV74TF zM0T{Ickz`;j=a)8$=|_DjMlt6n6Y8r$*yt#t?UYf77+rOR3yOgW~|(NVaw|~riZGh zNxL5IR)yIe;H39(BNs(F-oTU{er80z0xc_qh=*J?ii=`-356s~tyqiF#AIOin2Uq& zlMyR|ZzdMiE^-S1)^awAk{5*ns59>~rb;Am_zsVGH-P6Ha)=7ZoKfNloGK&(;p*h5 zpewHGcnBeI$k*;vz2&8^L{#2usDH^TFs2;C(JS8u?3MA4j3$caVC7XcI1i6Ul^^=0fQb61ojRMo_0;Jx^6BdjUoI}l zB3SfDAXa_*AM0$#<4iUy1H*VIrb!ejVn6+r+ZQAM-ciMA{#)VS+2WWhvGs|I0U@lx zr-}`;xXSRe$Pr?D7V&?MH%V0%-9+8M#yfv@F;XOgcfRNw3dky~v2C`#`-nzJ&VxQQ zg%$7#$_=iuQW)8zC3DrD&Eurj;N)ANeH$>2nQ$okl`$Cb})0XkV@EMcoF!0dq zNUS8ECEssu{Ccl9wzb6wiCZ3r*)u|8JTpj-{u6t05@ z5QKGDfSO(9R`^)e8rj%D#18||)U{=XAfGV`lG8B&EzqAoMYjB&6$eYc4!d;p*Tuww zEn50^COntrG$WMMyY~LlS=w~6#42w98pTf3zwh7RUepn!8@}4B4yA6M9Nc3?fCAF} zUZ9!>qnh&Zz(4ol;xzkHCJr%iWj!Jm(73?zGy6@0U5r~%gXC)6u~O~zskTxEDX+bT z)SS9vS9`+fa7VWf-YknC!1aXe&1BcB(Tg6Cl#`uV`x!^= zkE*j2xq2t=32)yCB4q!AAo2y6k_4tMFG-d19Vxn6x{rZ9$(RM?H>0U~KCZ}AVg>Vo zaC|c8Fy@0zEDK~3)P&0S`2u*UFcbk8z*E~K0R_!e(|F$W8iA(Qw!aBXxOak#0uhzN z6i}0pNHRG+Z!)hO7QOg2s5IrbnTLQ8>wLTXC$Gy`??Wn+e(9C

(C9w)Tq)KV5=O zDcuQT)IxxMNp!k_fa@)|vnsp!JdVq=RQK1AbK)?{__yG3 zJMHXW%qZWP?)1XXGt#uz#1BpED_lY&Z%;WBH{g9t@se%Sk`GE7QphZ=HUxE3f16SfnBo)JW;`x_kQT=x9#Ur5gihP!Yd(jE^8 zA!W)nQXc}we5KWSl&Umn_ENUafBI)EUt4*)(lY8*=w)ZZp2UQeyS>MHoXs48jy3f1 z6gKxxr}VFb4Dg9*j_tmHgFp_jq+${Tfdo>Usi6q`|8^@uEX~mq*}MSU1x?n>)R$M2S}QuxKp9-rs! zS7=ieyB|z{m2Y8cu(AWi2>yTg4$KL;3U$g=nES#gjM_m9G{$^A$XNHXF{=YmHlgg6 z^n8(bjIxe5khN}%9s{4D+t!E(O+*$gaDpQKeQ10{DZl%sP6!G8s_=^*=*vVu1f7T zFPS1=-pYJv?-wfQ`IC;N*zGkU8WHZ}HHUpDU`vKTIqq@M4seKr!)oRWb!J}Kl1sy1 zHFsT)ekA@a(hRx&4=a*vVe2SNrHYnp<%@66=?{TTbRY~Pzg7P=LGfUtHqBI%d!R5& z;A19VI&DvsYeU})8e*yx;txH8;C8o-ie{yo$lre;oIxRSmD;L;%#BIiI*D$0yd+L2 z65Zm!1wwhX>uC?+4qMj?HG^oNvLnpFuJ0v~vYXsp;Th{=)i9J@&u*BbNM*)7mjNxj zUOfP9cTLc^#YPOojBZL zwvHqf3!X_KVJf`LeYhY{E)y$BJ+;02lXB{6?eax;WI}Cof=PdWVxnvBmoU&R*4MC; zpCKZ<;i=}Dpy_-=-0{wcGH>!=s}9alPNq+EY)rgF=+%g=OeC1!kI@4=yaE)FSRXWame(DocheIu9W>^#}^ zcW$iDqdM7qL-*4uybBeec4-Z{hIBJh$;NI@pBU91d{f7}P;;7Nm!Xz*nVQ-=$;Hlm z_fzMg0QLL8k-BdT($S3Ag~uFAnI=At2Zae|BW^s^Yv=uS>zi^-#L|CWMPwxto~7j? zp1fTlDW5TF4>-vj`9#A#LRF`{Q9Co+71dlAK9v5=W>>L(YgSx9caPL*$F?l4r?{Yg z8p3GR7D=*w-8bvBw`1EkoyhBn5dQr}ke}&mdpY-1 z(e99e?+5%yxCrI3{Oa__k%cz+8%R6TVF+DFO7F30apv)S@)7kFLq0sn&XV`4Uv0`{ z$EY*Q$8%V|-5uDCv?qOWUrIhjb^_gHVnoAbxy>lH3mR(SPWc`$19^QqTVA`}eA`sY7t0ZkX1BSq)>EAI>{S%Ks?mk3GTfOV)!kUr zy?fDyO@49c9|qks3viJcyvn>q+ae#mp8or4;GY@T@5)uLO)>6Y&sG+^{)8Am*JZuw z2zBjdJYf>u&I`=Vn@cOFteqpXbrtva03mXgFWw(p~N}pWBo1_2B*6$}nDV-a8XO6JUFqU?lw? zXhO^m`CXn{?<ruhs_gZz0_`8g z|B1i**8=^oee-`+pwM<7+}2h`_OmX_>L(Q!PFqF)qL^9M530b?OF)vBp8EZunC?>KPK)`}Me0gKTZ(efO;!7lR}t*+Y3do*;SMai;$txuZ+c z=pa7RlghaFn{3wRg~R>|5#2`L_$j{e67Y=;45ym*G10*z*>C{k#H#&sC?3Dz9B@t$ z&B{l=mj1o6q%4BY~#=Z>a!p;cZ|q2aq@kx8|YWO+y{pIAHe$=(!W)s_7OkKyAp zf*$vAg>XuSInwNdu5=pUYf=Y?Ovp!^^)QHY_@1c>vs2y(LP87fRPY{HWgCFF*^}_9 z+I<S67|DO&cjGKo0^>AfbP?u+OUK=k5!dLwO%NtO>GKVM z)jC5uC|He1!fLh+6SpazoDOVOcJM7s!P-e0Y4Q~kg8`Tqyeji#203&% zaLDdRu1;&gQkY2V+>Aj5c4QQ7haG99vw0AV_);5i65h=5y9*9c-{j6P)~^0?Fo^7~r4dE-a{AypE(KC z|4%}zDP=1lU@OoeRg|qbezfv^3iQJ*%r#@E!UULXzUHZ$qq(C~pYx|)ao||y+7s}45dUq{nbd(kw96ciAZ($%m;J6*DUy|e3Ws)qkmj=@(3ble4A-D}Z;wm}edonoVYDijRzKH83fp}AZxl*3@)hBPX4MxVRr$jel_3buhp z^RJ<~L^?(vzhTqJ_xwQP?f3((NrP24PUC<@@=*ampY4{T5T&yeZpBv%FCJg^Xiw7! zgVNPSLa1l070qdP?~!5k5x<)W3bIUs)?y^jMWyx} zMs@08e6?z(*E+519$?25N8Qe+SkL8p{DA*FH*%4pkXL|0{+}S1H5?cgd$;8YG0NFI zdqOM@@~|@0`L`jRQ8b*v=pBbrB*IS6w(BOyblE|qN20}^BWXYUeUHyq5^7c5#ti9{ zj@Coz>J`@QM=>#xX9{B!!tix!rYa$l{OkpjdlQZ285}nt18{`pyT~wJ!`&9H%?81Ydl+{yx#=~n zhmF54lQ+d)=_~9@%F(14uYAr2V04=}Kb@h-wz<10mwrmEni%#^eea~&>{(kMk&e27O!M zp_}QQhjpb*Jv$a12q&BsG|XPqVn;@N6gvNw>{vB{U}C1!^y0HOaEZ6~rDw1B+||z& zQXsjod|`jZn}-+}RkRf%)VN(B3`Dbd&5-U?G`7LdI!ZXt+Wi%7Mg!B(Ess~v&CgL> zh8j>JcpUv(Hrb;qZC#%<3(M*w22*H3NMSk*YPD8LoMU;Qd) z{|vB31EX>>69UvYS~4%@#{O1CvhQt`cD#JkzSZ@frmYEct<$LtJ@c?ZNwU!w&$ZT| z0f~LvJOZ0AC>{=|Q#)!GZu6LIWDg#BaWr2}v*~5XE1Tetb$$_!Tq#lN46(1X9w)i! z|N0RCfqzpno75S?!I&AEPVFt*`zHM}W44)N3!!)aY^aBMC5oW-H>i@HHEzh$a4lZ6 zf1h3O#dnr)n(uf@x8$BOh1Hs&&;U2?>fDwFFYH*P7HGOn}T<3`;JZTOZkN1SO275 zxgp?@=A~YhUfaKI7x$m4hqK0v!(3BTa8bVgXpfdGV_Hnioi2%l7zy&DeOMn~<Vgw<*dp~=L4UV_1)n$!?6kXw_ zU`{PS0;YW<6IW-Y6UG4vB_lL^f_#7JuQxuFyFzk(xNKee2x2xHMNcWV^5BstN1;zw zKK+infI7XP-qI+%M*tu2);rG{=O;D!1HNGW`vv)!h=J8RKYAc_Eza-4;2rXQ9-%VP z5l46U;8kO6^WXi(z$sm+UUiy^)8~J2-~aBK ze;@Pjrv0mF|DKzFjm^KN^Zy-xbK;JXWshJ1QxNCuNfrv|_P%-|)NYjZgRBCs$aEmWu8Qm*KWHBstcG(b zMs(*VZQXtUCFCAmgdANV-3> zpvu`%H%n0k@zGNsJ$RvA=Fev-OQ<~}em9hWL-3PH+4o`0TNj~{s*F)GI1@gE;8^o^FFV}ngLdc z7$r24<(qIG$PoSFZt^M0_G)@NR>M1Ju!$+}TcS}nw060?()HstANOA(FBw|#wW%GV zIHRBTPD%l?2~h&^=}t35Vn2vwg_B4qClg@`K~Zx7ME+I`Turp(>-jWTr(NrymFh6| zBRNkdvMTBari4VA@+{TSlVh@Gn3JOo{xGlYH!$WCWF&v^2%nZT?K?rM?yFu=Kc)vd z(jAm@!LToUg0g?QQqF3+w~=J zrrce-ip(5gIj?CocrGpLCHcCE6hOjk8BsKw%Zw{)0omy!0KyTMG&U&U(&(fQSlxA_I^EOXiWXHKQB&8V0o%O^E%D8@#$Kj6pqR{n|9GX+ZgMk<%QChvbpNv+QZ2OTK{)fB+f z*)}!8MwCU~^1d~Uqv3$LrCqV2MddxKg>;p&8-C(J8^uGEkMHe_w;InMv)FLnaLy8; z^a(b_8TrtWH{i=CpkN?kD)7#~!0r_d|r-r_S1GmW)mI4{k0_ScUjTLQNOcIavMr~FXvr$ZlZ ze&Pck5CJ;-g8GX7egdAg9_Vbg#{o)!cvijyY-#tK=d|PmJqRViGa=5Ep|%?r9p0!+ zU9svb*6=h~j{aT&SX*t$e_|*kn@RLnA%}3$lwPX>9W|_#Hr%vMSG#UgoF6GGj%FDC zs!cxOU(bMbGG7oUXI~E<@w+B1u5sy3z~6}184%zqXpnWrz5EmN#mqHQkBif2GMt?a zHgi!nj0;Ayd>9#QuU~j%1mIff#t1KoWM0a<5-jkf&=YF1yrfx! zzyhx_=l_j+UXjvg;6&7kq26moY?#(UQe4y{ARZsOD4F2tlMfDkdVNPJJCp;42o89{_Ld$en^88vRiTg2l#uuJz#%H2 zoHTzvQ;Ijv%HIPiSYU731mW~|(-aYvZTCR6$3+8Yis4s3QFyRz_OuIHJf%`yJLG1b zF{B)(4ERgvPtF&D6hrxm6q?c*dr`LVE3dTpDDe;3ZJl6MRVR_{r>NjacNIWblU4=z za5|^YT@>DF`UKd)V;n{hm6VbCFdwcVF0uFnI+V8v25c8v{lhT%d90m4WcJ&%(z}!w zNG7H1e?o!ZLv>%ANmgc0$||tor^Dt)_~1<0U}(pA5ek#*#|fDC$!H&(ePk?&b}zj> zcAfm*@+7j`5{00cD<~k<)F&<*BPo;;ZjW~lzlDJ>B3^-l8MV#Y1Sj&vZ*QEXl}6vD z!`7LMg?e~X!GFN*s>4o`jpf+@a4X@aQVLfRY5-ImFP6VdNhVa1@*h`?ATbLg`V>=g zoNGRZ73{*`Ny(wRNHK%lUwQxEs;6Ey^`nS4)49ot<6@mYj$NcZA z^Zr$!|1T8CUeIU~^q+@=@fe#`8Fs@}_+$mzf#Pv`Fw40-$8uwNqRF_#c_yYB^owZk ztPNAQtjtPou;iFE25V;M)bf-}4{bS2f2sD{Nt${@HoRXm_o|t4Ktkw$Tc7ved2VHP z*!E&Q@8X}A)ODd;@CWhLx&o03yDdMkHhsk+3M$ALj{69jP#&8n8jfN%e4!lj2pV+$ zFo)_y`G(%*l{HD!M$LyS_lIJSO;LQ?Tarzb5zqMArx0<{#E4S3n5+#9VB_JhJ(QG0 z2jI6&x6k6q2J)x<$`w* zDxy*=&SG)tMx==Ns?OftSgVfr5>?QsW^sU-tb{v^K_j!>g0;$DRp1P7p2@Sr-LGxV_>4fel59C%Vyqad>XBKa+$ zB(u)NAYV+WMeF%%ZvB!DCVoJxe~_Ht`1ZW*f-&EuYH zafLc?SG9j@I{Kbmu_f9MU$%W0PYnGY^8hEu>2W=0jE85rke0efWy49NflXN>lxnW& z!xy;JDRJ4Jxt{fB6a63a-ZSva3gF%)rZE? z15{T!tdo&xf>gP`|As+;IC#b0xJd>I(g->L95SvcR#2eFO#s+%YO%L4?H@%Q$65K! zn}S78JBLKa$3T`YWWg-|$?I-=%Y>{w34dkz=ktPhdm_!9wraNfh-|cGbn)hd(C}<` zs?4=@;?INa|nl!#? zeUh-4su{v4mlwWa4l?ZAtA1TgC&@_Qgd9-(OXmHQ{3$exgwmLGk(3gJ!M)&M(g$bO z7$pLqm{512@87Y)*Q$yB_!ufYE7-$tlWc;k2WRA(H_E24SKmY90$hy zE$csf_nD5sRq7J%zBJj{S|=Hl0tO1{!>T~4i)K^d9JDD4zO_<-yP9WJ>7bk#su>0~ z!#&FKZkuX>Te?g_qU3*4QY?d{-8OF&qr@c>An1m~4nwmjyDh%A+tIf`TjEWT@r0Kn zV3bOjE&VPRQG8PwpX8!mKZc!z(=!M-dZ@L|vs*q2`S_YzvQ;4ps*b43kk`n!(q<5K z{PfQy;ad-LtSCjR2S{)Fyntsh6%W#`z7KVjEZ5fvCSY)cBvS?pMk86k7aD?d#MwC> z$2}@2zbQ187|tkH;6jsLqEoiB| z%mcc_6W|%RPrfQT`l&F6Aa7totA;op_uX0Lc3aA^Jrvz$ss8;K@fr3k_-f;q_bd{k z&!os2{9O8P$$1zaM^M(H7&x$0a*jGLO%z!xLi*|1t|J10;o51(qWYXvQhmSwRbX=B1C6$Ta$tH zN^D(lDq3twP65qeImO~$J?p{Oi*Uk89&Ulo_Ctf4bs|Cm|A^BQQDWdU^fWNHAzHC? z1Z!b(#x`cZa$Qe{2AlgLR5KWFf*ZF~Yf;Vtnhf{lT~O(BC-awJu9Aeo z4dsbY)J?MKcuY$6WpYx=cBE%XMPU6At;S@X|9peI$=wCEyffW-Ar44G)?JroMTJ0R z;+f;MqY?q=)$o55HzG`&({(V3;!gK@BUgr>guGudYq-*Xl2m^_|CyWxOeU2#1&c=B zbFN$U;mTmc?54-ASKLGDeAZ4GN_&*`aXPm;uIVIdMmdKFc3dW9p(lG*rFHB^_Skn~ zuqFHk9D!FaW0Am#qC+o|m0GnB9Ku1_X^I&?!3HWvpvm6_$qSH9c($kG@wc3y#5nu* zYgy-c%29zmJhPCfUX!Pyl58_B{JrxIY!#t9kown9}u692hF)evIBqEJp2nUvh6#iF{-Jq|2#p;wqfaGrez;!r&*ifK6DJp{_cRnXl&xNOtUAbrQA`E`J{l6!xHcOB2L(&PpKy|Kn4;S#jAY$3rMBHZfd>(=kj`zeF+b zFtuO*NNIn*Y0lPahr0IdiKD;)5X(^lwK!zGpmI1f!C_IM73$-qWklciOYwDpRt zpuA{7MK{{vJDHkFQ4wC2nvl0GrPY&5I@n3|Bu{#{6NK?~=f0l)XM93x8wafY)5H76 z&Rlvl;)6p3o(>k0+SFX;7<-tp`XRL^1moC{3u#jdthhVFfL7+2l?DA_*n0r8zM2K85(wcns=^@7{?!*P~uM^`#?z+D5@;VQ7F|CWP?q# zxh~C?D&+61XgxNcjCYEg_MAX__q@;qLk&&33Ox|NIL!OvIqpJfF}bPg%R_*W>+DQd zuT_Y#EO&64n|wjQcDH{V4$k6Z>^bms-!j)I0b|#D$pyJzLU7>FD&SA1wed7$V>p5( zn-R-_^0E-eWOP)wVer26%9g4Mk}x!RJY_`SR2?W~ktH_SKl@u=Y9$O@s3v$g+&=k`V|7(8PduJ3Fov_K&t z6ixy-!tN$YCJ2RFg-4QK!2NJ?=^EW6S%gZR(!vsD>Wo%Pd8#kE*;MRD2_7NICh zHLnPWT9iN@=D_vr=B)uQAv&y}NR~^cs*yVym#S8zS5zZ88{&jbZ6DxX4dOB8C`|jy zy|Mu%5B7ON3B;vYNmRzAi<*B~2ht0Xw4O^zT<7y+Z+ON;43nH_`^Vrfojy3H`gbpvM?U& zi+FHC5PhlWB9|^X=cjG*9hv$!vPw6iVDUTUT#xM19VhVGsTvtkmHbHvlKt`413o4W zl1BwE=(T?*KL7QwavnCC#Y;vqN`e>H9Ksm#iy*Q!CSYRD!CQ#_??*@2P_VjEl{J8NgkohDotW(o!(PkF;pwkU(FI56B5 zH6XeNUofN&x88H7m*z&ExmT57pwBO|lS^uTgJeUt`9%KmPkO^TckCZ&NEm-{JdgWy z%S}2ZbB}1Gm)ShJv(C%FlYO?Rd@a;+Y=jy4`GVjVGADT2Q*w@ieG&gKdMQ zYG-qfH&$hKq=!?3H*uf@0iTUeu8VR85Xt)%iA;l9SGEEDz`Rs={pj=Kpi(jSAYMDJ zmIIcRZ4p{h?@D%^P|D|(JQyv4<7l`G^m{dO?L%EEG`SgTZ-vOyf!JZwM!)1^+~}u?=If?l}?9|c%d`5E0iN5 z)y*y2Q@ILuH!p~chK7W650r%L&^#IWbbE2Oq;`A3@$13O`lAG5h>gCAo#&lF>l@?i zzl^9O*eZ{EM8~-yL&0~xnhJR6cmr-}=v}zk`!JS$oH|&&l-K&|2c^B{AXqlHQQb@q z2X}j#o`Uo3)}c`}*Knrt+M_Zj-P#^p>a+<>QmVj!?jp=y9Yjzb)i)Wo3vaS4724`2 z(nnpw_^RCyvI^Zg1RI!*485g+cZKraL?kw~$X%Y8GR9UEPEJmZtkWAT#*PsOP@|hG zgSZsp*|PBo{Q&XBXKoX(2&HNGMLpgN2FR`h1MYzgckU?*4+{UcN)WTJ1jrvHKJ3!( zX~G2NNJY};4WGNFt~oCRcvy~DFf3+yRrly6f^U|%`0IIg{baYi#zft5**w0Ju;oLv zPSxyFC|^g0fial``wo$^C&eOecty~$%iOt!ccZ=*JI8$Z`(9+_O|zHg0A_qUvD5I2 zN}RYh<6NK4vD5JpZ3*YYZndW@4cb@PWnk+6$kFC^mVMs~T0J(4sNf*HN^j6D#f$XE z2H4L3`NoG_wgAXYsnYp-|06t;$LzX+%S^ld1UtQgfkAERv7#Bw(nBfTX7SC^x%1tZ zdUei7ZQTM3KYyavec%?u&e!`thlIZjQ!V~ZqK3-wAB7v$Ux1@Vu+g?bDe+wWr#tRb zBW_%a^MF})^xhfN4Z4N?@W%f{vi=_1E0=Qzh_!@6kxo4}l?_enQSp=x*Bx6Nh1e`s zcvbuj?bgw>p;pfPth~puQZClnw!KOzyL&6dLL@=UOJuS8imx-3b##Vns^LJt{dcJ> zbRGJ}8|PVewUgL}KRcY}MG?aUGacaGrFj5Y$9U#`-w+d7k>J`9duEMU zbN+GtXTh*MFx;#+K`63`2c3FCN*o*#Nt=kpuk)LxQIW5+I^DLPC|})pV>$uTffC%S zzwRUSgde1A21d{bDwmKK*^!3YT;+2dS4DW$eoj6nLyIMYMA<((0B88BzRDvgSGaWk zE{MTx<=z$osZAp&Z5q#($rFGPp*s?-A*-f%umD(9Y$i z$^Gq(m65I#x%z(hIXV{=8tf4M^Fiz4FwNvo%)$ zVrx6&{K$(lC7+(%HumX_pF(W1T;xg0;_jerVvkC9u890%<4WOuYAKyCZe5lx!?_fX)!H{>{fzw+u*=cQCiEt~Aow=mTc>h5A1nb%*wrh^R-G(#5i zcmErhCqn2-)kqsJfK5#$FnQ>_fQLLv3?IFrSwk(gb&>Y58_|7nK`z;W5K@|!Ju5=L z63mnxD7B;BBwk|vr^&j9#R{7su0ui*brHDOFdlu5%bv?YtwotZ1)PqPWv3rqvN8sm2q*s3&7C9#g-VO+LfYb!x3wj& z6pB7JYMpiK=_Ga#Gt43HJElCM1SVa+@UO(X#5+pxLdEm!M{U6XWATBbpT?IuAnDxsum8Qe?*~Oc+?|&A}|ya&GeEW73R!-^0Si=Rk?+1ZdNS_MPxq zaj~C7KF%`D%s4*~d=VVJOQaGLU^BtjD>wRFQfhxFz-a`cCyJ(u)k6{nGg^+4DZBKez)o$Kc5^x70{o-0d~z42K18D1Xiv~}5ioxlMpraR5N>w4 z5n@q2Lbm-@HcjPMh}6t1OQ6b}it`ddeQusPcl#(6{4ON@KC8nX(pnY~S7=3^>Y><7l{Dpr)+7R?5!Z5)z-Y*XeX) z{m?NFxNYy7G6|vcRa90pp*>4OKj2fHS>fkY{KHD-ig@Qs2|KssQq^%Zh1_sWj*weu zE&`(?OYi%C)Qp%9ofvrmqK`>gk@SiXc;{hvZqRG97WQ9^E$(yj_S_PFjf&4={!TfX z*o%4-@_Sgf_LO$E3GR~p?}w7Un%vZ(xGWB3=o0hU`Kx=voI7w*bB~`31+98}$9Wsz zqb7BiB)Pz_Yu&Ne>HAhZDvj)DBTDHK5~+WsKGfl|{PXKY>cf_vBtz=Uz4w=2f6_Gt zN4~0bBQm7)j+H94_U6<*ID&AU;f`hK@=TA=#(ZuCPt$2hV)6iTlX;?Z_bSnJWZ@?v z9-R~*dUa8>C+^w9tod`Teh;mwCHTy$g$%u9RtLN)B3AlA=?!l!0nrxeXnrZA**{6VGqKXf=VtTRO;freXjrhif?nk~{f zFBq+S@X?*eb(%_r-Jh!s@aq!_zWqG8*6hA1f3;EJ8ozy6Qd95^&J;T$!?MaZpkNI1v`O*PCyHfACydd{ zWBAf_7JT8tY`I_vYA|2SrC){P3PDJ_z$Ug$a8!m#;L}`g*M?e$?h^ zLQBDwrgvcMmVA6Uea$jaYJTS9OvBoM`R({OR!R{Y{jl)$dfp1**2|fCMQY9&U(y6D zeoHe(H@A9j&P31WOuqC*8cjJ|YENHM>)Dy3-wlx&%h~Kn)yVE*GaD!9>=L_k6=;_R zRymqHw@w|*BBkYs67M#}feA90^$N3EvwYo_r6=;tuWV&~eR1mb>BVYnW3b_`kA;__ zZelc29J@>F9uDM1UC;B_K9=IA(R-}nm`k^WQrO9;#b({e)Vn?3lczq>)83))&JV7F z7xa0CgK1eIzda^(dhnx)@e;7(SG ze(7O%54fv}sJUb}2ZBt$Y|5m>@`rpi!Ed1f#W~6uo9kW`XSbDG2|8uDtZ`4TbFW&l z6nJ=y_y@bH1xE)xRhq`u+8`Y~7J}Kwj-T&oSif`DKV{jylWB_G4icoF9|g6w+|BWw zqv_&(^!eA1Uy4_&HL?uKekD8gt*69~)!%I0fh?7km^CuuG&7{exshJk<;%&Q{LWT|ebqqS^cV0mWZW`T82 z)erhn$DDEE#+%EiCz(Mvoy#vzb!1F!Ngzkg$^FPk$b=u-7Iw*Wuwm@9NY6EYHjtgyc?o_0Ys=j)tF9xNZRg5X9k*PBI+=TaD|_{BfFM~0snxNi|LpA- z=K?vw2NG9geGd(SB&Z3=vLIi7VxxjDHAp0ZQT%u8huk>M{F-LeuW)#NaH zqn(easl(#>9Db42Am)o@yJh53qfmB3uZm8-Rb*>G)mdbGnp0X>;ujse3liblIpx9Z zis2F9J8_AfzrZSn^=vJAR{unF36{=%B=#)pl<**%r||XQ0~d;f5HW=TNy2&uv&Z~h zwU({N55pPw%|tt&_cAlibkw*o%XiXqA|}A}ooBQ6i)JQ`GrIF&(`}U{slNz6-E6Jf z{H?7A0^9Q2*VDQT#fS&<9z8dRf7p7s5hiJq9&4MK1#FX-6R{@ocKU3z#o&&@UR9bj z0s!qe$O;ww`y1+TUE8wu^=y>u)~4E{#MZR?ydev7O($Z?=YD)&4Vl_-yeY5%**NT~ zA5V)heJ5+*I?O9alZ|wdRPV^pi)m@cMVDtcF10%rmwWH*RY*Q%L2C6VwyPs@sy+iF^x&RZc{IQsGF+HiBm z0uYY->RoI_r6{BHd5YJvUEdtdG@M`R{d&qA`O&&<{LA9Fv5GMLhZkowuVp+-hSxex zbo5a@=-W=LPqh5nH+I(RXJ*OlT0x9m)r9@_X`%YH1=_y*sK6xxik`~R>E*FkS;{CS z7Oy8h4lkPvatN<>f)XkO*sItB`tb&?KGK_ICP$^nVJe8~v zQq>Y2?8)qCV=U|c3_I)JS<}qnYqcDaVhXsG1!udCruo$)|bruPy zFPpL(sGYXA)uvezx;16Q(;;i&{ z#qI$(ruE5)(gexlw$y;91VLHB8Md1BOKu9!--e`Z5`ytwWq^*`uV z!r)03XkD4Sqy{@fxnahGdjpFg^5Y3FO*pT+cp&&QB$$5SF-IkL#DDy zsI@8{U7&yWHPZNHBDq9k9suD3$Rl^jyc# zAK$T<43fJXE;d`r+5gdds=8t==91ly!KVCipX9?Zd^1y4*|ZoB^0Lw&F9P>&V1L>1 zPn~XMo95?B(BlW5w6L z8a+1=A35q*&l@zAStdIFXg2;x_Gd6e0s4_#yMXtDG)CQ_HPs6WVj#EhKYB$qu zdhtHND|KB@h3|`ax6T&WuJ!wqY?$gtkz!I4{U!&y;+{DUqj6ApWt$(}jgbVwqx30y z(n_$XRRb%S<)&C4N~+8?iAr^2TlaS&J)K;D>pkoi!PIT%sMn!o64&^S+0XvFZK|*J zF+(?}UZ16erKowla7$|ZPi;SYo9=SWvbM=^8Et`D{g4tGZk=z6#$8$lkx>=}HG=*N zxqb-8%C-Urvnn=GgnjI6ik)iqyZ%dY8+9Z1hF_WV7)t?`MV!R4yjMuwRhHcNJ^W-R z068i}JDTuPhjaRarkVxn*|f`O;6Sq-nCjV96)AqI`Vd;d47=v&tcuCpv|5wDTD@Y(Kik8M|MF^`r__CZULIbSyF$2xv;)XFk zIQn?64qP&Z5DL4e#E}G2EB?C^LmH@SQ#vR*Ad3379deNdbl^yH?WJ&l=iXpwL9FMNjskOhGUE)U zb++tT&rv>?mMr^LT3)$eY%gwwr*vDp} zmAs*rLPFIs&8n6k0huYzylSiy@rW25e;}AgbwWca@eB|;6}UH; zksy_I+qVRa?l=jxQl5O!pqv$LC}xRUO5~9#V!*X??>J3a%b-q~@76c)O6|IB-|?=t z)LwN!uJYt2YA%24D|S97;WbACvLZrPn`bnZ^YfH4%rNw?^B5r@P7amaJ5UI4pw2{f zOSZVY?@`QHL^bB^IvR=w>MTg78I&k;=M% z^<$;5ol}Q=&6Is5t5D1mQ*s>au!;8*^rr1jJ2u~@ zi%p4<9!Aag`0D{}kcsAMUVGFUOmx3^L0yXTz-F83eHRw%o5;##THjKdk5E>-FrymCDv zR(yh8B-xtDe0H)r-W8f}(*rq0e=}HU0NEpS2HBcDbH&m)$owTE5}jd2~hxS9@&iu@6U|eM@e35yAIM@7l24o}-02w-&HhF7dB26b)8g@wTRKmlQR!1bNe- z`i9elaT(h`mWPlpkF7KoW;%E>Fz9o^0*h9o(ncUTpAo)#|mlM5CtqLcVOy}!f z(=PXT)ev*1-d8D+*gDr7Zg7dP=`I91)7)c3^AQf8t@!BFPnDPrv!pCk+xRnzbiy4c zzb43p-~~i7J}GkixK84DIpf;c=iBbAif?_sk4cYwtvk#%7kJ?1nYW~aO{Mk(5T+*4 zq&Qi&!MRf1k#|}2!OCQN?9<<(^=~wv;o1A0X#G{1rrP1XC&QP9#MpBJ4JszgPBK5>^q!D-PKaZe zO0%CVwF};bj+MdPr1)A~CoWE*6v_rxGa`$%(^T1Y5^1r8UcvJ3tU(`<4rzX?{Z%7q z{cAARUma8!U4NNXEZbD(=9p}+{_FTSIqD4se4Wl2@%iU9JX0OEp``jNzym%Ufxtz% z2TaX#Ly~l6jCd|I1mAsmOs2b?jcZ#j{5XrNbg|Ra80^Y;y8KcF6!}uc3z1b(NaPWn zd8;fn#DhG{GtSX)pZZJ)yu@ii;~M@;TT${$EZahuRD1rN=N7%WuQmmPdJ>V&@I?BKOPn>l@U(a!mHt(lAP0okP?33$*I3l_7}mX|L&SB(D@ za_KUgO^{liPqHUU5KBN3rsb|h;wkqiHYY;tZdm?Ur9oVgDuzR6CGBC-YvpLsyha(b zjht~A+9+hS9Yivz* zlrGaB2E_n@b5BegnjYS0`_wY)zSe>CY8mWN^`S?$Xz-RJ>0=Fbo7?sIB#a;ysrMv^ z?|8%q6s(qZS}?|`qf53G*PMBtad)LvyN0WK2CRhh=@&Z@%VU=+PATcMy=&+;hqFMv_WC3jDC(V1}*uI6^1g34&?9-b~?@VlDC)Hn7$39boRc39x zXXfWKOJyz-Mh?n^SE;YIZLfsmkb~{|p87>EUW zKK~2Ov%sA`7GnPEtCuSX&|X$)G~c(aw7$Pz39`v$wT>){L0reE#vMyvM$CT*^Cip6a$ zsCorw+p>8Rx%(N4W{!Ua(s8;x6;D)QcE^Zc$9=eF;|uw~=qix72Zd{+VBEClGn=B( z3!DrS^zcRmesiGaH!l8|XI!rd4zxEwD?GPj9$-PYh)C;t#-r^NhX&9|;HTVJ;Gywt z>g(%7O-WEL%)xq&b8zzQVMfL6?vjnwNBQ=7IX0wP2)9L(rBk`_sGio9M37*3ffa7` zbUiF}+D|9nhN)Ge>|v6S)r+u-oef>(aaViT(Zh4+k;vY}pYKLLe-B)^bFM7VC5a<2 z2EXD+2)B)z>BFo0;~U&hzb;d>qrvi&FZ)HX@s^!fpY5>~*6=EwDQT{j*iF{l6{ndcSDqmPCfV;@1Ow3*!Bo?Nk#x%ZR;PggDw5N5b|%0mmg4*RKcdSGy#V zhpDQMI|Vt3u#rX?zZ3wJewdQy-3w=U<<(no^CY0BF&4gJlMTOmTSVDe>@e`E$(wN{Y zv6*wIQH{>3(p^Pfan7hU=3EcJF4$N4#=aD!ORH4>^)r2Ay~}!#^v~ST*uthIQxeC97D*D45{;P z4LBlBz1_HhPhby1If9_(S3A>>*~Eq4!~st_hjZ)L+G3zm$HCpX~3iC|ka$k9V>j z4G^0<7YnT_u`r#MyX(**l2r_dI^;2A$H z3F+$Tkih=%s5{%8Tg(10f=8E&{rl%{P6p3jlu5gH$;BfjqP1gkc*E_K&hqgODY2fK zFnrq#mf=0_GC~26p&-jy$j_H%B5F?8HVFg*w+t;=0`aVesbY50d^4dKN zV8%s9m?#Z)xq1sp-Q>=FPerxNvFcQrxn?ltvky+aKd|jG!?cTZTEq_#f3bL!S?-+V zyB;}-vDBxTAq&Ht#c5XqTd3f@Qog_DLB_*g9^?rj=737A1DTPiT2f1uW+WcB2C{?o zRDK)FBF*cC2)7@IvG7j!+~4q~B19-Wa`IJAb9krJx}XhSW0{bv@lKY{>KQd>Es4%* zGK)>ja{Jz$-OFZ_C(y$S%4-yYqj;;Mc$@L6M$nXimf)Ed?IGlX#cBiZ)%FAb2YYY* zmQ~lh4~tULN`tg?N=k#2(ny1Jw{%>TQqtWe-ICJXjdX)_ccd1hugqs82G^r(cj3;2UKm`= zJJ{Bto#b+?&f0I{oHR}Pqicq>q42g(^N**le8)dl+bTRb|AW<)RH0gGx5aFPz-Pr4 z^8HRF_TPjTiOzNrVY2>)mg8#$<0dv$aav*e*%D3mH7ok4^s)~Vb_LRyl_$0IhTDzE z_{rypvk!V9&`cu@htpt;Njq)ivBhlo?lili9z{HEBv61%jOT?dUjjzG{?lo{y zCbY{tTsK?#=*2C;ro+(2aJAQ+6{B%*iHvkxBKaAhO2MEa4svbO&2bA~VSGsaVqi*TTo4{LZJ2t;)X zx5+A%17yep$19Zt#~XFl8sQ!c|w7>@HrhOpT&m^#a>@sJfG)92R7S01uWqKWA_ z7cDL~gXvr!xHwcy4C3RXBH^t))|b_)V9wf)HGUp2pKjzfywV09w>LYXozJ7ONyWR< zw)oa4!U`)!_)emt=&xfUiHA%&9eZsZyslr&{h$w5btdDL>lP#(w|xI0J=_Q%(0rvw znh*LGPy?jBa-uT~hwjy|3TKEpcuQB-eJLc637mW-AqNCklVOQjjt2|r(OH1%QT8eQ z2nQW!+mdZL{?cmnrmb}>fk{mElT#dIig|VcjqAbN-QjTTY|&W`Z{$mONrfyMdtO(w zvOiZFCC%a;y@NunZOPF(7UcMH>Kh2leO++%y=-nK7T>CR@G9N$X1rW^G0yx#7!z@B z<@8PN%s_6q%-fSEI}SxSn+Gn zcs4`Pq*_Px=^T4j0hh=sx?i5C+dPHxfTKgJ)$@;k z)K7qR(qFo+{i{IP1Mcogkx9RkTnJZ9^657uN43?} zjonN>RrZEU9LnX;`EYS%I`JndALBtkv<}(Fc8lvzz0gSepsluW|1D#t;}zJy><4Qa z*1S;pkN0vgg;)oR0dunAWxP*qIPr{3xLm%Je*tMjflnu<3HYunlAn7Ta!MhBk@Z0= zKv&R3F8{r9*g`l1eC}zwC;WTNl3PqclLZgW!5*oy$oXAOb_nDKpFd7t&9E`Dp}yYv z1QuF=xD;L><=Cjc;a)nX$a1ETb0C>pOA}A5?gfU}HV?<_8FCV1(WVl+)xx{1zHBNqDVuhV}x-xb!wp!7Oq%lSlf?Hcog?fpoM(i4<{gUYDjxEWd}l z-c#+B&ftpAdyc0|W0<}*pR71; zG3hR&N~I*2LO-6j);@0r2j_BSP*#caCfnC&e94pF-BLoDx=FKr(+4X*so|K+Yu0?W zN-h6v&ilu`4enaEwUK}(+t+A49zxsoL6&pFN|~4W&TE_yYaBM+xQ+(Cx*E4jxgBt#@lWo3 z8Q7hUg!MD#@AA06qMVPVOl?r@WV1?Bs5GZ`xh?IYIuJq~VN=ezB^bvN(0_-12o6_$ zYEzFRNpQt}#oG%jKJr<7{yIdpq;%x@67Ke7xzQ&`axG~axvvg7Bv1EQj&_U5EH6Ww z!E^=&zD1roOtu(!VfK?vR#q>1WbLGVU;hRSSXhnZ;@~V>TW+h&PbH6A@i- zH2eIdLY67=o`sXT0QP3m3kPIn_Qk*UO_>Q;Isc!-`Aq~;wgFocM{Y?a`(jkl|qy=Cf?>6Kj zM1A%4ebH=1dFI8=4OD|lQNW9w(E`?7tyq`F`T38c4Zozi-T9nJdC#I0mD6ID=)IhG zwAqB)fJrkWRPnOa)`#fUk)7`s!Pd24=wn2q3<^GhUXFgUnl}}cw11a`=aqN1Sok4& zBLfke0Y|f4wW;+F3IUgJLC1t!{o856U0C_^0~gItJnNBi=ejdH4tw0HJe)_aIQZ&$ zf|QKj2~}lPJ$%X?XR{|IRio;b4bxK;stx=XMic!ec2@fWIdGlzEpzj_?O^*Yu@RviTx`Se*@C%wy6ciAjPzSTBP_k0|5Pg76R z9zq{H3)+(3EPWbU%h0+qq~3kh1x3p@{ceGJs;Y9h=<|3{#OM4W>U*z+JLBKqNn-SG zXnHElnX>TZ9j;t1<{ee9GwXg8F(}20-f*t7A1$s*C)aH!82PU(HkY>w{Lt^grYcq; z@cQrxF~z&-(UgCV~B6%v}_PwU^ z1Yu5MoMP4LsB>-Zr@W`gcvC}~(dV@r+z05ib7Re&i{{XS3u?|Hxp=LAy~Tce%!KCC zsj99jvx@fBZTwdlWX|}-Cd;55uW>)thwv@~!uxI~729G@*?3`BPvU`GUu7egmr?T3 zVCR|HPj%l+#rc3;+t*#^dke%1??Q!uwsPLv9E9of*DbIXrr&&96j%+S#x6L5?E=Jem+U8tVhLY&p0$*MEJ6pXb`4FXTS01$?Ya z?_PMMv9TdCqB6sWe2q7uDLNp5~2RW(k%t*0nm8SGT`GoAq z`AS8aLa9N7B6^)cZz}t5_J0$xt`!hz@P-m>^UB1ga_Zoif`+vLsiM3-K>MJAhV#q4jkwufTFZrlaX&sht|Uec7|pa+b-1Hd=BMyXP)*QOjK*CB zEm1R$?8d#XE4S;8%KFBPSCV-7lhIOA-G4f}BXsBbciX9oD$nkl1SH6zPFTK|sgjAQ z>+i-%&QwZSc6?Fp8 zIlJ02<%!kE>9}W+_1MkK&~&89O=VH3MJfT(4?$vr7oI%P4zMh92l~@Cn%`Q{X-rj0 zZxL;2XCpoCL@pL$LACQL0E0mooia!+P-W2mKtuv|)@QOd+HqkIbD}D}h!ZL{AI|60 zkO@-?SL9;XJEL#ZxwsNv@<>}y^tqG%3#g~WXhzV)G98A^x+Y8=2aAMOO?pSW7$`8~ z+Tt9JSkfA`^@Yl{N1c*}9}B_Vl7OS^Ie63)gT>cAFnLiEjDFUSlRXJPw?M0*bs%HQ z*(Z4G6qe$eUqY^G#N=~@j!62+^9lTGFlv7_&zm)FdBZO_bL!Frq?~+x-a?%7wVL<_ zk~kw>PB#TXCjPlof2JUidh{V5$g^;yz;|Z^ZZ4KFTc}ng!6M-ZB(m33QB97oIVO!l z6BRE^!eCWfHtn(3uEiuGbFAin3FK{(7SJIhWv8$~ci6lC5`gKk5TR(q)PXzIZSwm& zDzeuri7&+1baY2Fe}KYvE`s)xSKj?ISh>{3XLR=7GF!QmTVnm!WZEP27`rP(5{ymQ_wC?*R(p zqJUhu9=vU_JSeuD5r=1Pn9c5E`Y zu|pg7)^1OvU|s+0S!p;rzVuNI@1cWp*U+ty2jY;w^cP;`dD4X%4lQ@w>8e}X83!5V zNw)a%5&6Bkk0H8w9+X?#p|7PWW%4v{$GGg(ORZ~1u{e{mZ*GQ;!eOtZH=4Qt9xPQj z*`{Tb&k32Jx1hs~0$SYJUt=aLQE}astC5(uv_XdyZd~!5K?FqF#B?W{AtPpy4D>2V zmbxlzacZ@8oJR=n*fuM9K8}u`fR0|dn-GmLs)*TVMXKd7`Hd=l5fjU2>toV5G&Rq; zLO*eNQU3^Rc#A}MOi~IJo46NIgVYCa>#fT&OW=Z9n*@e93J|+L7f2C@=xv;Ht5zoQ zzE#duP}Ich0;kxIm<=T2ZrE-Na@2F=?mUYrZ-B06=sl^;Z&cW{@Wqm8r0A)Gz=P%O{92)YYpc7tie zLSFf%VOmXYOlX@r9AxVrXH+ds2Lu-_Q+uoh~q4xGP=K2L&A!(8%}&USrvULQGLtjdVRYUi!1aj%23xp${1kEyKkxBR2q!usi- zet05M_#C8zjBU3tfw|V`J13dyI*BpJ+1niEl7ZNa(HhJl60vl4KT+Sxgz-f!Zl6ge z_lKU_nwy+@V0VQQ<$!250ye6k(BKBh#a3CoHJPu6@U4!2*c9~b%kTByU!lUv&keCq z{>ijh;m_76&mQR^^LyuTR~r%3&WjZ_L1jfBfs6KC1)6h9$L zGgb*HL*YBda;@o8Oq;_jjPx>1QAzfrl{s_TAy_Vw9dBkHnKV;2iGDxqlCy)szB?R> z95x4?Tt@W~RsQ^DZ|-NJl3Pu}gw@>poe4LBkzX5$_65`uF{?$@d-j|fe#~(*G(7e( zk{vNV^N`cb@C;FPOMdq`W4%P<`Bu*W%--R!79}!Q37xffM#3BVOyq&3f-{}Li6-Nw zEsE7%RkT(He9rnq8WLDTIT8#t!lFy?0BlMFA}gNwY-|0&qW@&`p9>52RTktk2yVcP zG^)Ix$l~sNSCu|X(RfwBIO>JU^W99hyLxxJ{DsGf&3h|Y`Qa$JxLCJR#kaNfj*B;* zPU?K18%nZ=Crs|InJxQ2f@~!^q-=-%Igt*DD7#&zAu|lu?GL>a`lt)xx7 z`;}30$k|Dip*yp6v00LDvB||Ts^|*OXSD+eFkH{ZXFMrv>qJBGq_NGgv|;s8UcBhn z4hR&r<@-pfRs5+j&St$Lr2GdWm)-?nd}S#8sqbID{rUtxQ~9ZTk33Tx!pUg3QRWhsW5QZvyu4*<;uzu&OWqOwObh?()U;9>}ae9&h zJl0FH?K43l3BEdPQi=5SuMG$mGZpcj@XBZP2m;uZR`c4^Hm^Z!_6cnK9*fsto>!|m zKXbazZKb+whdo!xyhfuMp+HVaDV#pFVne{y@L{D(y^4RX+MRyhWv2)zJ}=KE7dOj$ z`H$!FPRYqW4q z8FB1qEH2AOUEiXuh8koki0_h9cyrwwxJ(tJfM?k0ap_L^Db!Y+z$Na^akPFb(akbF z9(l|6=hJh%JL}_fr(yRHdJczbZJ`N9<)ZARHZhZ60>x*Hel%#wPaeHO0GAO~-c-wR z;5Nx&AVplPQ6opxY-oBE0}`lPEbkC1_sO$C)ViJ_I5=PW*4FnPOWocVp{5U!jQWVt z_6wzuL9nVz^)W`1#K}5@^?O78fc1v--m_(Uk3S7gIYitJL4@vOy^3diIKR-;q4Aez zc(I%fm<;MLOVh3HZ+%!-Gt!_gR_oJ(w)f7C>;bk-M(XSxQlyRD&PV)Kpwyt`S@wDO zE9YtRGw1ggNT27meyF@G8Ti?tJAcyY{0`(U_i|dvyC&!^w(#HJFQ842 z_;v?i#uuL4BnLOAQc+^qo$Il1+ib0TnlB?;mWUQz}%dms4`%n z#kq&8wKsl5bW--TkmH!PzL?^YC}i-IJ#-Aj8B_kh@xbOn|MD^54>zRpZ=NxX=d1GS zd)d`S6U?%kV*kjCF2&v*)Tqsqi{e#h-<~e#<|TJ9t(mLzdTzwS$Wvl86douu@EuRm zI@4`GXy?<(I0B1@sSHT?n2ubM3;n?3)5U0*KWXsHcHEl#G9^Iuvt_WKFV;|I1OTcX5wJ}z$B zT(~*zm00O6K(4Zye;=!fw`tKHanyvETr#MM6vL>l-}6I$lrDv8w z-25@1s%_1}8cctH9>Ip{mR|_XNd@Hc403+^-X}07EVeTo z*>kEq!cA_{D6(^uWr)Y32Y*YX!j85U#$Z=R+`U|MMw0>CUsHsGBvA<|JDoa%sd!So zBHLut=r|8|4kzbNi4iI$^>vb}XiD|?v)a+ouQLiM|m>!QM3Nolp)Zh2EZ)Q=f{?qQp?t#Y^xy?!V%_veOYFR79*xo|Nm$ z-H79tGx_}rIGN^ikX&iers=1A2-vPQWgq`cD1w$=$+2`1#O;XzQxn4VJ+~pk9%!w% z!TKk;1L(?YYJ~LmN^^X(>Lo= z{~iPKDRj`2YEj796Nl};%TzRPk* z&sA0_N+1pnqd#EBXTyVtXnDNsx91c!6S_ENDl%i}H4zV+nPi+&j7P?}^14Lj9S*QR z$$4Gd=WWc+4{)u0P-Bnd`g};td!?W=t#HyUssko$raD{jbJ}f|e8#_h*POXmU&G>` z`W!d?>{WT7j%D37WbJ$+*YeDXe6~gGo|ixDV#yPvxKEMiT}P!%m69lN9w}@|XL(E1 zF2B`emuAkCQ}2L-o3d8I7iNQgW2fW@`;r{$EjgN~w6Wlt18m=q$fK(OH}Ti%y*>uV zZ0Bs{ef4>^Ag4&9ocZP1wVEaRfMc!nQP=G8QTv2QE6yPGW|V9a$0sl9dq|UVx8}{o z0p&tMv_b7Qqf&+#k=xYPgl~Vx0Uew7ilSf)q5)IKl?raB_#3t;di4ZfH&&HkgtwCx zb;gVPvaxM!T0*tIYq1^Q`{EZ8 z?x}iVHYU&^y|K=H{$c&-jAL=+D@@=fVOmo)#|3W`t+I5VzTV%YjoO>IWj--^(c!Jt z%M`HL*#|zYNit=E!S(S6U9s?)aA2p>WeKRgu&qGO-WBDl^;vYl6XJU%deC5%{HFvG zH*(g|b5gCwk1u_(KN|a^cAKX5Vqva*uVy8r5XzR%9qfb~N#uk;1$;Q~l`X!PfO1=9b|7JV z*+Dqjw&e41&3LwQuLt|jT@z%IL9~u8ytiYyL&Bd@a8GAwpTMpIQyFKN=yYG~860w{ zk@Zh;0S?X{%&obyvO}#bHT&!HS!Ae-WqO!e`#p@`%*q>hY~M@1eLj8?0{~Su5f?d+ z2L}Bordd`Bg_}O{jcv9aX!Gao>cs9hXUZ`>hsL~JJT-|YDLkg-NM1cs_>I|M=F`Ya zM#dx_+gDS6gqpij>AduGK}E&$_^Y7{Q`|?+S62@7dkJjgmpPr>$tN*x=ERu2?*sa} z+A1N^cdM80*Yf`I*DtWsh#Nx`npxSt#toy+eaqPc2?bTmgOG;FNYlw5xM)K!MveN@ zCpE3Iq!1^yP4{Yx^TfyTVrs>ss4S_Hz&gO-Tb$g;B6kE}k(>`=NdM}2?I1Fluc(E4 zAO~q6Lcx8H*}GFkrde)Cujp19(*Tc5IF?GINN3f#bKT-EgAjXPzh;>&$r0y#-)FWR1m9q|1U5_II5i)`FLH%rB#I0d$$f?b!K+Ug+=h(oG zti?c9)6TcQ_(1>XnRH;#7*86{vn=v?1jfQ;7$s9}#?iL+30G-Yt->~H5~RF6LXsT! zduraR_7zdZ@J&U#$T*Xp$GpB(OSd}XZ2U3wM*ERo(4Nouo8?;qZhLaWY((J3`WOTx z?O&e2x08W=t`wJT{)Te~R^Gu4iE($a)S^7YyiDEPOkJ^GV;b8URJxoXKY37L8L$#L zjC|uVT)ST|4GEPJY9SYj#c>%#;2CV95kk_xlQZBEX78S;x(ZRciG{cN7|%_Gl1&@{ zZWgfa`uaj*12br4@0u`V<*+BtdTecAzq97f1KiBI%&y&MWI(s5pl>5`w3#s1(ZO^v z)C}Q*35#6Ux^NN+#{#XS`%7n{(zJ1_raLU{`WIziag4s%0Ut8l!O;BFs4+XynHkL5 zy7bn8dT3&zp6eH(65XG#Hf#MRqC20o%Z?3uS3meFzh=pJtFtEc2g>Uk{mtIe4MF18 zj9D>ThP~w5@LBaA=D4+cmFio?@;P*xmQxbYw41xLai2Na4V^)Oh#E{LO(!ri-kGqd z&`z`8;T)v&(r6A6E~VUAzF{?;lhjNQOD=tJk%(MlI+1U*9!a_TJXhub!;2|dLNz{i z=ZAU@#afRozX67(=-WetR{F#$ys!21+EOvLGmM`$6oq1z$RK}c6mp3T29x67OZFdN zrZhbtoLEgs?VEQ<^&(X(F-p1(&VKeYV< zI6ThRnugEu%vrg9hhMW7B9(1RM%is*Um8!@N%LhsF=x<8lIl$8b?HlnAe&Ch#yY{Pdc3cpysEa?u%YIc8m zwpeoqC><?TrTJEBw%>fx6;-W4K%WgfW~Z z5Fp#Bx7XoMWuU2EYMCtr%~V+8{xl6y_>;SbY|9>S7FmA8|ue6d&dgpF^54Q7l2v03W9KhXuD zHZ9gjI1Q@cFj-UYEM=H7tyPTwm@lV^U5O4lS*QPnHz<|xHUTm3-rEXph96br1GQu#f7D@Qe5uJ6bqYf^^ChI*eZm_gK5L8*V~Pr0CAp zzd-ZR7TePJ-2PD_Z=y$yO&)cdaJuraRChMHSDtYnm9+0&f9e^kvyb&3a$RoAbK?f{ z>3}EBN+IY(ieA*+R5Z9rUcd`k9=(wFuNT%HoY&f$4$oTIa~L3h&?``>*Zir5yjN8> zuN}~5cQ70&8iMfYwj;0)pTni+Bfph=A7RwOZUT=V^+8XU;IkXKHE|^)l+t4+@>w?B z)vorGpL<_6rd9mVKYV8Kcv*Dy-m-XfVl1h%wjN05ye+GjT+&vqJK|QxIG_Hmf29B_ zIGwl8<-verwD+w4rU!ZwIBh8&ru(?=GG^du@MWiZ+>Ms{78KV9t)II2s8w0gSNhC~ zu^47n^ElE)b-pA`{*9P}Z(gXdd^OTpNqla@GY!biQ(v@}f~U#Q-+ov*kS;7sBTG*# zC;3(JI1|edE?HBO5!_wH;UvbZk&O4GFEpA8G%%)OQysz&B;D7LUng2kf&(rF)q_-- z|2Vcp>hz0g{M-QZ1sAhL`q;4?Z%w&Xwz}2#-`o^8sufVE4o((o3W8)}d3*3H&V;E% z`I7HDsSF-DA$#AH8@OO753r@LygD3>7h{}WPEdpFU(zvb;K5uTZzp$D$2)n#9L!}doqL)v2 zknEDs-WfP4*|=2s%#e0!a%j~7q~t1%4oT`nFGJ<|%&$R5f#kS1CsiMzfIam)c8vj| zy<(VL-~!>hVZ+xxih-EQB4@vCe3zB4Hk}ZBg}`?gRm!_q+;lHatNdf6GST28`?0PU zJv3mtry^i)I_(@C0tJk~+E&QfNLJrk)|&Aoqsq%ab??n;qlYLwq%9VVi_P+Nn9hEC zId7hBHJOZWk7H>Bs5SGM#1R67&;*iVQ{QVHl3}3`;}r&LZIgr20WrtzrsA^s_6!Q` z8^#GD{&Fp;xuzmi1v?~nKc`9!GQg~$ zz)?LL63QKu@SIPKDZx8gSCI!_VoG_|tPECIu~0Sy_VmE4G&?qaol!+NIPoohQ@3j^ z87<1R)E3Ai6NT|u-M=#(IgR#oV$)p=<(5JfXHJQZDlD|a&z4D)EK>XV6TaQS$MAIk z@7aC*@pp%LU#OH9V>~T`{MVm}qZxA+ZL$@296}f-y~gvh+5Xn~H69AeZ#4F5&j>Kn zXWk{euM>L%iE(0z<8nUET+(RkY5ui9d6wXF(i2Jfi=Jb#P*i;|7AVqP=mp{j3byW*Dyu~jJJK_=aA{1eB{5iIIe_tdmk zu@KBeDwrkjEgnN-)MLsKw=CSBs)Dxk6tH-xhoUlI@n8M&Kyy#)$}sX+u@*lbvjL2h zdSlPWJ|V#Ci;PY_eyOj?`piLbdT_Cgu8>xU zkpAc2Spe;#av7pXZ1vmTFONy(cBk<>R^~oXy>iYne5*4T7aH6no5O50l)^?K?p!By z1LrA^i#znr8U*S*ha$Wm7lnq(2YcLhC=j2FdP<_JHvP*IR03qHWl-X|Y1!ot=-K<+ zd3v=Wj!dpU|(F9AM zMccwIc*+Ws`LAkKWq3QEuil^1)IOiCFlOqw3(O8`jr^+D8Ilv~i-H=ry9()R)~wXB zoQYcxg!v|ws9H5$3W-~02E_@^hZ@*_6+jOuseS4l-I<>UtJRTy;$Gko@(>~kMm9^+ zD=bImxaBf1WPqh%Y;&z-eeiPDZKS=l^HrpahjR)RfN}KT%=dJVjqfvz7h9lSDgUrS zj|ej$>=!9(YhqezJRsH!p;K@CdX2!VR&pin0DH6m;oUmTlLt*;6EK;e@Cd3EwGa8| z*9f2}M~x#XawuHtn0MPcZg8WTW9BTm(xadzpqnx_azJ7(p-&gh4HX19@}-~cXVC*cEVq0?fmR? zHs~Ql{L<(Y?&57?K?tVR@|mAWKqmxN>C(5vW{C8~%TAdc4s-Zi$M(Zeq!s)emylPS zrsn>gqI`5o3r>0zwSVq!HrzG_pEgccp1@LZOxvDfpGSjpp9YKID=Q%EDw zOr7L=uNSjsU~3h=o79996{sJ!FHKpm_+Mn9tce8i8iEu^g6VjnrFrSfHf*J&c|VJ^ zQ%fAr+KH#NT=}tB_eE>n^g@GDC~}L^G}m5H(ZtUBZG+-@&R)?f;;C~5UtdOk@6^22>1mR`|NQyJ zQJ?{CaFp>eV+Bu<-V%j9w_J+CxSEH@wgYRP)qBvt)`w*hF1(XGcz~ILHd-UO(KJAw zLNC4hW~+ARM@Cwks4N(8Tvah-$@J6C!D-21UtJyEvj4;j|2 zpeL);9yd_IQnk86UeuR)H+q7_T=d`hMWuFu+h@kC*oMxDcGi@l|CA%GUyu231p()m= zlP;RD84SEsHM;+LxSQ)jUZwvMyXo$noA>e;S&T8|icNgaz^!*8PZ^){YKIOejz-0< zm!?k1EdxT?zavYzw7?Cv7E^9#6zkFKf%X$mO7|8+j>o=SO$0>q9WvCKpP&l2cg`+nym{`W*}gD5u?a$vAq7!SIxat_=Pgga30nSt9vUGvKJiBj0>x$deANIs6T+0k1)A) z8-Bb~+%y~xj`R5-qS*t{%f|Poq&cW(sjKmDDm6+)WhzYIytAc|ZN6^#ecfroL?-jQ zY$PJpVd1TtF;K&{A z;G146(>-Y3XIVI)qg}7Ru@sXDmp*eQ@K|bvS!sYMbQ9ANm2r$oa_BP$)sz_xVVybR zSV0X$=9&I}u9^~Ok3ct+f@WdxL#&To%z?9C;y4W>nZ~dpGF>+2M zE9zEFX1F2GSNPxX=&O-NBX(0EASHol-Hr?(moEkbguijT7foYsT9B zZj2en|2zQB|G}4m-sTtsDf{D5$u4$E_JiOEh(RgXqk2<#x!3w)LlLkUB+qsx{n8X@ zrm{EE>74FvtRi#@U*@L*@R;+}CqT65wq?RPjEx4L+WcdlAD$9A-izT=fq6Y&jJxcc&^`A6r_aX-5K7$_N z_%hFbD*$FlP&mj8=?oT{oF2Aac{#XD>~fy=7SPiP-=o=o0{lScn(@vZAQWw$1$28I*SpDg% zc`TXw3OI!zcr<`>zL9{Hc;g+a?j;Zee>g~Zvd+j_8Mshwjn4Z}pJ%f%mbKcgZbk&5555#vxOP`U!ILo{2qJ~ zV9*Vxt*>a%E2)DE1O;vB#A{sMqf0#~12m|o!xWwyZ)d#any?=W{l>Ka8o=GlxZ^7Y z)A1S8*F!1k3tLxMih1VtB4>ySwXp2o4NoT}@V-4fYKVj)q-<@|ok+R#J zvc6tVJgd-NO82aP_2z2yxkAZr`59JW5QBhD3?0Y@hBEvry#(~3r?{Oi2zj3<U@V zEzxh^-|T1XP9J>#b9aC`Q)7!AjL-jum{F|4a{TK|MWqYMq@nQZM-Q|8$HO*IU)IJt zz#|bdE9|`KwLrA0-4adUvuB=nyU?%Wf^Zs;lvF31fk z84meeoHp&UG>X82#=o=zfAN3Fs@#TLJc_m=4F$PNj9Xs0{QkltctZRF`rV7S4!bzf z4C=#EA&d%|Ij68^J0FLt>bS|t2pyG}B*iE1{q`q#6YS`q6aW{Y`Rgt@#V`FMsv4G{fXT-WX2WfM~W%68f^tzuh31`LB)9g0fmE{2uIxZe-&s&zXW48O>bDi z3AL6#djh=f5a=5bQdQNck7Vzk&Rhtm86kZ1L$TOOt4Ga_&Q2%T@@@wCMw9izX;$4; z<7)tyNFd-~G85DBWBXn=R4iy;ZyzLZ>()}>jekNV!b5$UNAbWaS&vtSE9|z8!|ZwQ zRiI26f_h3zNM6(EgB5wt^pEY8z#+~{aYH|x-#F6%LEW2e3I#|=7+cHrMQPulWW42f zb<3J~!ok$kGQ)ug2fUydPfy<`DSF5l!W~hMS;%B>0OK*_;NV|lL8U~^)tGS*Ty8zt zo39F$PUVw|)l3KnWl?bL7-#>v@HHOTTKw6UHyQu=%ZFKT052Xt^%RfVFY013l>gdRd(fl15&Y|J|1-k>SnL0c@X=8JXN3QYgedbV(q>_YLs(@G7RP*C3Im@_GjM0UsV6-UMCg}9%i4IcoYkugX-wsEE$Jawi? z5ks}Oh!7~bvS&Q-sugIK_y?ZajEy*J0By18LF1%y;XWrpMUKUyv7lms0(=7HNIR%f z%0*@u<9F0GPN(!nxwjNL z5#fOzoZt|PkT7kpSOXGDDUKu;@@kqIbdPQQZV|Hk-Ap2(mKQN3=XYMj`v(pA9FCVB zU-GBvXn5nbDS?LbT6Bf(G!J6IsRI-gYeO*AH9F#hrAW^+LeU&!Wk-3pC?Et1b9(Va z*M|G@M02@QAwPYD*{ftI&NMa-mg4USKMVD6qOL+2vA;ixc>*x?8m_cOq0rhQm)~Rp zM;6!50`-8pJMLygE>*(chtrudo8Yhm*1?r652m<)oZ+%c%;TtNze(k=oR4B-dyB(k z^W+v$o#1hC;3`PZA0M~T-WUpg^Dj3LA0jG6fT|ojI9{JMl7WC>}I zmP&o&2a8N-*!fTlthF;W(}Y;R+(qRAcSW3Z%|+~)okC*z1nM?~)B_fDxc&EidxQ6# zM`S>C`f&)2%~OCBP#w%GVoeQ*40Kfq_`wqaD-R$v2mhSW&iR4y_5sEX-k}E0%^Ly45!f%_ zfn8><*qtl6X#>N=Xy)#`co#y+#J^$wVODR{wyHxweisz*BC3{Yl`CJ{Z_P32TXlv0 z34--_JJ)?7UM>n`9P}3PD_t_bZeg^3g+eZdOZ6zJBAE(nfg1bt*0zJ%Xt1ur;Om{B zqaM>4XyzJG2IEgAwTg3u{6cUps&DpR*@3f=WlPh2HX|e$h8L7Y^Vd*`IK^>=@8@a` z(jc}Q>0*REGRmK2p+i7w`eS^~xHyD3KWYK=R=}R*V&Noa^`>C0kXjMC0?_k?% zae3TVY}_}omyYVU70NF&0u(aB5ArEq<#Zf_UOOQHwp)@n?yW|muJO!_vLW2%qagWrM=0~KRN`X+AR4-irjJL9#&-`4(x#0J>ueUx(7fDG2$E$JZ z3WdJb;bhWX#kmGwsXZF&6{P4~T5R#> z4ctnN3Ry}pnD!nAnw=y;TrR2LiCAp7yK2~*Q17t1R6kO`pTSwI+wT=*Y*2^=4M!a| z#oE|gXO0+!L;ex#fX>6nJmeeR@NIkY7!Xi)%L|9)5X*dse|fAhbHnie*n7*MD%-Yg z*g^yqq@_Vhy1P-jTe?Az?nSDANO!|Rq!%FFrF3_9cP_fW1F!43?`OVm=KKBrcxM>L zaZWko*kjvk+ly~orFv*V{|>H8$78i$;fN%t9WH4eEJKN2tp$HZNz{FX~TZynGn7TCO4hq61WJL@E@P=u}brDWSQ zXvpVBUFdG~-(IZ0nDx4{isrN-a+BNmz^dz(+k*$Mvb=~ZQ{BMl9?8>Eu6^d5JCJ0B zamk88;Y-94Hh?hIe7ZZ2TcZ$aMyT81PsCPI72~eL|7x2?V;wgX>U4PwO42(MhxKWK zt4TOGCo^u{y<)t`I5atn8^s;%K!3f7PGjE#EF) z%U4p&i>39iUTUOvT=wOQ5UZ6*2*2aBDg@)N*B*AR*N5Vpom51nX3T}EDI|hE^86Q7 z3E!grNmV8!p@(PZN0Z14L#4Li(U&dOIQy%kdElf>RgDHl6 zEGqi`gh6o(**=J%X(VjB5f!$P$IH0%XOSo^Nh zzNb=8r@cEU3X-lF2Mx22YZI1j=0@0E%=W-v^a~R4IwylBCTydi#S+5?-E}|K5AT4( z%3FPt(5&2jG@q$zm<+K#D~k7zbLgPMD4EIW!skPEzgUgSZ4Gf?ydqTKezO$#PabV) ztN5U?SQR#!_81Wbm-E(eQDzwd8;0e5;}qBxooDKr&=tAroXBjYBoqM#t`rMVpFU~n z{w@{MrFd0A|5#V)&+QM;ihc9>kA>ho0!pcfbh0kG~h3bZCyYtxWX5pstg^90H&$$91 zeQ+X!*`&IB+#HJeR-Bk94z0923~bGjZaa$5>!`c@ELh=`_O4d#o5)vnTe}Z6t`)Da zXQ&^aQ(U$vw}#j|ZK-g+sH$;xZ?CGjW7Mk12g8+Dp-)+^Jzf&AG#xvdGWP5Ci-o+l z42_Xdk1+rgAX0@KHb%M2U9^Q6qR+F2P2wmTe_v$IR_Ned-kjZa($I-xKX9ubCtKiN zlc6Kv@ZNnXePdyu_N?4ulrQ5)cC2DQS%DzIQ#faPW6IN)TMAbwI-``YznNdxbuP5- z-`2a-44wx>ZSoo%WPf8eteep9mzC&mB;&l1--p~!gD?C|=(ULx0!Q731jk&V?ocMj zbf9LTSjjCr(}{%R(AxFiPXX#%Inb9C3M@q3(q&5;6niI* zX6M-4Pd&&iW+u?uM3ftBY0ox}8y7b;@Hrv95lEHkDFfWmkUJx7O)!?F?>rH@^u3t!xDnO6a@%Ks@hzJQxow!eWqh7vX zBf!Yu`!iOm$)2YO`rtLl?rM=K9GLxG<~O%KZs2bb_KS_`@RVof{i7Ko(sh4QoE9Ew-0fePUb_>*48xHV_+v<*0wP?daklb94(4%Y8-hC9%@*=a?p5 zbo_*l-^ibVS`0ESk)_sCb`Df2@>|U0G}N($0`2M!v-T1`RQqhPAXw6?XCnsf9o`+>^x_X|B~te% zY`KhVMm0Ry*PKI!PjYCQt89i|1x`2j3jsK?S-#fUMXgIeUNo4uR#43^kF>7}iX9nX zk|BxDar#3EXKrG7fzd@r^F^?km}lF>tALl4B9LJg{KI)ki!D_DFW0?x^P}tj)1ET< z;U1+9yfkn5tn3c9Tna;mIhqyYenOfcAl}uoo$IM_4%-dNS z$3(!3#Ny-)=(&RWXMBB{q}5hoPQm$>bgg2_7W)126w>M(=^q$bU7V30%Pj=70tkl7 z!#=i1mn=A|EwQ1tr#LB*&Uz}hpw@r6C{AYHI6zjypt$u`W8WD-5L~N5jr7FU=4f>{ zw%mSWeq8ra(1P;f@FzbmmsekYCn>*T$F&F0$@t2VPb||{d%ae4k*ZGi`TJ|4e)*}< zXtOD$O;hk&{<9GQ>6kT|69>il|dLDVcoh7FVC%KON{YU#dP1RJoDA-Se&EaO9fJ;kvX3+8^1UCu=HbaK-P&;e z{s0?ib8(aIXttxnfE&X8GgHRooixRI&i+qug5el-Z3AkXM$Seuht--Suk%Imqm&*5 zw==it33hS%xvT7! z;KDoBdeQDvQ@m8|sskIPxL-C}LwDCl@~r)!M>OhKx6li$2ed(@*K%PR0(0ml^7c-> zRypGfCPze8(~Sw_6_{nwtIUzhquV~Wv1~E;>jr8~TG0vXBb&q6V#(I1HfK8~V|v-v z%NZ%P&Q#1=C>{iyd&;aj74KG!3;Vt3b+aC>`lDP;EHED37Ol6F8>CpS8KGFblJX%p zrQ2sz)22Xr$H@9Tto)LWPNQT-W;tpwRfehCo)C=VQAzGTu2lRs=lL`N(mEC?DPl(! z71^>Cn$e~DDQOdo0C5c8ULR#p?1H`sN|4&AOkmKCz*{D}BB@Yf8=gtdsJOL#-7%kR zxxGR?EQ500)3x5*Jl+kl-;pXpX)x()f*Grt zF@yfA2c!2I)WDVxefeVe`ogm#xrLyHlX&pxE>Ot=Kv*)kQu#nv1d7~86{*tkxO0RA zmE7So-z#GHXBaWs^sa{2WmL8dr;|YbU2%4yW_g>88GqZ}tUF+-lh4>H%<>Ru{^^Y# z9S@f&wzTTG+f1VLNG zC>5cA2YIeo!8cRh^J-+OA_f(BwD{P&uHQ!F*m{(psbRE-(|+Vbf+azAf4otaY&_Rw zBqd{&oQB}GGMdsozuOk>)F)78lz9SIVL|LrJ|vX~cxc9>@nEKKLIAA(LZ9x{7}{-g zKOt;eJ=>Z5WV(1k6^pTQ6}0|Mb<%JBG()=?0=UG6A{qFcG}m;@`iuL-`;*zn^OIIt zoa6%W|6Gi^=Q#u<6KxW_sgxe;b}(qXhSRE>ee2K8>OnY~DVu&J(;&4=KvXH5Vzz!^ zc}2j|@6_ehnchXGdE?xTcriqIANU3uzj=k>VSbc$Sfje-A6Z0qlHqo{%y9QgE{Q{0 zEBgkO6`#Bl1nf1}8-T8>K(BGIZXMr>S4;PMiLOA&VTdJur7&Rkl%?+9RoAOxLG^x? z_f5C)=C)RbCDdAQh2Agvxz}N#)|r)3Smm5N`gE0sKwXUG8X^}yTdweG8#3x5x1=mb z-{eRCN#@6W=}$SBqAbrpsz2$hqqEJq7>P^iS$13rAS=(G-H?tg#TU)BTC`hOKP|_$ zihBCuS^~S6VDhunT>CFer5J;PX-AfqUUXR3E~Fa8zcZiHZ4}#KSBhIIo0}SB`qec? zF=OHvbzX8a($>s;8yO=;d3=$y%)vvgT{WwFyO$u%)gRMEkLD$A;f--J15y#_7oECK z;VOoFnLwc1ap5YF21Se}4+LN=!I$@EEAkkwg8aNgxs&etoIx@TT4i=mI^qt*TZR-> zh-l!ZCgYZ@VDsK%(NrSI^JVG!oAA^!NAINbP`9|zuosa=L_eRLki=2B!CEihF8Uz; zcDrbsv|3;+#c>a=hR$fsYkzDuOJ8OOqob*VYr!48xA~W$_C4pf&Nsgf9vD;vIVD)w z=7}qv#1C@B!jXl1jlb zH-w-oMAx17T+j)EwjK(40$h@tIuRf=3E1~=xMn`YgEN~Q5;$*U$=140TpLlogV?{? z=@QO!)_i2a0u6(az0imagGKp*pe#|6Oe~bS`}uy9X`R~}K8^&)2xL?_TWPP?q0zD@ z{W%PcpEpL~U4{|pNq$o*+a2qjt7Z-@wL?GKuibY}v`drw+Nqv9%3VzM%qf2dMbLQq zTi9!>&g@W^vP=5?5F?L&Q%oKL#0_PdI(}r@Cz+Q}@h~FRyH_06mo=x4mFA2G77R>v zM?cU`5IbHB_A-*P=SV%PMJP&?zj0ON*Q%e-Yn+Td!RN>orCYy#q%ZoQ&{089id)&@ zWfmPLvOVd3Gb3gBOB&9rErxO))yXE^NMi;1%!_JUWXsL`2F%g86foOi!x?YymS*oo zL<~vQ-;Hp}6X$S^GPy`l^nty&vgqYur(V!z4>wBdvI@uEy-tQ(yvqK8ta)`tY}>h%*Xo-<#4$i-i!(_0Kw-4>8RSKT_khX$>uPooE7Cu}V@5xb_d!8`bja;iRCxN~!yoNna5q(_a!ruDm|t8F@muxOCG ztCQKBSU!{(t1*B%afSZp`174+Ur&ZDKtDpcaiWgk?X*o}l6iiqI7l_FP}^|9%0UxC z)ni)#xevWUGg?s<>LV;OD7zk77(*iNX?%XSr@AQEny zU@fK&Qwi;gc7yKKpAp@6uHhC!p9Q(noLb_NZ5_4~WdiCF#VGo9kcRjv;E9NDcXQPs zE-!fFOQGYkD0;KVWP910Yjt$#QaJ6eS+7^MzPamyX?-_rM3)Wmo6QLSqlkmkcTKKs9k*aj>G0><{p~!J@?AH(Xa>d;_ke%7;s)kLT^q#6@ z9X~HYUfxja=h+hj>&!~g>+y!0oo1>#9uUYM(0PL-=f@Sk>3;}SA0Pd5ro zYKHCl!`yRC3*v%}*M9RQe~tf;#bDE5Mcz2L#tu^}k4$hH-C`eE3+Zcf8m4@?k@>B& z#yK>e*@2<{%uA0MkcP5I&a)rM#t;9lPDp(`c^Xf<;9H+)^MYU>l+h3cESo)x=wu^B&+H z+)Tf^h{WoRD^Lswx+{+S5~9M@0e4=;!x@d&nDOdJLLiXyZGX5FrdMnjP+@b|N2+dL z7WGG^2z4HC$7CBci{oSEJXN-F-j)O;mh4M_qDmA{W)&>g&%4#)^rln}NT};Mha%ic zgHdHLwV&wbJuqDS48IbK?zk@Emoh^!i@{Bi?zjQ8R9u#KG6hcfT8 zt@;^g_WFE;*3(Vy)O&8v7x(>Utz~+M_nuuT4G}_faE1)&y1*C91jlVc>QCHA7UTI7 z`VI>BTDb=L5uu_t}1vx-YME+=+23*RsIBXRgz|`Rshr` z06iZ4!_BleZVl5(ru|SG<13I8t+~D2enG|zR0qt;`O(kkzyk z^OBq6{(B0&w+6}Gch!Src60iddU7s#W`J*PHJeCQ4rL1G(%$BOhOY+C;^?*15_wGO60#V)bSjJ)bUaT~P4VR3 zPyv0gcb20d{m0ID!!hrmfbQl+!L>a*y>^-J#Ovgcl9aE2TenMl%OhJ^gZ(x;6-8+j zCo05ecmF+m>TtE2O*UW6xznfE!B!kSV{*|q%UwL#9s;wDIV8*H9s37Oe#lBlq|3!$ z)VS__mdJX`(`i1JUW3ggZZI#T&dVVi!@BFxF}P7_^e+4r=;HrNE`k&G&JvG$=2aq5 zoJxA8gjV`(8a{{P1ODVY(stMgmVjkW>r*X)pW4zfPg^^niH^1WLNreZyD#9WQ;3q3!phNTK(wt%g&D zkMC2sxdT3YnRoRf&>{CuRdY}^V2+0`yJVEek2u`Zq4E9W8j`8b&vD|$RvubMMS1zY z{F#Vo z?A7>j@kPzzy!Mn7g^UM=@0`Zld~5lUuYRno}*r2(NZxAt@*_{ z_n+P%dPt;tag4s@@S1t{mo2Q;-=l5fcgV}xS9PSI#S=f&g8m~J>%Ko9VGGw<3 z@M0Rqd*3XN!khaG5`|nx6)^`aY-enotCz1 zC9oiI#+O+mIPrac+?ell`L)cWhJNVPOXO} zkHnvzs;H{G)+>IraN1LupoOWHtJePNx6&sjiv4D(H@b(dx{YHt6P8t?apoS;v?!{g zIJJY;13xMfdk?Q`J{4wuDy(l~)}eG&Y>X07n0v?1bF((WH+VancZTc)eb$(+@B*C_ zG$nLBkNtm(FV^+FS*|Ill6nqT3H%fN|2506Jif}`ZVd(U{ob`33d`C5NgdUm7_?$c zJVJ(_T@-hbrxdAaZml- zG_h{j&C$G7D-lz@){{sOJ1*mdQmm9|Ka!?HtL|-POnEYAB#0}fj(8YP-hB|U{)w?> z;|+TkmkaIkQ%p>>#=Cv*Z^4yL+bG3X1NPm&z$A3rz6a+&7C56%wm(@QfW@p~wpg;T z(o!6d^?sUWwhR9sE`SWgq<5#V`OufbBHFJGWT8Cndm>6zcYVqA;f`xNkmY$nvp$NO zoBrwyC)Pp*hIow;p0yqw{k9{?`;?^#)IIGh#qFvoeQynzHMNm+a3I|_ zLGivm%uagq5TaSJr(c$4JE-)~-1<$6*Dq6I-`ZXBY_IR5dZrD-*>@ayC~dtx7ghG&&WqgtLCZ*`uWrxQ3COSs%1q-A32@rq>NT z4qw8d1#jyX534S}fwQ*YeBK}F!W>D-bioAuG53W9(3iu71A=jBi`yxDQ=Mx*hXsL7 z0b~R*F4dZ@?Ry&@-uUtgfRp^o9noc%!a3Rz$eZg>5oQTrM{56TYGd?R*$-j{8lqkF zi(Pz!J*W^GG-$_)0EmDihQTC3_bBM(xVt5l&t&=vc8s`4B46BB1+Y?z{XuE&b1I#x z%|i&uu?@W%{6S@pq~OoCQWUli`t>;@kC6%w#MH*5JGsWvQuy8biUW(6DH9-wFLBr6 z`=Pd5Be@w59}BW{!!9-4b+bRI#!=VxB{>CHJ?eb}yHy(T*+`r|k37!0*JT*B?)XU-xg8#M@bTJI!zzt-{Jf zE~^M}7_O64vaOAdrX=Sr=N?cQ-1p>QGmIzP1B@kq1bFmzYH$Rz8hm8l`_8DLnMMV+ z$koUL>0)C|Wy)aY&F<1Rl$K+i>kYUJU3bx`5>BC=t*{cWYJIonf)}NLaG_Jb5tK>E z7)vqxl-JCkb2q}!ytq|w=~%k)ihCjhQ=&eXtz&amJtk{YO1q!PfUGgPh>v4? zO@QY_xQd+f$PRy|VW$dgt-y>+;nWjUYr=@heZA-b`!OQ?I?7HPUM~;RVeKC^tI_p| z>va`SL}0pd_+h$oTlzC7qy$X6=2IrD1KI~8P*eWh%9mx|8!@B`pH zxZ9BwE>zZP)OtGeEPFnA>i5UHy-{~R9(mt+#kWrb!uP<`Rlv0|8f(oroYt5id!=(OL9`ry&3gQjTc)?i|suCMl zqsvjD*o>4m9RtZAMbYEktex42sJc~flc{u5JF)4j*qzUnQn0FW7lm@TteFw$fWtODTSRDBvkp^NN}f3;~li6Z3{55#El{lRM(ey@>T9qa&@Zf z_AKtsd;hjX#kWi0b`YB;S4CMo%>&qXtFnUhdoUP_x~KULOcH0RlUHCpOx|MPX%H*!|Cs4T8*7Af&(izJG5r^7?@Cwc=r0s+wJAkZGowKx=L~m zXvD=i0#$RrATjGQcZwggy8;56n#jaeE2D}Arvoyl2F3ur%}B5ZfQVY zlN!TYf@;(zSH}5=>9ew64|m~Z$@91RK}BGDg|sUBROBSY(wNtk53*ydpgw1X)8=)0 z(0F%az}yxzqHmF~BpQN6bb7dU1#9Dm={M6#m|R_4j4>N#;+)B@Esq*ozq8nOQF^wu zw||^ex*oE&Kj&4bKOS(vi#&GsUh+u#a|ynnsQpWy-1iWgsH@ytdS4)Pf%Au;cAtmlrmLd_d-40#Emaa)Gn#{L`6MMuY;(8^t+>2^@P{OcNdt52&&OW{o#lg`;G7}r1mO_*ZxrC(^1 z!`x68`(U&C1&Px z%WL|h14Z`ul5XvtfG#4}KKYbd6@CL43X$ucrrC#<8g9s)%lx*H+MV}l-;=$prMqQ4 zt+dPXuAw(2Wi**(WC5>4G2hgxyswCSfBGu(4LO>Uq;Y{nkd*mwgB045-h0f$>vdLn z2Wa&=_xhZ}K7YSwMZYVgkA-!f^$6u+|i70IsR?-AA=iUObGp zRgXuxL)pkbd>H3Mk%t{ak1dfi7e37H!1urSz`NJx%d1#vV*}LbhSwDyd4sk${gg>i za2%pG@Izi*?b2jlIY)2rT%*@o%`0p`Tdm%1A@=q_!WFd6P~j@Cb3oy}I^B;W;=k&g zDkt7P8fDCU zgE-FiB9TFXxOtCzRja(Ibr4CMuRbk=wl3sPJKs zQ*09Fr=QCpu}0^QNsS&cwk?FKxf0pE#ibbTEnI$doLE2abyZ&n8!Hec+%4KVp-`&( z!0btb$H^PU0`JJ6%Gy*uTJOa!rDT(gX5`d)0A82kY-2oYec^blS#NN z)7R1GeXr#`Cg<7E2FN4CP+?xPE>Zpe#ylc=>vDXQ;Yf z1*Rf=x<6gGcj)w!AV1mZd!A|@O_<FWMmgIxa2HR$GU zB@t}Nwv=6drLUBV{LqjAUD#8~_Y(7j`ie^0lP2ZqNpA2y_tkAj-#&UR!G%-mrOH@2 z-^s(R$5pi-^*YZ(R*gML5l-g^d?|lD8AS z#rA&?*16j!5?GvSDv%PRtTZdbd9C*?QOGKUPoN*1dww{pm9>_K*f@3#@1z&I??;zc-~xVZHv&NRtGL1P9xK4Y||%A)PFqepj3?N{+1 zX=NZ4WiLYyp3l~t1xR=&melsSx|QhJL*>ICoa8?FgU})78F-0ljj^SSD;S%cFF$$N z6$2AQy8(-9lW73$6Z!^iKR@wg9Pi@dpi;dXd$zq+#dX%@bqyDf`pu_b*vIXJnU|wu zuxshK`mGJwf$Fvp!o`)=K8&bTbatO|f$Xa#p7Pt=-ATduQt)4WD6k z^$TtMmxC((EMt&>;_6Ihq0JK+uO&3@v*gkf0~RZm^+}xf+)Ugi)^@`$?dKrtGgB5djTVklcRpJPanLIEL7npOOVGcw_twCvqMAGCfbMe z3|%5dK-52X#yu>fY{hkepUF6*uEG#d=jb{PBCr@AJm7|R+(EKt%Rf~*?s)hgp&v;- zA^US|9@b60)!dIVNVHKbP!p3~@&fnr2YsKzT|fY;wCbwNDvE6d?#Y7d+2;3UN?AO~ zLg;LUL_`zXy35|RvS#^Sd}mt6&7;tc6`l`8w#6^-1=^fA;ID|AEus?zF50%GGd~pn zbQ8qm)DkHRMauAD#Tq(CsN1j@tI{4R3*-s7DLLvk>YGMUR&f2nG%1D~)n}Q+S*zmHN6{eAya;uSNA@w?iv%iHcEoZ*y`{Vs2b8YrF;Bc=DvOKUm{**!HpShZVrth^ zMYe#D=L475yR^8CrO7bVmXa`!qg|JwnvhDP@LWOyMM_z>3EY8?eMweqS`?NZXLG|^ z(-;wRyG-SF!-Yd>%e!(^(1^`BL#D-)*;=W^ricnD7oI|+q=!rMUJlg+_8p{XlH;DI zemNRXk{z7Q(j4H8DLzBGCR8`HR7Na-^|X(_GH}^=**RW>#{H*nuy%y|#!8>PpIewzMb%YIXFHZv>DVR^1$+7Ho9t-J~^h0UQMEC~N1 z3#ai6L{YBZ8|!Fzw7h)Sj4Fuc3Q0th$zrp$tr6<=bx2EOMkY4dQ&gr*nY5n1^=45G z5o+p@*|WVciIZ6Gv&yv34BX4{HH&BYs`l2OvD`8#n+(M?uW2K>#6+H@lhrDY&Qp~4 z1@691)PqoZ+l4>hSsH(2eT!ZsYY)_PACnxqgX-GrEPv~>%O~vVd5}$gCL_o6^To!z zIPXF{j;tD&Oqxf0h_o!lUa&2z$v3le&$H7AoHcq!Q}YtDYL?CGii&2;sh=+Udn_V{ znhhSJ@3DK_M$RO*rXp(NiuAJ>IZO$}ul0Z`Nf&Q4U8+A1E_t zB{NlL9sgSL^%G>aUBYKFbOauFd1fp|o>+IzU#`Mh_{ZTIRR2;WBvcx#UIcM;V|QVW z448DKVl}#x@j|V1ZwXtQNei=NV;*5W737ie6J|c^{2@Rg0!(7`O?Re%QykQjbHnoS zNH)tJH2;#Jvr6Q4HeDd*#7f@t^W}rRl6<$&!G_2~e7Uv;^cI1ya=*c*1@|dGeJbA@ zfvkm#iErX>eLRy=bKi80Gd%fy^RutbV@(@Iw(;3e512~c*%mr$>XHGiNNJkfAA>Lj^W&4fG);P+U2dNH6Q4Q8e+|yh zsnp@vTNk(omm5qmS9>7@ic2?FccXHE1*3)wD@oqCJ}Q4+F}4rA+C|&{O-M&*Cfuu@zulV0SQXkp8P@c)zWO3mc`1 ze~Kb7I=Fw!_`$NEUwWJU(hXTmrqPn|3|mEvW%KugVMXi78dV40lM(v_vG`Wnd8>hD zd-rEm?F|=e?ti2!GHUv}a@Ho zi{7$baZE*;=W~`Bvc!#AZsx_OMB7ywcD$FVSomXE#de{xx4; zs|`7HS@~t;#V2ZVB<>^GL)0d%E|RZqA^a~-az`qd z?jh0$B8!&;w+3;?Ta&eVLFb+DUf8>56$M~3tt74q4ohi+nH=GD52|2(9CpFf_6xv^ zgxk>$yl<{4Ch|h%q$fdK0<5Xs@H$|A>-1uHB#_mVm zkZ6B; z=iS{~GZL ziYPT`bL)BjmPRp^zf{$6Kig|uDQZSh-k(FaKUN$hTn?P*|0zmnjx_wfx=0$3~xfn;AWF~DarT&UCjMOkDs zFR(f5^11G84$&<$wbqb(4A^p2z_N|{1_!eJ=N1_~K3&`BO9JvgCGdU_`L`3X7&xTm6hkN6{Q zp9d#jk_S zi-*3Z^Fzi8{lDoCo0uq<2Pcq0^joC7@GYw4e=%DmoUe8L`_u zhTFkHMIm?uJe2&PK_Djq(11{q&nH$_In?-QeS&w|=951)Lf_&%7Y4#p`z%B13$hO~ zVOG-*30&}A96*{lUhYLbKq8j{U+L#ceApBFr@-iNrxSjSUg{Tg=>!FIlh!WI6|g9G ztUCjXQCFKr74{=`K959Q+bdVw_76n(J@d=^SGny%PB?Cf;%RsvfNn2a&+|2tBnUGN z1Ik$T3V1HR2N7>1Nbte2cZr?XIsT$NSQJm~kbaKcxt{91+4J^3Zj;IklxkF!Q<6<$ ziv@UzPJKMWPoD6flaSI$f=hu%{^v(ShC~%v<@M-~{}HXvPk;_dkXSw%$!-EP$M;vg z3jTe2a|cVvK$iUS2;r-VKFz&&-b+KM6&`l*KmS4W323|haWeH4;d$0ZV4aNazqk#u z+h^c;|10l*D=~(|z1=pvx7!gc|NiUeCrv<{X)J$6i~svjHbGFUfqkd0Y>J3FT555C+_vhZY=KKFL*B{f6)k*bGIVVf9_I&c7MoX z2%Ah;Per@_IVkYwGoatOMFC3xz0ivc9D8Fq*S7S3Z~BjnBG<0I4g1esrvGYN`q%%M z@&Azs@H`XmssDRnBO1{0dClY#ivJOiXGub^V`?C7v-bZ>x~%@19!25*D~A7Pi(&XQ z(tS|SaJ$CKUGBk6t$92!qnpB~=(VK``H8E6^j{e!2a<%pcr*lr_u|`cMtsiBcH+V) zuz^Q+yxQYJIm4jY&0ZqnO^MmQ?&QI6zf!e51@(s_p$3Ddz(^t8H~&}y$mXw3VJ8U4 zfSYs<<~kR(YM0ZIY3kM=KSwE>tlrgA#2yxZ*& zL?c!6Y!U~)Q_6TQLZ_1zoeXK)w7=Yp$#l$(Y}i!7S{%nlL?wy_sI(g_z0GhvTw=Lv z)c_z*JQMbzE)*3gs(`+dqg!ucd5Qj_p=Y_Si&KE+{s-*ngEv zNe*aQSH#g*jrR+Mji((&i|OUZfco?OuUvJi1JKSfK@FG>!yn%fg#*&ZuFN=HOfDNa zX)bY3Z||&z<}g0E#O8RVcqq*r=e!q{ydXdCB1^f=ye3VuroiI$WQ^TriTdiTa5EVL zYHd?qH%`acycb|`)!M9b=r4E^Ma939(cQIQ@UbEhc$cobTNmFwqhGKtmCUY5#}#`` zKVI^Mf4xK9#gS#?lYdgUQk*|}-4}7WH(M|wqvLNTZEBYpG-^+cxGy)-jW32SCiO^S zNmL%WpYBBLdw(c20gazhQUorRIq+pHj@!j{lhfpNrwXh>hT!haqP3Wp(TdJt+Fp|s zEY3Yeu8h6M7rPVnNG zb#o@Omf`C6)uklZ_`tUvF)c@_Rp^5_ypp@gy80Kx@IXOl?OE(nYoMrX9IV55I|XJB z=ef7y;nVkC)QUc~wCf5qadz%C-YWHBBCO`K%J+{o-4q-7j}*AnGdzB3=2BZPy#V*P zYYrPKQAJE4ih5P1(09sB|D@b#W##sd%e=eZ-p(MSLD_x!S|v}79h_POTB%B9b*4j> zG^d4%9@ry7W}Vd8{d`TTGqQdASmUC8wZS^;ktUU#z{UH7^9in9A(NCf1`s-k{^Q8$ zHfCOi38^*MHqn}RMB0~#VCu=nPX+x3)VuUn(=MZmE@!pUiQ3);>Lt-BN82jMN)LEs z5Yk%MATfVk>iOWk!-8mmoOs=A1Ekn_BwJ}5R)My6zAW9rY@y(fbhk5|ZDz^RK4Cb} zz9JbWFGH`{ z_N!f8=@@OMS3>ldZxh^jv6fK&Iz}N%fEQRu7X!GS9q%}W zyuil3d3b2A%^|<=O7SgGxDd*}#*aH^@JLCq1nw85lMD_cT1N&x%qj`BDv6A;BXD!x zk#EodHs6i`bH3{7g5P5Y8qg|p9W{HU7 zCH^)h@YkH15pDo7s1ti}WcoZ-*{iEra~SWiX;3^DfdqbTD@N$BW9FqDh+tN)34aw zNkrpIm`6Q|6jJ*a(dJus^1UG@TNJoCX1xI0txn)5;<6aS>xVf9h=^ zHDPE!reW4$o~;@QTUYBO$0uY1gNx(&Xx<4lkL$ALJ0PszA31yS#kpO5V9rP{W|tt)FzoCe)jfGDO2_>X#V0EPQ*W6&Z!J97-@us0JI_( za|g=4oA$ao>r&in@#$nGb$5UKYkEOXeG;hQ#Du;}fhBup%`xgVB(v3=CVuDR`t79F zcm&PYC{?Ru?@MvB;O<@O(o}C@b9-|)ZK0`CB*cApbEc=$rpeA2$2xMH-RVeEO_+6X zC8`0&Tcsz99kQbp8)uLDdDSiQOh{0um7a*Ye7(WvS@dNY+WEGf%yrgxcQe1=ck?Wv zHz~8wWKXW$2wj5WuRxCk+{Z^fIzaye6jIUC1Y!#TpH!gbJzT07!{{BTop*ek9@h0C zbRZ?HJ>VY7zvgVzju+moUSHqdm~?=SYxSHvgLv4j(RQ)PzI`_(WyjjR%dVY>c6;QE zokRec-JQf;D_mX zWD106WSa8vPo|JBxvuq?os`?!AN;trKVS6U42={GiraJ?%~OvGVyt0$6XyAOeX%RX zW<$B?P}|7;bW>rf?z+rXuXm_AS!`ZS)IAU7 zKYeZPc_fSGglr!kOyAQmuHXIcyU9F~#r{;ed*$toh$+}dvYLS*|NEC2(~DP-^pcor zvv);K5`60VXZbl$gwZ}hd6-(k67_I{p7rjK@I3K;U9A}7kuODTk)ttK-Tw0y%7<`7 z4s3)B@J)tqqO@ic} z*Ik-kLF|@b4s6Z`;W@T#Wb>D$LrLY;-;Iclf(Uc<&*-(-9EQp)oYKue@7gp2K*^wl zk+H2~GGfV_4f6^~WM{$Q&ZR{jG| zq?U8tjfk~7cEhTmqNg^oH#}i${#vwuK_%A^p}Jy`oq0YlV1sB6j>wO)#bh!~IdJv? zW-MtUeJ*rDTcCK>iu%>71O?VOI%c8}=IUhaQoTEGm*4PPr`GxZVec)Ys*Jw1ZvzDc zQ9z{|36YS7O-MJ0bT>$Mvq3EELzs}mhz)fx&;tXbLB%(0y4qNv`y7#$-KESl(b4i< z!d*XKobAU#qNb~fsl$ui6Ke^X^GKXAnvRYJyja85SK>vx=)?NhZwlX1OV&+!`sw8! zozXi)Au7Zjk%lXLNXxjPO4;lLb z^hzHQ5ajq$R3BXJy!Rl7L_uCZNT&3Y0@rE?{s+#H;DuBYQF=}H;WXZT8Zi21^26Kf ztuTz}2YVi)Z>!J9VoW{i2Eh9w*u}NH`%Q!LS1;Z@x%4KZ03V>?#vbgr`m>jbqFf$4 z7*c%^MtlH$Dh^-nL7wn$Uzdf`Dx^DU?+;0sBcI`afO+nQ^bDnXNp5O1UTY(Zes&OT zJL;ud7D7EQI3jk=t8cWH+Y|m0vQ4M0l~4F9%!c}ew}vPepTml@`Fegg@eL&F=tXEq z9rcl(GGyiX5O39SwaDDp-M7nru4t^*osP}bSykrHK03VN$d8hLO8l(Pf3@LA0r0!# zVuX6c3{l@v*rvpq%=`VJy^YBWJRW!D6N*1M&E05Qmf`e+8jUa&WL$x zfVt3jzS&2qlv$<)c&(o0V5SzATiB`4LY3r<8111S_cnVK#;N-DoKJ(kARp?qoQiM( z(phuRFMFV3lRz{)NKLqE250muv+N!-tp+zYjIAsqD=~eY$Kb@l4k;` z+v6ND`TKfn-Hp$IYhm}>){A5=bE{nIh;7MuCa`wk&V24ophw{hhKp#JJ4pY6v;a^9 zc~`u*lN}iSEcwwknh&MFVdJjN`VQIf907J^qN|si81Mtz(|oeeSzSi^ltUi~X_MK_ zi^D(Q2^?rIoOyoY9p_Z&a-$N=pLWi=g?3ZEq)=Ka2hCuEs?26J_hE}lGyYq-ovTHZ ze@7H*vq7#OYi?VG9SvO^EvWS^Xvpp&c=UcauUC|; zoAzj|Z?E7Hxia|4hTb)}^;5?iVPWV!C7;)&+fcr;9h5p6rg$6&y0ID^>Hj+Ay8ac` zK!DK`j!D9Qds;b=&LQ>E|8UD7+Nf)Q3;338AbPzK2QAlaM{l}a8ATow2^6cF#9(eS zJ?AqHzFP4=!yJ-u%IiB;QQlG;V#1!JHWPmED5RA7p5r*v?F?=0DciFVB#*lJ(dO{z zH=7?Ca4LfG#VFUnzTwgF40QXE2_>0!8I6YDZ;laK!dx0BkNgqbGaGHEtiR* zV6|bABCi&{hD3)w@n_*ZKPFOB$&HV8h51;su@oMa zn?>L}9Zb-LDhxQ2E#jFJT0V-Cg z2HcQM>da}=Ik--i$oeQn31j#zr(?nr=h*K?;>up|-LLqeTGj-f52ha9=-%eU8`L^w@W<5m=m* zJy#StZp_G-u)9qYpoTv1K%&;Z5=w=vm%v6Ss|-Itf-S#N5+Cd`_POOLw-hdO|8b`> z^^LeBy4qpd4Z(w1p31Mubm={72u{RAapb(M>QldGeosom{V2t* zj5!3gcSjt!T?nip5tmkegr^{Z1L0Jr)VQJxn0JvUMv<_6?rYAh_tu^sK1zQ-8mSYjMk!rFA#ZT7Dm|dkPzmnV>znE&Jt#*t zU@4C9J@F(X)_4xX=ctx;&gB>qk1&s4utK|OX}(gz-m~^!RREnm*S|_xaIEh4hqpQB zC9cPV13aA{4ExKF8eL7a+#-+tzP%rAd2D(QyH>fszfQk3b-!Oshfk+@jXCYlCBrXk zlTW?aj0lB@Nk^(?2TgGlOB0o|ly6z96*YxJZ9+J2#JF=txQ@ot+`0l4`uDgt%d?De z?S4lL6Wvc~9B>{*+yc8!K$nxO!LlhyV~bqYPWYP8fk3gvYvkt~@?c`g{FY4eZfNzQ zZ`Ni)UJ!EP%0I0tPZH%NzehXKwmS}Yv(XeL#F)S$k-cfc!7&c%M$O6Ja_@_Id>)_l zb3)=8Fa>89gp-L4rSe{J*&3VljL6G+?6RkhO+-CYXZTI#)fK`e+f*N>r9weH_vSpJ zH+XOB!wa!0ycu}it`+rQv6efh(O1nJ6fRrw&DZRfSCbOHH|UfR3Mja|YjQc!A340k z9%=pBqCeW#e%ZTD)E_s zu~#q+vMjZw?5O2!8rsDW6SrlztaG;I(w&#=Z28Fz8s61yfcy)Q&LdJTps$Ep#i6gQ z&(q^LM62O_vMm;d9}f(FytsOgz+Nh)cS8pTt*vCTDYFtA*K<9GP|urQ?#($yMs@s1 zptot@Rzb=j~PcSc&;qyF{g~-uK%Fs7IFJSGcklxit`fAkT5Ydb23gWO*Vn z#qhFN8#DHh^OG!{Y~m;OEl*(GR5(qeSWSQeEu*+`eNfb@Ppq-rO3Q$QsFa<`*j=%M$Sr6np3&X6bF+ls9f%qTsZFMq<(Sf2z zO$ey_rfjO0;zwv>6vFMvc%VO$6EQtb~$0O3M1D&5zH4x>TgD62t2|V*5zlXF zXyAE_-W}qaA{Y1(=%Z^Jr+S&AV0Jf0-GZ2j!*@eRs~EBn>sVC?riKc^O>0lUPv}+T z0)I2SBb;Ji<#fD@;CK1t%rM<4I9WHI$P%+yhb{5WNpsjUY`MP5%S#keWw+t%k`X?K z0TZe+wc)2jXq!>O+>d74;$vmf?F~B$p1v@+Az^`I4*Rs#Jy}Icakf}*J@CuQop&%4 zEZIXh(s@8~u`#!>4_g%$P-EL%7@~10Pvp!(`uKyD(GKO(WQmXZd5XtxR8cY?3(!YQ zwrRg8D*|R2ZW^JDCt+1`!wHs|r&G#2DlK=$!YN#3rH}D|l0?Cz=lI#D8(rydf(`D@ z-^(ZIiosULG261Yh!HE%ItY_v?=QmyMq1=;EWtxn{CNZ;bU7?WwdA*I~3nYq4%RFc$uC+=&Z zU$UFE)*$Hx(DK7!L#B#k_ovgJrFew1A5$oNU%J1bAjd$4Tfh3Q`xL8(7BO*so5^2) z0u1wMon@xtfI5LvXGei;{BI)?WO!PTAzC**S?f2tUFJ6m{g#pmz2e2mFi5Jn22<#j zJ!(;zZzw9DsQo)ssU@u+;3b;S`>7DWk6H7^{<%jMo|+ZG$BL!t4SY`x;Pu~Q@(X*d zPy#3wE%oneI-`i&6dJ)Wz%jL=bnc-erQ661E)Z<&bpu6ar%P1eRDm{)UX>b+(;k~4Y~zPaxHbLQ_~iPK8cR#xWk2K zoMB-MP(Cybq+z+OK0(b^x%DxFqQTa9Q zUIis|$;z-GHaw*v>&2V4nzwD`OLS!~MuVRX`~8>op`M5GMcUrR6K`Y=(eF>5*BqOI z{PIm1h!UABuAel$ydkdn1e30}=*Goe9dLD@SWwaN+SL>-F5Jzw1<`W_dN_p$A{n(| zz_&zk&u<=yVgM`WyBI^tST|R`VbjmBaLxAd9nU-!;$-rB9imC|(^C?w#1F4Kipod~O%xaqVVvq#u015L|3QHy06WQPO&DUcJqikO&UCbg^AeTYANL8OH*O($Xwb<^|GTvZK<< zT$=X8Ux5*ITR>)ljHQhVJ><;WRdK+`|549Z|x4@*=S1F zYAw~K(utrqHnSN{Fx>H_7qv9_Zp+UOhpk&B`>M|k={;@P*R|lNljUJ2gSh#Rrojg! zM=h}7(uAWHV*A{yoTF~k*BIz#2ZDGj7be_v<<(xL0o~TE^VIulYy%JaPd)C2WZ@5l z=KZN=;A%F;fOSHg2&hw6Dm~XHV_Sx$uFcAFgydSipat)?SU${}lxn?!fEyY0=M-32 z-m+XhgWYJi)v*1#QfBsT-1DU0BHvi}W)6JW`@6Gl8i1*|E^LqHpap|4WZ?QGcN$UD zXru*~_O+A7MKO<$$4298qtm3<=%$B59F8_}7ZFAK4=)3e#)pnLrQ5uzW_9=V4$IEY zfX_O_1F{rQT=>f_p@InhY0=Pu3aY%C_M8v`;#ADEo}SYCfclLHRv|VX+OcKb?fAjH zz;^MGTs38ZeaLlpsaF&@z^TxdzYsCkdiNEh#bp{>dYo&llJPGUHS zd8^w!BE#cIwRJmNnHKXbFK+r;;4XnJs7()0jAi41Y>U&B3;4QNWi5hS1elSBr8=Ey zlUW1d&TX*g}Cs51Vk%X1c4Gy%!4xF=%2hDEa zEkF-^RcTzIqMxIfU)@mKr+h}D!M0c5bn#n|di&>eyg1M(rx>uk(<&ooZ(lH@Kct$@ zn}$kcIKki@w+bI`PoAj;t8>+E=L5ckD63lM(QCMRyFwn%JEbAMak@sn>B}k5dbHfs z_AMZM$54cEwsRDNG6D7blzVI6eKHlp{5yxmgl2k|`W7%e+@S>KMnpbm#h8cC4(pL` zz?`8clzwif12HVTJzucQtb6NiK^;-S7Alladsgt0bOQ?$&_VGL_E#W)unqAy1hP%Z zG^;op5NE(*Z>KU0%KkDclq&r9ERU=Z=)~U<`3tJ#f6_(_el99Hv6B7MJ_*kiOY#DmpL~H0EzY2XJDL3l>T~Y8t(TWNu7`F zu*Gw%On|o;;&$dfR;hBuagQ(*UON@8z&{moz8qUIWKM`2pIDewckvCbnq?MZv-81y>p02=BCV4j1^L_0v) z*a5R~%9J$y{IOW-smHc$yJ;y)d_Lq)0xsJ3M!l-CWUNZ3uCZ|TBnBLd|7^E=Cfg}$ z<7*QN{l6R|NryX`(wepX=Bmx(Ev_7cEf%hlZ%)Ub%73N#^ z>_DGCwPz|P;(mvF`yd;I?4C$E{ex5-qt1_TX?|bzUXhZ9hDbht=YelxqV7hMn-i2s zV`nvKZcF>Shl9Ez|FIo_pK?<;;6lCvlZikSz=0aQF_^?D5j`47NX7>exblmb^r+SM z8f>HkUyGGm&wW1ENd+Q%%-}g;%4ssSg^r#;=U_hK(=$RKFR4~_$h8Ekk#$-6+G1zf zaeAk;gsu#DLu+qAvbl^*Q`VhRlk?|kx9>luuV=JTq|D8@#n>~45!DuVd1MK60*OXu z3GTc;wc~)DO$Oznd~B0=-lR0sO6e-df~Estw8?zBmLOyTGFyB6xo~5BsJyv@PZ%(- zRtEj`n;9vgZD7{#@?8r~yqZrmdn^_r#aJ)SB{vxn%-Hhj*_-#ckzJlEGZ+dkNBOhq z4s%9Q+A#)UT-@a8;4+8V!c1e#vAplkiD(>4Bst!{J5a7Kk&ptn7zG>8={`V??JvnM z9B$)!5~OiX3>FC`53qqVbtS3xd23-*TE8N%#SW6^To#76+q1~n4eyPtWc>++S{?Nd zO9f(e2PS=26b*9|PY*t0u1TyL|5+fBqvcEF&uqeQ8Z~Ik$7j#|z1@xftqYa@hj&izoPHBPJBxbG! z-3`gi7b}PAg-$}n`Sq_|D4ApfW;o92;CXypLK9V$GqGaSA(3c|oH_?5FHqNz{#rlj z{+Mq-hCp%rg?dLJ@%axtho*Btmn24b!jA832v*1qD8g?}tN&KTpMp2jyhgVl)R_BO zmjW6HmE(>k?UtqqN<1(#vvHjp`|X%eu}51&2!n=^*K{bVE=}+6CK>=$vD3WT#qno6 zVDz2(K1q)V)uK^$oGLU&XNj0Q-Ic)=oW6tf@Q%_9aVdP25|zm`Hjh77MD7IEB#DGF zJC9{zzfARZnyK}IXlk8v--hnje3t3KTr-tf z4gOx)Zxzu}&v?}#QZqF}JZ4s{gX8F3M`8?~kxI|G!%9}j(VNuH({k6GZmw$dGS+5* z#GM+_p_mtDnWNBsYVM}h@2S#|NSQ_9s@2bjQ`!;J=rt1O2WI&)Ry<5q=w4TfeLADb zp`4zdF1zKND(q-=?F^%a?lv_djw5AKi7`JK%)G6B+i%mDlImwYHAA+*(mpJ&PSdNQAdWLEq5@%|oNXvyH=m+z4epG_c4;DDbZcyFE0zRR#c zvmi6g67{L@w`rC4Z>rf#SdwMmza1$|^Zf2%aOg1HzWTNUegXE}N2k?*Q_7FO2}%l6 zpblSuV&Oj9NR&(Z;Co!+@PLx6DjILB4emUEQKSO$%Cm(oi9_H&5kVOf@Lf#_QO+KH zF>_9!6Zux~LJMPNuYGs(?S>uKT7=N4se`C9q_Q+Gp8Zwo_@uOknX4%EUFdYYsEZ}C ze29!jV?XBJ47gUc1%$KI}IgWA#y zdvL2xZ;&CU_Z@3M@i)fbcR9DoeA@H<@IVsX1>fnjgw&@jvonuro5qebZGf4NPh}8C z&gFvMcQOcG$}Nm`-~5tG+V2Rw*AfSYO(*JuI2%kx%1;cI(wf_d*(@(QleSywhY6_> z4{CfQQI|43gzWKC3`ZE2b&2|$4<{rgAFOT+5JB0~^$;*xrMxEeLKM88q2bM(v`00uCZUucmzO1}yL& zU!6yahVFpWERs{~nOnma$cRo|u|B?!23#|pi1m$lq$CNKDI9Gwsj-}C8XM+>5 zNpQKx@HqDvUR+hl@~j|jx<6lHPDmZcC{Gc9omZtYPTj4B^HEOzRC?W*2DeDpzO1#l zl)=}EFY%{bWm-?;9S76T3}(C_bvavln?+GyYD9vV#ayW_6^rJkcPLgg_(zf)Or73; z+h&Rl8M3?&TP+A)zzOgu_oNtgV7pdZW_Wzs+)YA|cgE_h8DRibe(X=-tOG+>A_?7L zALis+q!Y)|$bl0xq+2PS3t8x?y8da)Fcl;&4m?nwbbBQKg?wU*6S@rz6z6fwW-Eqc z44#GXm}#lxeYdhUz4kKzNzW>D@pGJSOEaR0Wz2bdqe#Adlxy4ss|Y^hyFD>K+EL8S&&Qcc1=1 z=|VO3OM1SY=8n8;Z^Pqz)XzAOz$Lcq;J3WaWOS_eOj_DGNG)#4^CEB=-zi|-(qe2* zszxsm(s-RK*KGFNz|yy6X7BpE_?DL%S(>zqW}ZcVx}O4NsZH4K`|k;D2do_y)(_8OPFg4k}syuE7xaIdSyIpMRxc z?Z47+v;cUA!TZG5T{z9P`*V7qhn&J6W6Whs*?-&O#0_^X0?JI#*iZ)#7#bZlAP4Ui zWGjE26Si1S6<-T#YaF?C4m9A-ct0dYUjZc2*BD}qw7FT7z#|7c7!qzNZSJ#7Kd~<> zM|N3<Xv9V))F%Qm0{F#ZOtPO`#$rH7#oN23}%UEw`FJ#nfpLMTmCwD27aYuKa~e zME!7ceze>3q)N~ppqzfTf)q#dfSl8KSoh^qO?)au6ic<~cX9xO%H<>|1kOtIy_|dN z(_%1Vv*a`_ra$dtiZnOqxjH#;qOKBY32KIU`E`cT{cn#}Mf=|3sDvlXLT6Ah!*xM@ zdQ)(xy)lz>@$j>I_qF>w>a7r=!^+{SO=EPxZla2)+eMg#!ira$nsiHI-n)8;8h&jC zYEGN9=HZ@B2|4b!?L|>IG}JlAW~c%&mq4p!n5<5lCD1|OfX_(a{@&!}HE(DlH=|)%t3g|?Yf%{<6= zj8d&hBDKo|&X+afd=W7N2#*(R^6i5|tr+&HevE^$pL1@~t6@T{*>!{O9?_2H!T0zh z-W&kz5+do93ZX&tSCMN#L237U19EDo9<01~ z_ThNuM_cvasjHEyWMkevX|oO>xKx1wWuy1eo^x|^-cUF6F=?^e z_V&eaaRYjjmufB#9JTs;5yRtSx;!?}yPZ1#U@*SFH3jW0j1vh-S`@ykv`&xCb4-@q za9A#8R_3}y=4Tq?SOQ!zoZB%%Y1Z5j6t<3pXp+4fKq_{l+FRJvrd|N5X^OF#^9exa z5baF#)o6s<9A9g7WS`B+f{#t9?}K8kUEYpvwhp$a080zxma4Qd>$(RIK8MbqNoEcg zgg>NC)w#}}9Zq4rpqFzwMcs4()Bq1779XUF;IE@XcZ%Go4%k~XBT6BQSfxYJvD*c5 zM$=kRl_fxWznM2*?s6%9B9D9)5HdE8+MD7DQ>8<Uur882oP=C}8(+1Rpbuv1~@)f7D@ zo2znDToB%B!jR}bz83`2RS%NC>HT=x&m}Q<^1v44+;vWr0-Qnyh!$g>4Ijvi9a1Gm zoSJa3VAyh$bM%N}hd8w`WF>zV+4j7O?-F3;ywoWK9 zX9t7;oii1vZMQtI0;|(ak4{4q%x5q6_~@|1EpdmnuZd31I3jP=H`F<;7a#W3_oX=1 zY!E#IK~yfbvgA^4Sd0gbB(cs?@CP>6{1-9lKQb~K`3+&qT>uJ0N)r)i0h4XFXm*&( z^wy!g%#rdHjX31x7#=U%lyf0%mL0PYJN3-D2>DeC1JbMwug+Un3M0e$A;qyI1AJ8?|liFAeoH zTq;~9q?=jFfeD3(1RotC47qOu9gr#j;LgTC>h}5mEy!|jE_}?G@1#iiRkPU-V>df( z^1i|a34Q*2%k^=mk*_{$dAJty7ljlY3m+X?BSVRBLk5BuIi*(KZa4|z0rDR`vS}zb zD)CJq67Ym6uOYO6(l5B}A^N8A4;lFta5}H?BA3Mtj}6SdUVWuV>6@VW#af+PWr8=6 zG%I@-nbqZ*d&KPu=v%TaFZeEc=mM?8a6Led+i6aWCkBUYk#QCwUS4xe zu4rR6Bmy<4W5;`*Mk29sgpp@7pn4%xzB%U zteg)FL{mmQ|Nn{#-w7xQ7$m^&u(;0(l1veER=fp%Jn*{!OpJ#7QLS>n@;MAHk=iqN zhMT)?5>qB720-)Ff(3xLCUV0@+VI*D5mCZ0?au?ZZYJTL+M`z~>Ab&E+t{T6szuxXmRKvYT zo@dAOonDw_0!XGR6y3xqn|avzv%iQE(cUoF!Y4ykMWs90@scBSnmfM8HNr-pqWnJB z#qC;Uij_u)bWf|DMOb6F%PcL-x@hwj3zuAnQx!>|7B?_IaTMtD{a^fdGni!5!1*A@ zegVh_f{0(>RS2fwJXi`da_ZrgOh{Tr+?kWU4*C7nF9?@xe})*)XVj9`YzvY zP5M9Zr?yYsO{x;_DA#Gdeu%MHCO6wgtb4!cPBJ4u#P{?TdTZSakRcfM12G5unCccd z@yQkdSur6$z_N+^v#@cxFQ6mz?3^#`yfNQdxm%P2JwrfoSN0iHl&&$g`&RnYO_>y2bmz47BcJhZwf+fL z%}|5Ir8(S)Wv}wZ2W+e~lt{!-f}uBF$^P5=!+JRD3Sh&H1uo#lFQ?0e2->*& z_L+c$i_iA+y~8;=v{chPThFtd^HcR2rzAZgWXaS*v)Q~yd)M@@^%ymf1+*1@T0?8J zk``QoSyESkkVKCkPRfDiIpDfmYa3lX`w*9p2XaeDah$@Fz40gUeBXS9ZgWfltY$bk zQ?izTG$QYuB1XA9xl@@8s%2lJNkDM6eS#5{5=$2u;ijdwWb0-MGh-?utrAT&*VD)k zpEEmcF?-X2xI|240-y7(TbJufPXQ_UjHMOg{UA> zZ@NEaH4e${k#~&DD4w9v5kqQ(@&B|y zF3^)&0qE=ebVQl26h}-KEpIQ!q!`DRUT&x)DmZ9BHht9kP}k4YKi?vvUBLAASxYx8 zXEu`fiapL{sop+s-eL85qJv(x-XS#*NJy8d_+Tu7?jiS^py<;N!9?LJ;7vr`d%LMp ztoc47FamfLuetXPAaCa*tZq8O`(a$eyYE%uw<||4j4NbXogNT8YUffKilU9C-U8p0 z$NRT^_#M%OVa86rJyD;`=l50w_ztCXDE?@Rv(wH8tFFFIY~y)%Ec{dr)FsqJPv zo;%pkQx-Zud4kdW3R6~BB3?eLI}kr&LyHaiMqgSc8m7w=t*tRP^VSiDPc=o|A6} z(n3)hSpNn}f=P|m1}OjlH%YNgl1^tI4U`40CZu2W1}*&h z^pS)z)K!d$f9@wqRjK3I+v)txZ{2ATi7e@pN>3|IjHP=|8_Qhl&VA?1<}YEZ8Mi<8 zP4vlc_uS$8u^T@R@SR>Gy^nSQ@{L9(8}wrrS8uKe(}+%VQr?P@IL7cf-3QjbkmoY& zMUdsXNxa@oYrBUcrv6ruJX8<;|BhF=dg@oH4uM+Otm8Y^3#0tGOQrQXgYef)JWC$- z)ilEnM9)poX%wl175IMORwF?~q%X&JM%3$i}PB(-?*A># zKDih_X)ga;Qb6w6XtHTaF^m}X#9YN?TxB+r3|8M6=?y+}2&D+!V=^km4sNoc`l)te zhX}IDQ}jB5W}oK&oBHBQJocle;(u%QQ#$ocpFPfct8#&zh!z8zeuw;G$q-onKB=(UfMDuOl;|+>hp~X*XQKah^fJy!F%+KYgoyXQ8D#ZZy9F#w z>yxib%{RHIz2|H}(quzL6rs1f_#BEDU#WZWB)K?s7S5^aQV*A0P+0E$r2OfvT ztLV5d)O*=7>hd~XKVA;ySd8Pl-Dmlo-Ss+NvRGZ^OE=vFc9%j{N`mmwVkLk#GRz>X zb==F?u}jJyt@UA^d5>`FAIh)e);?YBb@(_?C|` z{AHJ|czs9{jmCrhYirT6QIPvfjak2`egf;3J@g{M236TgfL3Q~VI@v77)gVd{HY3| z7H@rnjT||3PZ{id{=|irtAE)|8$$uEYr+{o&|Q`*LjVfvc6pI0CrKZf8yw1)I8|&FgRPX_ z1)yhwlSDpG6p7|a&e5VxGd~=f-&6ELC#-v!k<6CwRjuh^>!{VDRJi!2I_SGZNp1O} z8fM^R+d2OY4ZVhA0B2~6FgiJ-v!oh$FP3g8V8j)6mlF_jPt*xan%B>{ak6!K4jL!v zhlll^ZAXpr&QGJd5&miBIr@mYY9*Dq0O9|K@wd>6Gz3J`grr)90I7P?Wu0yF_b5yB zo^>s<`20*$;AsOLSoc}qG2jn7?)fIspz63g6$i|p6UdF{y2kzMfW?~in~QB>AuiX2 zsUh>dI6wsrkV4++%*zI<*!|8fcqGEC-r9Y2;V)`dsu0Z(cYHZmyRw9%#nPTE*QEWNX*eaL9oS?q5DxsS6?7x@)4^2N~3;Rp1g1Z*}@ zohSNYRMpyLY2E{v%asNMA~I3`T-^gdHs6pu?;<__hvmcEP6N38#Q5i5I=RmMUz6{R z;$Q}9A!}ELk_AE&cKWDnLJHMZ?aq!^#l+t3FimC%XzhLb5;D2JyNpW`n_xR&ZdfVt zBCmNj$#CGCV~*V+J{P&rj}O~`>YMWM52wO02f?YZ_XnbnczePK;8;CDzTDe9xnBm~ zgsAyW<&ZoKWW06)1MqYz8WHY|i^bh>=a1ix=I8n0Z&+aZZ}i+h2HZXm2)mfpRwMO8 z!>OsX<$ng$HuB4qct+tpH6qQ8S8SWf@8fuXtp#r|`LXtT=p>uFSY~m}klvPPHRc#> zf>Q9Zn+=zpxxjO)c0oHdC(qz4Lv+NOOd9fkVTK_~PRvf;s%OV^$U_~*%*!nycr#f! zBJ%+&zS;0twoIxH(mcR(>O6M34bEe2T;blFX^zg9p;1QkA2Sac=aW7}f7f!FM+@g; zR{u`pj?Z1UYMbDbBD`za7qJCm(sqxpC$528<8*tn_>*Eh3~Nt#*g3!&<;i}cQ>wP& z%OiI&G%yflB2J2qIGh<<^s4~?iXD z#)-^f;-b0Dyyx@phB9`6H8=f$hz%Vz%bn+UeuZ`#KmoEHvqz^Y_#F_J7|1+>&EpW7a9raX-|u@mOGNLMviYY$fyzLR ztRxyxU~gJ9v@$7^fNzlM=O00b)54!tlLIdm8UvcOjxDlF5WKvbDHpOb8y%`wfmT_O zInOW7zT(}Px(jP#$rlan&&)j!3Q-wG$f%xind$d{*dr=^_h6H=2-hg((*k(RX?As6 z$N{91s8(#@I#2yj=x`tf1g;{l#mGJ?2l43Har%M3fYNj%}p8$o(Cc3@2n zui!`zD-^&MsZ_F7k5c3TBM6jQ4C`cOsy~_Q1~R3buk@&> zIOv)z%A^VJ#O$Tp&JLs6t4eYGRI0Xq*a;>w+tqvq#Jtj6lc&s;*sjefx*nPNIK(IUazJxW$s+vg*9X$kZW`0FpOpry4EeBKs{e-zLe+4A@Fj#1Wl{FU@%E+;a&<{7%1Nhf4B#4*GqKD7tU-B--#E{>XE2+LJD9hd zYmC3sa?YM9i7H7C?-D=vamS)?Ox9eY$?O=AA|BG~ef%E$mC0#Xh$3;-l8#32@(7;F}*a`>#$I!A5&de2OqVKW6!XTlw?AT}67QmS|z7%p=BIZt~N@SOHI zw@9|~zGNHMzf&#C01T?uDwlaKTb5h=ThKiJiO;vMjq%hW72NHbAUL{$Z*0e#tNf<` z9g#CQacv}Y#2820riE+0QASwo__eV}=MGK~e8DU*aGS}m3dlsl*?!M*RGR2T@Db|Y z2);}m8A{F{vg{Y%(0C&CCW~aU^qwIJ(2v!=R?LPahRfj6;b>+kzYf9#%)b|bLCQ`L zp1{*uAre3BASV5p+s_(Y$_>8FgxqPRXgY3F=W1A0FEDRwFL+l#;n6I0fhRNnoQ?Bq zt}uxQ#Ancn&)O~#ZC|wDG11im9W1sf)GNh}m(%oamo)&VZ`){Vp5?ximRTd(cXFy2 zY6uwn8wkaII;Km-zr*Vb*uc@zq)BKe(QEI>s>Y7xv$<_U`9`l%+ZV>~B#D>vDm^0( zexeYdrDj09zjR+}FIuOQts9%~(^ZmR)Y%5l5y`> z8bwPqC_}_{z2-8+R`kqN+^gzA#Y;zsc=XlWTS>ygSO$p0g_ea91Wnq{Gn@G$_MO(4 zvodQfdWhh!)2uIrzjqe-0bC+Lb@i`{_OlCF+M8bTDC}4JIdOF5ys@tuI&HDL)h;$9P#zzYR7V@Xj)hT4ML^sWM~>KTyPgl*+ts~KTS*6?P% zo6yZF64?ngu?<8u6TCdYejfxn~W_-OY{*sl!OZ?6hp z(WxskCi`zfR9es9U0E)F@yoH6isjL!2YYB{w2ejhd*W&$-xAt{wB8pz8?k5V7$Fl0 z`f^*A{my(OA|&k98ot1_pHELvEEUHVarw^6??b6tOYh2e;s{nNDGXG zEI$XcNn&N(KbMas=rcDe64hZFG6`*W@)A-d_NAYIuNaD`8u>sXn+#~?B4^zd3nlnL z(|CCrmmtuRozmQv87g4>!I=Tvwe{S87%y_fuf5imm4a|G51FFHQ6kK%<#->Spc=Ay zt5v2)`;$mG6G}R8g%>dxyu7rjaN9^U$w^Fl4cp2JJ07Ue>tGy%b+L0}NIiY7LNSkr zAdr#PA|QlNjfnN(0;J=huo#8Q3Qfugl!tRoSU)$Y$wGf6o)~7>IVNi&U+bN71umKba40vux z@EUpC<+jgl8ve26=zjdiJ2ONCJ==WTxq^XDFlCbXy$pgZr_ZAQ3=7brRn_yOtk!kZZ%iYx7h)J>|1!ulowU zzy3PK5&?$%MMNDD4~Fyr82+;+SSCdb=nvWFG4Rjzd55->uS-61l^5%aecmP*{WbW3 zr8Wa8&j8jxk^k+W*bmB={N8NlQ#Z^zi}zcNO8hr71kX$Jxu0jf52t z|1};%VKqp~Xf2=(!IO9SwVrSatWgi2U+{_mFgMy0%vuQi_{H7boas9=K~V(J?;`_Z z;vUcXDmZZ!bxnzgw%ga_p#*IP{(XE9-khqZox4(Yjx*Ny`?L`#X2 z$P_T9RmES=@+5t)9CIvYqoW#8?4v)TKjOc;hz2swq?Z6!WKQ7cmEWcmaN^c`DDH76 zsIw$Uum1}6x&JtFAB}8 zN{op>A(GtBH>jt48-8%FqFki;Rw}NAe97Y^HDR_=wop_4UBNv92{hZdBhlvb#Lj|9 zl?g#83qUx_TmnDvqPk%B^m9i!hq?koTt47;weuuckHyOU6YSTnH&6}d5nEnvW94!= z{Q8O^c820eh91*jR*=Mz%Xph zPl)(0{+=K36LMa%Gm88N(-%RF`23;=`y~GhoR}T)_e#tulXs>4FD_fr+dphU^^yN& z3;r+S66t>tmjIOQCHw!wh)Yf4=vshKs0P4#O^TnrW}xgQwhux0wd+r#g0q3EoM-&V za0-*tg-K>n<8>W>%qW!=}O_mU=j29e~|4D5@&BJzbgSdjet^8 z&htXA`R1q_gZgeOD?F;3DkK&tfDwtF zm&1&v;*_6Vpv@2kfE_Uf z`%}e`USOrpgnxqf7a+An^$uF=I;dy1ImDkMyU>+HXMCG zxe)13#4Rndy!;TT>Dd1OPDLmG6)FFX;04N`|Nq?IOOhi8D)9=C^1U$C}Y)XZ@wa2T_!bo^nd-d{90u?JI>5uHr(<}Y7NjkM@xx@J)kZC zHJmxc1yrtUSl*aQcK&ft{P`1KE? zE=RqqpP8C1ad*;q_2ES9%o#H9RHV{Q3#5t8%7d?)XZXf3qE{@b`fBB8^4BLqQe+4?5EA}9U+<@GMFWB57IM4Z_<1-%So?rR#RCnFWr z<1XJ4YId6#6 zsIMs`d54zvF&vH?AHFnG6ujUUvX!0UAv?VKU~O=#IS>?PBo$_5i5T=-9FdxQOnamF zek(m_tb{QTrP-$rulu1wUkKft9ds1W0Xr+fVlKWNk?@tdi~pknczrwF4YF|aRM*PH z?X4Cnxu6Paa-C%5@tjw@|-6IM$NXdE~n| zSS^x}oRYF+y`b;z?*7$dX$BAMK%qct6#e^NZcrkzVb zP6z3Q27UBo?a3~M_@?hdzu6P*mSOf(-vJcyMw)}78y6Gmc57uD--o-V zCEbUhR^X0gNCijFG3#~@JK=_)w%hJw1El!^5kWe-Osy;zWAJ z3(f!W@An&@v_PpaoiA%t%FLgS4bzs>>|d^NeBY|s_~(tK z8VenMBZ`+v&!9`KLyyqKHflA(5sfV_?G74G|9oWGoSy&rXmYJS%rQ4Gw7w;Y)>$?O zTM3*;V3FZYdCK{5loIf`?2|)7w0A2ODdW6wuXk2bx*?-NJs`E=eK1VZWP`o{ z;c&q8i#S7_VBO(QBQWUA!Jr;DFJ+1hxDopU`^9EYJ0^^O6?& zq2CYOuKvhJwAR9Bf~vx&P&(Q3IE_zi6z(ViCQ#=>dVio$IAg1)EI z=~DH{flI3ybro9Mk-U%#jzg7eC#mWqghrAD2ia2x<8*4S$DJ9-L*;nRJRhYdD88 z!vKPq%Qtx!x_T#w1^)Q8Aog?s38_S;gJKVzxeFD-w-Ybr1fKQ+lLm##zW0DXe2%33 z?QyYUR*pbsVYG|I2#8|ZW{q<~C_dQz_#H8m+KgK^JZ@#4Bz_;m;=a6193uC;B^0p0 zq4k9{-8k~G$W*7V*s=!st@Q-&uLl~&5+o%OOGmT$X`TppCM2ovl-J^m7|GJYPQVcw zl+{<#%IhP>G2%|^z(Eibu;^^r99raxOBkz}dSOt4B=r=&YA(0Hs#rUJBJ5C&=c%)l zl!n~!`UrjbO&3;tlw3JUdgEZ?WXu~RzsSUX^c(41F{d}MS_F+h2PpTjMtPw>MOOPz>U|_S{K6XWotg`$4o&p@4xX^DvRLFE;KI~ zDypB1Bbj3`sMV5!20K0r`?X~SuO!Kudpbcz$Q6pVwm4}D|5x(xX4^(R%r_@c8?~{l z{He%YTcB)q@v(QGBp4&V_Fdn`%Hw@2sT~o+S{v|lU-9IInD67;v$yL;MlLU?ZhlX; z*$LdGpGm#LBum0PmK|v)QXYolJkEHP|Eve-HybC>*se2LRg)CnY^QIoUke;52kO1Q zL@TMvM+(c!X|g)_Y6_cGAr%(q1E=M;1o)o02`e1d^m=e^`T4ClLt9;#g{rmsBT+=U zc922wT7WToa;2d4MvC>1|+Qr$euTkoM>8ar@Ie#txRJRK&}%MgM} z%H$Bjbt%}BX#DlMhG!SOB#pQFTn8)3d7fThmosOMq!WAWlx#L@luFCjfSq7_g}0cW z=X*RTSRPUaJd7C-g(sB%Q?n@nO#a6xth(*kS_}34R6a%^CoR}4YOSX-*Y=0o_QcWn z7Z>NmuE*+T6orr)5Vl?=1q1h+{gEg~$<^MqZ}Z<@nv9be!WtbyI|@5TEQ}uPE6K88h;IGK72nepwg$wFMQW7`8zkRUV<*o&?2YuXDxF5%gXXd zecHf-G!G39!I3nCF!-SHxrHuu&ptf;N55Bv>f6%EFmr?z)B)%Jq~yS{$ZQG*t6uZO25y& zj_+@Rzhr%(ONJ;8c#qUF`mi~vBD%!>PmI9sw;tE9QCo6yLCf-va~|+2U{_T@@YX2o zsc-^n3&&t2xrCgbE?_p`*1CAJ^UH^a3qB&L+o8BV+0(W!U})tf!`a3Wlz*1^?O0@l z?)m!!H_Ll~KfN3CX~4+JF(`zkMXjOv@cCyXLdiG%QNq?Li5yjYloC}qBa~pz%A+9L z&ab`kUQ!{A62Qn7+L6fYQsmXLyrN!gaEX5e_FTHj+`BN1dlIBGj9TLvT2YfsWl&p$ z<8bW_dh@--IoOu1ZJgUk3|LB)HOmtRUvfcXg=FnS6ioSc((@J3M1$A4yg!ML9yrb# zs>3Gu86Mml*uvK0g@fBKH;dkI0^NnpIq0lPf1xmpS+4=l*EI0 zA2~fgp&Jjpq}O|@)*Yv$Na4lSKRbU8NEoIw@S1^XwKjY0nJJpf))JXchkGTP4(h6= z7caG8{vw1j-!l5fO)jWTmo#|MeP&|y<${!D&u+|5Vx^M%oD)p`%FfPa47@rCsgX2h z-49%T7iKYMHBi-60Vab}Lku?EjO7Ejcxitwkq^Y%7LE8L+jX_h%bs(y(Ma{1(ddm2 znscL`2A;7gw^tEGGo-IQN*~7{?|yX%U%^xH_vh!r$P#VmmQvlSTwlg|$W|`R_$nnV zjc6Bc^@&mS9%hj4+UGvTKT!v`jb>1f;e!ew@t}X&W*K{$r5@ z+0|ZT?0h##wdZxEB#_W8Ujfvr>rJJ;N&bGLm8*?9oFxAl!1+xbibJo|I{+oM+w*!% z6sIJx*(h!zX~qS!je8V>nqVuQUwl7AcY^}6*LW&(@xnGWzYKSW2Tt^m1p#4r&3x>O zq3S*v)ckHrPwZVK!6e!!EW1t8THN9-rhvk!QTf%T@rx`6pH#7mpZH& zh0$64XMPjRI7yZZtEFHx8C9FrllVLdyI}gLNVq=fW@%<=FtmIe=doG7*6o3jY_HSz zR8XmWMs@lADXm%>PmsIYmU<{Oou{0|NFdi4QuJZ?TXj!}0Beq+3iTu4C=(c8YiszT zcp~60pTw6>11weUv{mCJT6dsW>1GCRg__5C2&ORVx@UU{__aZAI|3 zkM986^>;({z#4jr-31(B2C%;EP}rC9g+;%F<%al(=MpeJ{>3BDkP`cR>VMeplc&D+ z{WSKsp_(wvc2G`zGG9+%!{)(9ts3Oed%GMsz{h>E@O=%y6W|Z6_6HF9AhcC^s<<(D zBvoh}q}JVDecfJrw6_wz6Ov{c2eni#n8=1c>Ti{ zR&(8ob65NRY&dpZK$u!OKRurxP~rR0kkZp*gS@@oO;W>F+I_wBfc3d{s=C0@(62O4 zQ=Rg|NlTHnHgs{(yiQ_3*SlFoR~l$ew|EVWp4|op5S!@9jZS2Mg##|YZuWP!REj>( zVIn><4dDQRR?5Ig7yG*3;kfcCwic*saUnBbLDAT~BCzYpfQYLGiUy37jIXMtJR0^# z%J<)GZo(S32MjVhL(H?A+)UzRh7C;NUL{uNXzRDD7n{k%`=vF$fVi%VrnHg)Z~#d> zB8COF3erla5VHjbq2&?{AE=ecNEGd&~MDS zW|F#%Po211{sYu{S7-ZQDG1iB;)QJZ#lZqvRzVcMO38dcFZSk$9#3=6%zu#(F(K)#R2LC5c5ZgC<%7rRTlyD z=x!g2n8%!$H``I5xKCCqRwaPv7^Pj%=%1Wj5eYZK-%(PiGc_}j^Ks4wZVWjOJU+?r zNd6zos{wBhMFKqllc8j)C>2=6h5+d{4F6Q>0I#suj|JpN%+^|%NhE3w{99Q2MEIJp zzU)wCACwTS?CpCt@$^c>{9-d&Oo>3Fq4LNl# zZsU~i*xQbQFS3yWa;c>sfR52Cy=@}QlT`)XcTI!iN?iaVU2i5i5$7!0VG`$AACtfa zFEPSV@;)|2rIcw8@mxn*GXD(zlHgY^87VGqrt!`op8nDx61d5X(JQodQR7B3 z(njOQKccaMHIXV5M`aW31?aio;Et}>i&X4Ges-uX42+qw(3BLPnE{P!h5jvZMn zaJ8h-vE^%K%?A&e(sij9o}$IA-SEGNL-c1Ieccjrq3bWa$8EulggSXRf*5peE%gkJ zaClp%>)qZfM$yZX%KN41lDHw+MuNA6H$4Iu>JlU_MBd_?l@S6@KkxYRrLbeu=C|#3 z)iBRaL(AwFDE;J$JG#d%Mb0bbf&MxMIkz8ZTN+g|hk)C?4sTZxkIf2VjRo9GPM1N8 z*;tW61p!zJ+}WWpk=&4zVib0w2KtT@Ic86A`s_6R>ZTspyy%dY9h=c85cO^`UsXXT zlOPB^{+4tdMfeTe`Lh}tg1J721OW5!;>yiSnf{6`I3egKy3;q)`xgu#2mK2M(02Zroc{&mUof_d*?%oa{OcM2 z*T4X|I^c*z740*l_9b=59xD~%V@^`vg^t(<)Nqw$!{vFW0Q5;FRG4eKL#3y zCYIuyB zthk-c06udm*1?Xl)z3y8Kp>!{Rb2zh>KghEID2M1y>N%oJ3QpyrdLi=Vu@c&vfh|; z#Ji;t7qiQ$I!J~+d_9NshoMab?w_9;w{_&fJ=ukn1BF}Wu*Be@eGo&wUW+zVB7&c8x^|{Ekc_thI>jYJh(u%^5|847%95lPZt-8$l+G;gkRxpB-XY8TjVQ zi?h~<(_ui9=>!w11)18Gg#cMMeGY)4a8LdUdyoQ_z!V>*S?}g7rtLd;q7Y-fSOvY> z$kOZW*3|k?R20#uX0+e8aGcmJD+fFq(ncgH_6Qr%CRO#Nm|ogr7rQ1{yfrFLys)Y( zLs>m8A`8bg8#rKTK&gTH8 zXSM`Owk~WppwBA%rt5&VL)!pO2tAMV^pw*o z<>!&cmciJMj#;A#{3bIPN!fag9DF2N3*sAPO~F($gZcvzdzJNf9~2$GqA}1BEr!W>>5W z&E-I0MJ;Od|5$>kCvd1W*w;AFbE73hrqa^k4~f66T_Z?;eGE^z;_EAs*cANil9dB) z@m`nQKR`o-3IUrZskC#lxN$$3ncN4?_*W8XaK`G3=$4WujiiCib|1 z(Y5qd&pU;6S(j~`xASa^YuZb~;(Xt-6)i?td-Ol!F+{(%`opcnIiU$g@^JNPIT?2>=l_fk%5_< zpow$Nm_g!RncmJh!`}TbO&4NOo>m|n@opCOd~Z=m-U7MU+1_6z|FZa88}-zdKBD#K zd0yRA=yy_6m5STaQWK%1>S(#Z7l^f6V|mKr?R5oR43%~106%P#Sa<&EEDSC;kmH_z zvkkLo58~Nz6TL>jhc>W(Gn-^ocSiJwYKI=P>mXnDQR8v&A~7m+*Z|_0m)9$S>a{?5 z=2=;S_8U1L!75vrH(Itnv2H!)rS@t7eu?9en0Lu+e|Hun*bE7h3@*w{+u{Nd~8O{%ESo#e5Ztvmq~BXD9wI z`_JCnab+S1-UwxVm4v-?d!lsHS#hlXTh~C4l2I$%9CQ&bcvB@ejavBa27wa-TxzC* z*ZnlUFq{DALe=GJt5aS@WENIIeY@|qQX>h4Z=j=U^GlCBMskRBj6(6vV zPl^txlNl!{Q-%WS_RIauN%=fuein2{`sMa&)9}lmhRx`1W;cCgDp#NMPOTnXf+bCs z-pNd-m}pG4tlP1#f!PlY{^y(k6B_xAnzKPid?2vhC|a_^gpRadAp7aQ*l}h7Wi;

NP`3$v4a;K6%=GV+GN7#hLP1BZz*!g&i`1dG z!(Y%W71JM?pmx9MoWJ?9hg-T>FAyJl(!$N?Ni3b$l{#!^H+`treZEegh;|FR)q10~ z?CXMGXrVo;!(^q|bt#MOkKurWjxp`mOV?}C!!U01_ICE{gmL!Kb_Ss+kfSTvku^c$ zj_EX6x#562tu_-j@r1z0gw)jn>vh}Ebx3mixK~!@!ncw)up8}Y1gE?m0eD!0w#;$P zw*r9tQ2E|GiJcHmMCrX_LNUDAZi+4Pn{FDioZ4-uYUCLRWc=q;((n@Gu}!KOIs7L^CO(=D0EmkWaP_Hg8r!h zXJRHRk^!K+ge3xI^La(f`9C8MHlnvZcKYLXP}<_Wv2)f06lLdBp#3$b8%4is4h- VU)#cWWEb#r(_WRH1TM}mrXgOWxrz!f$vWrb4bgQ zX(+Fz)`wFkFvUNdI)NuWG2jo=A5Wj0iw*nn>?xW!hm^F@;#C~vMHJa!=u{`8h7J)! Y0co`V&!KW7xc~qF07*qoM6N<$f@bik5dZ)H diff --git a/docs/logs/images/logs-time-selector.png b/docs/logs/images/logs-time-selector.png deleted file mode 100644 index 5e6a9b7222c541184425c9f49d421a32e2686e1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5793 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 y?B%NyF3K9xaG_)s458A=`}V;@ui diff --git a/docs/logs/images/logs-view-event-with-filter.png b/docs/logs/images/logs-view-event-with-filter.png deleted file mode 100644 index 4e378af39ab0574d0d718649b5f986b17167b90c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 929 zcmV;S177@zP)Px&TS-JgR5%f}R9j0_Q562>mO5S%O3=x%iBd}(?GFT&m(sTgwT!U53zil{Pd#;c z3GpEl>MbXtWs!XxqB~5m*9POqiUSh3EAf%*}nl6wS?a ziZdw@iH-!E$j*X`<|-vD#MY!uo3FxbHbYevw0Cr&yZaSVQ&Zq}ry=>!K?2Y)=9|F4 z;3s%TMp00Zhmv!Juvje6IE7$gVEt3*c)wp2w{G7PRW%L5>-AAE8=}#`pDx2AW1_OU zUfj9cC=^8%(l-bTIw+4Ut!&MFFl~qwzQ776vo=e+cECZMx zLQG7~h{EEFf}{EASHw30U*6_pou6zz4|%1})byNS3?1BfJbsw&7d<$7)Q!}XgJ^7O zfv2|*yKJ`Ln=|GFirkzmT&=G~Mn*dMzCv|nDF|EI7{E-Y4V}1Pxaaf@P zHhh>_Hp(I*B3y!VfC&llSX^8pUI&QhR=ICPEZsKokt2K1@(6uz-%BvI;X^pWYYla@ z;?L33 zGh?xASkuHtrJ9-H#_Qg9QlbCsb~|EYchiy_2!!W$dxWl*V=wt+X1XPYt}uYPa`N-@ z(BD4*@921l5l7kBbRW&l4^V(t67!Ba|E76=zpTYDET4ITR!5pxvWP|g;gfzz3Y>o;z~=bMy~b7WDG;fS<{ z8|%@r32EbUC84PBwDi?8;c?q0)YjICmpvXFNjr>;^fVkwrY1z!z)fh7n$Xbj2=Y(n zpoF+?wc6+!eqYfaf#oLmU22=-lhg2cxNXj3W@c6vi_^Ie4u=Cd*;zQ?a{hhWWMEzN zM$bi{ssXuewOVBJ=e?a8{g$iHLH~6OdAxrG3-w00000NkvXXu0mjf DTn4r^ diff --git a/docs/logs/images/logs-view-event.png b/docs/logs/images/logs-view-event.png deleted file mode 100644 index 29dff68e3fdba9f2392e0251208de80ca0a3f3b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555 zcmV+`0@VG9P)Px$q zb#ieL1Q&M)Clv}Jf>5RYYin&A&yA^#Nn6`e2f<6yyu93Z&bjBlS4Dq0)$xm={vx&k z{ZEi_*rfox?BTXg6!cE8qw@&n_rgZH_&n0-!{Sga0zST3wvAHKE~3)sXbM+P31}pX z#C1&Xgs?PRgR$NK@Sb5Pt;t*;@Vn4at0DZDKu^0DZ4DakV;SJI6Qx;1S<$x?X0}79 zqa_2~e!L}gt21eQ6kmaW(~>z_qH(-B)&Qh{zGe?vs$Adv7nb6BkOrr67ss0uP4H-J z2nlrFvWpbkPGVYt!OR$&H=6}q5EP2HgUftw0;>{ci7m5RA^50xb26h`K#Xwq*O<;q zpfg!dnhQUjwR)Zx)$-9vK%mQq zB#y7+hJg#aw@{e1!G?OxhFaGDILvwuq*;ayd`|TT(AVmP#%hqvVRRlEX9dKl@u~>k z#Bp*FLw&Uy!SFj?UfC2978}lUK#(W?&#WBWVLurCI-TpI^%(4`EV>FOfk+gkDt}6_ t#9pD(BFPY|%K$D=*$L!Jnd0vgd;ok4noWRiK|ufj002ovPDHLkV1f>!_bLDY diff --git a/docs/logs/images/logs-view-in-context.png b/docs/logs/images/logs-view-in-context.png deleted file mode 100644 index 09a9e89fc30429072106b73b6e15fa84aef38325..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 388396 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 z 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�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

`>Vhgy3Vv1HBeu8p$*{vpJ!>?JJ3sC2Mlf~G z;ex=cIy2hPMY%rN)Y2I-Y|B`A6Q&QYw&|uc;Ui6!HUU92)a}^EuU~#38g0I`@D=@> z^*9gt#49YZUHNeqME%KIQDj4yrbv(etMQt)Ha93m}j3FSeejc(R|&A>1t=dEGwR0}$hajHrmm=BT*f+y^B2T1$fUf=DK2~OCv z)}@Cps1!MA1>bnDUp)Pxy8_RtkKS@9t6XBXtX?%$YW5ECb+C$VqA)f4fjDZn1oM46 zXU-ccCqeoVPexbn>NFY4{rvdB?BwaaG}6xDjO@T?M6pbq>wF$DraQTRji%%j8T7Pcn{=?GcmkuXcxipj4fhJpN$>S+l-!g@VWc*6 zo+b0qsiJpFpB(ZMSnm}0l#1subvivSWqOWwn%)U8`N~?|aFnr`@v)I7@?y9A|GoU!Cvb z#@I>~rhjY%;f&ncsHyJn8scATkHM`Iw1uJW+HO;cCV!liP(*@g=h2I1PTlx3@f#MAn67IG z>^apsE2TchNR$CAR(kSDu)=Z!5;OtVD@$d2Ul>d|-@vStH0Fg$^?;3vPz>hP83x=h zY0(R6OfqLYqDzWCj5P5@SUGJPM3g*J#J_EY@E-qh{2pA{Uut?S>#^7)36H_2S@g&` z^5*$5*8@)`Hcs#EVXd0uZ%hdyft$R3NKtJ0p1f;cFndz?Ct0Gr6I(S*&023>&pOL{ z$V*S7&T7eY5UMJ?NI9@V-8KPHSr0;p;+ZncC0#F2wB7KQ{_)0(5}mBGANuW=V@caa znu7gg6@?D=3y1ABCu4gGPY8lMzDd;eqj29NyW&1!k;!k@_hg=|^Kf+qzFU@a#Y7+8 zGsv)6)0^TVq2-arl^&#rIJvi#7glBfk))d&bVtOyZ|;VOGNZD3?3V|A>b%NgJIv5C zx%&$L=6f(gFSTiz9rV>x>b9WWhtKws4*_Ja=^sv5TFF`0lwZoZLH5r^+CB^B9F(Y{ zkUZY>g4uWu7~aR3HiUHkBE{<6S@(nKG0@RI0K%u0SP?Aq-*}k$n{RVeiy>TIXBq9u zm)o}@rv6m!(3`UaZm@r_eama*g)56FkD;aF*zod5{V#x(kGPMG2WW} zc$+KwEljA!C>0zo?)v7NB7RZ)SlwQ)kh=;hAc_z>^MIy4iuGqoG>-Y(PP{?M-zUds! zPi)we>X0ej8hH|2dpvb7$OhJSY4Rp{y5+!b?YWhE%L{>`a{+hDf$nDzs7~xGLlf{1 z*+7>qopZBqjxZE|K2cWT%asEOEW2-ac6!(-j{RH=dcU-7FzHkAbDQ#}?L07|HF^Gb z%C)J-L;HtY%EoD#byMpWEEoR8mq4IuG0^wu*15#{1?6qY=^#{=mp%fMqothShYLMX zF>gdWp8nq;-2Y9o1}0D*k_qQ{!64LS(3gl#_d%7;kO2UW!Kt18_aXdUCy08E>wJZE Tym;5uzgLC^X8MGiPEr2{zfWU{ diff --git a/docs/logs/index.asciidoc b/docs/logs/index.asciidoc index 0d225e5e89c17..45d4321f40556 100644 --- a/docs/logs/index.asciidoc +++ b/docs/logs/index.asciidoc @@ -1,9 +1,8 @@ +[chapter] [role="xpack"] [[xpack-logs]] = Logs -[partintro] --- The Logs app in Kibana enables you to explore logs for common servers, containers, and services. The Logs app has a compact, console-like display that you can customize. @@ -13,23 +12,10 @@ You can open the Logs app from the *Logs* tab in Kibana. You can also open the Logs app directly from a component in the Metrics app. In this case, you will only see the logs for the selected component. -* <> -* <> -* <> -* <> -* <> - [role="screenshot"] -image::logs/images/logs-console.png[Log Console in Kibana] - --- - -include::getting-started.asciidoc[] - -include::using.asciidoc[] - -include::configuring.asciidoc[] +image::logs/images/logs-console.png[Logs Console in Kibana] -include::log-rate.asciidoc[] +[float] +=== Get started -include::logs-alerting.asciidoc[] +To get started with Elastic Logs, refer to {logs-guide}/install-logs-monitoring.html[Install Logs]. diff --git a/docs/logs/log-rate.asciidoc b/docs/logs/log-rate.asciidoc deleted file mode 100644 index 56284a1c76219..0000000000000 --- a/docs/logs/log-rate.asciidoc +++ /dev/null @@ -1,94 +0,0 @@ -[role="xpack"] -[[xpack-logs-analysis]] -== Detecting and inspecting log anomalies - -beta::[] - -When the {ml} {anomaly-detect} features are enabled, -you can use the **Log rate** page in the Logs app. -**Log rate** helps you to detect and inspect log anomalies and the log partitions where the log anomalies occur. -This means you can easily spot anomalous behavior without significant human intervention -- -no more manually sampling log data, calculating rates, and determining if rates are normal. - -*Log rate* automatically highlights periods of time where the log rate is outside expected bounds, -and therefore may be anomalous. -You can use this information as a basis for further investigations. -For example: - -* A significant drop in the log rate might suggest that a piece of infrastructure stopped responding, -and thus we're serving less requests. -* A spike in the log rate could denote a DDoS attack. -This may lead to an investigation of IP addresses from incoming requests. - -You can also view log anomalies directly in the <>. - -[float] -[[logs-analysis-create-ml-job]] -=== Enable log rate analysis and anomaly detection - -Create a machine learning job to enable log rate analysis and anomaly detection. - -[role="screenshot"] -image::logs/images/analysis-tab-create-ml-job.png[Create machine learning job] - -1. To enable log rate analysis and anomaly detection, -you must first create your own {kibana-ref}/xpack-spaces.html[space]. -2. Within a space, navigate to the Logs app and select *Log rate*. -Here, you'll be prompted to create a machine learning job which will carry out the log rate analysis. -3. Choose a time range for the machine learning analysis. -4. Add the Indices that contain the logs you want to analyze. -5. Click *Create ML job*. -6. You're now ready to analyze your log partitions. - -Even though the machine learning job's time range is fixed, -you can still use the time filter to adjust the results that are shown in your analysis. - -[role="screenshot"] -image::logs/images/log-time-filter.png[Log rate time filter] - -[float] -[[logs-analysis-entries-chart]] -=== Log entries chart - -The log entries chart shows an overall, color-coded visualization of the log entry rate, -partitioned according to the value of the Elastic Common Schema (ECS) -{ecs-ref}/ecs-event.html[`event.dataset`] field. -This chart helps you quickly spot increases or decreases in each partition's log rate. - -[role="screenshot"] -image::logs/images/log-rate-entries.png[Log rate entries chart] - -If you have a lot of log partitions, use the following to filter your data: - -* Hover over a time range to see the log rate for each partition. -* Click or hover on a partition name to show, hide, or highlight the partition values. - -[float] -[[logs-analysis-anomalies-chart]] -=== Anomalies charts - -The Anomalies chart shows the time range where anomalies were detected. -The typical rate values are shown in grey, while the anomalous regions are color-coded and superimposed on top. - -[role="screenshot"] -image::logs/images/log-rate-anomalies.png[Log rate entries chart] - -When a time range is flagged as anomalous, -the machine learning algorithms have detected unusual log rate activity. -This might be because: - -* The log rate is significantly higher than usual. -* The log rate is significantly lower than usual. -* Other anomalous behavior has been detected. -For example, the log rate is within bounds, but not fluctuating when it is expected to. - -The level of anomaly detected in a time period is color-coded, from red, orange, yellow, to blue. -Red indicates a critical anomaly level, while blue is a warning level. - -To help you further drill down into a potential anomaly, -you can view an anomaly chart for each individual partition: - -Anomaly scores range from 0 (no anomalies) to 100 (critical). - -To analyze the anomalies in more detail, click *Analyze in ML*, which opens the -{kibana-ref}/xpack-ml.html[Anomaly Explorer in Machine Learning]. diff --git a/docs/logs/logs-alerting.asciidoc b/docs/logs/logs-alerting.asciidoc deleted file mode 100644 index f08a09187a0c8..0000000000000 --- a/docs/logs/logs-alerting.asciidoc +++ /dev/null @@ -1,27 +0,0 @@ -[role="xpack"] -[[xpack-logs-alerting]] -== Logs alerting - -[float] -=== Overview - -To use the alerting functionality you need to {kibana-ref}/alerting-getting-started.html#alerting-setup-prerequisites[set up alerting]. - -You can then select the *Create alert* option, from the *Alerts* actions dropdown. - -[role="screenshot"] -image::logs/images/alert-actions-menu.png[Screenshot showing alerts menu] - -Within the alert flyout you can configure your logs alert: - -[role="screenshot"] -image::logs/images/alert-flyout.png[Screenshot showing alerts flyout] - -[float] -=== Fields and comparators - -The comparators available for conditions depend on the chosen field. The combinations available are: - -- Numeric fields: *more than*, *more than or equals*, *less than*, *less than or equals*, *equals*, and *does not equal*. -- Aggregatable fields: *is* and *is not*. -- Non-aggregatable fields: *matches*, *does not match*, *matches phrase*, *does not match phrase*. diff --git a/docs/logs/using.asciidoc b/docs/logs/using.asciidoc deleted file mode 100644 index eb3025f88ce1b..0000000000000 --- a/docs/logs/using.asciidoc +++ /dev/null @@ -1,100 +0,0 @@ -[role="xpack"] -[[xpack-logs-using]] -== Using the Logs app -Use the Logs app in {kib} to explore and filter your logs in real time. - -You can customize the output to focus on the data you want to see and to control how you see it. -You can also view related application traces or uptime information where available. - -[role="screenshot"] -image::logs/images/logs-console.png[Logs Console in Kibana] - -[float] -[[logs-search]] -=== Use the power of search - -Use the search bar to perform ad hoc searches for specific text. -You can also create structured queries using {kibana-ref}/kuery-query.html[Kibana Query Language]. -For example, enter `host.hostname : "host1"` to see only the information for `host1`. -// ++ this isn't quite the same as the corresponding metrics description now. - -[float] -[[logs-configure-source]] -=== Configure the data to use for your logs -Are you using a custom index pattern to store the log entries? -Do you want to limit the entries shown or change the fields displayed in the columns? -If so, <> to change the index pattern and other settings. - -[float] -[[logs-time]] -=== Specify the time and date - -Click image:images/time-filter-calendar.png[time filter calendar], then choose the time range for the logs. - -Log entries for the specified time appear in the middle of the page. To quickly jump to a nearby point in time, click the minimap timeline to the right. -// ++ what's this thing called? It's minimap in the UI. Would timeline be better? - -[float] -[[logs-customize]] -=== Customize your view -Click *Customize* to customize the view. -Here, you can choose whether to wrap long lines, and choose your preferred text size. - -[float] -=== Configuring the data to use for your logs - -If your logs have custom index patterns, use non-default field settings, or contain parsed fields which you want to expose as individual columns, you can <>. - -[float] -[[logs-stream]] -=== Stream or pause logs -Click *Stream live* to start streaming live log data, or click *Stop streaming* to focus on historical data. - -When you are viewing historical data, you can scroll back through the entries as far as there is data available. - -When you are streaming live data, the most recent log appears at the bottom of the page. -In live streaming mode, you are not able to choose a different time in the time selector or use the minimap timeline. -To do either of these things, you need to stop live streaming first. -// ++ Not sure whether this is correct or not. And what about just scrolling through the display? -// ++ There may be a bug here, (I managed to get future logs) see https://github.com/elastic/kibana/issues/43361 - -[float] -[[logs-highlight]] -=== Highlight a phrase in the logs stream -To highlight a word or phrase in the logs stream, click *Highlights* and enter your search phrase. -// ++ Is search case sensitive? -// ++ Can you search for multiple phrases together, if so, what's the separator? -// ++ What about special characters? For example, I notice that when searching for "Mozilla/4.0" which appears as written in my logs, "Mozilla" is highlighted, as is "4.0" but "/" isn't. The string "-" (which appears in the logs as written, quotes and all, isn't found at all. Any significance? - -[float] -[[logs-event-inspector]] -=== Inspect a log event -To inspect a log event, hover over it, then click the *View actions for line* icon image:logs/images/logs-action-menu.png[View actions for line icon]. On the menu that opens, select *View details*. This opens the *Log event document details* fly-out that shows the fields associated with the log event. - -To quickly filter the logs stream by one of the field values, in the log event details, click the *View event with filter* icon image:logs/images/logs-view-event-with-filter.png[View event icon] beside the field. -This automatically adds a search filter to the logs stream to filter the entries by this field and value. - -[float] -[[log-view-in-context]] -=== View log line in context -To view a certain line in its context (for example, with other log lines from the same file, or the same cloud container), hover over it, then click the *View actions for line* image:logs/images/logs-action-menu.png[View actions for line icon]. On the menu that opens, select *View in context*. This opens the *View log in context* modal, that shows the log line in its context. - -[role="screenshot"] -image::logs/images/logs-view-in-context.png[View a log line in context] - -[float] -[[view-log-anomalies]] -=== View log anomalies - -When the machine learning anomaly detection features are enabled, click *Log rate*, which allows you to -<> in your log data. - -[float] -[[logs-integrations]] -=== Logs app integrations - -To see other actions related to the event, click *Actions* in the log event details. -Depending on the event and the features you have configured, you may also be able to: - -* Select *View status in Uptime* to {uptime-guide}/uptime-app-overview.html[view related uptime information] in the *Uptime* app. -* Select *View in APM* to <> in the *APM* app. diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 85d580de9475f..04959b2627a78 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -33,7 +33,7 @@ This page has moved. Please see <>. [role="exclude",id="logs-read-only-access"] == Configure source read-only access -This page has moved. Please see <>. +This page has moved. Please see {logs-guide}/configure-logs-source.html[logs configuration]. [role="exclude",id="extend"] == Extend your use case @@ -80,3 +80,28 @@ This page was deleted. See <>. == Developing Visualizations This page was deleted. See <>. + +[role="exclude",id="xpack-logs-getting-started"] +== Getting started with logs monitoring + +This page has moved. Please see the new section in the {logs-guide}/install-logs-monitoring.html[Logs Monitoring Guide]. + +[role="exclude",id="xpack-logs-using"] +== Using the Logs app + +This page has moved. Please see the new section in the {logs-guide}/logs-app-overview.html[Logs Monitoring Guide]. + +[role="exclude",id="xpack-logs-configuring"] +== Configuring the Logs data + +This page has moved. Please see the new section in the {logs-guide}/configure-logs-source.html[Logs Monitoring Guide]. + +[role="exclude",id="xpack-logs-analysis"] +== Detecting and inspecting log anomalies + +This page has moved. Please see the new section in the {logs-guide}/detect-log-anomalies.html[Logs Monitoring Guide] + +[role="exclude",id="xpack-logs-alerting"] +== Logs alerting + +This page has moved. Please see the new section in the {logs-guide}/create-log-alert.html[Logs Monitoring Guide] From 3b4fa6ade648d2aae22280713a809483e7fe55c9 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Wed, 10 Jun 2020 09:19:32 -0600 Subject: [PATCH 35/53] [Security] Updates Cypress README.md to show how to run-as-ci with Cypress UI [skip ci] (#68728) ## Summary Updates Cypress README.md to show how to `run-as-ci` with the Cypress UI. ##### Updates: > Note: To `run-as-ci` with the Cypress UI, update [x-pack/test/security_solution_cypress/runner.ts](https://github.com/elastic/kibana/blob/master/x-pack/test/security_solution_cypress/runner.ts#L25) from > ``` ts >args: ['cypress:run'], >``` >to >``` ts >args: ['cypress:open'], >``` >This is helpful for debugging specific failed tests from CI without having to run the entire suite. --- x-pack/plugins/security_solution/cypress/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/x-pack/plugins/security_solution/cypress/README.md b/x-pack/plugins/security_solution/cypress/README.md index ad3af2aaa4e8a..1a2ae696373b1 100644 --- a/x-pack/plugins/security_solution/cypress/README.md +++ b/x-pack/plugins/security_solution/cypress/README.md @@ -135,6 +135,17 @@ Note that with this type of execution you don't need to have running a kibana an As in this case we want to mimic a CI execution we want to execute the tests with the same set of data, this is why in this case does not make sense to override Cypress environment variables. +Note: To `run-as-ci` with the Cypress UI, update [x-pack/test/security_solution_cypress/runner.ts](https://github.com/elastic/kibana/blob/master/x-pack/test/security_solution_cypress/runner.ts#L25) from +``` ts +args: ['cypress:run'], +``` +to +``` ts +args: ['cypress:open'], +``` +This is helpful for debugging specific failed tests from CI without having to run the entire suite. + +Note: Please don't commit this change. ### Test data As mentioned above, when running the tests as Jenkins the tests are populated with data ("archives") found in: `x-pack/test/security_solution_cypress/es_archives`. From 8a5a7c303238a6190ddec5fb993b3dce9dc81a0b Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Wed, 10 Jun 2020 08:39:52 -0700 Subject: [PATCH 36/53] [eslint] Prevents importing of public code into server (#67149) We should not be allowing importing of public into server. Any shared code should reside in a common directory. After #66506, this will not even be possible as we will no longer be transpiling public code into commonjs. Blocks #66506 Signed-off-by: Tyler Smalley --- .eslintrc.js | 9 +++++--- .../public/lib/autocomplete/autocomplete.ts | 2 +- src/plugins/es_ui_shared/common/index.ts | 20 ++++++++++++++++++ .../public/authorization/index.ts | 12 ++++++++++- .../server/report/store_report.test.ts | 2 +- .../server/alerts_client_factory.test.ts | 2 +- .../create_static_index_pattern.ts | 6 ++++-- .../embeddable_enhanced/public/plugin.ts | 14 +++++++------ .../ingest_pipelines/public/shared_imports.ts | 21 ++++++++----------- .../server/routes/api/privileges.ts | 2 +- .../application/store/actions/start_basic.js | 3 ++- x-pack/plugins/maps/server/plugin.ts | 3 ++- .../components/open_timeline/helpers.ts | 2 +- .../endpoint/alerts/handlers/lib/index.ts | 2 +- .../endpoint/routes/resolver/queries/base.ts | 2 +- .../routes/resolver/queries/children.ts | 2 +- .../routes/resolver/queries/events.ts | 2 +- .../routes/resolver/queries/lifecycle.ts | 2 +- .../routes/resolver/queries/multi_searcher.ts | 2 +- .../endpoint/routes/resolver/queries/stats.ts | 2 +- .../routes/resolver/utils/pagination.ts | 2 +- .../security_solution/server/lib/types.ts | 2 +- .../server/utils/serialized_query.ts | 2 +- .../snapshot_restore/public/shared_imports.ts | 18 ++++++++-------- .../snapshot_restore/server/routes/api/app.ts | 2 +- .../public/custom_time_range_action.test.ts | 4 +--- 26 files changed, 88 insertions(+), 54 deletions(-) create mode 100644 src/plugins/es_ui_shared/common/index.ts diff --git a/.eslintrc.js b/.eslintrc.js index b5f8d106392d5..9657719f0f526 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -197,9 +197,12 @@ module.exports = { errorMessage: `Plugins may only import from src/core/server and src/core/public.`, }, { - target: ['(src|x-pack)/plugins/*/public/**/*'], - from: ['(src|x-pack)/plugins/*/server/**/*'], - errorMessage: `Public code can not import from server, use a common directory.`, + target: [ + '(src|x-pack)/plugins/*/server/**/*', + '!x-pack/plugins/apm/**/*', // https://github.com/elastic/kibana/issues/67210 + ], + from: ['(src|x-pack)/plugins/*/public/**/*'], + errorMessage: `Server code can not import from public, use a common directory.`, }, { target: ['(src|x-pack)/plugins/*/common/**/*'], diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts index b05c7ddbb020d..3959f2ed8cf46 100644 --- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts +++ b/src/plugins/console/public/lib/autocomplete/autocomplete.ts @@ -308,7 +308,7 @@ export function getCurrentMethodAndTokenPaths( } // eslint-disable-next-line -export default function({ coreEditor: editor, parser }: { coreEditor: CoreEditor; parser: any }) { +export default function ({ coreEditor: editor, parser }: { coreEditor: CoreEditor; parser: any }) { function isUrlPathToken(token: Token | null) { switch ((token || ({} as any)).type) { case 'url.slash': diff --git a/src/plugins/es_ui_shared/common/index.ts b/src/plugins/es_ui_shared/common/index.ts new file mode 100644 index 0000000000000..c13dff5cf1fa1 --- /dev/null +++ b/src/plugins/es_ui_shared/common/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { Privileges, MissingPrivileges } from '../__packages_do_not_import__/authorization'; diff --git a/src/plugins/es_ui_shared/public/authorization/index.ts b/src/plugins/es_ui_shared/public/authorization/index.ts index 3a02c0d2694f3..e18ab32ffdfa8 100644 --- a/src/plugins/es_ui_shared/public/authorization/index.ts +++ b/src/plugins/es_ui_shared/public/authorization/index.ts @@ -17,4 +17,14 @@ * under the License. */ -export * from '../../__packages_do_not_import__/authorization'; +export { + AuthorizationContext, + AuthorizationProvider, + Error, + MissingPrivileges, + NotAuthorizedSection, + Privileges, + SectionError, + useAuthorizationContext, + WithPrivileges, +} from '../../__packages_do_not_import__/authorization'; diff --git a/src/plugins/usage_collection/server/report/store_report.test.ts b/src/plugins/usage_collection/server/report/store_report.test.ts index 29b6d79cc139a..d8327eb834e12 100644 --- a/src/plugins/usage_collection/server/report/store_report.test.ts +++ b/src/plugins/usage_collection/server/report/store_report.test.ts @@ -20,7 +20,7 @@ import { savedObjectsRepositoryMock } from '../../../../core/server/mocks'; import { storeReport } from './store_report'; import { ReportSchemaType } from './schema'; -import { METRIC_TYPE } from '../../public'; +import { METRIC_TYPE } from '@kbn/analytics'; describe('store_report', () => { test('stores report for all types of data', async () => { diff --git a/x-pack/plugins/alerts/server/alerts_client_factory.test.ts b/x-pack/plugins/alerts/server/alerts_client_factory.test.ts index 50dafba00a7e4..a2d64c94ce007 100644 --- a/x-pack/plugins/alerts/server/alerts_client_factory.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client_factory.test.ts @@ -11,7 +11,7 @@ import { taskManagerMock } from '../../task_manager/server/task_manager.mock'; import { KibanaRequest } from '../../../../src/core/server'; import { loggingServiceMock, savedObjectsClientMock } from '../../../../src/core/server/mocks'; import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks'; -import { AuthenticatedUser } from '../../security/public'; +import { AuthenticatedUser } from '../../../plugins/security/common/model'; import { securityMock } from '../../security/server/mocks'; import { actionsMock } from '../../actions/server/mocks'; diff --git a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts index d788ae81a7db8..ea7cc9b145696 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts @@ -4,8 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server'; -import { apmIndexPattern } from '../../../../../../src/plugins/apm_oss/server'; -import { APM_STATIC_INDEX_PATTERN_ID } from '../../../../../../src/plugins/apm_oss/server'; +import { + apmIndexPattern, + APM_STATIC_INDEX_PATTERN_ID, +} from '../../../../../../src/plugins/apm_oss/server'; import { hasHistoricalAgentData } from '../services/get_services/has_historical_agent_data'; import { Setup } from '../helpers/setup_request'; import { APMRequestHandlerContext } from '../../routes/typings'; diff --git a/x-pack/plugins/embeddable_enhanced/public/plugin.ts b/x-pack/plugins/embeddable_enhanced/public/plugin.ts index e6413ac03aeae..a14cdfd035d2e 100644 --- a/x-pack/plugins/embeddable_enhanced/public/plugin.ts +++ b/x-pack/plugins/embeddable_enhanced/public/plugin.ts @@ -127,17 +127,19 @@ export class EmbeddableEnhancedPlugin }); dynamicActions.start().catch((error) => { - /* eslint-disable */ - console.log('Failed to start embeddable dynamic actions', embeddable); - console.error(error); + /* eslint-disable */ + + console.log('Failed to start embeddable dynamic actions', embeddable); + console.error(error); /* eslint-enable */ }); const stop = () => { dynamicActions.stop().catch((error) => { - /* eslint-disable */ - console.log('Failed to stop embeddable dynamic actions', embeddable); - console.error(error); + /* eslint-disable */ + + console.log('Failed to stop embeddable dynamic actions', embeddable); + console.error(error); /* eslint-enable */ }); }; diff --git a/x-pack/plugins/ingest_pipelines/public/shared_imports.ts b/x-pack/plugins/ingest_pipelines/public/shared_imports.ts index a2ee321526052..ab56ae427120b 100644 --- a/x-pack/plugins/ingest_pipelines/public/shared_imports.ts +++ b/x-pack/plugins/ingest_pipelines/public/shared_imports.ts @@ -7,11 +7,18 @@ import { useKibana as _useKibana } from '../../../../src/plugins/kibana_react/pu import { AppServices } from './application'; export { + AuthorizationProvider, + Error, + NotAuthorizedSection, + SectionError, + SectionLoading, + sendRequest, SendRequestConfig, SendRequestResponse, - UseRequestConfig, - sendRequest, + useAuthorizationContext, useRequest, + UseRequestConfig, + WithPrivileges, } from '../../../../src/plugins/es_ui_shared/public/'; export { @@ -41,14 +48,4 @@ export { isEmptyString, } from '../../../../src/plugins/es_ui_shared/static/validators/string'; -export { - SectionLoading, - WithPrivileges, - AuthorizationProvider, - SectionError, - Error, - useAuthorizationContext, - NotAuthorizedSection, -} from '../../../../src/plugins/es_ui_shared/public'; - export const useKibana = () => _useKibana(); diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts index 69cba215beafd..e82e05323e644 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts @@ -5,7 +5,7 @@ */ import { RouteDependencies } from '../../types'; import { API_BASE_PATH, APP_CLUSTER_REQUIRED_PRIVILEGES } from '../../../common/constants'; -import { Privileges } from '../../../../../../src/plugins/es_ui_shared/public'; +import { Privileges } from '../../../../../../src/plugins/es_ui_shared/common'; const extractMissingPrivileges = (privilegesObject: { [key: string]: boolean } = {}): string[] => Object.keys(privilegesObject).reduce((privileges: string[], privilegeName: string): string[] => { diff --git a/x-pack/plugins/license_management/public/application/store/actions/start_basic.js b/x-pack/plugins/license_management/public/application/store/actions/start_basic.js index 5ae93bf84c2f8..bce6195caecf0 100644 --- a/x-pack/plugins/license_management/public/application/store/actions/start_basic.js +++ b/x-pack/plugins/license_management/public/application/store/actions/start_basic.js @@ -45,7 +45,8 @@ export const startBasicLicense = (currentLicenseType, ack) => async ( 'xpack.licenseMgmt.replacingCurrentLicenseWithBasicLicenseWarningMessage', { //eslint-disable-next-line - defaultMessage: 'Some functionality will be lost if you replace your {currentLicenseType} license with a BASIC license. Review the list of features below.', + defaultMessage: + 'Some functionality will be lost if you replace your {currentLicenseType} license with a BASIC license. Review the list of features below.', values: { currentLicenseType: currentLicenseType.toUpperCase(), }, diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index a265cf80c73cd..f2331b9a1a960 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -23,7 +23,8 @@ import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/s import { emsBoundariesSpecProvider } from './tutorials/ems'; // @ts-ignore import { initRoutes } from './routes'; -import { ILicense, LicensingPluginSetup } from '../../licensing/public'; +import { ILicense } from '../../licensing/common/types'; +import { LicensingPluginSetup } from '../../licensing/server'; import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; interface SetupDeps { diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts index f521ffa9b6b5d..c8a47798f169c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts @@ -221,7 +221,7 @@ export const queryTimelineById = ({ variables: { id: timelineId }, }) // eslint-disable-next-line - .then(result => { + .then((result) => { const timelineToOpen: TimelineResult = omitTypenameInTimeline( getOr({}, 'data.getOneTimeline', result) ); diff --git a/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts b/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts index 4f0a7ba2450dc..e398e70f1d7b7 100644 --- a/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/alerts/handlers/lib/index.ts @@ -6,7 +6,7 @@ import { SearchResponse } from 'elasticsearch'; import { IScopedClusterClient } from 'kibana/server'; import { AlertEvent } from '../../../../../common/endpoint/types'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; import { esQuery } from '../../../../../../../../src/plugins/data/server'; import { AlertAPIOrdering, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts index 440b578bde413..debb455ac728f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/base.ts @@ -7,7 +7,7 @@ import { SearchResponse } from 'elasticsearch'; import { IScopedClusterClient } from 'kibana/server'; import { ResolverEvent } from '../../../../../common/endpoint/types'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; import { legacyEventIndexPattern } from './legacy_event_index_pattern'; import { MSearchQuery } from './multi_searcher'; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts index e4b2559a1780c..f357ac1a43d72 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/children.ts @@ -7,7 +7,7 @@ import { SearchResponse } from 'elasticsearch'; import { ResolverEvent } from '../../../../../common/endpoint/types'; import { ResolverQuery } from './base'; import { PaginationBuilder, PaginatedResults } from '../utils/pagination'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; /** * Builds a query for retrieving descendants of a node. diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts index e14b222500d7c..04202cfd007f9 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts @@ -7,7 +7,7 @@ import { SearchResponse } from 'elasticsearch'; import { ResolverEvent } from '../../../../../common/endpoint/types'; import { ResolverQuery } from './base'; import { PaginationBuilder, PaginatedResults } from '../utils/pagination'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; /** * Builds a query for retrieving related events for a node. diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/lifecycle.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/lifecycle.ts index 74fe44f39615c..93910293b00af 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/lifecycle.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/lifecycle.ts @@ -5,7 +5,7 @@ */ import { SearchResponse } from 'elasticsearch'; import { ResolverQuery } from './base'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; import { ResolverEvent } from '../../../../../common/endpoint/types'; /** diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts index 7f55fafeafb59..4c0e1a5126e7c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/multi_searcher.ts @@ -7,7 +7,7 @@ import { IScopedClusterClient } from 'kibana/server'; import { MSearchResponse } from 'elasticsearch'; import { ResolverEvent } from '../../../../../common/endpoint/types'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; /** * Contract for queries to be compatible with ES multi search api diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/stats.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/stats.ts index 359445f514b77..a728054bef219 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/stats.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/stats.ts @@ -6,7 +6,7 @@ import { SearchResponse } from 'elasticsearch'; import { ResolverQuery } from './base'; import { ResolverEvent, EventStats } from '../../../../../common/endpoint/types'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; import { AggBucket } from '../utils/pagination'; export interface StatsResult { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts index 9a852d47e0e85..61cb5bdb8f146 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts @@ -6,7 +6,7 @@ import { ResolverEvent } from '../../../../../common/endpoint/types'; import { eventId } from '../../../../../common/endpoint/models/event'; -import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../../../../src/plugins/kibana_utils/common'; /** * Represents a single result bucket of an aggregation diff --git a/x-pack/plugins/security_solution/server/lib/types.ts b/x-pack/plugins/security_solution/server/lib/types.ts index 2a897806dc628..ff89512124b66 100644 --- a/x-pack/plugins/security_solution/server/lib/types.ts +++ b/x-pack/plugins/security_solution/server/lib/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AuthenticatedUser } from '../../../security/public'; +import { AuthenticatedUser } from '../../../security/common/model'; import { RequestHandlerContext } from '../../../../../src/core/server'; export { ConfigType as Configuration } from '../config'; diff --git a/x-pack/plugins/security_solution/server/utils/serialized_query.ts b/x-pack/plugins/security_solution/server/utils/serialized_query.ts index 09b227d8c5a32..357aec1db480b 100644 --- a/x-pack/plugins/security_solution/server/utils/serialized_query.ts +++ b/x-pack/plugins/security_solution/server/utils/serialized_query.ts @@ -7,7 +7,7 @@ import { UserInputError } from 'apollo-server-errors'; import { isEmpty, isPlainObject, isString } from 'lodash/fp'; -import { JsonObject } from '../../../../../src/plugins/kibana_utils/public'; +import { JsonObject } from '../../../../../src/plugins/kibana_utils/common'; export const parseFilterQuery = (filterQuery: string): JsonObject => { try { diff --git a/x-pack/plugins/snapshot_restore/public/shared_imports.ts b/x-pack/plugins/snapshot_restore/public/shared_imports.ts index e0024ea8e0c12..cad8ce147bd25 100644 --- a/x-pack/plugins/snapshot_restore/public/shared_imports.ts +++ b/x-pack/plugins/snapshot_restore/public/shared_imports.ts @@ -5,17 +5,17 @@ */ export { - SendRequestConfig, - SendRequestResponse, - UseRequestConfig, - sendRequest, - useRequest, + AuthorizationProvider, CronEditor, DAY, - SectionError, Error, - WithPrivileges, - useAuthorizationContext, NotAuthorizedSection, - AuthorizationProvider, + SectionError, + sendRequest, + SendRequestConfig, + SendRequestResponse, + useAuthorizationContext, + useRequest, + UseRequestConfig, + WithPrivileges, } from '../../../../src/plugins/es_ui_shared/public'; diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/app.ts b/x-pack/plugins/snapshot_restore/server/routes/api/app.ts index f9714bcc02e47..e978fae0af5bc 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/app.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/app.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 { Privileges } from '../../../../../../src/plugins/es_ui_shared/public'; +import { Privileges } from '../../../../../../src/plugins/es_ui_shared/common'; import { APP_REQUIRED_CLUSTER_PRIVILEGES, diff --git a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.test.ts b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.test.ts index e82ebd9a5a4ad..0d6e9743f0f4b 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.test.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/custom_time_range_action.test.ts @@ -13,9 +13,7 @@ import { mount } from 'enzyme'; import { TimeRangeEmbeddable, TimeRangeContainer, TIME_RANGE_EMBEDDABLE } from './test_helpers'; import { CustomTimeRangeAction } from './custom_time_range_action'; /* eslint-disable */ -import { - HelloWorldContainer, -} from '../../../../src/plugins/embeddable/public/lib/test_samples'; +import { HelloWorldContainer } from '../../../../src/plugins/embeddable/public/lib/test_samples'; /* eslint-enable */ import { From 497ecf8164215493e59e3df5557605aa14b6d5be Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 10 Jun 2020 18:28:00 +0200 Subject: [PATCH 37/53] [Lens] Add description property and check duplicate title on save (#68219) --- .../helpers/check_for_duplicate_title.ts | 7 ++- .../display_duplicate_title_confirm_modal.ts | 2 +- .../vis_types/vis_type_alias_registry.ts | 1 + .../lens/public/app_plugin/app.test.tsx | 58 ++++++++++++++++++- x-pack/plugins/lens/public/app_plugin/app.tsx | 26 ++++++++- .../editor_frame_service/editor_frame/save.ts | 1 + .../editor_frame/state_management.test.ts | 2 + .../editor_frame/state_management.ts | 2 + .../persistence/saved_object_store.test.ts | 3 + .../public/persistence/saved_object_store.ts | 1 + x-pack/plugins/lens/public/vis_type_alias.ts | 3 +- x-pack/plugins/lens/server/saved_objects.ts | 3 + 12 files changed, 102 insertions(+), 7 deletions(-) diff --git a/src/plugins/saved_objects/public/saved_object/helpers/check_for_duplicate_title.ts b/src/plugins/saved_objects/public/saved_object/helpers/check_for_duplicate_title.ts index 8895336aa9ffa..0313b7978c5ab 100644 --- a/src/plugins/saved_objects/public/saved_object/helpers/check_for_duplicate_title.ts +++ b/src/plugins/saved_objects/public/saved_object/helpers/check_for_duplicate_title.ts @@ -31,10 +31,13 @@ import { displayDuplicateTitleConfirmModal } from './display_duplicate_title_con * @param services */ export async function checkForDuplicateTitle( - savedObject: SavedObject, + savedObject: Pick< + SavedObject, + 'id' | 'title' | 'getDisplayName' | 'lastSavedTitle' | 'copyOnSave' | 'getEsType' + >, isTitleDuplicateConfirmed: boolean, onTitleDuplicate: (() => void) | undefined, - services: SavedObjectKibanaServices + services: Pick ): Promise { const { savedObjectsClient, overlays } = services; // Don't check for duplicates if user has already confirmed save with duplicate title diff --git a/src/plugins/saved_objects/public/saved_object/helpers/display_duplicate_title_confirm_modal.ts b/src/plugins/saved_objects/public/saved_object/helpers/display_duplicate_title_confirm_modal.ts index 0b02977830fda..1b9e6fb6e996f 100644 --- a/src/plugins/saved_objects/public/saved_object/helpers/display_duplicate_title_confirm_modal.ts +++ b/src/plugins/saved_objects/public/saved_object/helpers/display_duplicate_title_confirm_modal.ts @@ -23,7 +23,7 @@ import { confirmModalPromise } from './confirm_modal_promise'; import { SavedObject } from '../../types'; export function displayDuplicateTitleConfirmModal( - savedObject: SavedObject, + savedObject: Pick, overlays: OverlayStart ): Promise { const confirmMessage = i18n.translate( diff --git a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index 6f18cbc5026ec..73e3360004e5a 100644 --- a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -25,6 +25,7 @@ export interface VisualizationListItem { stage: 'experimental' | 'beta' | 'production'; savedObjectType: string; title: string; + description?: string; typeTitle: string; } diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index 811f42590f07b..53498a8e5afa1 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -5,6 +5,7 @@ */ import React from 'react'; +import { Observable } from 'rxjs'; import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { App } from './app'; @@ -13,8 +14,11 @@ import { AppMountParameters } from 'kibana/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { Document, SavedObjectStore } from '../persistence'; import { mount } from 'enzyme'; +import { + SavedObjectSaveModal, + checkForDuplicateTitle, +} from '../../../../../src/plugins/saved_objects/public'; import { createMemoryHistory, History } from 'history'; -import { SavedObjectSaveModal } from '../../../../../src/plugins/saved_objects/public'; import { esFilters, FilterManager, @@ -28,10 +32,20 @@ const dataStartMock = dataPluginMock.createStartContract(); import { navigationPluginMock } from '../../../../../src/plugins/navigation/public/mocks'; import { TopNavMenuData } from '../../../../../src/plugins/navigation/public'; import { coreMock } from 'src/core/public/mocks'; -import { Observable } from 'rxjs'; jest.mock('../persistence'); jest.mock('src/core/public'); +jest.mock('../../../../../src/plugins/saved_objects/public', () => { + // eslint-disable-next-line no-shadow + const { SavedObjectSaveModal, SavedObjectSaveModalOrigin } = jest.requireActual( + '../../../../../src/plugins/saved_objects/public' + ); + return { + SavedObjectSaveModal, + SavedObjectSaveModalOrigin, + checkForDuplicateTitle: jest.fn(), + }; +}); const navigationStartMock = navigationPluginMock.createStartContract(); @@ -644,6 +658,46 @@ describe('Lens App', () => { }); }); + it('checks for duplicate title before saving', async () => { + const args = defaultArgs; + args.editorFrame = frame; + (args.docStorage.save as jest.Mock).mockReturnValue(Promise.resolve({ id: '123' })); + + instance = mount(); + + const onChange = frame.mount.mock.calls[0][1].onChange; + await act(async () => + onChange({ + filterableIndexPatterns: [], + doc: ({ id: '123', expression: 'valid expression' } as unknown) as Document, + }) + ); + instance.update(); + await act(async () => { + getButton(instance).run(instance.getDOMNode()); + }); + instance.update(); + + const onTitleDuplicate = jest.fn(); + + await act(async () => { + instance.find(SavedObjectSaveModal).prop('onSave')({ + onTitleDuplicate, + isTitleDuplicateConfirmed: false, + newCopyOnSave: false, + newDescription: '', + newTitle: 'test', + }); + }); + + expect(checkForDuplicateTitle).toHaveBeenCalledWith( + expect.objectContaining({ id: '123' }), + false, + onTitleDuplicate, + expect.anything() + ); + }); + it('does not show the copy button on first save', async () => { const args = defaultArgs; args.editorFrame = frame; diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index f88c1c5aca31d..fc8d5dd9eb395 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -24,6 +24,7 @@ import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/p import { SavedObjectSaveModalOrigin, OnSaveProps, + checkForDuplicateTitle, } from '../../../../../src/plugins/saved_objects/public'; import { Document, SavedObjectStore } from '../persistence'; import { EditorFrameInstance } from '../types'; @@ -252,9 +253,11 @@ export function App({ // state.persistedDoc, ]); - const runSave = ( + const runSave = async ( saveProps: Omit & { returnToOrigin: boolean; + onTitleDuplicate?: OnSaveProps['onTitleDuplicate']; + newDescription?: string; } ) => { if (!lastKnownDoc) { @@ -276,10 +279,30 @@ export function App({ const doc = { ...lastDocWithoutPinned, + description: saveProps.newDescription, id: saveProps.newCopyOnSave ? undefined : lastKnownDoc.id, title: saveProps.newTitle, }; + await checkForDuplicateTitle( + { + ...doc, + copyOnSave: saveProps.newCopyOnSave, + lastSavedTitle: lastKnownDoc?.title, + getEsType: () => 'lens', + getDisplayName: () => + i18n.translate('xpack.lens.app.saveModalType', { + defaultMessage: 'Lens visualization', + }), + }, + saveProps.isTitleDuplicateConfirmed, + saveProps.onTitleDuplicate, + { + savedObjectsClient: core.savedObjects.client, + overlays: core.overlays, + } + ); + const newlyCreated: boolean = saveProps.newCopyOnSave || !lastKnownDoc?.id; docStorage .save(doc) @@ -492,6 +515,7 @@ export function App({ documentInfo={{ id: lastKnownDoc.id, title: lastKnownDoc.title || '', + description: lastKnownDoc.description || '', }} objectType={i18n.translate('xpack.lens.app.saveModalType', { defaultMessage: 'Lens visualization', diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts index b292299c569af..d62f3dbcf029a 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts @@ -48,6 +48,7 @@ export function getSavedObjectFormat({ return { id: state.persistedId, title: state.title, + description: state.description, type: 'lens', visualizationType: state.visualization.activeId, expression: expression ? toExpression(expression) : '', diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts index 71aabaae3c65c..e1151b92aac51 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts @@ -388,6 +388,7 @@ describe('editor_frame state management', () => { filters: [], }, title: 'heyo!', + description: 'My lens', type: 'lens', visualizationType: 'line', }, @@ -406,6 +407,7 @@ describe('editor_frame state management', () => { }, persistedId: 'b', title: 'heyo!', + description: 'My lens', visualization: { activeId: 'line', state: { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts index bb6daf5641a64..09674ebf2ade2 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts @@ -18,6 +18,7 @@ export interface PreviewState { export interface EditorFrameState extends PreviewState { persistedId?: string; title: string; + description?: string; stagedPreview?: PreviewState; activeDatasourceId: string | null; } @@ -157,6 +158,7 @@ export const reducer = (state: EditorFrameState, action: Action): EditorFrameSta ...state, persistedId: action.doc.id, title: action.doc.title, + description: action.doc.description, datasourceStates: Object.entries(action.doc.state.datasourceStates).reduce( (stateMap, [datasourceId, datasourceState]) => ({ ...stateMap, diff --git a/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts index 515d008d82586..f7caac6549389 100644 --- a/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts @@ -25,6 +25,7 @@ describe('LensStore', () => { const { client, store } = testStore('FOO'); const doc = await store.save({ title: 'Hello', + description: 'My doc', visualizationType: 'bar', expression: '', state: { @@ -43,6 +44,7 @@ describe('LensStore', () => { expect(doc).toEqual({ id: 'FOO', title: 'Hello', + description: 'My doc', visualizationType: 'bar', expression: '', state: { @@ -61,6 +63,7 @@ describe('LensStore', () => { expect(client.create).toHaveBeenCalledTimes(1); expect(client.create).toHaveBeenCalledWith('lens', { title: 'Hello', + description: 'My doc', visualizationType: 'bar', expression: '', state: { diff --git a/x-pack/plugins/lens/public/persistence/saved_object_store.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.ts index 015f4b9b825f4..7632be3d82046 100644 --- a/x-pack/plugins/lens/public/persistence/saved_object_store.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.ts @@ -13,6 +13,7 @@ export interface Document { type?: string; visualizationType: string | null; title: string; + description?: string; expression: string | null; state: { datasourceMetaData: { diff --git a/x-pack/plugins/lens/public/vis_type_alias.ts b/x-pack/plugins/lens/public/vis_type_alias.ts index a58288191325c..3bb2dbbae1f9c 100644 --- a/x-pack/plugins/lens/public/vis_type_alias.ts +++ b/x-pack/plugins/lens/public/vis_type_alias.ts @@ -34,10 +34,11 @@ export const getLensAliasConfig = (): VisTypeAlias => ({ searchFields: ['title^3'], toListItem(savedObject) { const { id, type, attributes } = savedObject; - const { title } = attributes as { title: string }; + const { title, description } = attributes as { title: string; description?: string }; return { id, title, + description, editUrl: getEditPath(id), editApp: 'lens', icon: 'lensApp', diff --git a/x-pack/plugins/lens/server/saved_objects.ts b/x-pack/plugins/lens/server/saved_objects.ts index 1f7d22e2b5642..a16cc3dab7967 100644 --- a/x-pack/plugins/lens/server/saved_objects.ts +++ b/x-pack/plugins/lens/server/saved_objects.ts @@ -29,6 +29,9 @@ export function setupSavedObjects(core: CoreSetup) { title: { type: 'text', }, + description: { + type: 'text', + }, visualizationType: { type: 'keyword', }, From 8d1a3194721a66cc04732a08734dcc743acfd740 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 10 Jun 2020 18:29:22 +0200 Subject: [PATCH 38/53] keep custom labels (#68498) --- .../dimension_panel/dimension_panel.test.tsx | 101 +++++++++++++++++- .../dimension_panel/popover_editor.tsx | 26 +++-- .../operations/definitions/column_types.ts | 1 + .../state_helpers.test.ts | 55 ++++++++++ .../indexpattern_datasource/state_helpers.ts | 5 + 5 files changed, 177 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx index a9e9efa8d1039..4397ad65d63a5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx @@ -467,7 +467,7 @@ describe('IndexPatternDimensionEditorPanel', () => { expect(setState).not.toHaveBeenCalled(); }); - it('should update label on label input changes', () => { + it('should update label and custom label flag on label input changes', () => { wrapper = mount(); act(() => { @@ -485,6 +485,7 @@ describe('IndexPatternDimensionEditorPanel', () => { ...state.layers.first.columns, col1: expect.objectContaining({ label: 'New Label', + customLabel: true, // Other parts of this don't matter for this test }), }, @@ -493,6 +494,104 @@ describe('IndexPatternDimensionEditorPanel', () => { }); }); + it('should not keep the label as long as it is the default label', () => { + wrapper = mount( + + ); + + act(() => { + wrapper.find('button[data-test-subj="lns-indexPatternDimension-min"]').simulate('click'); + }); + + expect(setState).toHaveBeenCalledWith({ + ...state, + layers: { + first: { + ...state.layers.first, + columns: { + ...state.layers.first.columns, + col1: expect.objectContaining({ + label: 'Minimum of bytes', + }), + }, + }, + }, + }); + }); + + it('should keep the label on operation change if it is custom', () => { + wrapper = mount( + + ); + + act(() => { + wrapper.find('button[data-test-subj="lns-indexPatternDimension-min"]').simulate('click'); + }); + + expect(setState).toHaveBeenCalledWith({ + ...state, + layers: { + first: { + ...state.layers.first, + columns: { + ...state.layers.first.columns, + col1: expect.objectContaining({ + label: 'Custom label', + customLabel: true, + }), + }, + }, + }, + }); + }); + describe('transient invalid state', () => { it('should not set the state if selecting an operation incompatible with the current field', () => { wrapper = mount(); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx index 6bd4263014b13..7bed770e63fd2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx @@ -314,17 +314,23 @@ export function PopoverEditor(props: PopoverEditorProps) { data-test-subj="indexPattern-label-edit" value={selectedColumn.label} onChange={(e) => { - setState( - changeColumn({ - state, - layerId, - columnId, - newColumn: { - ...selectedColumn, - label: e.target.value, + setState({ + ...state, + layers: { + ...state.layers, + [layerId]: { + ...state.layers[layerId], + columns: { + ...state.layers[layerId].columns, + [columnId]: { + ...selectedColumn, + label: e.target.value, + customLabel: true, + }, + }, }, - }) - ); + }, + }); }} /> diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts index 639e982142f57..3244eeb94d1e2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts @@ -16,6 +16,7 @@ export interface BaseIndexPatternColumn extends Operation { operationType: string; sourceField: string; suggestedPriority?: DimensionPriority; + customLabel?: boolean; } // Formatting can optionally be added to any column diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts index 1e3251a8dedd8..074cb8f5bde17 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts @@ -331,6 +331,61 @@ describe('state_helpers', () => { ); }); + it('should carry over label if customLabel flag is set', () => { + const state: IndexPatternPrivateState = { + indexPatternRefs: [], + existingFields: {}, + indexPatterns: {}, + currentIndexPatternId: '1', + showEmptyFields: false, + layers: { + first: { + indexPatternId: '1', + columnOrder: ['col1'], + columns: { + col1: { + label: 'My custom label', + customLabel: true, + dataType: 'date', + isBucketed: true, + + // Private + operationType: 'date_histogram', + sourceField: 'timestamp', + params: { + interval: 'h', + }, + }, + }, + }, + }, + }; + expect( + changeColumn({ + state, + layerId: 'first', + columnId: 'col2', + newColumn: { + label: 'Date histogram of order_date', + dataType: 'date', + isBucketed: true, + + // Private + operationType: 'date_histogram', + sourceField: 'order_date', + params: { + interval: 'w', + }, + }, + }).layers.first.columns.col1 + ).toEqual( + expect.objectContaining({ + label: 'My custom label', + customLabel: true, + }) + ); + }); + it('should execute adjustments for other columns', () => { const termsColumn: TermsIndexPatternColumn = { label: 'Top values of source', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts index a34d0c4187485..3a1aaaa819dc0 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts @@ -87,6 +87,11 @@ export function changeColumn({ ? { ...newColumn, params: oldColumn.params } : newColumn; + if (oldColumn && oldColumn.customLabel) { + updatedColumn.customLabel = true; + updatedColumn.label = oldColumn.label; + } + const newColumns = adjustColumnReferencesForChangedColumn( { ...state.layers[layerId].columns, From 713f323447218269b6757d3468bb3dd97f8ef0d5 Mon Sep 17 00:00:00 2001 From: Clint Andrew Hall Date: Wed, 10 Jun 2020 11:30:36 -0500 Subject: [PATCH 39/53] [Canvas] Fixes for expected prop-types, Shape Arg UI, and i18n strings (#68304) Co-authored-by: Elastic Machine --- .../canvas_plugin_src/uis/arguments/toggle.js | 8 +++++-- .../canvas_plugin_src/uis/views/markdown.js | 2 +- .../canvas/canvas_plugin_src/uis/views/pie.js | 3 +++ .../canvas_plugin_src/uis/views/shape.js | 3 +++ .../canvas_plugin_src/uis/views/table.js | 6 +++++ x-pack/plugins/canvas/i18n/ui.ts | 22 ++++++++++++++++--- .../saved_elements_modal.tsx | 4 ++-- .../__examples__/edit_menu.examples.tsx | 14 ++++++++---- .../workpad_header/edit_menu/edit_menu.tsx | 5 +++-- .../workpad_header/edit_menu/index.ts | 12 ++++++++-- ...{clone_subgraphs.js => clone_subgraphs.ts} | 9 +++++--- .../public/lib/element_handler_creators.ts | 2 +- 12 files changed, 70 insertions(+), 20 deletions(-) rename x-pack/plugins/canvas/public/lib/{clone_subgraphs.js => clone_subgraphs.ts} (83%) diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js index 299f96ff1b4e8..b3e735d202220 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js @@ -41,8 +41,12 @@ ToggleArgInput.propTypes = { onValueChange: PropTypes.func.isRequired, argValue: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.object]).isRequired, argId: PropTypes.string.isRequired, - labelValue: PropTypes.string, - showLabelValue: PropTypes.bool, + typeInstance: PropTypes.shape({ + displayName: PropTypes.string.isRequired, + options: PropTypes.shape({ + labelValue: PropTypes.string.isRequired, + }), + }).isRequired, renderError: PropTypes.func.isRequired, }; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/markdown.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/markdown.js index edae739ee0d3d..bebcc290a313d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/markdown.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/markdown.js @@ -37,7 +37,7 @@ export const markdown = () => ({ argType: 'toggle', default: false, options: { - labelValue: 'Open all links in a new tab', + labelValue: strings.getOpenLinksInNewTabLabelName(), }, }, ], diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/pie.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/pie.js index f1b6a48d1e7b0..6a32da2c3c0e9 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/pie.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/pie.js @@ -75,6 +75,9 @@ export const pie = () => ({ help: strings.getLabelsHelp(), argType: 'toggle', default: true, + options: { + labelValue: strings.getLabelsToggleSwitch(), + }, }, { name: 'seriesStyle', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/shape.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/shape.js index c3e97b4bd5dea..5eb8b1deb219b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/shape.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/shape.js @@ -46,6 +46,9 @@ export const shape = () => ({ displayName: strings.getMaintainAspectDisplayName(), argType: 'toggle', help: strings.getMaintainAspectHelp(), + options: { + labelValue: strings.getMaintainAspectLabelName(), + }, }, ], }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/table.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/table.js index 73324feddcab0..126559269f95a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/table.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/table.js @@ -33,6 +33,9 @@ export const table = () => ({ help: strings.getPaginateHelp(), argType: 'toggle', default: true, + options: { + labelValue: strings.getPaginateToggleSwitch(), + }, }, { name: 'showHeader', @@ -40,6 +43,9 @@ export const table = () => ({ help: strings.getShowHeaderHelp(), argType: 'toggle', default: true, + options: { + labelValue: strings.getShowHeaderToggleSwitch(), + }, }, ], }); diff --git a/x-pack/plugins/canvas/i18n/ui.ts b/x-pack/plugins/canvas/i18n/ui.ts index 1abe56c99dc89..f69f9e747ab90 100644 --- a/x-pack/plugins/canvas/i18n/ui.ts +++ b/x-pack/plugins/canvas/i18n/ui.ts @@ -791,8 +791,12 @@ export const ViewStrings = { i18n.translate('xpack.canvas.uis.views.pie.args.labelsTitle', { defaultMessage: 'Labels', }), - getLabelsHelp: () => + getLabelsToggleSwitch: () => i18n.translate('xpack.canvas.uis.views.pie.args.labelsToggleSwitch', { + defaultMessage: 'Show labels', + }), + getLabelsHelp: () => + i18n.translate('xpack.canvas.uis.views.pie.args.labelsLabel', { defaultMessage: 'Show/hide labels', }), getLegendDisplayName: () => @@ -1075,10 +1079,14 @@ export const ViewStrings = { }), getMaintainAspectDisplayName: () => i18n.translate('xpack.canvas.uis.views.shape.args.maintainAspectTitle', { - defaultMessage: 'Fixed ratio', + defaultMessage: 'Aspect ratio settings', }), - getMaintainAspectHelp: () => + getMaintainAspectLabelName: () => i18n.translate('xpack.canvas.uis.views.shape.args.maintainAspectLabel', { + defaultMessage: 'Use a fixed ratio', + }), + getMaintainAspectHelp: () => + i18n.translate('xpack.canvas.uis.views.shape.args.maintainAspectHelpLabel', { defaultMessage: `Enable to maintain aspect ratio`, }), getShapeDisplayName: () => @@ -1099,6 +1107,10 @@ export const ViewStrings = { i18n.translate('xpack.canvas.uis.views.table.args.paginateTitle', { defaultMessage: 'Pagination', }), + getPaginateToggleSwitch: () => + i18n.translate('xpack.canvas.uis.views.table.args.paginateToggleSwitch', { + defaultMessage: 'Show pagination controls', + }), getPaginateHelp: () => i18n.translate('xpack.canvas.uis.views.table.args.paginateLabel', { defaultMessage: @@ -1116,6 +1128,10 @@ export const ViewStrings = { i18n.translate('xpack.canvas.uis.views.table.args.showHeaderTitle', { defaultMessage: 'Header', }), + getShowHeaderToggleSwitch: () => + i18n.translate('xpack.canvas.uis.views.table.args.showHeaderToggleSwitch', { + defaultMessage: 'Show the header row', + }), getShowHeaderHelp: () => i18n.translate('xpack.canvas.uis.views.table.args.showHeaderLabel', { defaultMessage: 'Show or hide the header row with titles for each column', diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx index dba97a15fee5c..474b8f3494917 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx @@ -84,7 +84,7 @@ export const SavedElementsModal: FunctionComponent = ({ const handleEdit = async (name: string, description: string, image: string) => { if (elementToEdit) { - await updateCustomElement(elementToEdit.id, name, description, image); + updateCustomElement(elementToEdit.id, name, description, image); } hideEditModal(); }; @@ -94,7 +94,7 @@ export const SavedElementsModal: FunctionComponent = ({ const handleDelete = async () => { if (elementToDelete) { - await removeCustomElement(elementToDelete.id); + removeCustomElement(elementToDelete.id); } hideDeleteModal(); }; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx index a0ab8d53485f5..8bbc3e09af4bf 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx @@ -7,6 +7,7 @@ import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import React from 'react'; import { EditMenu } from '../edit_menu'; +import { PositionedElement } from '../../../../../types'; const handlers = { cutNodes: action('cutNodes'), @@ -41,11 +42,16 @@ storiesOf('components/WorkpadHeader/EditMenu', module) )) .add('single element selected', () => ( - + )) .add('single grouped element selected', () => ( ( ( { const pageId = getSelectedPage(state); const nodes = getNodes(state, pageId) as PositionedElement[]; const selectedToplevelNodes = getSelectedToplevelNodes(state); + const selectedPrimaryShapeObjects = selectedToplevelNodes .map((id: string) => nodes.find((s: PositionedElement) => s.id === id)) .filter((shape?: PositionedElement) => shape) as PositionedElement[]; + const selectedPersistentPrimaryNodes = flatten( selectedPrimaryShapeObjects.map((shape: PositionedElement) => nodes.find((n: PositionedElement) => n.id === shape.id) // is it a leaf or a persisted group? @@ -70,12 +72,18 @@ const mapStateToProps = (state: State) => { : nodes.filter((s: PositionedElement) => s.position.parent === shape.id).map((s) => s.id) ) ); - const selectedNodeIds = flatten(selectedPersistentPrimaryNodes.map(crawlTree(nodes))); + + const selectedNodeIds: string[] = flatten(selectedPersistentPrimaryNodes.map(crawlTree(nodes))); + const selectedNodes = selectedNodeIds + .map((id: string) => nodes.find((s) => s.id === id)) + .filter((node: PositionedElement | undefined): node is PositionedElement => { + return !!node; + }); return { pageId, selectedToplevelNodes, - selectedNodes: selectedNodeIds.map((id: string) => nodes.find((s) => s.id === id)), + selectedNodes, state, }; }; diff --git a/x-pack/plugins/canvas/public/lib/clone_subgraphs.js b/x-pack/plugins/canvas/public/lib/clone_subgraphs.ts similarity index 83% rename from x-pack/plugins/canvas/public/lib/clone_subgraphs.js rename to x-pack/plugins/canvas/public/lib/clone_subgraphs.ts index e4dfa1cefcaba..c3a3933e06a6d 100644 --- a/x-pack/plugins/canvas/public/lib/clone_subgraphs.js +++ b/x-pack/plugins/canvas/public/lib/clone_subgraphs.ts @@ -4,16 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ +// @ts-ignore Untyped local import { arrayToMap } from './aeroelastic/functional'; import { getId } from './get_id'; +import { PositionedElement } from '../../types'; -export const cloneSubgraphs = (nodes) => { +export const cloneSubgraphs = (nodes: PositionedElement[]) => { const idMap = arrayToMap(nodes.map((n) => n.id)); + // We simultaneously provide unique id values for all elements (across all pages) // AND ensure that parent-child relationships are retained (via matching id values within page) Object.keys(idMap).forEach((key) => (idMap[key] = getId(key.split('-')[0]))); // new group names to which we can map + // must return elements in the same order, for several reasons - const newNodes = nodes.map((element) => ({ + return nodes.map((element) => ({ ...element, id: idMap[element.id], position: { @@ -21,5 +25,4 @@ export const cloneSubgraphs = (nodes) => { parent: element.position.parent ? idMap[element.position.parent] : null, }, })); - return newNodes; }; diff --git a/x-pack/plugins/canvas/public/lib/element_handler_creators.ts b/x-pack/plugins/canvas/public/lib/element_handler_creators.ts index d280c62888df0..a2bf5a62ec1f7 100644 --- a/x-pack/plugins/canvas/public/lib/element_handler_creators.ts +++ b/x-pack/plugins/canvas/public/lib/element_handler_creators.ts @@ -37,7 +37,7 @@ export interface Props { /** * selects elements on the page */ - selectToplevelNodes: (elements: PositionedElement) => void; + selectToplevelNodes: (elements: PositionedElement[]) => void; /** * deletes elements from the page */ From e616935d0bc79bf5fb323404399a274195602c23 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Wed, 10 Jun 2020 09:55:42 -0700 Subject: [PATCH 40/53] Using re2 for Timelion regular expressions (#67416) * Revert "Revert "Using re2 for Timelion regular expressions (#55208)"" This reverts commit c90293d03f3b8beabb2ae523e861dde67b00016c. * Updating re2 to 1.14.0. Still need to update build patching * Extract the gzip to the destination, supporting multiple extract methods * Adding 'node' to jest's moduleFileExtensions 'node' is in the defaults, not sure why we aren't using the defaults... https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring Co-authored-by: Elastic Machine --- .gitignore | 1 + package.json | 1 + src/dev/build/build_distributables.js | 2 + .../nodejs => lib}/__tests__/download.js | 0 .../build/lib/__tests__/fixtures/foo.txt.gz | Bin 0 -> 32 bytes src/dev/build/lib/__tests__/fs.js | 38 ++++++- .../build/{tasks/nodejs => lib}/download.js | 2 +- src/dev/build/lib/fs.js | 13 +++ src/dev/build/lib/index.js | 2 + src/dev/build/tasks/index.js | 1 + .../__tests__/download_node_builds_task.js | 2 +- .../tasks/nodejs/download_node_builds_task.js | 2 +- .../build/tasks/patch_native_modules_task.js | 103 ++++++++++++++++++ src/dev/jest/config.js | 2 +- .../server/series_functions/label.js | 5 +- x-pack/dev-tools/jest/create_jest_config.js | 2 +- x-pack/test_utils/jest/config.js | 2 +- yarn.lock | 47 +++++++- 18 files changed, 215 insertions(+), 10 deletions(-) rename src/dev/build/{tasks/nodejs => lib}/__tests__/download.js (100%) create mode 100644 src/dev/build/lib/__tests__/fixtures/foo.txt.gz rename src/dev/build/{tasks/nodejs => lib}/download.js (98%) create mode 100644 src/dev/build/tasks/patch_native_modules_task.js diff --git a/.gitignore b/.gitignore index b3911d0f8d0c2..b8adcf4508db2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /.es .DS_Store .node_binaries +.native_modules node_modules !/src/dev/npm/integration_tests/__fixtures__/fixture1/node_modules !/src/dev/notice/__fixtures__/node_modules diff --git a/package.json b/package.json index 419edcf268356..0bf173d9603e7 100644 --- a/package.json +++ b/package.json @@ -236,6 +236,7 @@ "pug": "^2.0.4", "query-string": "5.1.1", "raw-loader": "3.1.0", + "re2": "1.14.0", "react": "^16.12.0", "react-color": "^2.13.8", "react-dom": "^16.12.0", diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js index 66f0c0355c2d9..2ea71fa2c1d33 100644 --- a/src/dev/build/build_distributables.js +++ b/src/dev/build/build_distributables.js @@ -47,6 +47,7 @@ import { InstallDependenciesTask, BuildKibanaPlatformPluginsTask, OptimizeBuildTask, + PatchNativeModulesTask, RemovePackageJsonDepsTask, RemoveWorkspacesTask, TranspileBabelTask, @@ -136,6 +137,7 @@ export async function buildDistributables(options) { * directories and perform platform-specific steps */ await run(CreateArchivesSourcesTask); + await run(PatchNativeModulesTask); await run(CleanExtraBinScriptsTask); await run(CleanExtraBrowsersTask); await run(CleanNodeBuildsTask); diff --git a/src/dev/build/tasks/nodejs/__tests__/download.js b/src/dev/build/lib/__tests__/download.js similarity index 100% rename from src/dev/build/tasks/nodejs/__tests__/download.js rename to src/dev/build/lib/__tests__/download.js diff --git a/src/dev/build/lib/__tests__/fixtures/foo.txt.gz b/src/dev/build/lib/__tests__/fixtures/foo.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..46fef5a6af78cbc805d40977495a9abf2f6b9653 GIT binary patch literal 32 ncmb2|=HTdWI2*^noR*)jS5i^J;C=f1b0&rrsYZ1y3=9kawLS`2 literal 0 HcmV?d00001 diff --git a/src/dev/build/lib/__tests__/fs.js b/src/dev/build/lib/__tests__/fs.js index 0b2db4c538fb8..bf7596b012f79 100644 --- a/src/dev/build/lib/__tests__/fs.js +++ b/src/dev/build/lib/__tests__/fs.js @@ -23,11 +23,12 @@ import { chmodSync, statSync } from 'fs'; import del from 'del'; import expect from '@kbn/expect'; -import { mkdirp, write, read, getChildPaths, copyAll, getFileHash, untar } from '../fs'; +import { mkdirp, write, read, getChildPaths, copyAll, getFileHash, untar, gunzip } from '../fs'; const TMP = resolve(__dirname, '__tmp__'); const FIXTURES = resolve(__dirname, 'fixtures'); const FOO_TAR_PATH = resolve(FIXTURES, 'foo_dir.tar.gz'); +const FOO_GZIP_PATH = resolve(FIXTURES, 'foo.txt.gz'); const BAR_TXT_PATH = resolve(FIXTURES, 'foo_dir/bar.txt'); const WORLD_EXECUTABLE = resolve(FIXTURES, 'bin/world_executable'); @@ -323,4 +324,39 @@ describe('dev/build/lib/fs', () => { expect(await read(resolve(destination, 'foo/foo.txt'))).to.be('foo\n'); }); }); + + describe('gunzip()', () => { + it('rejects if source path is not absolute', async () => { + try { + await gunzip('foo/bar', '**/*', __dirname); + throw new Error('Expected gunzip() to reject'); + } catch (error) { + assertNonAbsoluteError(error); + } + }); + + it('rejects if destination path is not absolute', async () => { + try { + await gunzip(__dirname, '**/*', 'foo/bar'); + throw new Error('Expected gunzip() to reject'); + } catch (error) { + assertNonAbsoluteError(error); + } + }); + + it('rejects if neither path is not absolute', async () => { + try { + await gunzip('foo/bar', '**/*', 'foo/bar'); + throw new Error('Expected gunzip() to reject'); + } catch (error) { + assertNonAbsoluteError(error); + } + }); + + it('extracts gzip from source into destination, creating destination if necessary', async () => { + const destination = resolve(TMP, 'z/y/x/v/u/t/foo.txt'); + await gunzip(FOO_GZIP_PATH, destination); + expect(await read(resolve(destination))).to.be('foo\n'); + }); + }); }); diff --git a/src/dev/build/tasks/nodejs/download.js b/src/dev/build/lib/download.js similarity index 98% rename from src/dev/build/tasks/nodejs/download.js rename to src/dev/build/lib/download.js index fb3294e2d1221..fbd2d47ff7b06 100644 --- a/src/dev/build/tasks/nodejs/download.js +++ b/src/dev/build/lib/download.js @@ -24,7 +24,7 @@ import chalk from 'chalk'; import { createHash } from 'crypto'; import Axios from 'axios'; -import { mkdirp } from '../../lib'; +import { mkdirp } from './fs'; function tryUnlink(path) { try { diff --git a/src/dev/build/lib/fs.js b/src/dev/build/lib/fs.js index 864a07e837c3f..b905f40d0de1e 100644 --- a/src/dev/build/lib/fs.js +++ b/src/dev/build/lib/fs.js @@ -195,6 +195,19 @@ export async function untar(source, destination, extractOptions = {}) { ]); } +export async function gunzip(source, destination) { + assertAbsolute(source); + assertAbsolute(destination); + + await mkdirAsync(dirname(destination), { recursive: true }); + + await createPromiseFromStreams([ + fs.createReadStream(source), + createGunzip(), + fs.createWriteStream(destination), + ]); +} + export async function compress(type, options = {}, source, destination) { const output = fs.createWriteStream(destination); const archive = archiver(type, options.archiverOptions); diff --git a/src/dev/build/lib/index.js b/src/dev/build/lib/index.js index afebd090d797d..6540db6f37a72 100644 --- a/src/dev/build/lib/index.js +++ b/src/dev/build/lib/index.js @@ -28,10 +28,12 @@ export { copyAll, getFileHash, untar, + gunzip, deleteAll, deleteEmptyFolders, compress, isFileAccessible, } from './fs'; +export { download } from './download'; export { scanDelete } from './scan_delete'; export { scanCopy } from './scan_copy'; diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js index bafb5a2fe115e..be675b4aa6ca4 100644 --- a/src/dev/build/tasks/index.js +++ b/src/dev/build/tasks/index.js @@ -33,6 +33,7 @@ export * from './nodejs_modules'; export * from './notice_file_task'; export * from './optimize_task'; export * from './os_packages'; +export * from './patch_native_modules_task'; export * from './transpile_babel_task'; export * from './transpile_scss_task'; export * from './verify_env_task'; diff --git a/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js b/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js index 9357735e3f5a3..c1764d06b43b3 100644 --- a/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js +++ b/src/dev/build/tasks/nodejs/__tests__/download_node_builds_task.js @@ -22,7 +22,7 @@ import expect from '@kbn/expect'; import * as NodeShasumsNS from '../node_shasums'; import * as NodeDownloadInfoNS from '../node_download_info'; -import * as DownloadNS from '../download'; +import * as DownloadNS from '../../../lib/download'; // sinon can't stub '../../../lib' properly import { DownloadNodeBuildsTask } from '../download_node_builds_task'; describe('src/dev/build/tasks/nodejs/download_node_builds_task', () => { diff --git a/src/dev/build/tasks/nodejs/download_node_builds_task.js b/src/dev/build/tasks/nodejs/download_node_builds_task.js index 86ddb0506f972..c0907e6c42a97 100644 --- a/src/dev/build/tasks/nodejs/download_node_builds_task.js +++ b/src/dev/build/tasks/nodejs/download_node_builds_task.js @@ -17,7 +17,7 @@ * under the License. */ -import { download } from './download'; +import { download } from '../../lib'; import { getNodeShasums } from './node_shasums'; import { getNodeDownloadInfo } from './node_download_info'; diff --git a/src/dev/build/tasks/patch_native_modules_task.js b/src/dev/build/tasks/patch_native_modules_task.js new file mode 100644 index 0000000000000..fba33442fad10 --- /dev/null +++ b/src/dev/build/tasks/patch_native_modules_task.js @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import fs from 'fs'; +import path from 'path'; +import util from 'util'; +import { deleteAll, download, gunzip, untar } from '../lib'; + +const DOWNLOAD_DIRECTORY = '.native_modules'; + +const packages = [ + { + name: 're2', + version: '1.14.0', + destinationPath: 'node_modules/re2/build/Release/re2.node', + extractMethod: 'gunzip', + archives: { + darwin: { + url: 'https://github.com/uhop/node-re2/releases/download/1.14.0/darwin-x64-64.gz', + sha256: '54c8386cb7cd53895cf379522114bfe82378e300e127e58d392ddd40a77e396f', + }, + linux: { + url: 'https://github.com/uhop/node-re2/releases/download/1.14.0/linux-x64-64.gz', + sha256: 'f54f059035e71a7ccb3fa201080e260c41d228d13a8247974b4bb157691b6757', + }, + windows: { + url: 'https://github.com/uhop/node-re2/releases/download/1.14.0/win32-x64-64.gz', + sha256: 'de708446a8b802f4634c2cfef097c2625a2811fdcd8133dfd7b7c485f966caa9', + }, + }, + }, +]; + +async function getInstalledVersion(config, packageName) { + const packageJSONPath = config.resolveFromRepo( + path.join('node_modules', packageName, 'package.json') + ); + const buffer = await util.promisify(fs.readFile)(packageJSONPath); + const packageJSON = JSON.parse(buffer); + return packageJSON.version; +} + +async function patchModule(config, log, build, platform, pkg) { + const installedVersion = await getInstalledVersion(config, pkg.name); + if (installedVersion !== pkg.version) { + throw new Error( + `Can't patch ${pkg.name}'s native module, we were expecting version ${pkg.version} and found ${installedVersion}` + ); + } + const platformName = platform.getName(); + const archive = pkg.archives[platformName]; + const archiveName = path.basename(archive.url); + const downloadPath = config.resolveFromRepo(DOWNLOAD_DIRECTORY, pkg.name, archiveName); + const extractPath = build.resolvePathForPlatform(platform, pkg.destinationPath); + log.debug(`Patching ${pkg.name} binaries from ${archive.url} to ${extractPath}`); + + await deleteAll([extractPath], log); + await download({ + log, + url: archive.url, + destination: downloadPath, + sha256: archive.sha256, + retries: 3, + }); + switch (pkg.extractMethod) { + case 'gunzip': + await gunzip(downloadPath, extractPath); + break; + case 'untar': + await untar(downloadPath, extractPath); + break; + default: + throw new Error(`Extract method of ${pkg.extractMethod} is not supported`); + } +} + +export const PatchNativeModulesTask = { + description: 'Patching platform-specific native modules', + async run(config, log, build) { + for (const pkg of packages) { + await Promise.all( + config.getTargetPlatforms().map(async (platform) => { + await patchModule(config, log, build, platform, pkg); + }) + ); + } + }, +}; diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index 64db131f5219a..04b07748c4052 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -79,7 +79,7 @@ export default { ], coverageDirectory: '/target/kibana-coverage/jest', coverageReporters: !!process.env.CODE_COVERAGE ? ['json'] : ['html', 'text'], - moduleFileExtensions: ['js', 'json', 'ts', 'tsx'], + moduleFileExtensions: ['js', 'json', 'ts', 'tsx', 'node'], modulePathIgnorePatterns: ['__fixtures__/', 'target/'], testMatch: ['**/*.test.{js,ts,tsx}'], testPathIgnorePatterns: [ diff --git a/src/plugins/vis_type_timelion/server/series_functions/label.js b/src/plugins/vis_type_timelion/server/series_functions/label.js index 4d9a26c46aaaf..b5282967a62e0 100644 --- a/src/plugins/vis_type_timelion/server/series_functions/label.js +++ b/src/plugins/vis_type_timelion/server/series_functions/label.js @@ -51,7 +51,10 @@ export default new Chainable('label', { const config = args.byName; return alter(args, function (eachSeries) { if (config.regex) { - eachSeries.label = eachSeries.label.replace(new RegExp(config.regex), config.label); + // not using a standard `import` so that if there's an issue with the re2 native module + // that it doesn't prevent Kibana from starting up and we only have an issue using Timelion labels + const RE2 = require('re2'); + eachSeries.label = eachSeries.label.replace(new RE2(config.regex), config.label); } else { eachSeries.label = config.label; } diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js index 74553bbde0cd6..4bf03828bb461 100644 --- a/x-pack/dev-tools/jest/create_jest_config.js +++ b/x-pack/dev-tools/jest/create_jest_config.js @@ -9,7 +9,7 @@ export function createJestConfig({ kibanaDirectory, rootDir, xPackKibanaDirector return { rootDir, roots: ['/plugins', '/legacy/plugins', '/legacy/server'], - moduleFileExtensions: ['js', 'json', 'ts', 'tsx'], + moduleFileExtensions: ['js', 'json', 'ts', 'tsx', 'node'], moduleNameMapper: { '@elastic/eui$': `${kibanaDirectory}/node_modules/@elastic/eui/test-env`, '@elastic/eui/lib/(.*)?': `${kibanaDirectory}/node_modules/@elastic/eui/test-env/$1`, diff --git a/x-pack/test_utils/jest/config.js b/x-pack/test_utils/jest/config.js index deee585b91fe4..f36099bd1f347 100644 --- a/x-pack/test_utils/jest/config.js +++ b/x-pack/test_utils/jest/config.js @@ -29,7 +29,7 @@ export default { ], coverageDirectory: '/../target/kibana-coverage/jest', coverageReporters: ['html'], - moduleFileExtensions: ['js', 'json', 'ts', 'tsx'], + moduleFileExtensions: ['js', 'json', 'ts', 'tsx', 'node'], modulePathIgnorePatterns: ['__fixtures__/', 'target/'], testMatch: ['**/*.test.{js,ts,tsx}'], testPathIgnorePatterns: [ diff --git a/yarn.lock b/yarn.lock index cf9126b668e51..f9f15ab79310d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12158,6 +12158,11 @@ env-paths@^1.0.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== + env-variable@0.0.x: version "0.0.5" resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88" @@ -21160,6 +21165,11 @@ nan@^2.12.1, nan@^2.13.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== +nan@^2.14.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== + nano-css@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.2.1.tgz#73b8470fa40b028a134d3393ae36bbb34b9fa332" @@ -21421,6 +21431,23 @@ node-gyp@^3.8.0: tar "^2.0.0" which "1" +node-gyp@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-6.1.0.tgz#64e31c61a4695ad304c1d5b82cf6b7c79cc79f3f" + integrity sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.1.2" + request "^2.88.0" + rimraf "^2.6.3" + semver "^5.7.1" + tar "^4.4.12" + which "^1.3.1" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -21620,6 +21647,14 @@ nopt@^2.2.0: dependencies: abbrev "1" +nopt@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" @@ -22329,7 +22364,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@0, osenv@^0.1.0: +osenv@0, osenv@^0.1.0, osenv@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -24205,6 +24240,14 @@ re-resizable@^6.1.1: dependencies: fast-memoize "^2.5.1" +re2@1.14.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/re2/-/re2-1.14.0.tgz#727076590acfe868cf04e115a3a3f6c373ddd63b" + integrity sha512-TYogJmzni8zNVaw4gNOVORRTUaggLZwnMhJoTD0POKeACEoCxTWa9BAYehRnh3S1JUXIMEfcEUa7piiGEn71Zg== + dependencies: + nan "^2.14.1" + node-gyp "^6.1.0" + react-ace@^5.5.0: version "5.10.0" resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.10.0.tgz#e328b37ac52759f700be5afdb86ada2f5ec84c5e" @@ -28673,7 +28716,7 @@ tar-stream@^2.1.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@4.4.13: +tar@4.4.13, tar@^4.4.12: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== From 332a1386d02b18c35133dc5eb3f6ce0321a721e9 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 10 Jun 2020 10:57:23 -0600 Subject: [PATCH 41/53] [Maps] bump @elastic/ems-client and incorporate types (#68444) * [Maps] bump @elastic/ems-client and incorporate types * tslint * update to ems-client 7.9.2 * bump to 7.9.3 Co-authored-by: Elastic Machine --- package.json | 2 +- x-pack/package.json | 2 +- .../public/classes/fields/ems_file_field.ts | 8 +- .../ems_file_source/create_source_editor.tsx | 11 +- .../ems_file_source/ems_file_source.test.tsx | 13 +- .../ems_file_source/ems_file_source.tsx | 33 +++--- .../ems_file_source/update_source_editor.tsx | 23 ++-- .../sources/ems_tms_source/ems_tms_source.js | 5 +- .../ems_tms_source/ems_tms_source.test.js | 26 ++-- .../ems_tms_source/tile_service_select.js | 5 +- .../kibana_regionmap_layer_wizard.tsx | 5 +- .../kibana_base_map_layer_wizard.tsx | 2 +- x-pack/plugins/maps/public/meta.js | 111 ------------------ x-pack/plugins/maps/public/meta.ts | 111 ++++++++++++++++++ yarn.lock | 8 +- 15 files changed, 165 insertions(+), 200 deletions(-) delete mode 100644 x-pack/plugins/maps/public/meta.js create mode 100644 x-pack/plugins/maps/public/meta.ts diff --git a/package.json b/package.json index 0bf173d9603e7..d5f738fad0400 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "@elastic/apm-rum": "^5.1.1", "@elastic/charts": "19.2.0", "@elastic/datemath": "5.0.3", - "@elastic/ems-client": "7.8.0", + "@elastic/ems-client": "7.9.3", "@elastic/eui": "24.1.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", diff --git a/x-pack/package.json b/x-pack/package.json index fb708ab09d841..6a84bcf449455 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -189,7 +189,7 @@ "@babel/runtime": "^7.9.2", "@elastic/apm-rum-react": "^1.1.1", "@elastic/datemath": "5.0.3", - "@elastic/ems-client": "7.8.0", + "@elastic/ems-client": "7.9.3", "@elastic/eui": "24.1.0", "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.3.0", diff --git a/x-pack/plugins/maps/public/classes/fields/ems_file_field.ts b/x-pack/plugins/maps/public/classes/fields/ems_file_field.ts index 73d6c1ef9f790..2e9c5c9fe60c2 100644 --- a/x-pack/plugins/maps/public/classes/fields/ems_file_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/ems_file_field.ts @@ -30,12 +30,6 @@ export class EMSFileField extends AbstractField implements IField { } async getLabel(): Promise { - const emsFileLayer = await this._source.getEMSFileLayer(); - // TODO remove any and @ts-ignore when emsFileLayer type defined - // @ts-ignore - const emsFields: any[] = emsFileLayer.getFieldsInLanguage(); - // Map EMS field name to language specific label - const emsField = emsFields.find((field) => field.name === this.getName()); - return emsField ? emsField.description : this.getName(); + return this._source.getEmsFieldLabel(this.getName()); } } diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx index e398af4acea3b..a78a49032503b 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/create_source_editor.tsx @@ -8,8 +8,8 @@ import React, { Component } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -// @ts-ignore -import { getEMSClient } from '../../../meta'; +import { FileLayer } from '@elastic/ems-client'; +import { getEmsFileLayers } from '../../../meta'; import { getEmsUnavailableMessage } from '../ems_unavailable_message'; import { EMSFileSourceDescriptor } from '../../../../common/descriptor_types'; @@ -33,15 +33,10 @@ export class EMSFileCreateSourceEditor extends Component { }; _loadFileOptions = async () => { - // @ts-ignore - const emsClient = getEMSClient(); - // @ts-ignore - const fileLayers: unknown[] = await emsClient.getFileLayers(); + const fileLayers: FileLayer[] = await getEmsFileLayers(); const options = fileLayers.map((fileLayer) => { return { - // @ts-ignore value: fileLayer.getId(), - // @ts-ignore label: fileLayer.getDisplayName(), }; }); diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx index 24c111a72ac05..52524d0c9a5fa 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.test.tsx @@ -11,17 +11,8 @@ jest.mock('../../layers/vector_layer/vector_layer', () => {}); function makeEMSFileSource(tooltipProperties: string[]) { const emsFileSource = new EMSFileSource({ tooltipProperties }); - emsFileSource.getEMSFileLayer = async () => { - return { - getFieldsInLanguage() { - return [ - { - name: 'iso2', - description: 'ISO 2 CODE', - }, - ]; - }, - }; + emsFileSource.getEmsFieldLabel = async (name: string) => { + return name === 'iso2' ? 'ISO 2 CODE' : name; }; return emsFileSource; } diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.tsx index 94f5bb0d2ba07..f7fb0078764c4 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_file_source.tsx @@ -8,12 +8,12 @@ import React, { ReactElement } from 'react'; import { i18n } from '@kbn/i18n'; import { Feature } from 'geojson'; import { Adapters } from 'src/plugins/inspector/public'; +import { FileLayer } from '@elastic/ems-client'; import { Attribution, ImmutableSourceProperty, SourceEditorArgs } from '../source'; import { AbstractVectorSource, GeoJsonWithMeta, IVectorSource } from '../vector_source'; import { VECTOR_SHAPE_TYPES } from '../vector_feature_types'; import { SOURCE_TYPES, FIELD_ORIGIN } from '../../../../common/constants'; -// @ts-ignore -import { getEMSClient } from '../../../meta'; +import { getEmsFileLayers } from '../../../meta'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { UpdateSourceEditor } from './update_source_editor'; import { EMSFileField } from '../../fields/ems_file_field'; @@ -23,7 +23,7 @@ import { EMSFileSourceDescriptor } from '../../../../common/descriptor_types'; import { ITooltipProperty } from '../../tooltips/tooltip_property'; export interface IEmsFileSource extends IVectorSource { - getEMSFileLayer(): Promise; + getEmsFieldLabel(emsFieldName: string): Promise; createField({ fieldName }: { fieldName: string }): IField; } @@ -72,13 +72,9 @@ export class EMSFileSource extends AbstractVectorSource implements IEmsFileSourc ); } - async getEMSFileLayer(): Promise { - // @ts-ignore - const emsClient = getEMSClient(); - // @ts-ignore - const emsFileLayers = await emsClient.getFileLayers(); + async getEMSFileLayer(): Promise { + const emsFileLayers = await getEmsFileLayers(); const emsFileLayer = emsFileLayers.find( - // @ts-ignore (fileLayer) => fileLayer.getId() === this._descriptor.id ); if (!emsFileLayer) { @@ -94,19 +90,25 @@ export class EMSFileSource extends AbstractVectorSource implements IEmsFileSourc return emsFileLayer; } + // Map EMS field name to language specific label + async getEmsFieldLabel(emsFieldName: string): Promise { + const emsFileLayer = await this.getEMSFileLayer(); + const emsFields = emsFileLayer.getFieldsInLanguage(); + + const emsField = emsFields.find((field) => field.name === emsFieldName); + return emsField ? emsField.description : emsFieldName; + } + async getGeoJsonWithMeta(): Promise { const emsFileLayer = await this.getEMSFileLayer(); // @ts-ignore const featureCollection = await AbstractVectorSource.getGeoJson({ - // @ts-ignore format: emsFileLayer.getDefaultFormatType(), featureCollectionPath: 'data', - // @ts-ignore fetchUrl: emsFileLayer.getDefaultFormatUrl(), }); - // @ts-ignore - const emsIdField = emsFileLayer._config.fields.find((field) => { + const emsIdField = emsFileLayer.getFields().find((field) => { return field.type === 'id'; }); featureCollection.features.forEach((feature: Feature, index: number) => { @@ -123,7 +125,6 @@ export class EMSFileSource extends AbstractVectorSource implements IEmsFileSourc let emsLink; try { const emsFileLayer = await this.getEMSFileLayer(); - // @ts-ignore emsLink = emsFileLayer.getEMSHotLink(); } catch (error) { // ignore error if EMS layer id could not be found @@ -147,7 +148,6 @@ export class EMSFileSource extends AbstractVectorSource implements IEmsFileSourc async getDisplayName(): Promise { try { const emsFileLayer = await this.getEMSFileLayer(); - // @ts-ignore return emsFileLayer.getDisplayName(); } catch (error) { return this._descriptor.id; @@ -156,15 +156,12 @@ export class EMSFileSource extends AbstractVectorSource implements IEmsFileSourc async getAttributions(): Promise { const emsFileLayer = await this.getEMSFileLayer(); - // @ts-ignore return emsFileLayer.getAttributions(); } async getLeftJoinFields() { const emsFileLayer = await this.getEMSFileLayer(); - // @ts-ignore const fields = emsFileLayer.getFieldsInLanguage(); - // @ts-ignore return fields.map((f) => this.createField({ fieldName: f.name })); } diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/update_source_editor.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/update_source_editor.tsx index daeb1f8bc6b2b..ac69505a9bed5 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/update_source_editor.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/update_source_editor.tsx @@ -8,8 +8,7 @@ import React, { Component, Fragment } from 'react'; import { EuiTitle, EuiPanel, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { TooltipSelector } from '../../../components/tooltip_selector'; -// @ts-ignore -import { getEMSClient } from '../../../meta'; +import { getEmsFileLayers } from '../../../meta'; import { IEmsFileSource } from './ems_file_source'; import { IField } from '../../fields/field'; import { OnSourceChangeArgs } from '../../../connected_components/layer_panel/view'; @@ -42,22 +41,18 @@ export class UpdateSourceEditor extends Component { } async loadFields() { - let fields; + let fields: IField[] = []; try { - // @ts-ignore - const emsClient = getEMSClient(); - // @ts-ignore - const emsFiles = await emsClient.getFileLayers(); - // @ts-ignore - const taregetEmsFile = emsFiles.find((emsFile) => emsFile.getId() === this.props.layerId); - // @ts-ignore - const emsFields = taregetEmsFile.getFieldsInLanguage(); - // @ts-ignore - fields = emsFields.map((field) => this.props.source.createField({ fieldName: field.name })); + const emsFiles = await getEmsFileLayers(); + const targetEmsFile = emsFiles.find((emsFile) => emsFile.getId() === this.props.layerId); + if (targetEmsFile) { + fields = targetEmsFile + .getFieldsInLanguage() + .map((field) => this.props.source.createField({ fieldName: field.name })); + } } catch (e) { // When a matching EMS-config cannot be found, the source already will have thrown errors during the data request. // This will propagate to the vector-layer and be displayed in the UX - fields = []; } if (this._isMounted) { diff --git a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.js b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.js index 36c9e424a8b22..83c87eb53d4fe 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.js +++ b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.js @@ -7,7 +7,7 @@ import _ from 'lodash'; import React from 'react'; import { AbstractTMSSource } from '../tms_source'; -import { getEMSClient } from '../../../meta'; +import { getEmsTmsServices } from '../../../meta'; import { UpdateSourceEditor } from './update_source_editor'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; @@ -66,8 +66,7 @@ export class EMSTMSSource extends AbstractTMSSource { } async _getEMSTMSService() { - const emsClient = getEMSClient(); - const emsTMSServices = await emsClient.getTMSServices(); + const emsTMSServices = await getEmsTmsServices(); const emsTileLayerId = this.getTileLayerId(); const tmsService = emsTMSServices.find((tmsService) => tmsService.getId() === emsTileLayerId); if (!tmsService) { diff --git a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.test.js b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.test.js index 08c54299d721b..2f466add28262 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.test.js +++ b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.test.js @@ -6,7 +6,7 @@ jest.mock('../../../meta', () => { return { - getEMSClient: () => { + getEmsTmsServices: () => { class MockTMSService { constructor(config) { this._config = config; @@ -19,20 +19,16 @@ jest.mock('../../../meta', () => { } } - return { - async getTMSServices() { - return [ - new MockTMSService({ - id: 'road_map', - attributionMarkdown: '[foobar](http://foobar.org) | [foobaz](http://foobaz.org)', - }), - new MockTMSService({ - id: 'satellite', - attributionMarkdown: '[satellite](http://satellite.org)', - }), - ]; - }, - }; + return [ + new MockTMSService({ + id: 'road_map', + attributionMarkdown: '[foobar](http://foobar.org) | [foobaz](http://foobaz.org)', + }), + new MockTMSService({ + id: 'satellite', + attributionMarkdown: '[satellite](http://satellite.org)', + }), + ]; }, }; }); diff --git a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js index 4d5d6655609c1..3931e441ff254 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js +++ b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/tile_service_select.js @@ -7,7 +7,7 @@ import React from 'react'; import { EuiSelect, EuiFormRow } from '@elastic/eui'; -import { getEMSClient } from '../../../meta'; +import { getEmsTmsServices } from '../../../meta'; import { getEmsUnavailableMessage } from '../ems_unavailable_message'; import { i18n } from '@kbn/i18n'; @@ -29,8 +29,7 @@ export class TileServiceSelect extends React.Component { } _loadTmsOptions = async () => { - const emsClient = getEMSClient(); - const emsTMSServices = await emsClient.getTMSServices(); + const emsTMSServices = await getEmsTmsServices(); if (!this._isMounted) { return; diff --git a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx index b778dc0076459..ca78aaefe404f 100644 --- a/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/kibana_regionmap_source/kibana_regionmap_layer_wizard.tsx @@ -12,13 +12,12 @@ import { KibanaRegionmapSource, sourceTitle } from './kibana_regionmap_source'; import { VectorLayer } from '../../layers/vector_layer/vector_layer'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; -// @ts-ignore import { getKibanaRegionList } from '../../../meta'; export const kibanaRegionMapLayerWizardConfig: LayerWizard = { - checkVisibility: () => { + checkVisibility: async () => { const regions = getKibanaRegionList(); - return regions.length; + return regions.length > 0; }, description: i18n.translate('xpack.maps.source.kbnRegionMapDescription', { defaultMessage: 'Vector data from hosted GeoJSON configured in kibana.yml', diff --git a/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx index 227c0182b98de..84d2e5e74fa9a 100644 --- a/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx @@ -12,12 +12,12 @@ import { CreateSourceEditor } from './create_source_editor'; // @ts-ignore import { KibanaTilemapSource, sourceTitle } from './kibana_tilemap_source'; import { TileLayer } from '../../layers/tile_layer/tile_layer'; -// @ts-ignore import { getKibanaTileMap } from '../../../meta'; export const kibanaBasemapLayerWizardConfig: LayerWizard = { checkVisibility: async () => { const tilemap = getKibanaTileMap(); + // @ts-ignore return !!tilemap.url; }, description: i18n.translate('xpack.maps.source.kbnTMSDescription', { diff --git a/x-pack/plugins/maps/public/meta.js b/x-pack/plugins/maps/public/meta.js deleted file mode 100644 index 46c5e5cda3617..0000000000000 --- a/x-pack/plugins/maps/public/meta.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - getHttp, - getLicenseId, - getIsEmsEnabled, - getRegionmapLayers, - getTilemap, - getEmsFileApiUrl, - getEmsTileApiUrl, - getEmsLandingPageUrl, - getEmsFontLibraryUrl, - getProxyElasticMapsServiceInMaps, - getKibanaVersion, -} from './kibana_services'; -import { - GIS_API_PATH, - EMS_FILES_CATALOGUE_PATH, - EMS_TILES_CATALOGUE_PATH, - EMS_GLYPHS_PATH, - EMS_APP_NAME, - FONTS_API_PATH, -} from '../common/constants'; -import { i18n } from '@kbn/i18n'; -import { EMSClient } from '@elastic/ems-client'; - -import fetch from 'node-fetch'; - -const GIS_API_RELATIVE = `../${GIS_API_PATH}`; - -export function getKibanaRegionList() { - return getRegionmapLayers(); -} - -export function getKibanaTileMap() { - return getTilemap(); -} - -function relativeToAbsolute(url) { - const a = document.createElement('a'); - a.setAttribute('href', url); - return a.href; -} - -function fetchFunction(...args) { - return fetch(...args); -} - -let emsClient = null; -let latestLicenseId = null; -export function getEMSClient() { - if (!emsClient) { - const isEmsEnabled = getIsEmsEnabled(); - if (isEmsEnabled) { - const proxyElasticMapsServiceInMaps = getProxyElasticMapsServiceInMaps(); - const proxyPath = ''; - const tileApiUrl = proxyElasticMapsServiceInMaps - ? relativeToAbsolute(`${GIS_API_RELATIVE}/${EMS_TILES_CATALOGUE_PATH}`) - : getEmsTileApiUrl(); - const fileApiUrl = proxyElasticMapsServiceInMaps - ? relativeToAbsolute(`${GIS_API_RELATIVE}/${EMS_FILES_CATALOGUE_PATH}`) - : getEmsFileApiUrl(); - - emsClient = new EMSClient({ - language: i18n.getLocale(), - appVersion: getKibanaVersion(), - appName: EMS_APP_NAME, - tileApiUrl, - fileApiUrl, - landingPageUrl: getEmsLandingPageUrl(), - fetchFunction: fetchFunction, //import this from client-side, so the right instance is returned (bootstrapped from common/* would not work - proxyPath, - }); - } else { - //EMS is turned off. Mock API. - emsClient = { - async getFileLayers() { - return []; - }, - async getTMSServices() { - return []; - }, - addQueryParams() {}, - }; - } - } - const licenseId = getLicenseId(); - if (latestLicenseId !== licenseId) { - latestLicenseId = licenseId; - emsClient.addQueryParams({ license: licenseId }); - } - return emsClient; -} - -export function getGlyphUrl() { - if (!getIsEmsEnabled()) { - return getHttp().basePath.prepend(`/${FONTS_API_PATH}/{fontstack}/{range}`); - } - return getProxyElasticMapsServiceInMaps() - ? relativeToAbsolute(`../${GIS_API_PATH}/${EMS_TILES_CATALOGUE_PATH}/${EMS_GLYPHS_PATH}`) + - `/{fontstack}/{range}` - : getEmsFontLibraryUrl(); -} - -export function isRetina() { - return window.devicePixelRatio === 2; -} diff --git a/x-pack/plugins/maps/public/meta.ts b/x-pack/plugins/maps/public/meta.ts new file mode 100644 index 0000000000000..54c5eac7fe1b0 --- /dev/null +++ b/x-pack/plugins/maps/public/meta.ts @@ -0,0 +1,111 @@ +/* + * 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 { EMSClient, FileLayer, TMSService } from '@elastic/ems-client'; + +import fetch from 'node-fetch'; +import { + GIS_API_PATH, + EMS_FILES_CATALOGUE_PATH, + EMS_TILES_CATALOGUE_PATH, + EMS_GLYPHS_PATH, + EMS_APP_NAME, + FONTS_API_PATH, +} from '../common/constants'; +import { + getHttp, + getLicenseId, + getIsEmsEnabled, + getRegionmapLayers, + getTilemap, + getEmsFileApiUrl, + getEmsTileApiUrl, + getEmsLandingPageUrl, + getEmsFontLibraryUrl, + getProxyElasticMapsServiceInMaps, + getKibanaVersion, +} from './kibana_services'; + +const GIS_API_RELATIVE = `../${GIS_API_PATH}`; + +export function getKibanaRegionList(): unknown[] { + return getRegionmapLayers(); +} + +export function getKibanaTileMap(): unknown { + return getTilemap(); +} + +export async function getEmsFileLayers(): Promise { + if (!getIsEmsEnabled()) { + return []; + } + + return getEMSClient().getFileLayers(); +} + +export async function getEmsTmsServices(): Promise { + if (!getIsEmsEnabled()) { + return []; + } + + return getEMSClient().getTMSServices(); +} + +function relativeToAbsolute(url: string): string { + const a = document.createElement('a'); + a.setAttribute('href', url); + return a.href; +} + +let emsClient: EMSClient | null = null; +let latestLicenseId: string | null = null; +export function getEMSClient(): EMSClient { + if (!emsClient) { + const proxyElasticMapsServiceInMaps = getProxyElasticMapsServiceInMaps(); + const proxyPath = ''; + const tileApiUrl = proxyElasticMapsServiceInMaps + ? relativeToAbsolute(`${GIS_API_RELATIVE}/${EMS_TILES_CATALOGUE_PATH}`) + : getEmsTileApiUrl(); + const fileApiUrl = proxyElasticMapsServiceInMaps + ? relativeToAbsolute(`${GIS_API_RELATIVE}/${EMS_FILES_CATALOGUE_PATH}`) + : getEmsFileApiUrl(); + + emsClient = new EMSClient({ + language: i18n.getLocale(), + appVersion: getKibanaVersion(), + appName: EMS_APP_NAME, + tileApiUrl, + fileApiUrl, + landingPageUrl: getEmsLandingPageUrl(), + fetchFunction(url: string) { + return fetch(url); + }, + proxyPath, + }); + } + const licenseId = getLicenseId(); + if (latestLicenseId !== licenseId) { + latestLicenseId = licenseId; + emsClient.addQueryParams({ license: licenseId }); + } + return emsClient; +} + +export function getGlyphUrl(): string { + if (!getIsEmsEnabled()) { + return getHttp().basePath.prepend(`/${FONTS_API_PATH}/{fontstack}/{range}`); + } + return getProxyElasticMapsServiceInMaps() + ? relativeToAbsolute(`../${GIS_API_PATH}/${EMS_TILES_CATALOGUE_PATH}/${EMS_GLYPHS_PATH}`) + + `/{fontstack}/{range}` + : getEmsFontLibraryUrl(); +} + +export function isRetina(): boolean { + return window.devicePixelRatio === 2; +} diff --git a/yarn.lock b/yarn.lock index f9f15ab79310d..df16cd891ea6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1297,10 +1297,10 @@ once "^1.4.0" pump "^3.0.0" -"@elastic/ems-client@7.8.0": - version "7.8.0" - resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.8.0.tgz#8cc309bc8128c03a78e876b43bf04f4d2b4789c5" - integrity sha512-+6WjxZy/mhVWXTdSYjHd+ArsvH1s7GEummaGq9DlnCW6CyGIYkYxOISKpuytReeYhhMk7F06f/GKw+8ivi2zPQ== +"@elastic/ems-client@7.9.3": + version "7.9.3" + resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.9.3.tgz#71b79914f76e347f050ead8474ad65d761e94a8a" + integrity sha512-aun5rW9TQgWLVH77xBLLhempT3P+6AeQIEyK/CWYuVfCDpHfDxzMKWgQ076a7rSUqF059ayDGZbyOxf7l0M2Sw== dependencies: lodash "^4.17.15" semver "^6.3.0" From 3197a00e790ac630610b9dfae792f9dfcd6211c8 Mon Sep 17 00:00:00 2001 From: Quynh Nguyen <43350163+qn895@users.noreply.github.com> Date: Wed, 10 Jun 2020 12:02:52 -0500 Subject: [PATCH 42/53] Revert "[ML] Transforms: Add ability to delete dest index & index pattern when deleting transform job" (#68793) --- x-pack/plugins/ml/common/util/errors.test.ts | 78 ----- x-pack/plugins/ml/common/util/errors.ts | 75 ----- .../analytics_list/action_delete.tsx | 2 +- .../analytics_service/delete_analytics.ts | 2 +- .../ml/public/application/util/error_utils.ts | 32 ++ x-pack/plugins/ml/public/shared.ts | 1 - x-pack/plugins/transform/common/index.ts | 17 - .../components/toast_notification_text.tsx | 12 +- .../transform/public/app/hooks/index.ts | 2 +- .../transform/public/app/hooks/use_api.ts | 15 +- .../public/app/hooks/use_delete_transform.tsx | 255 ++------------ .../transform_list/action_delete.tsx | 128 +------ .../public/app/services/es_index_service.ts | 33 -- .../transform/public/shared_imports.ts | 1 - .../server/routes/api/error_utils.ts | 10 +- .../transform/server/routes/api/schema.ts | 14 - .../transform/server/routes/api/transforms.ts | 154 +-------- x-pack/test/api_integration/apis/index.js | 1 - .../apis/ml/data_frame_analytics/delete.ts | 2 +- .../apis/transform/delete_transforms.ts | 318 ------------------ .../api_integration/apis/transform/index.ts | 32 -- x-pack/test/api_integration/services/index.ts | 2 - .../api_integration/services/transform.ts | 23 -- .../test/functional/services/transform/api.ts | 63 +--- 24 files changed, 107 insertions(+), 1165 deletions(-) delete mode 100644 x-pack/plugins/ml/common/util/errors.test.ts create mode 100644 x-pack/plugins/ml/public/application/util/error_utils.ts delete mode 100644 x-pack/plugins/transform/public/app/services/es_index_service.ts delete mode 100644 x-pack/test/api_integration/apis/transform/delete_transforms.ts delete mode 100644 x-pack/test/api_integration/apis/transform/index.ts delete mode 100644 x-pack/test/api_integration/services/transform.ts diff --git a/x-pack/plugins/ml/common/util/errors.test.ts b/x-pack/plugins/ml/common/util/errors.test.ts deleted file mode 100644 index 00af27248ccce..0000000000000 --- a/x-pack/plugins/ml/common/util/errors.test.ts +++ /dev/null @@ -1,78 +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 { - BoomResponse, - extractErrorMessage, - MLCustomHttpResponseOptions, - MLResponseError, -} from './errors'; -import { ResponseError } from 'kibana/server'; - -describe('ML - error message utils', () => { - describe('extractErrorMessage', () => { - test('returns just the error message', () => { - const testMsg = 'Saved object [index-pattern/blahblahblah] not found'; - - const bodyWithNestedErrorMsg: MLCustomHttpResponseOptions = { - body: { - message: { - msg: testMsg, - }, - }, - statusCode: 404, - }; - expect(extractErrorMessage(bodyWithNestedErrorMsg)).toBe(testMsg); - - const bodyWithStringMsg: MLCustomHttpResponseOptions = { - body: { - msg: testMsg, - }, - statusCode: 404, - }; - expect(extractErrorMessage(bodyWithStringMsg)).toBe(testMsg); - - const bodyWithStringMessage: MLCustomHttpResponseOptions = { - body: { - message: testMsg, - }, - statusCode: 404, - }; - expect(extractErrorMessage(bodyWithStringMessage)).toBe(testMsg); - - const bodyWithString: MLCustomHttpResponseOptions = { - body: testMsg, - statusCode: 404, - }; - expect(extractErrorMessage(bodyWithString)).toBe(testMsg); - - const bodyWithError: MLCustomHttpResponseOptions = { - body: new Error(testMsg), - statusCode: 404, - }; - expect(extractErrorMessage(bodyWithError)).toBe(testMsg); - - const bodyWithBoomError: MLCustomHttpResponseOptions = { - statusCode: 404, - body: { - data: [], - isBoom: true, - isServer: false, - output: { - statusCode: 404, - payload: { - statusCode: 404, - error: testMsg, - message: testMsg, - }, - headers: {}, - }, - }, - }; - expect(extractErrorMessage(bodyWithBoomError)).toBe(testMsg); - }); - }); -}); diff --git a/x-pack/plugins/ml/common/util/errors.ts b/x-pack/plugins/ml/common/util/errors.ts index e165e15d7c64e..4446624bf2e7f 100644 --- a/x-pack/plugins/ml/common/util/errors.ts +++ b/x-pack/plugins/ml/common/util/errors.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ResponseError, ResponseHeaders } from 'kibana/server'; import { isErrorResponse } from '../types/errors'; export function getErrorMessage(error: any) { @@ -18,77 +17,3 @@ export function getErrorMessage(error: any) { return JSON.stringify(error); } - -// Adding temporary types until Kibana ResponseError is updated - -export interface BoomResponse { - data: any; - isBoom: boolean; - isServer: boolean; - output: { - statusCode: number; - payload: { - statusCode: number; - error: string; - message: string; - }; - headers: {}; - }; -} -export type MLResponseError = - | { - message: { - msg: string; - }; - } - | { msg: string }; - -export interface MLCustomHttpResponseOptions< - T extends ResponseError | MLResponseError | BoomResponse -> { - /** HTTP message to send to the client */ - body?: T; - /** HTTP Headers with additional information about response */ - headers?: ResponseHeaders; - statusCode: number; -} - -export const extractErrorMessage = ( - error: - | MLCustomHttpResponseOptions - | undefined - | string -): string => { - // extract only the error message within the response error coming from Kibana, Elasticsearch, and our own ML messages - - if (typeof error === 'string') { - return error; - } - if (error?.body === undefined) return ''; - - if (typeof error.body === 'string') { - return error.body; - } - if ( - typeof error.body === 'object' && - 'output' in error.body && - error.body.output.payload.message - ) { - return error.body.output.payload.message; - } - - if (typeof error.body === 'object' && 'msg' in error.body && typeof error.body.msg === 'string') { - return error.body.msg; - } - - if (typeof error.body === 'object' && 'message' in error.body) { - if (typeof error.body.message === 'string') { - return error.body.message; - } - if (!(error.body.message instanceof Error) && typeof (error.body.message.msg === 'string')) { - return error.body.message.msg; - } - } - // If all else fail return an empty message instead of JSON.stringify - return ''; -}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx index 38ef00914e8fb..2d433f6b18484 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/action_delete.tsx @@ -18,7 +18,6 @@ import { } from '@elastic/eui'; import { IIndexPattern } from 'src/plugins/data/common'; import { FormattedMessage } from '@kbn/i18n/react'; -import { extractErrorMessage } from '../../../../../../../common/util/errors'; import { deleteAnalytics, deleteAnalyticsAndDestIndex, @@ -30,6 +29,7 @@ import { } from '../../../../../capabilities/check_capabilities'; import { useMlKibana } from '../../../../../contexts/kibana'; import { isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common'; +import { extractErrorMessage } from '../../../../../util/error_utils'; interface DeleteActionProps { item: DataFrameAnalyticsListRow; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts index ebd3fa8982604..26cefff0a3f59 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/services/analytics_service/delete_analytics.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { extractErrorMessage } from '../../../../../../../common/util/errors'; import { getToastNotifications } from '../../../../../util/dependency_cache'; import { ml } from '../../../../../services/ml_api_service'; import { refreshAnalyticsList$, REFRESH_ANALYTICS_LIST_STATE } from '../../../../common'; @@ -12,6 +11,7 @@ import { isDataFrameAnalyticsFailed, DataFrameAnalyticsListRow, } from '../../components/analytics_list/common'; +import { extractErrorMessage } from '../../../../../util/error_utils'; export const deleteAnalytics = async (d: DataFrameAnalyticsListRow) => { const toastNotifications = getToastNotifications(); diff --git a/x-pack/plugins/ml/public/application/util/error_utils.ts b/x-pack/plugins/ml/public/application/util/error_utils.ts new file mode 100644 index 0000000000000..2ce8f4ffc583a --- /dev/null +++ b/x-pack/plugins/ml/public/application/util/error_utils.ts @@ -0,0 +1,32 @@ +/* + * 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 { CustomHttpResponseOptions, ResponseError } from 'kibana/server'; + +export const extractErrorMessage = ( + error: CustomHttpResponseOptions | undefined | string +): string | undefined => { + if (typeof error === 'string') { + return error; + } + + if (error?.body) { + if (typeof error.body === 'string') { + return error.body; + } + if (typeof error.body === 'object' && 'message' in error.body) { + if (typeof error.body.message === 'string') { + return error.body.message; + } + // @ts-ignore + if (typeof (error.body.message?.msg === 'string')) { + // @ts-ignore + return error.body.message?.msg; + } + } + } + return undefined; +}; diff --git a/x-pack/plugins/ml/public/shared.ts b/x-pack/plugins/ml/public/shared.ts index ff83d79adff67..6821cb7ef0f94 100644 --- a/x-pack/plugins/ml/public/shared.ts +++ b/x-pack/plugins/ml/public/shared.ts @@ -14,7 +14,6 @@ export * from '../common/types/audit_message'; export * from '../common/util/anomaly_utils'; export * from '../common/util/errors'; - export * from '../common/util/validators'; export * from './application/formatters/metric_change_description'; diff --git a/x-pack/plugins/transform/common/index.ts b/x-pack/plugins/transform/common/index.ts index 79ff6298a2ca2..d7a791e78b3ab 100644 --- a/x-pack/plugins/transform/common/index.ts +++ b/x-pack/plugins/transform/common/index.ts @@ -38,20 +38,3 @@ export interface ResultData { export interface TransformEndpointResult { [key: string]: ResultData; } - -export interface DeleteTransformEndpointRequest { - transformsInfo: TransformEndpointRequest[]; - deleteDestIndex?: boolean; - deleteDestIndexPattern?: boolean; -} - -export interface DeleteTransformStatus { - transformDeleted: ResultData; - destIndexDeleted?: ResultData; - destIndexPatternDeleted?: ResultData; - destinationIndex?: string | undefined; -} - -export interface DeleteTransformEndpointResult { - [key: string]: DeleteTransformStatus; -} diff --git a/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx b/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx index 3f664cf8bb09b..1044081670523 100644 --- a/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx +++ b/x-pack/plugins/transform/public/app/components/toast_notification_text.tsx @@ -29,14 +29,9 @@ const MAX_SIMPLE_MESSAGE_LENGTH = 140; interface ToastNotificationTextProps { overlays: CoreStart['overlays']; text: any; - previewTextLength?: number; } -export const ToastNotificationText: FC = ({ - overlays, - text, - previewTextLength, -}) => { +export const ToastNotificationText: FC = ({ overlays, text }) => { if (typeof text === 'string' && text.length <= MAX_SIMPLE_MESSAGE_LENGTH) { return text; } @@ -51,9 +46,8 @@ export const ToastNotificationText: FC = ({ const unformattedText = text.message ? text.message : text; const formattedText = typeof unformattedText === 'object' ? JSON.stringify(text, null, 2) : text; - const textLength = previewTextLength ?? 140; - const previewText = `${formattedText.substring(0, textLength)}${ - formattedText.length > textLength ? ' ...' : '' + const previewText = `${formattedText.substring(0, 140)}${ + formattedText.length > 140 ? ' ...' : '' }`; const openModal = () => { diff --git a/x-pack/plugins/transform/public/app/hooks/index.ts b/x-pack/plugins/transform/public/app/hooks/index.ts index b439afe2b2165..a36550bcd8e57 100644 --- a/x-pack/plugins/transform/public/app/hooks/index.ts +++ b/x-pack/plugins/transform/public/app/hooks/index.ts @@ -6,7 +6,7 @@ export { useApi } from './use_api'; export { useGetTransforms } from './use_get_transforms'; -export { useDeleteTransforms, useDeleteIndexAndTargetIndex } from './use_delete_transform'; +export { useDeleteTransforms } from './use_delete_transform'; export { useStartTransforms } from './use_start_transform'; export { useStopTransforms } from './use_stop_transform'; export { useRequest } from './use_request'; diff --git a/x-pack/plugins/transform/public/app/hooks/use_api.ts b/x-pack/plugins/transform/public/app/hooks/use_api.ts index 5d7839cf5fba7..f3c35d358f1f2 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_api.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_api.ts @@ -5,12 +5,7 @@ */ import { useMemo } from 'react'; -import { - TransformId, - TransformEndpointRequest, - TransformEndpointResult, - DeleteTransformEndpointResult, -} from '../../../common'; +import { TransformEndpointRequest, TransformEndpointResult, TransformId } from '../../../common'; import { API_BASE_PATH } from '../../../common/constants'; import { useAppDependencies } from '../app_dependencies'; @@ -45,12 +40,10 @@ export const useApi = () => { }); }, deleteTransforms( - transformsInfo: TransformEndpointRequest[], - deleteDestIndex: boolean | undefined, - deleteDestIndexPattern: boolean | undefined - ): Promise { + transformsInfo: TransformEndpointRequest[] + ): Promise { return http.post(`${API_BASE_PATH}delete_transforms`, { - body: JSON.stringify({ transformsInfo, deleteDestIndex, deleteDestIndexPattern }), + body: JSON.stringify(transformsInfo), }); }, getTransformsPreview(obj: PreviewRequestBody): Promise { diff --git a/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx b/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx index 1f395e67b7d31..0215d723188b1 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx +++ b/x-pack/plugins/transform/public/app/hooks/use_delete_transform.tsx @@ -4,257 +4,52 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback, useEffect, useState } from 'react'; +import React from 'react'; + import { i18n } from '@kbn/i18n'; import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; -import { - TransformEndpointRequest, - DeleteTransformEndpointResult, - DeleteTransformStatus, -} from '../../../common'; -import { getErrorMessage, extractErrorMessage } from '../../shared_imports'; -import { useAppDependencies, useToastNotifications } from '../app_dependencies'; -import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common'; -import { ToastNotificationText } from '../components'; -import { useApi } from './use_api'; -import { indexService } from '../services/es_index_service'; -export const useDeleteIndexAndTargetIndex = (items: TransformListRow[]) => { - const { http, savedObjects } = useAppDependencies(); - const toastNotifications = useToastNotifications(); - - const [deleteDestIndex, setDeleteDestIndex] = useState(true); - const [deleteIndexPattern, setDeleteIndexPattern] = useState(true); - const [userCanDeleteIndex, setUserCanDeleteIndex] = useState(false); - const [indexPatternExists, setIndexPatternExists] = useState(false); - const toggleDeleteIndex = useCallback(() => setDeleteDestIndex(!deleteDestIndex), [ - deleteDestIndex, - ]); - const toggleDeleteIndexPattern = useCallback(() => setDeleteIndexPattern(!deleteIndexPattern), [ - deleteIndexPattern, - ]); +import { TransformEndpointRequest, TransformEndpointResult } from '../../../common'; - const checkIndexPatternExists = useCallback( - async (indexName: string) => { - try { - if (await indexService.indexPatternExists(savedObjects.client, indexName)) { - setIndexPatternExists(true); - } - } catch (e) { - const error = extractErrorMessage(e); - - toastNotifications.addDanger( - i18n.translate( - 'xpack.transform.deleteTransform.errorWithCheckingIfIndexPatternExistsNotificationErrorMessage', - { - defaultMessage: - 'An error occurred checking if index pattern {indexPattern} exists: {error}', - values: { indexPattern: indexName, error }, - } - ) - ); - } - }, - [savedObjects.client, toastNotifications] - ); - - const checkUserIndexPermission = useCallback(async () => { - try { - const userCanDelete = await indexService.canDeleteIndex(http); - if (userCanDelete) { - setUserCanDeleteIndex(true); - } - } catch (e) { - toastNotifications.addDanger( - i18n.translate( - 'xpack.transform.transformList.errorWithCheckingIfUserCanDeleteIndexNotificationErrorMessage', - { - defaultMessage: 'An error occurred checking if user can delete destination index', - } - ) - ); - } - }, [http, toastNotifications]); - - useEffect(() => { - checkUserIndexPermission(); - - if (items.length === 1) { - const config = items[0].config; - const destinationIndex = Array.isArray(config.dest.index) - ? config.dest.index[0] - : config.dest.index; - checkIndexPatternExists(destinationIndex); - } else { - setIndexPatternExists(true); - } - }, [checkIndexPatternExists, checkUserIndexPermission, items]); +import { getErrorMessage } from '../../shared_imports'; - return { - userCanDeleteIndex, - deleteDestIndex, - indexPatternExists, - deleteIndexPattern, - toggleDeleteIndex, - toggleDeleteIndexPattern, - }; -}; +import { useAppDependencies, useToastNotifications } from '../app_dependencies'; +import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common'; +import { ToastNotificationText } from '../components'; -type SuccessCountField = keyof Omit; +import { useApi } from './use_api'; export const useDeleteTransforms = () => { const { overlays } = useAppDependencies(); const toastNotifications = useToastNotifications(); const api = useApi(); - return async ( - transforms: TransformListRow[], - shouldDeleteDestIndex: boolean, - shouldDeleteDestIndexPattern: boolean - ) => { + return async (transforms: TransformListRow[]) => { const transformsInfo: TransformEndpointRequest[] = transforms.map((tf) => ({ id: tf.config.id, state: tf.stats.state, })); try { - const results: DeleteTransformEndpointResult = await api.deleteTransforms( - transformsInfo, - shouldDeleteDestIndex, - shouldDeleteDestIndexPattern - ); - const isBulk = Object.keys(results).length > 1; - const successCount: Record = { - transformDeleted: 0, - destIndexDeleted: 0, - destIndexPatternDeleted: 0, - }; + const results: TransformEndpointResult = await api.deleteTransforms(transformsInfo); for (const transformId in results) { // hasOwnProperty check to ensure only properties on object itself, and not its prototypes if (results.hasOwnProperty(transformId)) { - const status = results[transformId]; - const destinationIndex = status.destinationIndex; - - // if we are only deleting one transform, show the success toast messages - if (!isBulk && status.transformDeleted) { - if (status.transformDeleted?.success) { - toastNotifications.addSuccess( - i18n.translate('xpack.transform.transformList.deleteTransformSuccessMessage', { - defaultMessage: 'Request to delete transform {transformId} acknowledged.', - values: { transformId }, - }) - ); - } - if (status.destIndexDeleted?.success) { - toastNotifications.addSuccess( - i18n.translate( - 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexSuccessMessage', - { - defaultMessage: - 'Request to delete destination index {destinationIndex} acknowledged.', - values: { destinationIndex }, - } - ) - ); - } - if (status.destIndexPatternDeleted?.success) { - toastNotifications.addSuccess( - i18n.translate( - 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexPatternSuccessMessage', - { - defaultMessage: - 'Request to delete index pattern {destinationIndex} acknowledged.', - values: { destinationIndex }, - } - ) - ); - } + if (results[transformId].success === true) { + toastNotifications.addSuccess( + i18n.translate('xpack.transform.transformList.deleteTransformSuccessMessage', { + defaultMessage: 'Request to delete transform {transformId} acknowledged.', + values: { transformId }, + }) + ); } else { - (Object.keys(successCount) as SuccessCountField[]).forEach((key) => { - if (status[key]?.success) { - successCount[key] = successCount[key] + 1; - } - }); - } - if (status.transformDeleted?.error) { - const error = extractErrorMessage(status.transformDeleted.error); - toastNotifications.addDanger({ - title: i18n.translate('xpack.transform.transformList.deleteTransformErrorMessage', { + toastNotifications.addDanger( + i18n.translate('xpack.transform.transformList.deleteTransformErrorMessage', { defaultMessage: 'An error occurred deleting the transform {transformId}', values: { transformId }, - }), - text: toMountPoint( - - ), - }); + }) + ); } - - if (status.destIndexDeleted?.error) { - const error = extractErrorMessage(status.destIndexDeleted.error); - toastNotifications.addDanger({ - title: i18n.translate( - 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexErrorMessage', - { - defaultMessage: 'An error occurred deleting destination index {destinationIndex}', - values: { destinationIndex }, - } - ), - text: toMountPoint( - - ), - }); - } - - if (status.destIndexPatternDeleted?.error) { - const error = extractErrorMessage(status.destIndexPatternDeleted.error); - toastNotifications.addDanger({ - title: i18n.translate( - 'xpack.transform.deleteTransform.deleteAnalyticsWithIndexPatternErrorMessage', - { - defaultMessage: 'An error occurred deleting index pattern {destinationIndex}', - values: { destinationIndex }, - } - ), - text: toMountPoint( - - ), - }); - } - } - } - - // if we are deleting multiple transforms, combine the success messages - if (isBulk) { - if (successCount.transformDeleted > 0) { - toastNotifications.addSuccess( - i18n.translate('xpack.transform.transformList.bulkDeleteTransformSuccessMessage', { - defaultMessage: - 'Successfully deleted {count} {count, plural, one {transform} other {transforms}}.', - values: { count: successCount.transformDeleted }, - }) - ); - } - - if (successCount.destIndexDeleted > 0) { - toastNotifications.addSuccess( - i18n.translate('xpack.transform.transformList.bulkDeleteDestIndexSuccessMessage', { - defaultMessage: - 'Successfully deleted {count} destination {count, plural, one {index} other {indices}}.', - values: { count: successCount.destIndexDeleted }, - }) - ); - } - if (successCount.destIndexPatternDeleted > 0) { - toastNotifications.addSuccess( - i18n.translate( - 'xpack.transform.transformList.bulkDeleteDestIndexPatternSuccessMessage', - { - defaultMessage: - 'Successfully deleted {count} destination index {count, plural, one {pattern} other {patterns}}.', - values: { count: successCount.destIndexPatternDeleted }, - } - ) - ); } } @@ -264,13 +59,7 @@ export const useDeleteTransforms = () => { title: i18n.translate('xpack.transform.transformList.deleteTransformGenericErrorMessage', { defaultMessage: 'An error occurred calling the API endpoint to delete transforms.', }), - text: toMountPoint( - - ), + text: toMountPoint(), }); } }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx index d7db55990d333..c20feba29f582 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_delete.tsx @@ -12,14 +12,11 @@ import { EuiOverlayMask, EuiToolTip, EUI_MODAL_CONFIRM_BUTTON, - EuiFlexGroup, - EuiFlexItem, - EuiSwitch, - EuiSpacer, } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; + import { TRANSFORM_STATE } from '../../../../../../common'; -import { useDeleteTransforms, useDeleteIndexAndTargetIndex } from '../../../../hooks'; + +import { useDeleteTransforms } from '../../../../hooks'; import { createCapabilityFailureMessage, AuthorizationContext, @@ -38,25 +35,13 @@ export const DeleteAction: FC = ({ items, forceDisable }) => const { canDeleteTransform } = useContext(AuthorizationContext).capabilities; const deleteTransforms = useDeleteTransforms(); - const { - userCanDeleteIndex, - deleteDestIndex, - indexPatternExists, - deleteIndexPattern, - toggleDeleteIndex, - toggleDeleteIndexPattern, - } = useDeleteIndexAndTargetIndex(items); const [isModalVisible, setModalVisible] = useState(false); const closeModal = () => setModalVisible(false); const deleteAndCloseModal = () => { setModalVisible(false); - - const shouldDeleteDestIndex = userCanDeleteIndex && deleteDestIndex; - const shouldDeleteDestIndexPattern = - userCanDeleteIndex && indexPatternExists && deleteIndexPattern; - deleteTransforms(items, shouldDeleteDestIndex, shouldDeleteDestIndexPattern); + deleteTransforms(items); }; const openModal = () => setModalVisible(true); @@ -86,96 +71,17 @@ export const DeleteAction: FC = ({ items, forceDisable }) => defaultMessage: 'Delete {transformId}', values: { transformId: items[0] && items[0].config.id }, }); - const bulkDeleteModalContent = ( - <> -

- -

- - - { - - } - - - - { - - } - - - - ); - - const deleteModalContent = ( - <> -

- -

- - - {userCanDeleteIndex && ( - - )} - - {userCanDeleteIndex && indexPatternExists && ( - - - - - )} - - + const bulkDeleteModalMessage = i18n.translate( + 'xpack.transform.transformList.bulkDeleteModalBody', + { + defaultMessage: + "Are you sure you want to delete {count, plural, one {this} other {these}} {count} {count, plural, one {transform} other {transforms}}? The transform's destination index and optional Kibana index pattern will not be deleted.", + values: { count: items.length }, + } ); + const deleteModalMessage = i18n.translate('xpack.transform.transformList.deleteModalBody', { + defaultMessage: `Are you sure you want to delete this transform? The transform's destination index and optional Kibana index pattern will not be deleted.`, + }); let deleteButton = ( = ({ items, forceDisable }) => if (disabled || !canDeleteTransform) { let content; if (disabled) { - content = isBulkAction ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; + content = isBulkAction === true ? bulkDeleteButtonDisabledText : deleteButtonDisabledText; } else { content = createCapabilityFailureMessage('canDeleteTransform'); } @@ -211,7 +117,7 @@ export const DeleteAction: FC = ({ items, forceDisable }) => {isModalVisible && ( = ({ items, forceDisable }) => defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON} buttonColor="danger" > - {isBulkAction ? bulkDeleteModalContent : deleteModalContent} +

{isBulkAction === true ? bulkDeleteModalMessage : deleteModalMessage}

)} diff --git a/x-pack/plugins/transform/public/app/services/es_index_service.ts b/x-pack/plugins/transform/public/app/services/es_index_service.ts deleted file mode 100644 index 491213d0ddbe7..0000000000000 --- a/x-pack/plugins/transform/public/app/services/es_index_service.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { HttpSetup, SavedObjectsClientContract } from 'kibana/public'; -import { API_BASE_PATH } from '../../../common/constants'; -import { IIndexPattern } from '../../../../../../src/plugins/data/common/index_patterns'; - -export class IndexService { - async canDeleteIndex(http: HttpSetup) { - const privilege = await http.get(`${API_BASE_PATH}privileges`); - if (!privilege) { - return false; - } - return privilege.hasAllPrivileges; - } - - async indexPatternExists(savedObjectsClient: SavedObjectsClientContract, indexName: string) { - const response = await savedObjectsClient.find({ - type: 'index-pattern', - perPage: 1, - search: `"${indexName}"`, - searchFields: ['title'], - fields: ['title'], - }); - const ip = response.savedObjects.find((obj) => obj.attributes.title === indexName); - return ip !== undefined; - } -} - -export const indexService = new IndexService(); diff --git a/x-pack/plugins/transform/public/shared_imports.ts b/x-pack/plugins/transform/public/shared_imports.ts index ca3fb52cc02c3..56be8d7bb7de7 100644 --- a/x-pack/plugins/transform/public/shared_imports.ts +++ b/x-pack/plugins/transform/public/shared_imports.ts @@ -15,7 +15,6 @@ export { export { getErrorMessage, - extractErrorMessage, getDataGridSchemaFromKibanaFieldType, getFieldsFromKibanaIndexPattern, multiColumnSortFactory, diff --git a/x-pack/plugins/transform/server/routes/api/error_utils.ts b/x-pack/plugins/transform/server/routes/api/error_utils.ts index 5a479e4f429f6..295375794c04e 100644 --- a/x-pack/plugins/transform/server/routes/api/error_utils.ts +++ b/x-pack/plugins/transform/server/routes/api/error_utils.ts @@ -10,11 +10,7 @@ import { i18n } from '@kbn/i18n'; import { ResponseError, CustomHttpResponseOptions } from 'src/core/server'; -import { - TransformEndpointRequest, - TransformEndpointResult, - DeleteTransformEndpointResult, -} from '../../../common'; +import { TransformEndpointRequest, TransformEndpointResult } from '../../../common'; const REQUEST_TIMEOUT = 'RequestTimeout'; @@ -23,7 +19,7 @@ export function isRequestTimeout(error: any) { } interface Params { - results: TransformEndpointResult | DeleteTransformEndpointResult; + results: TransformEndpointResult; id: string; items: TransformEndpointRequest[]; action: string; @@ -63,7 +59,7 @@ export function fillResultsWithTimeouts({ results, id, items, action }: Params) }, }; - const newResults: TransformEndpointResult | DeleteTransformEndpointResult = {}; + const newResults: TransformEndpointResult = {}; return items.reduce((accumResults, currentVal) => { if (results[currentVal.id] === undefined) { diff --git a/x-pack/plugins/transform/server/routes/api/schema.ts b/x-pack/plugins/transform/server/routes/api/schema.ts index cf39f2e3829ea..0b994406d324d 100644 --- a/x-pack/plugins/transform/server/routes/api/schema.ts +++ b/x-pack/plugins/transform/server/routes/api/schema.ts @@ -14,17 +14,3 @@ export const schemaTransformId = { export interface SchemaTransformId { transformId: string; } - -export const deleteTransformSchema = schema.object({ - /** - * Delete Transform & Destination Index - */ - transformsInfo: schema.arrayOf( - schema.object({ - id: schema.string(), - state: schema.maybe(schema.string()), - }) - ), - deleteDestIndex: schema.maybe(schema.boolean()), - deleteDestIndexPattern: schema.maybe(schema.boolean()), -}); diff --git a/x-pack/plugins/transform/server/routes/api/transforms.ts b/x-pack/plugins/transform/server/routes/api/transforms.ts index 93fda56d319ad..55b2469a7f3a7 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms.ts @@ -5,12 +5,7 @@ */ import { schema } from '@kbn/config-schema'; -import { - KibanaResponseFactory, - RequestHandler, - RequestHandlerContext, - SavedObjectsClientContract, -} from 'kibana/server'; +import { RequestHandler } from 'kibana/server'; import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; import { wrapEsError } from '../../../../../legacy/server/lib/create_router/error_wrappers'; @@ -19,9 +14,6 @@ import { TransformEndpointResult, TransformId, TRANSFORM_STATE, - DeleteTransformEndpointRequest, - DeleteTransformStatus, - ResultData, } from '../../../common'; import { RouteDependencies } from '../../types'; @@ -29,9 +21,8 @@ import { RouteDependencies } from '../../types'; import { addBasePath } from '../index'; import { isRequestTimeout, fillResultsWithTimeouts, wrapError } from './error_utils'; -import { deleteTransformSchema, schemaTransformId, SchemaTransformId } from './schema'; +import { schemaTransformId, SchemaTransformId } from './schema'; import { registerTransformsAuditMessagesRoutes } from './transforms_audit_messages'; -import { IIndexPattern } from '../../../../../../src/plugins/data/common/index_patterns'; enum TRANSFORM_ACTIONS { STOP = 'stop', @@ -182,37 +173,15 @@ export function registerTransformsRoutes(routeDependencies: RouteDependencies) { { path: addBasePath('delete_transforms'), validate: { - body: deleteTransformSchema, + body: schema.maybe(schema.any()), }, }, license.guardApiRoute(async (ctx, req, res) => { - const { - transformsInfo, - deleteDestIndex, - deleteDestIndexPattern, - } = req.body as DeleteTransformEndpointRequest; + const transformsInfo = req.body as TransformEndpointRequest[]; try { - const body = await deleteTransforms( - transformsInfo, - deleteDestIndex, - deleteDestIndexPattern, - ctx, - license, - res - ); - - if (body && body.status) { - if (body.status === 404) { - return res.notFound(); - } - if (body.status === 403) { - return res.forbidden(); - } - } - return res.ok({ - body, + body: await deleteTransforms(transformsInfo, ctx.transform!.dataClient.callAsCurrentUser), }); } catch (e) { return res.customError(wrapError(wrapEsError(e))); @@ -269,51 +238,18 @@ const getTransforms = async (options: { transformId?: string }, callAsCurrentUse return await callAsCurrentUser('transform.getTransforms', options); }; -async function getIndexPatternId( - indexName: string, - savedObjectsClient: SavedObjectsClientContract -) { - const response = await savedObjectsClient.find({ - type: 'index-pattern', - perPage: 1, - search: `"${indexName}"`, - searchFields: ['title'], - fields: ['title'], - }); - const ip = response.saved_objects.find((obj) => obj.attributes.title === indexName); - return ip?.id; -} - -async function deleteDestIndexPatternById( - indexPatternId: string, - savedObjectsClient: SavedObjectsClientContract -) { - return await savedObjectsClient.delete('index-pattern', indexPatternId); -} - async function deleteTransforms( transformsInfo: TransformEndpointRequest[], - deleteDestIndex: boolean | undefined, - deleteDestIndexPattern: boolean | undefined, - ctx: RequestHandlerContext, - license: RouteDependencies['license'], - response: KibanaResponseFactory + callAsCurrentUser: CallCluster ) { - const tempResults: TransformEndpointResult = {}; - const results: Record = {}; + const results: TransformEndpointResult = {}; for (const transformInfo of transformsInfo) { - let destinationIndex: string | undefined; - const transformDeleted: ResultData = { success: false }; - const destIndexDeleted: ResultData = { success: false }; - const destIndexPatternDeleted: ResultData = { - success: false, - }; const transformId = transformInfo.id; try { if (transformInfo.state === TRANSFORM_STATE.FAILED) { try { - await ctx.transform!.dataClient.callAsCurrentUser('transform.stopTransform', { + await callAsCurrentUser('transform.stopTransform', { transformId, force: true, waitForCompletion: true, @@ -321,7 +257,7 @@ async function deleteTransforms( } catch (e) { if (isRequestTimeout(e)) { return fillResultsWithTimeouts({ - results: tempResults, + results, id: transformId, items: transformsInfo, action: TRANSFORM_ACTIONS.DELETE, @@ -329,75 +265,9 @@ async function deleteTransforms( } } } - // Grab destination index info to delete - try { - const transformConfigs = await getTransforms( - { transformId }, - ctx.transform!.dataClient.callAsCurrentUser - ); - const transformConfig = transformConfigs.transforms[0]; - destinationIndex = Array.isArray(transformConfig.dest.index) - ? transformConfig.dest.index[0] - : transformConfig.dest.index; - } catch (getTransformConfigError) { - transformDeleted.error = wrapError(getTransformConfigError); - results[transformId] = { - transformDeleted, - destIndexDeleted, - destIndexPatternDeleted, - destinationIndex, - }; - continue; - } - - // If user checks box to delete the destinationIndex associated with the job - if (destinationIndex && deleteDestIndex) { - try { - // If user does have privilege to delete the index, then delete the index - // if no permission then return 403 forbidden - await ctx.transform!.dataClient.callAsCurrentUser('indices.delete', { - index: destinationIndex, - }); - destIndexDeleted.success = true; - } catch (deleteIndexError) { - destIndexDeleted.error = wrapError(deleteIndexError); - } - } - - // Delete the index pattern if there's an index pattern that matches the name of dest index - if (destinationIndex && deleteDestIndexPattern) { - try { - const indexPatternId = await getIndexPatternId( - destinationIndex, - ctx.core.savedObjects.client - ); - if (indexPatternId) { - await deleteDestIndexPatternById(indexPatternId, ctx.core.savedObjects.client); - destIndexPatternDeleted.success = true; - } - } catch (deleteDestIndexPatternError) { - destIndexPatternDeleted.error = wrapError(deleteDestIndexPatternError); - } - } - try { - await ctx.transform!.dataClient.callAsCurrentUser('transform.deleteTransform', { - transformId, - }); - transformDeleted.success = true; - } catch (deleteTransformJobError) { - transformDeleted.error = wrapError(deleteTransformJobError); - if (transformDeleted.error.statusCode === 403) { - return response.forbidden(); - } - } - - results[transformId] = { - transformDeleted, - destIndexDeleted, - destIndexPatternDeleted, - destinationIndex, - }; + await callAsCurrentUser('transform.deleteTransform', { transformId }); + results[transformId] = { success: true }; } catch (e) { if (isRequestTimeout(e)) { return fillResultsWithTimeouts({ @@ -407,7 +277,7 @@ async function deleteTransforms( action: TRANSFORM_ACTIONS.DELETE, }); } - results[transformId] = { transformDeleted: { success: false, error: JSON.stringify(e) } }; + results[transformId] = { success: false, error: JSON.stringify(e) }; } } return results; diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js index b79dc3f3ffe59..2719486d0c502 100644 --- a/x-pack/test/api_integration/apis/index.js +++ b/x-pack/test/api_integration/apis/index.js @@ -30,6 +30,5 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./ingest_manager')); loadTestFile(require.resolve('./endpoint')); loadTestFile(require.resolve('./ml')); - loadTestFile(require.resolve('./transform')); }); } diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts index dc0ccfdc53a18..23bff0d0c2855 100644 --- a/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/delete.ts @@ -197,7 +197,7 @@ export default ({ getService }: FtrProviderContext) => { await ml.testResources.deleteIndexPattern(destinationIndex); }); - it('should delete job, target index, and index pattern by id', async () => { + it('deletes job, target index, and index pattern by id', async () => { const { body } = await supertest .delete(`/api/ml/data_frame/analytics/${analyticsId}`) .query({ deleteDestIndex: true, deleteDestIndexPattern: true }) diff --git a/x-pack/test/api_integration/apis/transform/delete_transforms.ts b/x-pack/test/api_integration/apis/transform/delete_transforms.ts deleted file mode 100644 index 40300c981ee2e..0000000000000 --- a/x-pack/test/api_integration/apis/transform/delete_transforms.ts +++ /dev/null @@ -1,318 +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 expect from '@kbn/expect'; -import { TransformEndpointRequest } from '../../../../plugins/transform/common'; -import { FtrProviderContext } from '../../ftr_provider_context'; -import { COMMON_REQUEST_HEADERS } from '../../../functional/services/ml/common'; -import { USER } from '../../../functional/services/transform/security_common'; - -async function asyncForEach(array: any[], callback: Function) { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array); - } -} - -// eslint-disable-next-line import/no-default-export -export default ({ getService }: FtrProviderContext) => { - const esArchiver = getService('esArchiver'); - const supertest = getService('supertestWithoutAuth'); - const transform = getService('transform'); - - function generateDestIndex(transformId: string): string { - return `user-${transformId}`; - } - - async function createTransform(transformId: string, destinationIndex: string) { - const config = { - id: transformId, - source: { index: ['farequote-*'] }, - pivot: { - group_by: { airline: { terms: { field: 'airline' } } }, - aggregations: { '@timestamp.value_count': { value_count: { field: '@timestamp' } } }, - }, - dest: { index: destinationIndex }, - }; - - await transform.api.createTransform(config); - } - - describe('delete_transforms', function () { - before(async () => { - await esArchiver.loadIfNeeded('ml/farequote'); - await transform.testResources.setKibanaTimeZoneToUTC(); - }); - - after(async () => { - await transform.api.cleanTransformIndices(); - }); - - describe('single transform deletion', function () { - const transformId = 'test1'; - const destinationIndex = generateDestIndex(transformId); - - beforeEach(async () => { - await createTransform(transformId, destinationIndex); - await transform.api.createIndices(destinationIndex); - }); - - afterEach(async () => { - await transform.api.deleteIndices(destinationIndex); - }); - - it('should delete transform by transformId', async () => { - const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; - const { body } = await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo, - }) - .expect(200); - - expect(body[transformId].transformDeleted.success).to.eql(true); - expect(body[transformId].destIndexDeleted.success).to.eql(false); - expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); - await transform.api.waitForTransformNotToExist(transformId); - await transform.api.waitForIndicesToExist(destinationIndex); - }); - - it('should return 403 for unauthorized user', async () => { - const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; - await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_VIEWER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_VIEWER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo, - }) - .expect(403); - await transform.api.waitForTransformToExist(transformId); - await transform.api.waitForIndicesToExist(destinationIndex); - }); - }); - - describe('single transform deletion with invalid transformId', function () { - it('should return 200 with error in response if invalid transformId', async () => { - const transformsInfo: TransformEndpointRequest[] = [{ id: 'invalid_transform_id' }]; - const { body } = await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo, - }) - .expect(200); - expect(body.invalid_transform_id.transformDeleted.success).to.eql(false); - expect(body.invalid_transform_id.transformDeleted).to.have.property('error'); - }); - }); - - describe('bulk deletion', function () { - const transformsInfo: TransformEndpointRequest[] = [ - { id: 'bulk_delete_test_1' }, - { id: 'bulk_delete_test_2' }, - ]; - const destinationIndices = transformsInfo.map((d) => generateDestIndex(d.id)); - - beforeEach(async () => { - await asyncForEach(transformsInfo, async ({ id }: { id: string }, idx: number) => { - await createTransform(id, destinationIndices[idx]); - await transform.api.createIndices(destinationIndices[idx]); - }); - }); - - afterEach(async () => { - await asyncForEach(destinationIndices, async (destinationIndex: string) => { - await transform.api.deleteIndices(destinationIndex); - }); - }); - - it('should delete multiple transforms by transformIds', async () => { - const { body } = await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo, - }) - .expect(200); - - await asyncForEach( - transformsInfo, - async ({ id: transformId }: { id: string }, idx: number) => { - expect(body[transformId].transformDeleted.success).to.eql(true); - expect(body[transformId].destIndexDeleted.success).to.eql(false); - expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); - await transform.api.waitForTransformNotToExist(transformId); - await transform.api.waitForIndicesToExist(destinationIndices[idx]); - } - ); - }); - - it('should delete multiple transforms by transformIds, even if one of the transformIds is invalid', async () => { - const invalidTransformId = 'invalid_transform_id'; - const { body } = await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo: [ - { id: transformsInfo[0].id }, - { id: invalidTransformId }, - { id: transformsInfo[1].id }, - ], - }) - .expect(200); - - await asyncForEach( - transformsInfo, - async ({ id: transformId }: { id: string }, idx: number) => { - expect(body[transformId].transformDeleted.success).to.eql(true); - expect(body[transformId].destIndexDeleted.success).to.eql(false); - expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); - await transform.api.waitForTransformNotToExist(transformId); - await transform.api.waitForIndicesToExist(destinationIndices[idx]); - } - ); - - expect(body[invalidTransformId].transformDeleted.success).to.eql(false); - expect(body[invalidTransformId].transformDeleted).to.have.property('error'); - }); - }); - - describe('with deleteDestIndex setting', function () { - const transformId = 'test2'; - const destinationIndex = generateDestIndex(transformId); - - before(async () => { - await createTransform(transformId, destinationIndex); - await transform.api.createIndices(destinationIndex); - }); - - after(async () => { - await transform.api.deleteIndices(destinationIndex); - }); - - it('should delete transform and destination index', async () => { - const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; - const { body } = await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo, - deleteDestIndex: true, - }) - .expect(200); - - expect(body[transformId].transformDeleted.success).to.eql(true); - expect(body[transformId].destIndexDeleted.success).to.eql(true); - expect(body[transformId].destIndexPatternDeleted.success).to.eql(false); - await transform.api.waitForTransformNotToExist(transformId); - await transform.api.waitForIndicesNotToExist(destinationIndex); - }); - }); - - describe('with deleteDestIndexPattern setting', function () { - const transformId = 'test3'; - const destinationIndex = generateDestIndex(transformId); - - before(async () => { - await createTransform(transformId, destinationIndex); - await transform.api.createIndices(destinationIndex); - await transform.testResources.createIndexPatternIfNeeded(destinationIndex); - }); - - after(async () => { - await transform.api.deleteIndices(destinationIndex); - await transform.testResources.deleteIndexPattern(destinationIndex); - }); - - it('should delete transform and destination index pattern', async () => { - const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; - const { body } = await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo, - deleteDestIndex: false, - deleteDestIndexPattern: true, - }) - .expect(200); - - expect(body[transformId].transformDeleted.success).to.eql(true); - expect(body[transformId].destIndexDeleted.success).to.eql(false); - expect(body[transformId].destIndexPatternDeleted.success).to.eql(true); - await transform.api.waitForTransformNotToExist(transformId); - await transform.api.waitForIndicesToExist(destinationIndex); - await transform.testResources.assertIndexPatternNotExist(destinationIndex); - }); - }); - - describe('with deleteDestIndex & deleteDestIndexPattern setting', function () { - const transformId = 'test4'; - const destinationIndex = generateDestIndex(transformId); - - before(async () => { - await createTransform(transformId, destinationIndex); - await transform.api.createIndices(destinationIndex); - await transform.testResources.createIndexPatternIfNeeded(destinationIndex); - }); - - after(async () => { - await transform.api.deleteIndices(destinationIndex); - await transform.testResources.deleteIndexPattern(destinationIndex); - }); - - it('should delete transform, destination index, & destination index pattern', async () => { - const transformsInfo: TransformEndpointRequest[] = [{ id: transformId }]; - const { body } = await supertest - .post(`/api/transform/delete_transforms`) - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(COMMON_REQUEST_HEADERS) - .send({ - transformsInfo, - deleteDestIndex: true, - deleteDestIndexPattern: true, - }) - .expect(200); - - expect(body[transformId].transformDeleted.success).to.eql(true); - expect(body[transformId].destIndexDeleted.success).to.eql(true); - expect(body[transformId].destIndexPatternDeleted.success).to.eql(true); - await transform.api.waitForTransformNotToExist(transformId); - await transform.api.waitForIndicesNotToExist(destinationIndex); - await transform.testResources.assertIndexPatternNotExist(destinationIndex); - }); - }); - }); -}; diff --git a/x-pack/test/api_integration/apis/transform/index.ts b/x-pack/test/api_integration/apis/transform/index.ts deleted file mode 100644 index 93a951a55ece1..0000000000000 --- a/x-pack/test/api_integration/apis/transform/index.ts +++ /dev/null @@ -1,32 +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 { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const transform = getService('transform'); - - describe('Machine Learning', function () { - this.tags(['transform']); - - before(async () => { - await transform.securityCommon.createTransformRoles(); - await transform.securityCommon.createTransformUsers(); - }); - - after(async () => { - await transform.securityCommon.cleanTransformUsers(); - await transform.securityCommon.cleanTransformRoles(); - - await esArchiver.unload('ml/farequote'); - - await transform.testResources.resetKibanaTimeZone(); - }); - - loadTestFile(require.resolve('./delete_transforms')); - }); -} diff --git a/x-pack/test/api_integration/services/index.ts b/x-pack/test/api_integration/services/index.ts index 2a0327ff57104..e7e166237c602 100644 --- a/x-pack/test/api_integration/services/index.ts +++ b/x-pack/test/api_integration/services/index.ts @@ -28,7 +28,6 @@ import { InfraLogSourceConfigurationProvider } from './infra_log_source_configur import { MachineLearningProvider } from './ml'; import { IngestManagerProvider } from './ingest_manager'; import { ResolverGeneratorProvider } from './resolver'; -import { TransformProvider } from './transform'; export const services = { ...commonServices, @@ -49,5 +48,4 @@ export const services = { ml: MachineLearningProvider, ingestManager: IngestManagerProvider, resolverGenerator: ResolverGeneratorProvider, - transform: TransformProvider, }; diff --git a/x-pack/test/api_integration/services/transform.ts b/x-pack/test/api_integration/services/transform.ts deleted file mode 100644 index 1403d5d2d67f0..0000000000000 --- a/x-pack/test/api_integration/services/transform.ts +++ /dev/null @@ -1,23 +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 { FtrProviderContext } from '../../functional/ftr_provider_context'; - -import { TransformAPIProvider } from '../../functional/services/transform/api'; -import { TransformSecurityCommonProvider } from '../../functional/services/transform/security_common'; -import { MachineLearningTestResourcesProvider } from '../../functional/services/ml/test_resources'; - -export function TransformProvider(context: FtrProviderContext) { - const api = TransformAPIProvider(context); - const securityCommon = TransformSecurityCommonProvider(context); - const testResources = MachineLearningTestResourcesProvider(context); - - return { - api, - securityCommon, - testResources, - }; -} diff --git a/x-pack/test/functional/services/transform/api.ts b/x-pack/test/functional/services/transform/api.ts index 697020fafb196..a805f5a3b6013 100644 --- a/x-pack/test/functional/services/transform/api.ts +++ b/x-pack/test/functional/services/transform/api.ts @@ -20,21 +20,6 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { const esSupertest = getService('esSupertest'); return { - async createIndices(indices: string) { - log.debug(`Creating indices: '${indices}'...`); - if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === true) { - log.debug(`Indices '${indices}' already exist. Nothing to create.`); - return; - } - - const createResponse = await es.indices.create({ index: indices }); - expect(createResponse) - .to.have.property('acknowledged') - .eql(true, 'Response for create request indices should be acknowledged.'); - - await this.waitForIndicesToExist(indices, `expected ${indices} to be created`); - }, - async deleteIndices(indices: string) { log.debug(`Deleting indices: '${indices}'...`); if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === false) { @@ -49,25 +34,11 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { .to.have.property('acknowledged') .eql(true, 'Response for delete request should be acknowledged'); - await this.waitForIndicesNotToExist(indices, `expected indices '${indices}' to be deleted`); - }, - - async waitForIndicesToExist(indices: string, errorMsg?: string) { - await retry.tryForTime(30 * 1000, async () => { - if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === true) { - return true; - } else { - throw new Error(errorMsg || `indices '${indices}' should exist`); - } - }); - }, - - async waitForIndicesNotToExist(indices: string, errorMsg?: string) { - await retry.tryForTime(30 * 1000, async () => { + await retry.waitForWithTimeout(`'${indices}' indices to be deleted`, 30 * 1000, async () => { if ((await es.indices.exists({ index: indices, allowNoIndices: false })) === false) { return true; } else { - throw new Error(errorMsg || `indices '${indices}' should not exist`); + throw new Error(`expected indices '${indices}' to be deleted`); } }); }, @@ -92,7 +63,9 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { async getTransformState(transformId: string): Promise { const stats = await this.getTransformStats(transformId); - return stats.state; + const state: TRANSFORM_STATE = stats.state; + + return state; }, async waitForTransformState(transformId: string, expectedState: TRANSFORM_STATE) { @@ -123,8 +96,8 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { }); }, - async getTransform(transformId: string, expectedCode = 200) { - return await esSupertest.get(`/_transform/${transformId}`).expect(expectedCode); + async getTransform(transformId: string) { + return await esSupertest.get(`/_transform/${transformId}`).expect(200); }, async createTransform(transformConfig: TransformPivotConfig) { @@ -132,27 +105,11 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { log.debug(`Creating transform with id '${transformId}'...`); await esSupertest.put(`/_transform/${transformId}`).send(transformConfig).expect(200); - await this.waitForTransformToExist( - transformId, - `expected transform '${transformId}' to be created` - ); - }, - - async waitForTransformToExist(transformId: string, errorMsg?: string) { - await retry.waitForWithTimeout(`'${transformId}' to exist`, 5 * 1000, async () => { - if (await this.getTransform(transformId, 200)) { - return true; - } else { - throw new Error(errorMsg || `expected transform '${transformId}' to exist`); - } - }); - }, - async waitForTransformNotToExist(transformId: string, errorMsg?: string) { - await retry.waitForWithTimeout(`'${transformId}' to exist`, 5 * 1000, async () => { - if (await this.getTransform(transformId, 404)) { + await retry.waitForWithTimeout(`'${transformId}' to be created`, 5 * 1000, async () => { + if (await this.getTransform(transformId)) { return true; } else { - throw new Error(errorMsg || `expected transform '${transformId}' to not exist`); + throw new Error(`expected transform '${transformId}' to be created`); } }); }, From ff97a034eefe2f4302cd86f47846bb386937774d Mon Sep 17 00:00:00 2001 From: Sonja Krause-Harder Date: Wed, 10 Jun 2020 21:43:57 +0200 Subject: [PATCH 43/53] Clean up main Ingest Management doc directory (#68785) --- .../images/ingest-manager-start.png | Bin 0 -> 75189 bytes docs/ingest_manager/index-templates.asciidoc | 7 - docs/ingest_manager/index.asciidoc | 212 +----------------- .../ingest_manager/dev_docs/api/epm.md | 24 ++ .../ingest_manager/dev_docs/definitions.md | 71 ++++++ x-pack/plugins/ingest_manager/dev_docs/epm.md | 30 +++ .../dev_docs/indexing_strategy.md | 77 +++++++ 7 files changed, 211 insertions(+), 210 deletions(-) create mode 100644 docs/ingest_manager/images/ingest-manager-start.png delete mode 100644 docs/ingest_manager/index-templates.asciidoc create mode 100644 x-pack/plugins/ingest_manager/dev_docs/api/epm.md create mode 100644 x-pack/plugins/ingest_manager/dev_docs/definitions.md create mode 100644 x-pack/plugins/ingest_manager/dev_docs/epm.md create mode 100644 x-pack/plugins/ingest_manager/dev_docs/indexing_strategy.md diff --git a/docs/ingest_manager/images/ingest-manager-start.png b/docs/ingest_manager/images/ingest-manager-start.png new file mode 100644 index 0000000000000000000000000000000000000000..89174686a9768ed560c30a3534fc2f4fe126651b GIT binary patch literal 75189 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 z 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 X7eBf{iQiBCvG*k#M{E4~TMz#Y+A77E literal 0 HcmV?d00001 diff --git a/docs/ingest_manager/index-templates.asciidoc b/docs/ingest_manager/index-templates.asciidoc deleted file mode 100644 index e19af63c3116f..0000000000000 --- a/docs/ingest_manager/index-templates.asciidoc +++ /dev/null @@ -1,7 +0,0 @@ -# Elasticsearch Index Templates - -## Generation - -* Index templates are generated from `YAML` files contained in the package. -* There is one index template per dataset. -* For the generation of an index template, all `yml` files contained in the package subdirectory `dataset/DATASET_NAME/fields/` are used. diff --git a/docs/ingest_manager/index.asciidoc b/docs/ingest_manager/index.asciidoc index 1728309f3dfd9..f719c774c7739 100644 --- a/docs/ingest_manager/index.asciidoc +++ b/docs/ingest_manager/index.asciidoc @@ -1,208 +1,14 @@ +[chapter] [role="xpack"] -[[epm]] -== Ingest Manager +[[xpack-ingest-manager]] += Ingest Manager -These are the docs for the Ingest Manager. +The {ingest-manager} app in Kibana enables you to add and manage integrations for popular services and platforms, as well as manage {elastic-agent} installations in standalone or {fleet} mode. +[role="screenshot"] +image::ingest_manager/images/ingest-manager-start.png[Ingest Manager App in Kibana] -=== Configuration +[float] +=== Get started -The Elastic Package Manager by default access `epr.elastic.co` to retrieve the package. The url can be configured with: - -``` -xpack.epm.registryUrl: 'http://localhost:8080' -``` - -=== API - -The Package Manager offers an API. Here an example on how they can be used. - -List installed packages: - -``` -curl localhost:5601/api/ingest_manager/epm/packages -``` - -Install a package: - -``` -curl -X POST localhost:5601/api/ingest_manager/epm/packages/iptables-1.0.4 -``` - -Delete a package: - -``` -curl -X DELETE localhost:5601/api/ingest_manager/epm/packages/iptables-1.0.4 -``` - -=== Definitions - -This section is to define terms used across ingest management. - -==== Data Source - -A data source is a definition on how to collect data from a service, for example `nginx`. A data source contains -definitions for one or multiple inputs and each input can contain one or multiple streams. - -With the example of the nginx Data Source, it contains to inputs: `logs` and `nginx/metrics`. Logs and metrics are collected -differently. The `logs` input contains two streams, `access` and `error`, the `nginx/metrics` input contains the stubstatus stream. - - -==== Data Stream - -Data Streams are a [new concept](https://github.com/elastic/elasticsearch/issues/53100) in Elasticsearch which simplify -ingesting data and the setup of Elasticsearch. - -==== Elastic Agent - -A single, unified agent that users can deploy to hosts or containers. It controls which data is collected from the host or containers and where the data is sent. It will run Beats, Endpoint or other monitoring programs as needed. It can operate standalone or pull a configuration policy from Fleet. - - -==== Elastic Package Registry - -The Elastic Package Registry (EPR) is a service which runs under [https://epr.elastic.co]. It serves the packages through its API. -More details about the registry can be found [here](https://github.com/elastic/package-registry). - -==== Fleet - -Fleet is the part of the Ingest Manager UI in Kibana that handles the part of enrolling Elastic Agents, -managing agents and sending configurations to the Elastic Agent. - -==== Indexing Strategy - -Ingest Management + Elastic Agent follow a strict new indexing strategy: `{type}-{dataset}-{namespace}`. An example -for this is `logs-nginx.access-default`. More details about it can be found in the Index Strategy below. All data of -the index strategy is sent to Data Streams. - -==== Input - -An input is the configuration unit in an Agent Config that defines the options on how to collect data from -an endpoint. This could be username / password which are need to authenticate with a service or a host url -as an example. - -An input is part of a Data Source and contains streams. - -==== Integration - -An integration is a package with the type integration. An integration package has at least 1 data source -and usually collects data from / about a service. - - -==== Namespace - -A user-specified string that will be used to part of the index name in Elasticsearch. It helps users identify logs coming from a specific environment (like prod or test), an application, or other identifiers. - - -==== Package - -A package contains all the assets for the Elastic Stack. A more detailed definition of a -package can be found under https://github.com/elastic/package-registry. - -Besides the assets, a package contains the data source definitions with its inputs and streams. - -==== Stream - -A stream is a configuration unit in the Elastic Agent config. A stream is part of an input and defines how the data -fetched by this input should be processed and which Data Stream to send it to. - -== Indexing Strategy - -Ingest Management enforces an indexing strategy to allow the system to automatically detect indices and run queries on it. In short the indexing strategy looks as following: - -``` -{dataset.type}-{dataset.name}-{dataset.namespace} -``` - -The `{dataset.type}` can be `logs` or `metrics`. The `{dataset.namespace}` is the part where the user can use free form. The only two requirement are that it has only characters allowed in an Elasticsearch index name and does NOT contain a `-`. The `dataset` is defined by the data that is indexed. The same requirements as for the namespace apply. It is expected that the fields for type, namespace and dataset are part of each event and are constant keywords. If there is a dataset or a namespace with a `-` inside, it is recommended to replace it either by a `.` or a `_`. - -Note: More `{dataset.type}`s might be added in the future like `traces`. - -This indexing strategy has a few advantages: - -* Each index contains only the fields which are relevant for the dataset. This leads to more dense indices and better field completion. -* ILM policies can be applied per namespace per dataset. -* Rollups can be specified per namespace per dataset. -* Having the namespace user configurable makes setting security permissions possible. -* Having a global metrics and logs template, allows to create new indices on demand which still follow the convention. This is common in the case of k8s as an example. -* Constant keywords allow to narrow down the indices we need to access for querying very efficiently. This is especially relevant in environments which a large number of indices or with indices on slower nodes. - -Overall it creates smaller indices in size, makes querying more efficient and allows users to define their own naming parts in namespace and still benefiting from all features that can be built on top of the indexing startegy. - -=== Ingest Pipeline - -The ingest pipelines for a specific dataset will have the following naming scheme: - -``` -{dataset.type}-{dataset.name}-{package.version} -``` - -As an example, the ingest pipeline for the Nginx access logs is called `logs-nginx.access-3.4.1`. The same ingest pipeline is used for all namespaces. It is possible that a dataset has multiple ingest pipelines in which case a suffix is added to the name. - -The version is included in each pipeline to allow upgrades. The pipeline itself is listed in the index template and is automatically applied at ingest time. - -=== Templates & ILM Policies - -To make the above strategy possible, alias templates are required. For each type there is a basic alias template with a default ILM policy. These default templates apply to all indices which follow the indexing strategy and do not have a more specific dataset alias template. - -The `metrics` and `logs` alias template contain all the basic fields from ECS. - -Each type template contains an ILM policy. Modifying this default ILM policy will affect all data covered by the default templates. - -The templates for a dataset are called as following: - -``` -{dataset.type}-{dataset.name} -``` - -The pattern used inside the index template is `{type}-{dataset}-*` to match all namespaces. - -=== Defaults - -If the Elastic Agent is used to ingest data and only the type is specified, `default` for the namespace is used and `generic` for the dataset. - -=== Data filtering - -Filtering for data in queries for example in visualizations or dashboards should always be done on the constant keyword fields. Visualizations needing data for the nginx.access dataset should query on `type:logs AND dataset:nginx.access`. As these are constant keywords the prefiltering is very efficient. - -=== Security permissions - -Security permissions can be set on different levels. To set special permissions for the access on the prod namespace, use the following index pattern: - -``` -/(logs|metrics)-[^-]+-prod-$/ -``` - -To set specific permissions on the logs index, the following can be used: - -``` -/^(logs|metrics)-.*/ -``` - -Todo: The above queries need to be tested. - - - -== Package Manager - -=== Package Upgrades - -When upgrading a package between a bugfix or a minor version, no breaking changes should happen. Upgrading a package has the following effect: - -* Removal of existing dashboards -* Installation of new dashboards -* Write new ingest pipelines with the version -* Write new Elasticsearch alias templates -* Trigger a rollover for all the affected indices - -The new ingest pipeline is expected to still work with the data coming from older configurations. In most cases this means some of the fields can be missing. For this to work, each event must contain the version of config / package it is coming from to make such a decision. - -In case of a breaking change in the data structure, the new ingest pipeline is also expected to deal with this change. In case there are breaking changes which cannot be dealt with in an ingest pipeline, a new package has to be created. - -Each package lists its minimal required agent version. In case there are agents enrolled with an older version, the user is notified to upgrade these agents as otherwise the new configs cannot be rolled out. - -=== Generated assets - -When a package is installed or upgraded, certain Kibana and Elasticsearch assets are generated from . These follow the naming conventions explained above (see "indexing strategy") and contain configuration for the elastic stack that makes ingesting and displaying data work with as little user interaction as possible. - -* link:index-templates.asciidoc[Elasticsearch Index Templates] -* Kibana Index Patterns +To get started with Ingest Management, refer to the LINK_TO_INGEST_MANAGEMENT_GUIDE[Ingest Management Guide]. \ No newline at end of file diff --git a/x-pack/plugins/ingest_manager/dev_docs/api/epm.md b/x-pack/plugins/ingest_manager/dev_docs/api/epm.md new file mode 100644 index 0000000000000..12fecc928419b --- /dev/null +++ b/x-pack/plugins/ingest_manager/dev_docs/api/epm.md @@ -0,0 +1,24 @@ +This document is part of the original drafts for ingest management documentation in `docs/ingest_manager` and may be outdated. +Overall documentation of Ingest Management is now maintained in the `elastic/stack-docs` repository. + +# Elastic Package Manager API + +The Package Manager offers an API. Here an example on how they can be used. + +List installed packages: + +``` +curl localhost:5601/api/ingest_manager/epm/packages +``` + +Install a package: + +``` +curl -X POST localhost:5601/api/ingest_manager/epm/packages/iptables-1.0.4 +``` + +Delete a package: + +``` +curl -X DELETE localhost:5601/api/ingest_manager/epm/packages/iptables-1.0.4 +``` diff --git a/x-pack/plugins/ingest_manager/dev_docs/definitions.md b/x-pack/plugins/ingest_manager/dev_docs/definitions.md new file mode 100644 index 0000000000000..0d9e285ab80d3 --- /dev/null +++ b/x-pack/plugins/ingest_manager/dev_docs/definitions.md @@ -0,0 +1,71 @@ +This document is part of the original drafts for ingest management documentation in `docs/ingest_manager` and may be outdated. +Overall documentation of Ingest Management is now maintained in the `elastic/stack-docs` repository. + +# Ingest Management Definitions + +This section is to define terms used across ingest management. + +## Data Source + +A data source is a definition on how to collect data from a service, for example `nginx`. A data source contains +definitions for one or multiple inputs and each input can contain one or multiple streams. + +With the example of the nginx Data Source, it contains to inputs: `logs` and `nginx/metrics`. Logs and metrics are collected +differently. The `logs` input contains two streams, `access` and `error`, the `nginx/metrics` input contains the stubstatus stream. + + +## Data Stream + +Data Streams are a [new concept](https://github.com/elastic/elasticsearch/issues/53100) in Elasticsearch which simplify +ingesting data and the setup of Elasticsearch. + +## Elastic Agent + +A single, unified agent that users can deploy to hosts or containers. It controls which data is collected from the host or containers and where the data is sent. It will run Beats, Endpoint or other monitoring programs as needed. It can operate standalone or pull a configuration policy from Fleet. + + +## Elastic Package Registry + +The Elastic Package Registry (EPR) is a service which runs under [https://epr.elastic.co]. It serves the packages through its API. +More details about the registry can be found [here](https://github.com/elastic/package-registry). + +## Fleet + +Fleet is the part of the Ingest Manager UI in Kibana that handles the part of enrolling Elastic Agents, +managing agents and sending configurations to the Elastic Agent. + +## Indexing Strategy + +Ingest Management + Elastic Agent follow a strict new indexing strategy: `{type}-{dataset}-{namespace}`. An example +for this is `logs-nginx.access-default`. More details about it can be found in the Index Strategy below. All data of +the index strategy is sent to Data Streams. + +## Input + +An input is the configuration unit in an Agent Config that defines the options on how to collect data from +an endpoint. This could be username / password which are need to authenticate with a service or a host url +as an example. + +An input is part of a Data Source and contains streams. + +## Integration + +An integration is a package with the type integration. An integration package has at least 1 data source +and usually collects data from / about a service. + +## Namespace + +A user-specified string that will be used to part of the index name in Elasticsearch. It helps users identify logs coming from a specific environment (like prod or test), an application, or other identifiers. + +## Package + +A package contains all the assets for the Elastic Stack. A more detailed definition of a +package can be found under https://github.com/elastic/package-registry. + +Besides the assets, a package contains the data source definitions with its inputs and streams. + +## Stream + +A stream is a configuration unit in the Elastic Agent config. A stream is part of an input and defines how the data +fetched by this input should be processed and which Data Stream to send it to. + diff --git a/x-pack/plugins/ingest_manager/dev_docs/epm.md b/x-pack/plugins/ingest_manager/dev_docs/epm.md new file mode 100644 index 0000000000000..abcab718f7ab9 --- /dev/null +++ b/x-pack/plugins/ingest_manager/dev_docs/epm.md @@ -0,0 +1,30 @@ +This document is part of the original drafts for ingest management documentation in `docs/ingest_manager` and may be outdated. +Overall documentation of Ingest Management is now maintained in the `elastic/stack-docs` repository. + +# Package Upgrades + +When upgrading a package between a bugfix or a minor version, no breaking changes should happen. Upgrading a package has the following effect: + +* Removal of existing dashboards +* Installation of new dashboards +* Write new ingest pipelines with the version +* Write new Elasticsearch alias templates +* Trigger a rollover for all the affected indices + +The new ingest pipeline is expected to still work with the data coming from older configurations. In most cases this means some of the fields can be missing. For this to work, each event must contain the version of config / package it is coming from to make such a decision. + +In case of a breaking change in the data structure, the new ingest pipeline is also expected to deal with this change. In case there are breaking changes which cannot be dealt with in an ingest pipeline, a new package has to be created. + +Each package lists its minimal required agent version. In case there are agents enrolled with an older version, the user is notified to upgrade these agents as otherwise the new configs cannot be rolled out. + +# Generated assets + +When a package is installed or upgraded, certain Kibana and Elasticsearch assets are generated from . These follow the naming conventions explained above (see "indexing strategy") and contain configuration for the elastic stack that makes ingesting and displaying data work with as little user interaction as possible. + +## Elasticsearch Index Templates + +### Generation + +* Index templates are generated from `YAML` files contained in the package. +* There is one index template per dataset. +* For the generation of an index template, all `yml` files contained in the package subdirectory `dataset/DATASET_NAME/fields/` are used. \ No newline at end of file diff --git a/x-pack/plugins/ingest_manager/dev_docs/indexing_strategy.md b/x-pack/plugins/ingest_manager/dev_docs/indexing_strategy.md new file mode 100644 index 0000000000000..fd7edcb7fcca0 --- /dev/null +++ b/x-pack/plugins/ingest_manager/dev_docs/indexing_strategy.md @@ -0,0 +1,77 @@ +This document is part of the original drafts for ingest management documentation in `docs/ingest_manager` and may be outdated. +Overall documentation of Ingest Management is now maintained in the `elastic/stack-docs` repository. + +# Indexing Strategy + +Ingest Management enforces an indexing strategy to allow the system to automatically detect indices and run queries on it. In short the indexing strategy looks as following: + +``` +{dataset.type}-{dataset.name}-{dataset.namespace} +``` + +The `{dataset.type}` can be `logs` or `metrics`. The `{dataset.namespace}` is the part where the user can use free form. The only two requirement are that it has only characters allowed in an Elasticsearch index name and does NOT contain a `-`. The `dataset` is defined by the data that is indexed. The same requirements as for the namespace apply. It is expected that the fields for type, namespace and dataset are part of each event and are constant keywords. If there is a dataset or a namespace with a `-` inside, it is recommended to replace it either by a `.` or a `_`. + +Note: More `{dataset.type}`s might be added in the future like `traces`. + +This indexing strategy has a few advantages: + +* Each index contains only the fields which are relevant for the dataset. This leads to more dense indices and better field completion. +* ILM policies can be applied per namespace per dataset. +* Rollups can be specified per namespace per dataset. +* Having the namespace user configurable makes setting security permissions possible. +* Having a global metrics and logs template, allows to create new indices on demand which still follow the convention. This is common in the case of k8s as an example. +* Constant keywords allow to narrow down the indices we need to access for querying very efficiently. This is especially relevant in environments which a large number of indices or with indices on slower nodes. + +Overall it creates smaller indices in size, makes querying more efficient and allows users to define their own naming parts in namespace and still benefiting from all features that can be built on top of the indexing startegy. + +## Ingest Pipeline + +The ingest pipelines for a specific dataset will have the following naming scheme: + +``` +{dataset.type}-{dataset.name}-{package.version} +``` + +As an example, the ingest pipeline for the Nginx access logs is called `logs-nginx.access-3.4.1`. The same ingest pipeline is used for all namespaces. It is possible that a dataset has multiple ingest pipelines in which case a suffix is added to the name. + +The version is included in each pipeline to allow upgrades. The pipeline itself is listed in the index template and is automatically applied at ingest time. + +## Templates & ILM Policies + +To make the above strategy possible, alias templates are required. For each type there is a basic alias template with a default ILM policy. These default templates apply to all indices which follow the indexing strategy and do not have a more specific dataset alias template. + +The `metrics` and `logs` alias template contain all the basic fields from ECS. + +Each type template contains an ILM policy. Modifying this default ILM policy will affect all data covered by the default templates. + +The templates for a dataset are called as following: + +``` +{dataset.type}-{dataset.name} +``` + +The pattern used inside the index template is `{type}-{dataset}-*` to match all namespaces. + +## Defaults + +If the Elastic Agent is used to ingest data and only the type is specified, `default` for the namespace is used and `generic` for the dataset. + +## Data filtering + +Filtering for data in queries for example in visualizations or dashboards should always be done on the constant keyword fields. Visualizations needing data for the nginx.access dataset should query on `type:logs AND dataset:nginx.access`. As these are constant keywords the prefiltering is very efficient. + +## Security permissions + +Security permissions can be set on different levels. To set special permissions for the access on the prod namespace, use the following index pattern: + +``` +/(logs|metrics)-[^-]+-prod-$/ +``` + +To set specific permissions on the logs index, the following can be used: + +``` +/^(logs|metrics)-.*/ +``` + +Todo: The above queries need to be tested. From b3445cad8f972ae5ca652a60ce35c9c173718637 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Wed, 10 Jun 2020 23:04:13 +0300 Subject: [PATCH 44/53] move @kbn/storybook to devDeps (#68791) Co-authored-by: Elastic Machine --- x-pack/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/package.json b/x-pack/package.json index 6a84bcf449455..680f700190726 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -36,6 +36,7 @@ "@kbn/es": "1.0.0", "@kbn/expect": "1.0.0", "@kbn/plugin-helpers": "9.0.2", + "@kbn/storybook": "1.0.0", "@kbn/test": "1.0.0", "@kbn/utility-types": "1.0.0", "@storybook/addon-actions": "^5.2.6", @@ -199,7 +200,6 @@ "@kbn/config-schema": "1.0.0", "@kbn/i18n": "1.0.0", "@kbn/interpreter": "1.0.0", - "@kbn/storybook": "1.0.0", "@kbn/ui-framework": "1.0.0", "@mapbox/geojson-rewind": "^0.4.1", "@mapbox/mapbox-gl-draw": "^1.1.2", From 49a45ecac5db4c894eb3c4989453bb0918324513 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Wed, 10 Jun 2020 16:45:09 -0400 Subject: [PATCH 45/53] [SIEM][Exceptions] - ExceptionsViewer cleanup (#68739) ### Summary - Adds missing unit tests for relevant files missing them - Changes filter search to fire request on 'Enter' - Breaks out the main ExceptionViewer component into smaller components to make more readable and better tested - Updates utility bar to have the specific list description text next to it as proposed by @spong in #68294 (comment) - Adds loading state any time async request occurs - Now fetches list on list type toggle (if user selects to view either only detections or endpoint items), before was simply filtering already fetched items --- .../lists/public/exceptions/__mocks__/api.ts | 15 + .../public/exceptions/hooks/use_api.test.tsx | 257 ++++++++++++++++++ .../hooks/use_exception_list.test.tsx | 16 +- .../exceptions/hooks/use_exception_list.tsx | 10 +- .../plugins/lists/public/exceptions/types.ts | 16 +- .../detection_engine/rules/details/index.tsx | 1 + .../exceptions_search.stories.tsx | 70 ----- .../components/exceptions/translations.ts | 2 +- .../exception_item/exception_details.tsx | 6 +- .../exception_item/exception_entries.test.tsx | 35 ++- .../exception_item/exception_entries.tsx | 24 +- .../exception_item/index.stories.tsx} | 53 ++-- .../viewer/exception_item/index.test.tsx | 7 +- .../viewer/exceptions_pagination.tsx | 21 +- .../viewer/exceptions_utility.test.tsx | 174 ++++++++++++ .../exceptions/viewer/exceptions_utility.tsx | 111 ++++++++ .../exceptions_viewer_header.stories.tsx | 67 +++++ .../viewer/exceptions_viewer_header.test.tsx | 54 +--- .../viewer/exceptions_viewer_header.tsx | 5 +- .../viewer/exceptions_viewer_item.test.tsx | 147 ++++++++++ .../viewer/exceptions_viewer_items.tsx | 100 +++++++ .../exceptions/viewer/index.test.tsx | 2 +- .../components/exceptions/viewer/index.tsx | 217 ++++----------- .../components/exceptions/viewer/reducer.ts | 24 +- 24 files changed, 1083 insertions(+), 351 deletions(-) create mode 100644 x-pack/plugins/lists/public/exceptions/hooks/use_api.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx rename x-pack/plugins/security_solution/public/common/components/exceptions/{__examples__/exception_item.stories.tsx => viewer/exception_item/index.stories.tsx} (66%) create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_item.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx diff --git a/x-pack/plugins/lists/public/exceptions/__mocks__/api.ts b/x-pack/plugins/lists/public/exceptions/__mocks__/api.ts index ecc771279b3ab..9651be0d04e8c 100644 --- a/x-pack/plugins/lists/public/exceptions/__mocks__/api.ts +++ b/x-pack/plugins/lists/public/exceptions/__mocks__/api.ts @@ -54,3 +54,18 @@ export const fetchExceptionListItemById = async ({ signal, }: ApiCallByIdProps): Promise => Promise.resolve(getExceptionListItemSchemaMock()); + +export const deleteExceptionListById = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => Promise.resolve(getExceptionListSchemaMock()); + +export const deleteExceptionListItemById = async ({ + http, + id, + namespaceType, + signal, +}: ApiCallByIdProps): Promise => + Promise.resolve(getExceptionListItemSchemaMock()); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.tsx b/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.tsx new file mode 100644 index 0000000000000..edf65839c07cf --- /dev/null +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_api.test.tsx @@ -0,0 +1,257 @@ +/* + * 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 { act, renderHook } from '@testing-library/react-hooks'; + +import * as api from '../api'; +import { createKibanaCoreStartMock } from '../../common/mocks/kibana_core'; +import { getExceptionListSchemaMock } from '../../../common/schemas/response/exception_list_schema.mock'; +import { getExceptionListItemSchemaMock } from '../../../common/schemas/response/exception_list_item_schema.mock'; +import { HttpStart } from '../../../../../../src/core/public'; +import { ApiCallByIdProps } from '../types'; + +import { ExceptionsApi, useApi } from './use_api'; + +jest.mock('../api'); + +const mockKibanaHttpService = createKibanaCoreStartMock().http; + +describe('useApi', () => { + const onErrorMock = jest.fn(); + + afterEach(() => { + onErrorMock.mockClear(); + jest.clearAllMocks(); + }); + + test('it invokes "deleteExceptionListItemById" when "deleteExceptionItem" used', async () => { + const payload = getExceptionListItemSchemaMock(); + const onSuccessMock = jest.fn(); + const spyOnDeleteExceptionListItemById = jest + .spyOn(api, 'deleteExceptionListItemById') + .mockResolvedValue(payload); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = payload; + + await result.current.deleteExceptionItem({ + id, + namespaceType, + onError: jest.fn(), + onSuccess: onSuccessMock, + }); + + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; + + expect(spyOnDeleteExceptionListItemById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); + }); + }); + + test('invokes "onError" callback if "deleteExceptionListItemById" fails', async () => { + const mockError = new Error('failed to delete item'); + jest.spyOn(api, 'deleteExceptionListItemById').mockRejectedValue(mockError); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = getExceptionListItemSchemaMock(); + + await result.current.deleteExceptionItem({ + id, + namespaceType, + onError: onErrorMock, + onSuccess: jest.fn(), + }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); + }); + }); + + test('it invokes "deleteExceptionListById" when "deleteExceptionList" used', async () => { + const payload = getExceptionListSchemaMock(); + const onSuccessMock = jest.fn(); + const spyOnDeleteExceptionListById = jest + .spyOn(api, 'deleteExceptionListById') + .mockResolvedValue(payload); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = payload; + + await result.current.deleteExceptionList({ + id, + namespaceType, + onError: jest.fn(), + onSuccess: onSuccessMock, + }); + + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; + + expect(spyOnDeleteExceptionListById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); + }); + }); + + test('invokes "onError" callback if "deleteExceptionListById" fails', async () => { + const mockError = new Error('failed to delete item'); + jest.spyOn(api, 'deleteExceptionListById').mockRejectedValue(mockError); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + + await result.current.deleteExceptionList({ + id, + namespaceType, + onError: onErrorMock, + onSuccess: jest.fn(), + }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); + }); + }); + + test('it invokes "fetchExceptionListItemById" when "getExceptionItem" used', async () => { + const payload = getExceptionListItemSchemaMock(); + const onSuccessMock = jest.fn(); + const spyOnFetchExceptionListItemById = jest + .spyOn(api, 'fetchExceptionListItemById') + .mockResolvedValue(payload); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = payload; + + await result.current.getExceptionItem({ + id, + namespaceType, + onError: jest.fn(), + onSuccess: onSuccessMock, + }); + + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; + + expect(spyOnFetchExceptionListItemById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); + }); + }); + + test('invokes "onError" callback if "fetchExceptionListItemById" fails', async () => { + const mockError = new Error('failed to delete item'); + jest.spyOn(api, 'fetchExceptionListItemById').mockRejectedValue(mockError); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + + await result.current.getExceptionItem({ + id, + namespaceType, + onError: onErrorMock, + onSuccess: jest.fn(), + }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); + }); + }); + + test('it invokes "fetchExceptionListById" when "getExceptionList" used', async () => { + const payload = getExceptionListSchemaMock(); + const onSuccessMock = jest.fn(); + const spyOnFetchExceptionListById = jest + .spyOn(api, 'fetchExceptionListById') + .mockResolvedValue(payload); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = payload; + + await result.current.getExceptionList({ + id, + namespaceType, + onError: jest.fn(), + onSuccess: onSuccessMock, + }); + + const expected: ApiCallByIdProps = { + http: mockKibanaHttpService, + id, + namespaceType, + signal: new AbortController().signal, + }; + + expect(spyOnFetchExceptionListById).toHaveBeenCalledWith(expected); + expect(onSuccessMock).toHaveBeenCalled(); + }); + }); + + test('invokes "onError" callback if "fetchExceptionListById" fails', async () => { + const mockError = new Error('failed to delete item'); + jest.spyOn(api, 'fetchExceptionListById').mockRejectedValue(mockError); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useApi(mockKibanaHttpService) + ); + await waitForNextUpdate(); + + const { id, namespace_type: namespaceType } = getExceptionListSchemaMock(); + + await result.current.getExceptionList({ + id, + namespaceType, + onError: onErrorMock, + onSuccess: jest.fn(), + }); + + expect(onErrorMock).toHaveBeenCalledWith(mockError); + }); + }); +}); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx index fbd43787a822e..eeb3ac63ee318 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.test.tsx @@ -11,7 +11,7 @@ import { createKibanaCoreStartMock } from '../../common/mocks/kibana_core'; import { getExceptionListSchemaMock } from '../../../common/schemas/response/exception_list_schema.mock'; import { getExceptionListItemSchemaMock } from '../../../common/schemas/response/exception_list_item_schema.mock'; import { ExceptionListItemSchema } from '../../../common/schemas'; -import { ExceptionList, UseExceptionListProps } from '../types'; +import { ExceptionList, UseExceptionListProps, UseExceptionListSuccess } from '../types'; import { ReturnExceptionListAndItems, useExceptionList } from './use_exception_list'; @@ -57,6 +57,7 @@ describe('useExceptionList', () => { test('fetch exception list and items', async () => { await act(async () => { + const onSuccessMock = jest.fn(); const { result, waitForNextUpdate } = renderHook< UseExceptionListProps, ReturnExceptionListAndItems @@ -65,6 +66,7 @@ describe('useExceptionList', () => { http: mockKibanaHttpService, lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, + onSuccess: onSuccessMock, }) ); await waitForNextUpdate(); @@ -78,6 +80,12 @@ describe('useExceptionList', () => { { ...getExceptionListItemSchemaMock() }, ]; + const expectedResult: UseExceptionListSuccess = { + exceptions: expectedListItemsResult, + lists: expectedListResult, + pagination: { page: 1, perPage: 20, total: 1 }, + }; + expect(result.current).toEqual([ false, expectedListResult, @@ -89,6 +97,7 @@ describe('useExceptionList', () => { }, result.current[4], ]); + expect(onSuccessMock).toHaveBeenCalledWith(expectedResult); }); }); @@ -100,13 +109,14 @@ describe('useExceptionList', () => { UseExceptionListProps, ReturnExceptionListAndItems >( - ({ filterOptions, http, lists, pagination, onError }) => - useExceptionList({ filterOptions, http, lists, onError, pagination }), + ({ filterOptions, http, lists, pagination, onError, onSuccess }) => + useExceptionList({ filterOptions, http, lists, onError, onSuccess, pagination }), { initialProps: { http: mockKibanaHttpService, lists: [{ id: 'myListId', namespaceType: 'single' }], onError: onErrorMock, + onSuccess: jest.fn(), }, } ); diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx index 1d7a63ba880bf..9595cb7b7558e 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.tsx @@ -23,9 +23,9 @@ export type ReturnExceptionListAndItems = [ * Hook for using to get an ExceptionList and it's ExceptionListItems * * @param http Kibana http service - * @param id desired ExceptionList ID (not list_id) - * @param namespaceType list namespaceType determines list space + * @param lists array of ExceptionIdentifiers for all lists to fetch * @param onError error callback + * @param onSuccess callback when all lists fetched successfully * @param filterOptions optional - filter by fields or tags * @param pagination optional * @@ -43,7 +43,7 @@ export const useExceptionList = ({ tags: [], }, onError, - dispatchListsInReducer, + onSuccess, }: UseExceptionListProps): ReturnExceptionListAndItems => { const [exceptionLists, setExceptionLists] = useState([]); const [exceptionItems, setExceptionListItems] = useState([]); @@ -116,8 +116,8 @@ export const useExceptionList = ({ exceptions = [...exceptions, ...fetchListItemsResult.data]; setExceptionListItems(exceptions); - if (dispatchListsInReducer != null) { - dispatchListsInReducer({ + if (onSuccess != null) { + onSuccess({ exceptions, lists: exceptionListsReturned, pagination: { diff --git a/x-pack/plugins/lists/public/exceptions/types.ts b/x-pack/plugins/lists/public/exceptions/types.ts index 286eb0570ebb8..013788cddc076 100644 --- a/x-pack/plugins/lists/public/exceptions/types.ts +++ b/x-pack/plugins/lists/public/exceptions/types.ts @@ -37,21 +37,19 @@ export interface ExceptionList extends ExceptionListSchema { totalItems: number; } +export interface UseExceptionListSuccess { + lists: ExceptionList[]; + exceptions: ExceptionListItemSchema[]; + pagination: Pagination; +} + export interface UseExceptionListProps { http: HttpStart; lists: ExceptionIdentifiers[]; onError: (arg: Error) => void; filterOptions?: FilterExceptionsOptions; pagination?: Pagination; - dispatchListsInReducer?: ({ - lists, - exceptions, - pagination, - }: { - lists: ExceptionList[]; - exceptions: ExceptionListItemSchema[]; - pagination: Pagination; - }) => void; + onSuccess?: (arg: UseExceptionListSuccess) => void; } export interface ExceptionIdentifiers { diff --git a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx index 0e527bf4dfc72..0021cd2f20a4b 100644 --- a/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/alerts/pages/detection_engine/rules/details/index.tsx @@ -6,6 +6,7 @@ /* eslint-disable react-hooks/rules-of-hooks */ /* eslint-disable complexity */ +// TODO: Disabling complexity is temporary till this component is refactored as part of lists UI integration import { EuiButton, diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx deleted file mode 100644 index 29cded8f69165..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exceptions_search.stories.tsx +++ /dev/null @@ -1,70 +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 { storiesOf } from '@storybook/react'; -import React from 'react'; -import { ThemeProvider } from 'styled-components'; -import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; - -import { ExceptionsViewerHeader } from '../viewer/exceptions_viewer_header'; -import { ExceptionListType } from '../types'; - -storiesOf('ExceptionsViewerHeader', module) - .add('loading', () => { - return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - onAddExceptionClick={() => {}} - /> - - ); - }) - .add('all lists', () => { - return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - onAddExceptionClick={() => {}} - /> - - ); - }) - .add('endpoint only', () => { - return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - onAddExceptionClick={() => {}} - /> - - ); - }) - .add('detections only', () => { - return ( - ({ eui: euiLightVars, darkMode: false })}> - {}} - onAddExceptionClick={() => {}} - /> - - ); - }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts index 23e9f64caf695..27dab7cf9db29 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/translations.ts @@ -135,5 +135,5 @@ export const REFRESH = i18n.translate('xpack.securitySolution.exceptions.utility export const SHOWING_EXCEPTIONS = (items: number) => i18n.translate('xpack.securitySolution.exceptions.utilityNumberExceptionsLabel', { values: { items }, - defaultMessage: 'Showing {items} exceptions', + defaultMessage: 'Showing {items} {items, plural, =1 {exception} other {exceptions}}', }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx index 12287f7cd0fa9..ce7d1d499de6e 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_details.tsx @@ -19,7 +19,7 @@ import { DescriptionListItem, ExceptionListItemSchema } from '../../types'; import { getDescriptionListContent } from '../../helpers'; import * as i18n from '../../translations'; -const StyledExceptionDetails = styled(EuiFlexItem)` +const MyExceptionDetails = styled(EuiFlexItem)` ${({ theme }) => css` background-color: ${theme.eui.euiColorLightestShade}; padding: ${theme.eui.euiSize}; @@ -68,7 +68,7 @@ const ExceptionDetailsComponent = ({ }, [showComments, onCommentsClick, exceptionItem]); return ( - + @@ -82,7 +82,7 @@ const ExceptionDetailsComponent = ({ {commentsSection} - + ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx index b2408a654b1c6..2d022591d9980 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.test.tsx @@ -44,7 +44,7 @@ describe('ExceptionEntries', () => { expect(wrapper.find('[data-test-subj="exceptionsViewerAndBadge"]')).toHaveLength(1); }); - test('it invokes "handlEdit" when edit button clicked', () => { + test('it invokes "onEdit" when edit button clicked', () => { const mockOnEdit = jest.fn(); const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> @@ -80,6 +80,39 @@ describe('ExceptionEntries', () => { expect(mockOnDelete).toHaveBeenCalledTimes(1); }); + test('it renders edit button disabled if "disableDelete" is "true"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button').at(0); + + expect(editBtn.prop('disabled')).toBeTruthy(); + }); + + test('it renders delete button in loading state if "disableDelete" is "true"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + const deleteBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0); + + expect(deleteBtn.prop('disabled')).toBeTruthy(); + expect(deleteBtn.find('.euiLoadingSpinner')).toBeTruthy(); + }); + test('it renders nested entry', () => { const parentEntry = getFormattedEntryMock(); parentEntry.operator = null; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx index 8c758e3b84f42..58667f1f78b0d 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/exception_entries.tsx @@ -22,11 +22,11 @@ import { getEmptyValue } from '../../../empty_value'; import * as i18n from '../../translations'; import { FormattedEntry } from '../../types'; -const EntriesDetails = styled(EuiFlexItem)` +const MyEntriesDetails = styled(EuiFlexItem)` padding: ${({ theme }) => theme.eui.euiSize}; `; -const StyledEditButton = styled(EuiButton)` +const MyEditButton = styled(EuiButton)` ${({ theme }) => css` background-color: ${transparentize(0.9, theme.eui.euiColorPrimary)}; border: none; @@ -34,7 +34,7 @@ const StyledEditButton = styled(EuiButton)` `} `; -const StyledRemoveButton = styled(EuiButton)` +const MyRemoveButton = styled(EuiButton)` ${({ theme }) => css` background-color: ${transparentize(0.9, theme.eui.euiColorDanger)}; border: none; @@ -42,7 +42,7 @@ const StyledRemoveButton = styled(EuiButton)` `} `; -const AndOrBadgeContainer = styled(EuiFlexItem)` +const MyAndOrBadgeContainer = styled(EuiFlexItem)` padding-top: ${({ theme }) => theme.eui.euiSizeXL}; `; @@ -118,19 +118,19 @@ const ExceptionEntriesComponent = ({ ); return ( - + {entries.length > 1 && ( - + - + )} @@ -147,7 +147,7 @@ const ExceptionEntriesComponent = ({ - {i18n.EDIT} - + - {i18n.REMOVE} - + - + ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.stories.tsx similarity index 66% rename from x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx rename to x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.stories.tsx index 5f2b0b93e9df0..de214b098d4ea 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/__examples__/exception_item.stories.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.stories.tsx @@ -3,22 +3,22 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { storiesOf } from '@storybook/react'; -import React, { ReactNode } from 'react'; +import { storiesOf, addDecorator } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import React from 'react'; import { ThemeProvider } from 'styled-components'; import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; -import { ExceptionItem } from '../viewer/exception_item'; -import { Operator } from '../types'; -import { getExceptionItemMock } from '../mocks'; +import { ExceptionItem } from './'; +import { Operator } from '../../types'; +import { getExceptionItemMock } from '../../mocks'; -const withTheme = (storyFn: () => ReactNode) => ( +addDecorator((storyFn) => ( ({ eui: euiLightVars, darkMode: false })}>{storyFn()} -); +)); -storiesOf('ExceptionItem', module) - .addDecorator(withTheme) - .add('ExceptionItem/with os', () => { +storiesOf('Components|ExceptionItem', module) + .add('with os', () => { const payload = getExceptionItemMock(); payload.description = ''; payload.comment = []; @@ -36,8 +36,8 @@ storiesOf('ExceptionItem', module) loadingItemIds={[]} commentsAccordionId={'accordion--comments'} exceptionItem={payload} - onDeleteException={() => {}} - onEditException={() => {}} + onDeleteException={action('onClick')} + onEditException={action('onClick')} /> ); }) @@ -59,8 +59,8 @@ storiesOf('ExceptionItem', module) loadingItemIds={[]} commentsAccordionId={'accordion--comments'} exceptionItem={payload} - onDeleteException={() => {}} - onEditException={() => {}} + onDeleteException={action('onClick')} + onEditException={action('onClick')} /> ); }) @@ -82,8 +82,8 @@ storiesOf('ExceptionItem', module) loadingItemIds={[]} commentsAccordionId={'accordion--comments'} exceptionItem={payload} - onDeleteException={() => {}} - onEditException={() => {}} + onDeleteException={action('onClick')} + onEditException={action('onClick')} /> ); }) @@ -98,8 +98,8 @@ storiesOf('ExceptionItem', module) loadingItemIds={[]} commentsAccordionId={'accordion--comments'} exceptionItem={payload} - onDeleteException={() => {}} - onEditException={() => {}} + onDeleteException={action('onClick')} + onEditException={action('onClick')} /> ); }) @@ -111,8 +111,21 @@ storiesOf('ExceptionItem', module) loadingItemIds={[]} commentsAccordionId={'accordion--comments'} exceptionItem={payload} - onDeleteException={() => {}} - onEditException={() => {}} + onDeleteException={action('onClick')} + onEditException={action('onClick')} + /> + ); + }) + .add('with loadingItemIds', () => { + const { id, namespace_type, ...rest } = getExceptionItemMock(); + + return ( + ); }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx index dca3afe4f9069..b4de3639944b1 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exception_item/index.test.tsx @@ -51,7 +51,7 @@ describe('ExceptionItem', () => { const editBtn = wrapper.find('[data-test-subj="exceptionsViewerEditBtn"] button').at(0); editBtn.simulate('click'); - expect(mockOnEditException).toHaveBeenCalledTimes(1); + expect(mockOnEditException).toHaveBeenCalledWith(getExceptionItemMock()); }); it('it invokes "onDeleteException" when delete button clicked', () => { @@ -73,7 +73,10 @@ describe('ExceptionItem', () => { const editBtn = wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0); editBtn.simulate('click'); - expect(mockOnDeleteException).toHaveBeenCalledTimes(1); + expect(mockOnDeleteException).toHaveBeenCalledWith({ + id: 'uuid_here', + namespaceType: 'single', + }); }); it('it renders comment accordion closed to begin with', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx index 0953a5c666c5d..2920f1a85eee7 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_pagination.tsx @@ -29,13 +29,14 @@ const ExceptionsViewerPaginationComponent = ({ }: ExceptionsViewerPaginationProps): JSX.Element => { const [isOpen, setIsOpen] = useState(false); - const closePerPageMenu = useCallback((): void => setIsOpen(false), [setIsOpen]); + const handleClosePerPageMenu = useCallback((): void => setIsOpen(false), [setIsOpen]); - const onPerPageMenuClick = useCallback((): void => setIsOpen((isPopoverOpen) => !isPopoverOpen), [ - setIsOpen, - ]); + const handlePerPageMenuClick = useCallback( + (): void => setIsOpen((isPopoverOpen) => !isPopoverOpen), + [setIsOpen] + ); - const onPageClick = useCallback( + const handlePageClick = useCallback( (pageIndex: number): void => { onPaginationChange({ filter: {}, @@ -63,14 +64,14 @@ const ExceptionsViewerPaginationComponent = ({ totalItemCount: pagination.totalItemCount, }, }); - closePerPageMenu(); + handleClosePerPageMenu(); }} data-test-subj="exceptionsPerPageItem" > {i18n.NUMBER_OF_ITEMS(rows)} )); - }, [pagination, onPaginationChange, closePerPageMenu]); + }, [pagination, onPaginationChange, handleClosePerPageMenu]); const totalPages = useMemo((): number => { if (pagination.totalItemCount > 0) { @@ -90,14 +91,14 @@ const ExceptionsViewerPaginationComponent = ({ color="text" iconType="arrowDown" iconSide="right" - onClick={onPerPageMenuClick} + onClick={handlePerPageMenuClick} data-test-subj="exceptionsPerPageBtn" > {i18n.ITEMS_PER_PAGE(pagination.pageSize)}
} isOpen={isOpen} - closePopover={closePerPageMenu} + closePopover={handleClosePerPageMenu} panelPaddingSize="none" > @@ -108,7 +109,7 @@ const ExceptionsViewerPaginationComponent = ({ diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.test.tsx new file mode 100644 index 0000000000000..d697023b2ced4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.test.tsx @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { ThemeProvider } from 'styled-components'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { ExceptionsViewerUtility } from './exceptions_utility'; + +describe('ExceptionsViewerUtility', () => { + it('it renders correct pluralized text when more than one exception exists', () => { + const wrapper = mountWithIntl( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsShowing"]').at(0).text()).toEqual( + 'Showing 2 exceptions' + ); + }); + + it('it renders correct singular text when less than two exceptions exists', () => { + const wrapper = mountWithIntl( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsShowing"]').at(0).text()).toEqual( + 'Showing 1 exception' + ); + }); + + it('it invokes "onRefreshClick" when refresh button clicked', () => { + const mockOnRefreshClick = jest.fn(); + const wrapper = mountWithIntl( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsRefresh"] button').simulate('click'); + + expect(mockOnRefreshClick).toHaveBeenCalledTimes(1); + }); + + it('it does not render any messages when "showEndpointList" and "showDetectionsList" are "false"', () => { + const wrapper = mountWithIntl( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEndpointMessage"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="exceptionsDetectionsMessage"]').exists()).toBeFalsy(); + }); + + it('it does render detections messages when "showDetectionsList" is "true"', () => { + const wrapper = mountWithIntl( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEndpointMessage"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="exceptionsDetectionsMessage"]').exists()).toBeTruthy(); + }); + + it('it does render endpoint messages when "showEndpointList" is "true"', () => { + const wrapper = mountWithIntl( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEndpointMessage"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="exceptionsDetectionsMessage"]').exists()).toBeFalsy(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.tsx new file mode 100644 index 0000000000000..9ab4e170f4090 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_utility.tsx @@ -0,0 +1,111 @@ +/* + * 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 { EuiText, EuiLink, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { FormattedMessage } from 'react-intl'; +import styled from 'styled-components'; + +import * as i18n from '../translations'; +import { ExceptionsPagination, FilterOptions } from '../types'; +import { + UtilityBar, + UtilityBarSection, + UtilityBarGroup, + UtilityBarText, + UtilityBarAction, +} from '../../utility_bar'; + +const StyledText = styled(EuiText)` + font-style: italic; +`; + +const MyUtilities = styled(EuiFlexGroup)` + height: 50px; +`; + +interface ExceptionsViewerUtilityProps { + pagination: ExceptionsPagination; + filterOptions: FilterOptions; + ruleSettingsUrl: string; + onRefreshClick: () => void; +} + +const ExceptionsViewerUtilityComponent: React.FC = ({ + pagination, + filterOptions, + ruleSettingsUrl, + onRefreshClick, +}): JSX.Element => ( + + + + + + + {i18n.SHOWING_EXCEPTIONS(pagination.totalItemCount ?? 0)} + + + + + + {i18n.REFRESH} + + + + + + + + {filterOptions.showEndpointList && ( + + + + ), + }} + /> + )} + {filterOptions.showDetectionsList && ( + + + + ), + }} + /> + )} + + + +); + +ExceptionsViewerUtilityComponent.displayName = 'ExceptionsViewerUtilityComponent'; + +export const ExceptionsViewerUtility = React.memo(ExceptionsViewerUtilityComponent); + +ExceptionsViewerUtility.displayName = 'ExceptionsViewerUtility'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx new file mode 100644 index 0000000000000..796af7cd760e2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.stories.tsx @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { storiesOf, addDecorator } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import React from 'react'; +import { ThemeProvider } from 'styled-components'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { ExceptionsViewerHeader } from './exceptions_viewer_header'; +import { ExceptionListType } from '../types'; + +addDecorator((storyFn) => ( + ({ eui: euiLightVars, darkMode: false })}>{storyFn()} +)); + +storiesOf('Components|ExceptionsViewerHeader', module) + .add('loading', () => { + return ( + + ); + }) + .add('all lists', () => { + return ( + + ); + }) + .add('endpoint only', () => { + return ( + + ); + }) + .add('detections only', () => { + return ( + + ); + }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx index bdc99370a6293..c609a2296b83d 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.test.tsx @@ -269,7 +269,7 @@ describe('ExceptionsViewerHeader', () => { expect(mockOnAddExceptionClick).toHaveBeenCalledTimes(1); }); - it('it invokes "onFilterChange" with filter value when search used', () => { + it('it invokes "onFilterChange" when search used and "Enter" pressed', () => { const mockOnFilterChange = jest.fn(); const wrapper = mount( ({ eui: euiLightVars, darkMode: false })}> @@ -284,54 +284,12 @@ describe('ExceptionsViewerHeader', () => { ); - wrapper - .find('input[data-test-subj="exceptionsHeaderSearch"]') - .at(0) - .simulate('change', { - target: { value: 'host' }, - }); - - expect(mockOnFilterChange).toHaveBeenCalledWith({ - filter: { - filter: 'host', - showDetectionsList: false, - showEndpointList: false, - tags: [], - }, - pagination: {}, + wrapper.find('EuiFieldSearch').at(0).simulate('keyup', { + charCode: 13, + code: 'Enter', + key: 'Enter', }); - }); - - it('it invokes "onFilterChange" with tags values when search value includes "tags:..."', () => { - const mockOnFilterChange = jest.fn(); - const wrapper = mount( - ({ eui: euiLightVars, darkMode: false })}> - - - ); - - wrapper - .find('input[data-test-subj="exceptionsHeaderSearch"]') - .at(0) - .simulate('change', { - target: { value: 'tags:malware' }, - }); - expect(mockOnFilterChange).toHaveBeenCalledWith({ - filter: { - filter: '', - showDetectionsList: false, - showEndpointList: false, - tags: ['malware'], - }, - pagination: {}, - }); + expect(mockOnFilterChange).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx index 92a8830310b51..0a630414e3267 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_header.tsx @@ -69,8 +69,7 @@ const ExceptionsViewerHeaderComponent = ({ }, [showEndpointList, setShowEndpointList, setShowDetectionsList]); const handleOnSearch = useCallback( - (event: React.ChangeEvent): void => { - const searchValue = event.target.value; + (searchValue: string): void => { const tagsRegex = /(tags:[^\s]*)/i; const tagsMatch = searchValue.match(tagsRegex); const foundTags: string = tagsMatch != null ? tagsMatch[0].split(':')[1] : ''; @@ -121,7 +120,7 @@ const ExceptionsViewerHeaderComponent = ({ data-test-subj="exceptionsHeaderSearch" aria-label={i18n.SEARCH_DEFAULT} placeholder={i18n.SEARCH_DEFAULT} - onChange={handleOnSearch} + onSearch={handleOnSearch} disabled={isInitLoading} incremental={false} fullWidth diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_item.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_item.test.tsx new file mode 100644 index 0000000000000..dbcae20eb1385 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_item.test.tsx @@ -0,0 +1,147 @@ +/* + * 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 { ThemeProvider } from 'styled-components'; +import { mount } from 'enzyme'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; + +import { getExceptionItemMock } from '../mocks'; +import { ExceptionsViewerItems } from './exceptions_viewer_items'; + +describe('ExceptionsViewerItems', () => { + it('it renders empty prompt if "showEmpty" is "true"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeFalsy(); + }); + + it('it renders exceptions if "showEmpty" and "isInitLoading" is "false", and exceptions exist', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeFalsy(); + }); + + it('it does not render exceptions if "isInitLoading" is "true"', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="exceptionsContainer"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="exceptionsEmptyPrompt"]').exists()).toBeTruthy(); + }); + + it('it does not render or badge for first exception displayed', () => { + const exception1 = getExceptionItemMock(); + const exception2 = getExceptionItemMock(); + exception2.id = 'newId'; + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + const firstExceptionItem = wrapper.find('[data-test-subj="exceptionItemContainer"]').at(0); + + expect(firstExceptionItem.find('[data-test-subj="exceptionItemOrBadge"]').exists()).toBeFalsy(); + }); + + it('it does render or badge with exception displayed', () => { + const exception1 = getExceptionItemMock(); + const exception2 = getExceptionItemMock(); + exception2.id = 'newId'; + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + const notFirstExceptionItem = wrapper.find('[data-test-subj="exceptionItemContainer"]').at(1); + + expect( + notFirstExceptionItem.find('[data-test-subj="exceptionItemOrBadge"]').exists() + ).toBeFalsy(); + }); + + it('it invokes "onDeleteException" when delete button is clicked', () => { + const mockOnDeleteException = jest.fn(); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + wrapper.find('[data-test-subj="exceptionsViewerDeleteBtn"] button').at(0).simulate('click'); + + expect(mockOnDeleteException).toHaveBeenCalledWith({ + id: 'uuid_here', + namespaceType: 'single', + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx new file mode 100644 index 0000000000000..e1ef3c10188b3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import styled from 'styled-components'; + +import * as i18n from '../translations'; +import { ExceptionListItemSchema, ApiProps } from '../types'; +import { ExceptionItem } from './exception_item'; +import { AndOrBadge } from '../../and_or_badge'; + +const MyFlexItem = styled(EuiFlexItem)` + margin: ${({ theme }) => `${theme.eui.euiSize} 0`}; + + &:first-child { + margin: ${({ theme }) => `${theme.eui.euiSizeXS} 0 ${theme.eui.euiSize}`}; + } +`; + +const MyExceptionsContainer = styled(EuiFlexGroup)` + height: 600px; + overflow: hidden; +`; + +const MyExceptionItemContainer = styled(EuiFlexGroup)` + margin: ${({ theme }) => `0 ${theme.eui.euiSize} ${theme.eui.euiSize} 0`}; +`; + +interface ExceptionsViewerItemsProps { + showEmpty: boolean; + isInitLoading: boolean; + exceptions: ExceptionListItemSchema[]; + loadingItemIds: ApiProps[]; + commentsAccordionId: string; + onDeleteException: (arg: ApiProps) => void; + onEditExceptionItem: (item: ExceptionListItemSchema) => void; +} + +const ExceptionsViewerItemsComponent: React.FC = ({ + showEmpty, + isInitLoading, + exceptions, + loadingItemIds, + commentsAccordionId, + onDeleteException, + onEditExceptionItem, +}): JSX.Element => ( + + {showEmpty || isInitLoading ? ( + + {i18n.EXCEPTION_EMPTY_PROMPT_TITLE}

} + body={

{i18n.EXCEPTION_EMPTY_PROMPT_BODY}

} + data-test-subj="exceptionsEmptyPrompt" + /> + + ) : ( + + + {!isInitLoading && + exceptions.length > 0 && + exceptions.map((exception, index) => ( + + {index !== 0 ? ( + <> + + + + ) : ( + + )} + + + ))} + + + )} + +); + +ExceptionsViewerItemsComponent.displayName = 'ExceptionsViewerItemsComponent'; + +export const ExceptionsViewerItems = React.memo(ExceptionsViewerItemsComponent); + +ExceptionsViewerItems.displayName = 'ExceptionsViewerItems'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx index cc8e8111064bc..b77b8380c39f1 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.test.tsx @@ -46,7 +46,7 @@ describe('ExceptionsViewer', () => { ]); }); - it('it renders loader if "initLoading" is true', () => { + it('it renders loader if "loadingList" is true', () => { (useExceptionList as jest.Mock).mockReturnValue([ true, [], diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx index 3cf59c7dda023..1051962852219 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx @@ -4,21 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback, useState, useMemo, useEffect, useReducer } from 'react'; -import { - EuiEmptyPrompt, - EuiText, - EuiLink, - EuiOverlayMask, - EuiModal, - EuiModalBody, - EuiCodeBlock, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, -} from '@elastic/eui'; -import { FormattedMessage } from 'react-intl'; -import styled from 'styled-components'; +import React, { useCallback, useMemo, useEffect, useReducer } from 'react'; +import { EuiOverlayMask, EuiModal, EuiModalBody, EuiCodeBlock, EuiSpacer } from '@elastic/eui'; import uuid from 'uuid'; import * as i18n from '../translations'; @@ -40,25 +27,9 @@ import { ExceptionIdentifiers, useApi, } from '../../../../../public/lists_plugin_deps'; -import { ExceptionItem } from './exception_item'; -import { AndOrBadge } from '../../and_or_badge'; import { ExceptionsViewerPagination } from './exceptions_pagination'; -import { - UtilityBar, - UtilityBarSection, - UtilityBarGroup, - UtilityBarText, - UtilityBarAction, -} from '../../utility_bar'; - -const StyledText = styled(EuiText)` - font-style: italic; -`; - -const MyExceptionsContainer = styled.div` - height: 600px; - overflow: hidden; -`; +import { ExceptionsViewerUtility } from './exceptions_utility'; +import { ExceptionsViewerItems } from './exceptions_viewer_items'; const initialState: State = { filterOptions: { filter: '', showEndpointList: false, showDetectionsList: false, tags: [] }, @@ -73,7 +44,9 @@ const initialState: State = { allExceptions: [], exceptions: [], exceptionToEdit: null, + loadingLists: [], loadingItemIds: [], + isInitLoading: true, isModalOpen: false, }; @@ -99,7 +72,6 @@ const ExceptionsViewerComponent = ({ }: ExceptionsViewerProps): JSX.Element => { const { services } = useKibana(); const [, dispatchToaster] = useStateToaster(); - const [initLoading, setInitLoading] = useState(true); const onDispatchToaster = useCallback( ({ title, color, iconType }) => (): void => { dispatchToaster({ @@ -114,7 +86,6 @@ const ExceptionsViewerComponent = ({ }, [dispatchToaster] ); - const { deleteExceptionItem } = useApi(services.http); const [ { endpointList, @@ -122,13 +93,15 @@ const ExceptionsViewerComponent = ({ exceptions, filterOptions, pagination, + loadingLists, loadingItemIds, + isInitLoading, isModalOpen, }, dispatch, - ] = useReducer(allExceptionItemsReducer(), initialState); + ] = useReducer(allExceptionItemsReducer(), { ...initialState, loadingLists: exceptionListsMeta }); + const { deleteExceptionItem } = useApi(services.http); - // TODO: Update icky typing once api updated const setExceptions = useCallback( ({ lists: newLists, @@ -146,14 +119,14 @@ const ExceptionsViewerComponent = ({ ); const [loadingList, , , , fetchList] = useExceptionList({ http: services.http, - lists: exceptionListsMeta, + lists: loadingLists, filterOptions, pagination: { page: pagination.pageIndex + 1, perPage: pagination.pageSize, total: pagination.totalItemCount, }, - dispatchListsInReducer: setExceptions, + onSuccess: setExceptions, onError: onDispatchToaster({ color: 'danger', title: i18n.FETCH_LIST_ERROR, @@ -171,24 +144,25 @@ const ExceptionsViewerComponent = ({ [dispatch] ); - const onFetchList = useCallback((): void => { + const handleFetchList = useCallback((): void => { if (fetchList != null) { fetchList(); } }, [fetchList]); - const onFiltersChange = useCallback( + const handleFilterChange = useCallback( ({ filter, pagination: pag }: Filter): void => { dispatch({ type: 'updateFilterOptions', filterOptions: filter, pagination: pag, + allLists: exceptionListsMeta, }); }, - [dispatch] + [dispatch, exceptionListsMeta] ); - const onAddException = useCallback( + const handleAddException = useCallback( (type: ExceptionListType): void => { setIsModalOpen(true); }, @@ -219,9 +193,9 @@ const ExceptionsViewerComponent = ({ onAssociateList(listId); } - onFetchList(); + handleFetchList(); }, - [setIsModalOpen, onFetchList, onAssociateList] + [setIsModalOpen, handleFetchList, onAssociateList] ); const setLoadingItemIds = useCallback( @@ -236,12 +210,14 @@ const ExceptionsViewerComponent = ({ const handleDeleteException = useCallback( ({ id, namespaceType }: ApiProps) => { + setLoadingItemIds([{ id, namespaceType }]); + deleteExceptionItem({ id, namespaceType, onSuccess: () => { setLoadingItemIds(loadingItemIds.filter((t) => t.id !== id)); - onFetchList(); + handleFetchList(); }, onError: () => { const dispatchToasterError = onDispatchToaster({ @@ -255,65 +231,29 @@ const ExceptionsViewerComponent = ({ }, }); }, - [setLoadingItemIds, deleteExceptionItem, loadingItemIds, onFetchList, onDispatchToaster] + [setLoadingItemIds, deleteExceptionItem, loadingItemIds, handleFetchList, onDispatchToaster] ); // Logic for initial render useEffect((): void => { - if (initLoading && !loadingList && (exceptions.length === 0 || exceptions != null)) { - setInitLoading(false); + if (isInitLoading && !loadingList && (exceptions.length === 0 || exceptions != null)) { + dispatch({ + type: 'updateIsInitLoading', + loading: false, + }); } - }, [initLoading, exceptions, loadingList]); + }, [isInitLoading, exceptions, loadingList, dispatch]); + // Used in utility bar info text const ruleSettingsUrl = useMemo((): string => { return services.application.getUrlForApp( `security#/detections/rules/id/${encodeURI(ruleId)}/edit` ); }, [ruleId, services.application]); - const exceptionsSubtext = useMemo((): JSX.Element => { - if (filterOptions.showEndpointList) { - return ( - - - - ), - }} - /> - ); - } else if (filterOptions.showDetectionsList) { - return ( - - - - ), - }} - /> - ); - } else { - return <>; - } - }, [filterOptions.showEndpointList, filterOptions.showDetectionsList, ruleSettingsUrl]); - const showEmpty = useMemo((): boolean => { - return !initLoading && !loadingList && exceptions.length === 0; - }, [initLoading, exceptions.length, loadingList]); + return !isInitLoading && !loadingList && exceptions.length === 0; + }, [isInitLoading, exceptions.length, loadingList]); return ( <> @@ -329,80 +269,43 @@ const ExceptionsViewerComponent = ({ )} - - {initLoading && } + + {(isInitLoading || loadingList) && ( + + )} - {(filterOptions.showEndpointList || filterOptions.showDetectionsList) && ( - <> - - {exceptionsSubtext} - - )} - - - - - - {i18n.SHOWING_EXCEPTIONS(pagination.totalItemCount ?? 0)} - - - - - - {i18n.REFRESH} - - - - - - - - - {showEmpty && ( - {i18n.EXCEPTION_EMPTY_PROMPT_TITLE}} - body={

{i18n.EXCEPTION_EMPTY_PROMPT_BODY}

} - data-test-subj="exceptionsEmptyPrompt" - /> - )} - - - - - {!initLoading && - exceptions.length > 0 && - exceptions.map((exception, index) => ( - - {index !== 0 && ( - <> - - - - )} - - - ))} - -
- + + + + +
); diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts index 40d5bb5f0a297..538207458f0ed 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts @@ -10,7 +10,7 @@ import { ExceptionListItemSchema, Pagination, } from '../types'; -import { ExceptionList } from '../../../../../public/lists_plugin_deps'; +import { ExceptionList, ExceptionIdentifiers } from '../../../../../public/lists_plugin_deps'; export interface State { filterOptions: FilterOptions; @@ -20,7 +20,9 @@ export interface State { allExceptions: ExceptionListItemSchema[]; exceptions: ExceptionListItemSchema[]; exceptionToEdit: ExceptionListItemSchema | null; + loadingLists: ExceptionIdentifiers[]; loadingItemIds: ApiProps[]; + isInitLoading: boolean; isModalOpen: boolean; } @@ -35,7 +37,9 @@ export type Action = type: 'updateFilterOptions'; filterOptions: Partial; pagination: Partial; + allLists: ExceptionIdentifiers[]; } + | { type: 'updateIsInitLoading'; loading: boolean } | { type: 'updateModalOpen'; isOpen: boolean } | { type: 'updateExceptionToEdit'; exception: ExceptionListItemSchema } | { type: 'updateLoadingItemIds'; items: ApiProps[] }; @@ -78,26 +82,34 @@ export const allExceptionItemsReducer = () => (state: State, action: Action): St }; if (action.filterOptions.showEndpointList) { - const exceptions = state.allExceptions.filter((t) => t._tags.includes('endpoint')); + const list = action.allLists.filter((t) => t.type === 'endpoint'); return { ...returnState, - exceptions, + loadingLists: list, + exceptions: list.length === 0 ? [] : [...state.exceptions], }; } else if (action.filterOptions.showDetectionsList) { - const exceptions = state.allExceptions.filter((t) => t._tags.includes('detection')); + const list = action.allLists.filter((t) => t.type === 'detection'); return { ...returnState, - exceptions, + loadingLists: list, + exceptions: list.length === 0 ? [] : [...state.exceptions], }; } else { return { ...returnState, - exceptions: state.allExceptions, + loadingLists: action.allLists, }; } } + case 'updateIsInitLoading': { + return { + ...state, + isInitLoading: action.loading, + }; + } case 'updateLoadingItemIds': { return { ...state, From dfa4cdf05a140e5eab794822b86203440be32681 Mon Sep 17 00:00:00 2001 From: Suyog Rao Date: Wed, 10 Jun 2020 13:48:02 -0700 Subject: [PATCH 46/53] Use Github token instead for project assignments --- .github/workflows/project-assigner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project-assigner.yml b/.github/workflows/project-assigner.yml index eb5827e121c74..30032c9a7f998 100644 --- a/.github/workflows/project-assigner.yml +++ b/.github/workflows/project-assigner.yml @@ -12,6 +12,6 @@ jobs: id: project_assigner with: issue-mappings: '[{"label": "Team:AppArch", "projectNumber": 37, "columnName": "To triage"}, {"label": "Feature:Lens", "projectNumber": 32, "columnName": "Long-term goals"}, {"label": "Team:Canvas", "projectNumber": 38, "columnName": "Inbox"}]' - ghToken: ${{ secrets.PROJECT_ASSIGNER_TOKEN }} + ghToken: ${{ secrets.GITHUB_TOKEN }} From 28d9c1407c7f24954883279dac86e2fb3238f5d2 Mon Sep 17 00:00:00 2001 From: Suyog Rao Date: Wed, 10 Jun 2020 13:50:14 -0700 Subject: [PATCH 47/53] revert previous commit which was unintentional sorry, i thought i was making this change to a different repo --- .github/workflows/project-assigner.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project-assigner.yml b/.github/workflows/project-assigner.yml index 30032c9a7f998..eb5827e121c74 100644 --- a/.github/workflows/project-assigner.yml +++ b/.github/workflows/project-assigner.yml @@ -12,6 +12,6 @@ jobs: id: project_assigner with: issue-mappings: '[{"label": "Team:AppArch", "projectNumber": 37, "columnName": "To triage"}, {"label": "Feature:Lens", "projectNumber": 32, "columnName": "Long-term goals"}, {"label": "Team:Canvas", "projectNumber": 38, "columnName": "Inbox"}]' - ghToken: ${{ secrets.GITHUB_TOKEN }} + ghToken: ${{ secrets.PROJECT_ASSIGNER_TOKEN }} From 577381d821b9c61fc927a9ccca2dd06a724948c0 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Wed, 10 Jun 2020 17:10:34 -0400 Subject: [PATCH 48/53] [Endpoint] Functional Tests cleanup (#68756) * Removed several unnecessary disabled eslint rules * moved common pageobject from endpoint_list to page_utils * Rename functional_endpoint to security_solution_endpoint * Delete `functional_endpoint_ingest_failure` no longer applicable --- .github/CODEOWNERS | 3 +- .../components/management_page_view.tsx | 3 +- .../view/details/host_details.tsx | 9 +-- .../public/management/store/reducer.ts | 1 - x-pack/scripts/functional_tests.js | 2 +- .../page_objects/page_utils.ts | 30 -------- .../apps/endpoint/index.ts | 14 ---- .../apps/endpoint/landing_page.ts | 22 ------ .../config.ts | 30 -------- .../ftr_provider_context.d.ts | 12 --- x-pack/test/plugin_functional/config.ts | 2 +- .../apps/endpoint/alerts.ts | 0 .../apps/endpoint/endpoint_list.ts | 6 +- .../apps/endpoint/index.ts | 0 .../apps/endpoint/policy_details.ts | 0 .../apps/endpoint/policy_list.ts | 10 ++- .../apps/endpoint/resolver.ts | 0 .../config.ts | 0 .../ftr_provider_context.d.ts | 0 .../page_objects/endpoint_alerts_page.ts | 0 .../page_objects/endpoint_page.ts | 48 +----------- .../page_objects/index.ts | 0 .../page_objects/page_utils.ts | 76 +++++++++++++++++++ .../page_objects/policy_page.ts | 0 .../services/endpoint_policy.ts | 0 .../services/index.ts | 0 26 files changed, 95 insertions(+), 173 deletions(-) delete mode 100644 x-pack/test/functional_endpoint/page_objects/page_utils.ts delete mode 100644 x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/index.ts delete mode 100644 x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/landing_page.ts delete mode 100644 x-pack/test/functional_endpoint_ingest_failure/config.ts delete mode 100644 x-pack/test/functional_endpoint_ingest_failure/ftr_provider_context.d.ts rename x-pack/test/{functional_endpoint => security_solution_endpoint}/apps/endpoint/alerts.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/apps/endpoint/endpoint_list.ts (97%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/apps/endpoint/index.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/apps/endpoint/policy_details.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/apps/endpoint/policy_list.ts (92%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/apps/endpoint/resolver.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/config.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/ftr_provider_context.d.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/page_objects/endpoint_alerts_page.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/page_objects/endpoint_page.ts (61%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/page_objects/index.ts (100%) create mode 100644 x-pack/test/security_solution_endpoint/page_objects/page_utils.ts rename x-pack/test/{functional_endpoint => security_solution_endpoint}/page_objects/policy_page.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/services/endpoint_policy.ts (100%) rename x-pack/test/{functional_endpoint => security_solution_endpoint}/services/index.ts (100%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 472d29ed29413..07546fa54ce4f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -222,8 +222,7 @@ /x-pack/plugins/endpoint/ @elastic/endpoint-app-team @elastic/siem /x-pack/test/api_integration/apis/endpoint/ @elastic/endpoint-app-team @elastic/siem /x-pack/test/endpoint_api_integration_no_ingest/ @elastic/endpoint-app-team @elastic/siem -/x-pack/test/functional_endpoint/ @elastic/endpoint-app-team @elastic/siem -/x-pack/test/functional_endpoint_ingest_failure/ @elastic/endpoint-app-team @elastic/siem +/x-pack/test/security_solution_endpoint/ @elastic/endpoint-app-team @elastic/siem /x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team @elastic/siem /x-pack/test/plugin_functional/plugins/resolver_test/ @elastic/endpoint-app-team @elastic/siem /x-pack/test/plugin_functional/test_suites/resolver/ @elastic/endpoint-app-team @elastic/siem diff --git a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx b/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx index 4fbbcfc8d948a..8f7e0e06fb7a1 100644 --- a/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx +++ b/x-pack/plugins/security_solution/public/management/components/management_page_view.tsx @@ -35,8 +35,7 @@ export const ManagementPageView = memo>((options) => href: getManagementUrl({ name: 'policyList' }), }, ]; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [tabName]); + }, [options.viewType, tabName]); return ; }); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx index 6c447df618791..9b0ca73cf021f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/host_details.tsx @@ -137,15 +137,14 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => { description: details.agent.version, }, ]; - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ - details.agent.version, details.endpoint.policy.id, - details.host.hostname, details.host.ip, - policyResponseUri.search, - policyStatusClickHandler, + details.host.hostname, + details.agent.version, policyStatus, + policyResponseUri, + policyStatusClickHandler, ]); return ( diff --git a/x-pack/plugins/security_solution/public/management/store/reducer.ts b/x-pack/plugins/security_solution/public/management/store/reducer.ts index e00b3ec9e0f5b..2ed3dfe86d2f8 100644 --- a/x-pack/plugins/security_solution/public/management/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/management/store/reducer.ts @@ -40,6 +40,5 @@ export const mockManagementState: Immutable = { export const managementReducer = immutableCombineReducers({ [MANAGEMENT_STORE_POLICY_LIST_NAMESPACE]: policyListReducer, [MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE]: policyDetailsReducer, - // @ts-ignore [MANAGEMENT_STORE_ENDPOINTS_NAMESPACE]: hostListReducer, }); diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index c120e1f780761..37b22a687741e 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -6,7 +6,7 @@ const alwaysImportedTests = [ require.resolve('../test/functional/config.js'), - require.resolve('../test/functional_endpoint/config.ts'), + require.resolve('../test/security_solution_endpoint/config.ts'), require.resolve('../test/functional_with_es_ssl/config.ts'), require.resolve('../test/functional/config_security_basic.ts'), require.resolve('../test/functional/config_security_trial.ts'), diff --git a/x-pack/test/functional_endpoint/page_objects/page_utils.ts b/x-pack/test/functional_endpoint/page_objects/page_utils.ts deleted file mode 100644 index daf66464f7e1e..0000000000000 --- a/x-pack/test/functional_endpoint/page_objects/page_utils.ts +++ /dev/null @@ -1,30 +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 { FtrProviderContext } from '../ftr_provider_context'; - -export function EndpointPageUtils({ getService }: FtrProviderContext) { - const find = getService('find'); - - return { - /** - * Finds a given EuiCheckbox by test subject and clicks on it - * - * @param euiCheckBoxTestId - */ - async clickOnEuiCheckbox(euiCheckBoxTestId: string) { - // This utility is needed because EuiCheckbox forwards the test subject on to - // the actual `` which is not actually visible/accessible on the page. - // In order to actually cause the state of the checkbox to change, the `

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 aH+8OOgGZutwn`3x*EKaA)qLgOL;erfWa<(C diff --git a/docs/logs/images/log-rate-anomalies.png b/docs/logs/images/log-rate-anomalies.png deleted file mode 100644 index 74ce8d682e1cc8818aae03899b94567b3638bb68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305676 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ℑxo#KH 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 kKP^ej!9E zN-ktJO!drM3_Kd#Nn{HNwo8__{ZUwL##C?jLP@-C-0|ikF&bh))asxExcONy)l~bY zu?0w>s{E&`=<2vpbzC*165_N>l!HI1Cs{pP)cyF)NOR?Kg%LPUEe4M);KqXr_AXE~ zY;jnwNc^laE%DKi{9!i{nCXB+e3M%9>EU_>EuU4$^w>2gV&N7*4R-)RQNZv!wfx z;)<_`W-_K42dlk_qnEaFGC@xpK2|~4w{^B(-oe!G17mvr#E)U#KjKIx`R|`@#)>l= z9#qjwK9C2^>=o^)1ln}3YNt*0&0nn0L#4FJdzu0%I9b`4> zb|1p+f=xpzwd$bBxhxKQUa~9CJEkn9mOh1(igw2z4@%n;o9;H*UmbKQT_ei^));3k z9(?QP1N}06c?@*=fg9kv_of=p7i76rpR5?FxLutGNZ~{eUa-^~uInX#u`p6par32b z!$svZ55XN=dT+J%D(Wbmatkd#TxC_U5zOrt`F;qN96Fv3lw+edo4f7T#0Mh!9nv90 zBREvCgQ|9LrbhKXg~OtyEHg5tT5|;jqEV7Vn>5Vl3`Q%u{2SjTYiB!1B`HPi*i1KQ z)!oM_C|zyL){V18%?LNm-o`dIiC_x@0=Z2$o|MAMX4q0pr?d0dTM^26thuiF#|>Ff z#?<(L>2(iCweDHO^CLQq8w4~gsA(;_CCU3W@=`3`eX!_FNkD#dIjMW_63?<;@_C}h=I(|m~#=fT`Ou$XsCk|Wl zJgWA})c5CF$II%fqfg2L+fpk(#lUMVuUq!=hJ}Mj_P%oGi51Xy@jMH#6Y*DLOIPWU zeLCWam1-+QBX!XY(pB;^#t6gIfU)8&HmSaSD}s?Vyp}=lox8sNn79Re5r=L{gfZ>X z;h@_%60+1U1zI2}36LN^^`*fV0i%shxJ3;I#$(%ovM*_pyqxUsd;k8+wim%3kkQ1m zc6aHMfs0-_($!V)1AdbqT4xX&c)?=6$MAxx_h!2+jDUE4fQ(qctiT+$1s*}hIAovq zrMT^B;h$D>;Se1|mTz&R_2-xG7g@#=D}KN$7jC z{T9}nq95_fp7|;C6sS<=-@9VK!&&-E{_}9xP79gHtSdh}cKS?*q^JQCaxmKV^0Q?!ErFf^T<%GW>dN z1)hy!k2ZK#*=TKE>4$%A<&Q1#&#nBS(f)ZVf9M?kH>c9%rU$E6$>F-E{{O%M{k&dt z=yq%GS-ua9-jCDAfB2C9CSsn@2vyLivI@?&=dGs7b!LR{_owilK;U-Y67O+k4A78d z>J`o$;ni8ccmayQx>AU6ULD}MIY1^7A|xg3;??Ks=>eCU{R-3YZx-;!hh`Z>qzHF| zw#U52hhsox)9Pv~`Sy>U*1ui`F9!pbR%7LHp7%2}7U-VJScb;(7j<&4n6(RT z@^|TRZ>;Lf=E%uB`@g>Rp|AOiWGrjsH(PqTwxy~m`4M1PM;QINWbIK}XUg8fXpKWN zXi8BOae`o#Ubh$_W8bWR<%>cJ!uPfdXr2c28G=jl`AM@YQ9lK_X}y-Hg>}gt-D&){5ug2L^6tVyKTo1Q>U(jj<~+wo4&m7FeQ+a} zikmF@8o|9z6jV#@no)-+bjRdv4r*)(*%=z=aR(yxxyjLqCv{=G9Ozp!yO+JXUSFav zz6bzKUZnz>e}&|53xglyj96znXmC%r>(%qpiL=ad?9Wg66mOs{>f*YEPT)qEK<7l* zH5zhqqCGjD`XlfFq$u`2EK&}*#- zA_mMJlu{%V4C-+)r_XA;c*b2Q8;29;+z!OyF4l})0f|tYk!Hk%l$isH?Y7J)#=Aw8 zlDtW5YYUCZsemc6Lw5}qfKV)i$GMuGfN>4nv^@Ae<$6o7rA$@5i+CX~3vpG5d$aZ- z_etg&1gXG!tl2i`WlXw6&iI%6l%;4^ zoF@mZKfukN($?0+)Xa3;cz5ep<_+}c;1hrY5r3n`$7xXA=2~02rlzo6h+zgOyp+UP zf;Vi8XNv*Vq@@5xIlQU6ZHsGuq41|)w@}4{ri;xNYu;`Llq^s6#bx6;pu*SOmMH$) z4CAg&m{jHCFn*@ibOlBFN*%PkR^OW4oPWl1EWMj4jYt*Ne-*q}_m+BMgEJ=>GKI|- z!n<>_90Na%&NYa;J@bdTHTqY>sf@j?lEN08Wunno*EXY1=I%x@fZcUeu?Tg=rH*0Z z*`K)u;f+*wYg`CSEDv<~7&rGNpA!i4kwJIFdYgD*E&C{W@@sX&mYtI{6y#mz#!BH_0#xfC}}I8~3e-rFG) z1$shN3qz*-b&xo)IPC z0o;b__!pA2?f}w0XhZK6)MCx}l)I>}!_Syoyd)yY#-bqeD=p*YaP94;Vq~S&M3(dd(Qy z;o87)nYNVPJY$JR7HTKl#8gh@8p2NcwFS@JqPtpibmFl$H~lak{gbty`*joO9@q5r zNd|*0N<&!C=No&QhnLQsmaJlbkwn@lo@XnkHvhVXRni@m9@k`5*BM1(s~($CTB&|= zeNkU6;N(d_`utw$=~^1xVbh)6LcV`gQ^;d{uMi@Wk!_;|$`#=!aVqL6vCoz{_~I)y z3xRGKs<@Tl9;pUf0RQQ(zO1uQx^pA4dbPd;L$7P;TzXM1Zo z&h+&sMh%bfpAf(m!r?0~U0{f42`xmlD7RP$!081?!f07R(AD%vE(YrWH#{6TQRAz0 z$^V@YaFh$YSm+JL`fAi`Yt3(8mRIV7nkVtir{${Z50^60oMfT)7{@q!m$>#!ok4XU zEosRb4GF@mOB=JZwyK_}QA{)u5xf(EL~E)+qf>q{ce9XigV=KJN8WS^D|r5ap%o#h zgI?I8{Y!>n^wHBA%U>=zLL_d~zy81|*;MU#3+>oPe@3Ts>nf(!K@jhlh?3E%j#R_w zXhek!B`pMVWTi<5=h^!*{u7YC*h?u|WpqrnC>hlFYRd6tOTfeem+RkDl8@UB9Z{-E zyH)`TmOeAxXHash1vkZiOTVNHR2D+i>W(|9RX1$IQR3W_3ffqu8?IlyVd4QK0F^MfndW?yBolmElW~cnNB45@upur}1gizYuZ&m7qyC`jwPGjIoiE zxVcOHO(@q(RxQU$j^!cJbvxsPJ}^!{T+f5~-g>$HoBcHbwds+nZ?BO`YSO=Xz&i;&2iD|sKVpH#W6DBYiW)3e9j>;-7hhOdYtwVMrx zFbj9K%u0xhr&Dv&t_3s64s)O4b`y)6(<1pr4I`~Z=@HYub`R0&s}?D}q%}Id#(A?= z$pRGjT*QLl-8p2_|JC_5Fm}6k@~Q|2DmPG0OL+x{&4zle*a_L=O&8g?&{HSDSsVrx zp6Q|~FjH3z{CJ|$`9_abYc~CcA1p0x8KI0Myr(A}eWu~{?cKEWirogOn-FYbTtAl+P;lh~V_}u?WSx*j(oj@T zdfifF{$}f>p&WJpP!lk0IrxoOx~#NFL5Jv(lh)odU#m#No=(1vLyeM)g#m0cd+Z`V z!p9&V<)@-hYRi0rldk^2_%&W2G7QdWbuo7veP^%J2$XepaidoiC7M7|l&Y*PSe2oS z0igmer?YIWy_lSXq7EpBCaTYh%v54ayP=6xI(;f%I>P$E*P~J-w$G=TEca+_ zO!> zwtmfL_!p*Z#idS^GUD~y5hkd#Wi8z#s=etIchUZ|A(FGAj7q*S%k1ENN*>3+%; zuHgw9Fl{q7B^&XYO9qiyn{erR-B?Um7oP0^=A!?S#|zlA=h6s6X*hCG!q>1F59;Q` z+}qe!_>pDQW~}B4y;NDHbQhhg1Q89hr%^ozi* zbyVGEWa?Ys=uv0f%-@wq)VS?oB(5d4PC6%H5b#FsY zStW~Dpfwldwwt^6W_0VL{3xO_waQYbb`&AoSdw)(rI*(?{jJ#Rgp@>9Df0u(z*FIg z3Y4&AgM1=pG0R+ZKdh7d@|D2a^#wZqtmH4+?p^ZRq8B`z~t4eeEGFS{;LT+<&naU|6r!iYm!S(IFGHY=9zYL?tg1tNQw-*uA{4BV1g))kJxWE&@ zVmh`|;x%6F&5;RVPz0TZM%($LLWM%=j8}(O#a{FsBYfH)g7FO2wy4P_Xfg#nyW_X04Sj7z>lb+h?%d4%(Y+F%46WA9#-U!$fQMJWb z`crpc6y{((gpt4rQ4#*p4EStVmCYo+CzeMV@S0IPe0XZBE<2CPfDcPhLn}%wP38}T@UiWSwObRcC3}ggG^f{%U--6{j z>nEmH-<+yqgBXy-xu@SP*+IifM7!W>WAo8PP!6)At7Rf z%`3I)DY8_P-uJcA27A#fgG8@8$ey3}cEU?X`A26eS)`KDZdQb=c{iTVey4Tx1x9Tv z0#o!t&rFu=z@XbBWU9|{HK)sJhy3_#d!*1&jK2KTwD>w;TacB5kyR@c%TKLE?J%@+ zTmL>UmVwjt`44wNHf=^7DDy<}~C5RtG;}I_%7O7&*qCq}pR9Ii&8K>@VWx+H^Wn%?jAV!2Jy@>)>U5O8j7Um5^SH{_ z+e%g`8v>y@9{tZ6$pu_ybsFkXsQ zXD-F5rR=ms`Ly|=e0x$8Me#bhq$PsCP7bO`BFb(Z17xUAn{{`37g|JEm*3A-<PvT+Ju*TvR>m;RJ>oq!Z9`z zZ35kkCWU6&B}Z0O32WKk2^?SYiz0Ny0@YoOtTtjx_iX>C8`qEWiBOu>!EIR*ne=b_ zf;uN1`#mVNfrEkAI!_i~1BQ8YkiEJ~smVUMx07NzwYPedG3a2Ke1Y<$L0H7X=r{*( z?VHGu4!x)3Gr|4k#Xj(F8-Ds}XR_{Zzg}w=L*`(K`Ke+Jg=W z!!_eeEBGFtf^T-*`xszRw55?iGP^N9MtN-3ac~)NhJ^Mej>BtXS8_iO;l4t>t^fv_ zWDw_rDc_S-s(89a=OUhSf?7jd!a10OD*?{8&XiVv#&=5JiF34exWbk4#u{nGg#g7u z=yL&+nL3z?Z<;BeTrt~GC1_1=6MLOS%#m%K@uE*|GlUh!%CS~P`LQw^k2cTyl^dxA z@>I0Bk+Z%Pj4uzEZmIGZ8ONy{@az9Dmo-z-nr3R^*nNlQNRJaef8s(1SCH^i-0!#X2Pz{o_uq3eiiOjxpcGF(#f0=K2m{dW zZkF1svP*zjhJTYdr0PfI@>@T5AZ!lp_wJEWYOF|+3JCoxO9%mZVG6*1sp1S!jy0-)`AON)%%dU zC$XHd0C3sqzTTfR*KuZSB2)5!1sZsgevq$aaW=)D_Zz-mFT6R0I=4@TitqXI5N*Sf(Qf7)cJaDnv%ePfc z*Q>TYNvx#SZ9xCGj5lGFeEjl)O#NffTqntel322!tBtic>El>q1Tocrxcx!3W)zop zsEBtFEx!w^3tHLE_bxWIp29+d*40bz;Z6WfV{ zmtJiNb5><46|jLtN|-=os|@O0cgQJTOa{2O6I?-|G3%_@q){$jF9%H%m2(K$*HCg2i{G>6?gH^#kHX=g=q)c1>A*u^G(gO(lOt7+>^&UEtX6#?^&<=tj@k&_)1|? z2K375$GSY-KX#tT07cVvXZW=K$VB=t^3oNsQ!B^s{ue*_$MBeO5B%b$Px5(3eg@>8(%fJ3T%_H&{RF7ep1X8`*HZMo zbM;_9>YoVnkl_9$-S~4Of5f`@b0dFX?SG!gA1u!Q&56uEUB#YCE}f_4^6q<{YL6h) zT&m3`4p-HiB@FQbZ+;J!jS}ygwqPS-dU$5FoEur)dBaYv2re!_Oyk+v{>f7Mkq7&e srS!v0?oXD|k9-(N5&lnDO3NJBL;k?fB$aJHfq%MMhQAe^zjgor0aG)4jsO4v diff --git a/docs/logs/images/log-rate-entries.png b/docs/logs/images/log-rate-entries.png deleted file mode 100644 index efa693a2ac5292aa6cf15a1872268843ba3a6bfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 235595 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≪*xwbfj!xtyHAReuu;;bep5< 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�wE}|eDiIqZ^#r} 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 diff --git a/docs/logs/images/log-time-filter.png b/docs/logs/images/log-time-filter.png deleted file mode 100644 index ffba6f972aeb776d31758c41fce5716f9776cd47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51802 zcmeEuWmFtnwlEMhxCeK);O_2j!4fpMy9I(1+}(q_2M;d6f(A=)Z>*7qhOfCZbLZas z=Djy-&G+;5s_HsjRp;!p?QA;`siq=}`jYS^6ciMyyquH<6clm=r0s_Y5BdJ_y6OrF z3Ps6UQc_J`Qj%QF#nIB*&H@TbE;2Iamcz9CM=8`Qh_u^JY$4{ z91If8P)NS1Y^t`?3FXVfsG6v@{WnnhOxF$c*WG$*`ug~~^#vESaBjd9Kn@_w_bHqI zGA}WsofB$*{>-AmPmAmWjCFw!1xGSBD@%^F4=lz97_7H1IJ?Ctwg!fWq3B-#0>_SQ zrwPX_JaHFW!B5&KA(Wv|P}HQG%mor^Q0K-_XIMc>#)wb}s6Y=*WDCY@==ua=c*J_8 zP*<)tt6ZjIu zaOcy(!J~{QCm&oF@P+uFeohc>Z(q8?*VE!R$M;je)E5Z^J?Y0jvB2GpL6gPS%?w&|Iq+W4%2vKc-E^?lu_GP`!{|vtoWI5>(yHfR)HjQJgNS3O$JraQBsqc}9kv9s ziD(^Q_em!&g(dQ*IEodbfU?Gj;%uxDxkd<`4ZrPn680v%Q%m;vOsxIS@%aGl>){md zQDT-S)cOeC-lqz^?Btj1xKN+oP|HV#>fxJGNgJCs4Z%0E;JKP1*lmx&YCl|KG)m8o zsG*9cCa}cGP5&5wiSy#l)WQ^rO((kY<)FNJCg|-7oS*x{XAIt`;_Pi`(gah(2{Bd) zb-gxP&njhV<%QkowItjy+V{iPBNtoE*L?cPWaYCf5_UE83Ujf8vbbN7%6|=;nTMXs zXY!p-7(VWMDGPaFMnD^4!0U-28Q`U(xC9kfca#%7&R$7DiNt>-CWkqF^Q|{R%RLT9 z1Y4Z_7Ml`N4J8&?`zA^Zb1sm0&L;Pi++fY1m^1-_RMHTtP+a7pS}QIQ%|{VBE??#% z#uNGzHyMxiMymkY+`xP8F=*q|^$#@c*{@_iQOaN#Ik^fUqW7Bpr>&5pT8mAYTf zJxiZf@e*rO*e74jre;V8#2tS%4Sh$|L}2Bg!G4O!-*v7ggwY^rnH`z+!qboXs=x1J zft6#~j?I?N&LoJ}8_n`e`dhOH4*E+4_JR<#>>kqcqlzQpk;01oG~moYCbypU>D#Hr z$99uBeZ-9!69ZG^I^iXTV|ovG!4KTfcpk58hbGMsw7s0rgf*rLpdFD8y)MY(wuu7$ zs#UdVa7lrrMxFU?bNb{Bb&WBCIg%DaQ$HoLc&7AP-_0NTq|>m zpF#H@UQY!qq;$fNt1WG81paJfg|9j2+UT=*yltF3z*t37g5ooxP#cTp5-Xgc8WMjk^N7A|s(Ku+qR0at6kUhg)`Ch6H!QJBc@pL1aL_78qop0S*Jcz7+ z45XY!!h_`v77dbpB|Ac)M3aokh-83xk4X2^=8(FR7AsPz5PJr{W{As_)fwIy)0xDX z?i{f`=Qe&xkuqUI&Y@ULgE&%^kvb(|A>Jb%Er~TjK;Cgwz}&Whjz2hCB{flTBxU<# zTXI`*n{HbqN@Or-Q#G;(k>NXoB7GJEOEPk@iUQgEheIjUVp?_A^2;*qIru}QLy|*9 z5)u*v649J`0j!*M0d0W}HTo;`Z6LCX~#?mh_esj}VWf>qM1O!CA@ugDVM; zsSgSG6_^xU%_`}c&Z??gCMetbrd9nW@zhl~D)%F)tYe{Zy>ZDpX&1838VJW<*1tx? zB(No*`7r=|1nPoE`G^Vc3=an%jnYDt&F*C*$Kl3>!iz(gO6b5LWO*AO#D4tBFzf?+ zUVVmh@Qk$-mkY-x!49GJE3n<1<(!$_d!bprL9a~b=5z5aG}<9I^NaMm37Uzu3EPPq z+EiL%?1WK?B={snT1Tbu^sw|OrEz7?Ok-|;#~}`6-f>O?%LQ|fMPgo0ZZcbudB3hZ zq{~wZ8A+Hh#IR)aW#R2qIGbNK32)i^O_K(_qm31r#^n?8fGeX%h3A(o zB~LVu+)cwHzroP`uO6eW`g<-jxb8p?+zy=%V<*Wqzg237qtzebSYaU46trp*pS7Ib zNoO{fTF)NQPyEc5dZTrp-%W+DpsSK~+ufG`$`k4oz7Xc|T_t_TXL=Qph{;0rcl@_WE{ibM3=EYhV0+8mFneB9qUqPnp@JGf}R`F2%(-ZjZ% zI^2j~uX>O9AOYUJB{}om18kY>_pChCLfw4m{BQ!TD$5^(74t*r@Lj$=xu}!bTUiVy zdd~gf{MffyZv&j{&pu*wV7wbiji)2VS7Eh6*z+!vEfaDx*(a(I^~Af8dxeKbphLQV z=kO|*xSQv}IK*B`Mao}Fwb*m}(+HJ%NZEdwh5Dj*st|N->>}q6&#S7L;Uepq$Qj!r zvVpdt5wkZ#`DQY4`s}+ZRgzU)EevP_=bJhMYcZZtd009BA+!-7-`Zdx@Jw6eMI4rceTJKsXHto7;_$Yu< zuh!3hZRy4UCe9}5$J==NtiLuPSt-=$+4nx#^*&!8FxKl{C9JD;%n70eNTQzckg%Hg&xQ10@UcD{tpmiFy%Iody zZEy*?)V%b>i$~@_zE(sn@t)mEs-{)VT4i;G%v0d=t*SnEi7YA0MxhuEHqN(DnX}#i z_(w}KdY;N$|snkx=$tfq+Z-2+_-t6KotF5GcNqEn#xagU0-9#MA-OOYcp&QUOuZ!@UE~RXl#kJ-{h&Y4H2S&|G`AX69 z(1iSdetOCPTP<5n+^r23r<0Y4p)@P_c_u21ybZR*TacdxhtFiw*<=6ejhr#6jG0IWTLd$ziYYkeMzeWGtkx;-Gb_2u8)ZDH13T1dE9xRn@E!I(GlzY_n%Xl zdy`W)kGL0$ce&2OIc(c(peN(2+2frBT`H62>!F)3 z#vFPvx;B}SNQ+<8qg!cDevipe+U2|~Gzt%wAkl}ORv0nW7ayE4bIFEmPrYr#xjZ$w zVV;m|PlIjFq4S};wT9hKF`+#AcKPsK!lCj7D(FI?=EiO7tfdo9cFKPh_7S1~vJZSx zRD_aaf$~efxw)x60z9=5!24oWVkVj%QLQ6SA-Ba<^E zyoj>Ulebh>hGK-Y5usqA38CO1EojIo0!{RLTLzjQ>cwyOVW6PGt)XE5{*DUd`uvH9 zoX>s!c72f;2896mg#|gi@?rk*HgZM&i+{AC{2^)>d)9a6j;0o@UiMDU<3I^{2|$|m z7H;pzz3lBATm`&@DSvxI0MdTG%|=Q7+beFi!jyW-YUGlRE*9k6tX!%ZIFMABW2-g=3?#SX6@)e{ygqGQ%83wiLWaQ!=45Cqwt zpRlpBzGnM| z&yEkYVg&-Kuvp~K|Je~#hn24;T*aqP@Sn}+8J*BWA%y>wMjv3mDtwRt)@_aF* zhX+o@CGmesAZRQ^Cg_**{ZUCN3I8F_ppewcCSCtO$Waw6y%su?ijK^GN+4>85KaAu z5(Me~e?s)XO4}$d^mA%?Nmy<;t zH!EuwYXDhuK*D#IgR#IGVnb?ZtOy2}NUT*_0!^Bfuk9N0-zYO^Oj?rJn;E8j7_@E% zzDoUXocL`)KxBJf^~RH$|LdwZfD+{Na^6>YgE_By1(y@mq8hSJQ($}5Na-A$OLWJN z8#zMy)}|4U|JT0%!tRM7!hTW{J^?dG&<|GeCia$p-=o%_6?8PmZnOXER3o@y5YTd_ zS6-&6b&c)=FXn5*O{>AH7)bGAPO!Nn{yj=wMP5!BMH$f&!1plb&VTLyFZC2L3}U+a z)S?8v$u&e>uRB-s4o};@)3=2D)#97Ri}8gXekvyYh!CZnB=!n%K*!u2LM5j3da=3p^4}Yu?0NiQ4jvoG_&oHkM1LJWQj9O;@CkgAr{!Z2L|3XIotK}6dh8V#(9Mxhtzw<@d29b1^e_@Vp<*g{3}cfl*>muG~D5N7NbntT6SXtvcu;Puo$ zNUjNl9u{Dk1^l^J(5(vj7YTPM&0&*V-n~Ij96M2@RSwtyQgumLt+?{C!%t-aVNL`FKurSkvwE(MDn6n_L^m+0-ULTk=lq2*sl~?J%yCzqMs=%zC&EDO@yF440R)E zol-U70AjY5#6L^af8%lpLHv=^NSaAnjWSXzbX20hxDyzXu!T$zFooqN?S9f1ExBZp zEauG+?*5`Z+p0TEB!34Z@3dn7tLDw(aKs^da7s$z9~to9wLgeLGWa5eDKSn0=tM@iAPd7T^R^MIf=($v+KqL}G6GG57Exf_fPqfeKlh|Hw&1&Y*qd z`Pz|^ab0TB(8G5k996Nfrm?-WG+L_3uY<74x7Z$53ep80@z2&gP4ydjr9qCC{thC4pT1qjAt}~CnI?zM`3m?i@Jqp{N#U`M6a?k1i-Dk z7lT%u$#8Tv&7Zj+Ap$|XXeypNUd)dQLNY%=(^fBE3XP}tJFG9~91}00f`K55292tK zBx2Q5`2UfZy)iUm1)!K6vcm-iE%cOEmk@*T$Jq^dKI3;oHFBLKw*MSEux^p6)ievYy|yk$LYA(TlYAO9Q5z=sGiJO~^A! zJBO(M5r?0jAu<4&eA6=?TZ0RK(Ict6XYyE$5XzBvV?yTAO;T^r*#%LpY&ysT-aY3X zIY-}QHK=!W5N0IL&SbT_3iD{2JIW9-(wxg>o26ka{P!Sp6Ka#`E1(c~Gr z2lvH7*pfFX)}jsZ2l!QCAmXs+EbMn1kf=s0JXMOo|p5xgW4U>9EhZtqiSZo9NKfjA1@~m5NJ8V?82QNwO z@4T-VU#bas4s}>qmU2KZ_|TE@JF8^I-OIEbi|po5d@4tB=uqZCtz?bFqK!~HT1HMQ z`Dt)TRXp4p(hO!&9NUg`Z_mDq~Pxqgu6)VL+qJ4 zWmFnLAy&oH%|_sCE*>pKYE6=%GT?k zXneNO%x06(i=9gI;XJ{epMCv_eCH&IyN`2;ypE*hdi9+`Ah}aS-@3QIu=IN#R}c^S zsIRnwL!%S z7sR}YYPMapl}%Zo{{_#4*7 zxx#b+G*a5VshpciT8lB?5~CGf@a!~R6NA=x0#z25PqT6H;AA#G6#$K}CJ!0LqVsZ6 zkjDM+o@GVb>PU(D%?=nhLrETBbC|Rz66sICafk5m5Y8fzSqYo{`c48;KTJaR(nDQ z%E@C}kr&9!NGIiniR?1Cg2MxFvC#@UExwR@e z0xabkCCQ%%IOH-oR27yvO0>vQnBNK>A-SER5Q)g3kq8{?3R#RLAFeOWvaw9V=zWM>VHDEVQK;O5CH&`d7ozY}25CNU z#nVvd(NB!W?nxHnGss+nU1fMl5|(DyeA96Jeu^+8(Nznj|2kFkJor4RS^!e^_iA_j zi`zsBSC{#uIt@68ssrcjXML=FTXkPyB${k}r#%@;P#wI_O7Ogs((`R#*Y%Am$&aS$aQnynT7lK`vSc2v_rt=~}05qMhal6CQ==nhfr)s;=rZU7&A*NUt{ zir-hZ7-Z)-C|IYQj;mzHo)rx1t<0`htc> zs7TzF$M+oGV{{3YgY7pe00)=79Fbb}+6jzE_x(Ae7DlVKkt)q_9*t6!m=F42muVx` z1U*hM`}l{}`J}wtx(m1J5bM{9<39hGA6qf{p%_D`{V-eD_}b;lD}%$rCxnq4#_08w ziQMf&G^&tv1m?>QEOIYW&O>3{il@y-Fha5A2|gIRNYAHI8QJ^ST`AZFt^(mEv?SV! zX)m^SkC5@}RJK)KEnSDF>_dU@Iar;7MD>#f3^Wt7?j!=G@Ra-KSGTQRqxiE$Rz2~y zr`H|`<;K-6&&pjf?=`8quP+_rHrps`<;lZ3j0MeirCnvX;%M8(qf@Q7pJvH6pc822 z_&s-{`H0Q>+|sw_a>UqiR~C(|ILG8$gRjrygEs+}dB{Xo>qys_BSEYx$&c1VsYn<> z!fL~29f68_4f8OogBhxDSRC;pJH8bheS_}DUBR8{gC~PZmy*(A-6_@tTx9DtT@!yQ z`yW0gD|u77yTk8NHpA~hz@?CLD(XC!$>@nyu!^~NJsMa;*WJ-wFb%F^uLylu-eG46 zBL!7wZ^ep}Qs8CR%ma713817b%2oKEiYi5pu_6IPU5OiMqv>G^0wo~YpDWPciZOb3 zX|U25s_ry{QWcR~)%@2Vq%XjpqVHpK1e#Nd$6 zTu!M6X$l1k;Ao(=J4t;uqH02ZKx3=NEJU%El6%g0jMU7len+w_=Ne z58?#l#t3ko`5YH~cYZ0|$mKHMD9j*eGF3|rfWba1?=rwKZ2NM<0^ZcxQ6oJ$(pA59 zRr#y0OoU4v7X;scW|}mb-wtI3miE_$w>GGeOs;-o6fKrM?8|?6SXmRuY;lH{%~-;# zK+nC5Cgyiuw`PTTWvP;*)Ja*OfgWN5H&==z}^vp6Kiz^_OP zWRCIK|H4*Q6tFoVO;CRpmw!R2xw(QZ_x&Y5^`MbREnRJ}A}?7y;EC_BS)ugTyE^e@ zyF?0$#1G!D?FK_E1e0~=OFnpSUc7`jlzaO)tZ!r-%lz7BXKNkf-rLXNr8n8lXc>Fo zg}$H1HwdLzaC~@!+{ND+e>&S2@K}uTw0ti`uFFseR#ksGZSfdxIJO-A+>6+p zG-LBc0@jOU+h=n7))1aprFSjM?a9UvGlyz(0n|__pVVz&VOv8r%VKBf59b{>*F%hB z(Iwoung)rKVT*2GAyaD&gVwvgD9~_Uh?%!Ie~-KHX7RjKbLYz*i5z>9SP?v8HQ0mKA-5 z?qx`N*4fWS)QC6#QpXU#;v*vQ9;jkN<9gpeDCE$|vKJ6Da(s2bsqs1cCgL5$pOlF` z`aKInNrjOm0X+TAQz>WB;qHn7u2#x*(|9ATJbZ(K%}F6{5K zsTgtYGM*^ibKD91g;&wDR^3{qSO12}sL3gH)pbhv9EL4`?RcqPvz6QEOOp+C#n0{) z?~~Q~tzn>};HP-pk#%ixDg_~R=IKKNR+65|ENvA3L4#Om&-A~?Jq|K3 zx?0mEk>ii?Gtrdj7uw}w@Q{47aXZsFcRhob(!(Y?LHkeL7|VcGmqdQ;*(^-Wrt5mRrnf{Yqx7C{eXQ_k{Y(z`5K8a6W#yX%pgnYw^l9jz}BAevoqncL8W45Rmr9 zol++AP0O|`5R3K{jY{q}{Sv*Aq9rLOF1@k9Wq?Ar2|AuWzr6V6vJu@N=B*@9n9E!H z@F6z9VV0a;)c3JrHR;$xT-M$WnA+cR)|UI@=e%X^%m8M!`$ji7_nYHlONr2p9Z46Ogg&BW?QjiU;TK&TCp)6A zR#IU%Si}K#XroDV(G9Pzac6WF z1HtxU!y!&c^K6yf-30=zFi5;x(P|`W2CX)%Y+biiyF?jk;2Bx6RCL%o^(LdJWkRzsDM=lW&qjlNb8pHafR1Ak7Sbvg-i{^M7?1tq>bOlV@vy-v`Em;^BW z6j1nM)ND9bF;t;hs8QPEDeGYd)_cD%J7CABi&G4b)$lM4Z$5Yh3I48&GKq==1)HwB zU$ZR6-MEN9q*8gQdxh1wvsgwWgJL7FhyAA<^Dl_@0J9--Uu%4s(gZkb=~xzL8J3cA zZ~O&u#&u&|{l68q-LqMRX6io<3b~ua?Z36Un7H!`x*~f$zzkA`RAl=5;C{Cn7>EO5 zY9wT%L~(D}FbX8|ja%K&$_+TOF6)KWT-6;8GjllHabW<4bL#WqJd8LN?P9<+lmncK z`&de;oftyiMP!H-PI%K?VYK*5xR5yBpvg9&cTJYr~^_iZC9IvSpMf*e%XwSe zZ_NIOc+=rFp)Q-Gd`DKY*`)io6d)g0Tz~(K8BUHN7rsbE3HR^UDgI2OVBLH4hjq3e zkC}Dr+vl0I-NFT=qYqz8n2alhzuOgnzEmTW9HiF@UrMK@bLgA43(wfQoaxOaY|L1# zm;dnI^}B*WG&3nsmd3d)V`eN62&R=3CCsz?K5dgo{|<&b7~%2j#)Tesg(~QMg_s^J zlMzV14`ZfIg=8a9ptgyh95A%DnCa$`YZm#y;3Q~RQ(p+!$JpsY$dRk z=faLmsVHf)@O7;^WouKFAj_%$n zf8M@7M>1V-Qnq+i z0S`N>3=T^SLo*Tqk7#n8s{2{j*+b>0t@n%Xc0WeW5wRA0S@X<1SK2gcx znBn}we(|%&D#d1MX&Johh*#i~=lMk*;^NA9wRrMK4qXK#gr2w;Omu|i;#7o7unBp8 zYc$RO;RLRFgLz(}p>*RJ^uuhn3sgqPU9pcT`PvkXxOtaNkD1JGKQPZlwqw0W3Pn}) zKB{~n!vnCOK9OjMKWV5bl6zXk$%%|Vkvyl<)WgHbC@4eTP_2o8$Wn2H&xY|< zDO2d1x8u8ucB-!MMrBK)>#I0X54km6!WDVU-F_Oajlx{bpI0~;?V*SGtcDmUqGTz} z-j$jmm{53=c@*WErBO{~9UFZkENdN}vlgtzZDj!L#=VKO=A#AKvb~Q_F$uC{qt)Nn zfJ+%Gt+q5%B3mbNL4H#`OXOd>#*$0b*5ZFA|063%t_4$1p%r+#Hh*!yA(8+Zz#Gij zKkzW1Fb{v%wL_eq$o-oa;%fF8onOa_hg!aBsrPL{7(gc^R0WoDZD*A6x~@{7NP56zM)GB0+OYz z5`bTHoeH=q$O_9ynd(7`&c!#1cO=v}6@v6IlMpWrL%EpAfg2(S<>-Oc5tbLH$9WbP zV|kkb;*9|p(YaEaLb zs%>!kICZ{MlbuK@74Y#OD^=p&$eZgJm;-%{{away4_a=LfPhSuUsTRO&EB2p6QeqFY_ES&PqFerlknGJ>t%-h3VhSwD zx|YvV4UFRAYh2_p6+HQjQSnrozv%tB<`F6;Ztu3unzBMXpZnlrJ#_mcB${9+%dFI{ zq+V{Y#PkzeYdVkx-XyIS6y}I$t9Kh(kEXIH_WIOqPAoStrYN*6E849uRb5QRk}tkqswx&pzzsNHgJhj98v4WI=nHl=?p*g&_`S~RigitwiI*E0 zKGRTZe*R=Eoy{dR{15<11)sEvUYQiGU>|JV72D|k`WnZS5C;Icyp-bL^qIJKQI9lk zEpvUrX83MLtK)mwd&WAU3b0;SdmQJFpol>XBCzjqx>)b*c5_%F^(eRM<`MtRYNuia z{R|{L)qW07?N)D##BO!lrnfZ8@(Hi^Y}_oQ($}kE2S1YqCRQ7?SQoIua?DriCamD* zIlZBma7XOzzI6%hz9A8Ek~?kNLi4X3NoA=Ndh`kq{grA>B_j0m@h!@t#Fh*&xenMV z0N*p>sgU34f1j7g2=u>rTa#^5HuF;8W%+2_0g}6kOY~%gc6D*f3E;!eb-XbiA0Y13 zek$MN(PCg_sQf)TaWa>+hT^r|@|+1CL*c23@y$g-(GW7F3Q>Q(AK#7SbK>u4q$v;} zO5X0W8?Qm5IHG$f8DWpnEu6ZCDJVZxtLZ-j@6NiUBT2G%yxjOhKH$D$b9){I2JUe-8fqf77F}zb_ zYEd=AO^SW65f{ZD*f_NqjluqyR8A%rOT4Uv3C@NO$~L$X@t*ba-Y+l|Flqa-O~V|L z{zOF+rJ8xgTB_XP0j8Pin(oyfLdmu0G33#m7L~P}!K`rHI4=#DWVthUc8}d4TeiFc z&)LpVcEqQttr?TOe{7~@$q`xJ7MHp!gN*n(yp4=95VAJ=9qhtk<$ue$m7*dWx}y^lxj09cz!d6Uj<U zJpH-v=<@)2p%obrP&cZBkUJ5P}#@&oTrTF0NW>5Rbpt;8tu95xfuAlDaRIIRHb_qyL{Ye8#U z31Mr%vJk5dBPl z=UsG;OS<)U5UTfis8x2;tVJb=-&DK$jk=H9B~rdJts(w&8(C3YV5K?wK8=f>ftZoFX~IzkbM)UZupC z*uJy6$$}VQbOik0BWDS6jPJii&f}c`k0bj1=r3vLuTX_ej=aCjXNAw7*$GP>YWoD1 z4<5dn>|Bh#6S`bGj(qmrogf=zyzsTYC|MX$bZ4k&0uat?e%O;SA#Ago`2*ZPR|wtm z_*D{x9=3uAdckzR6=&NBkc0%CQe0SpaP$UcxhtF%BNN8(31%g^CL;%z-Ew_I;X0m8 zDmWFsn3t+WYHNA2b&9QtY9#72Rvyenfr8uv`ue&(z013bWFZWxuiX zU^K%k@oOzo}PDB1O?7n$} zM{r@33OKe~=i)sj;k52wp=!%nVXgk01D}kTp=n?&&9SqljCFYWOxXVRPW9ehBx0P7 zKK$NPVS+S+MATLM$0NY^4#W%ip!h1s)Tcuu@p_#)L7PhS_*V81)rg29&Y;YgJ>_*nXf)q4gw0`5Ef=DBIj{5BO5KA5D^y)S@kbM9FYep zeBN~XH8a2IoZw{ZJf(0uYtV1p8yiu_eh`saxg$r(;d^He`|fj>Kh^~O}zig1!74R`{CVzLQ=FCS+KTDX>3>6Dn{y*_v(Bm!XWCH6xC5;sYj94SFFG|hl*}|z!S|B;bPYhbJUZvS0p7M`sFd#?<)Fwf2 ztW>SvZFf8%PAHxyBX%iZ_rc=seqUezs{av@7h@YeJXEp_P2D~^^#sQFV??H)&zx`U z&&4$dDHH!LecR>FQZvTz1uwGYhGH*cRx#!=PL18A=4BAOSIUmYVuvDpjsqy?0&M!j zlxGc5T?s~xN76A4@gezqEB~Do{OzxI$QK7zjo_%vfN6)MgN_G|3b?E27aKsJ>Z!Y4 zK(+G=Nd8uO3V#s8UQEdxB<|^rxCVa>*kQPJ+8b;zVBVfIJ0+2Oa+=lJR3%sqgWIeE8My zHslb4{uk*sp8K*rRILhQuv0bh_BexXWj{*>QCm-XhAt&uFl5K`v%y9&FqOL z8xu>wgGY{@C*<4}_aXwzQ$e4JiB&P=*X@n>g24|sH9WucJ`oGAJ6@6qHl>yx-8M?X z-)GF@q`wXb*&fdtX7*9BFA&HbKV0;c4?`u}N?TN%K&1P4L#N_$fl54WFjgkQ9pCKm zU0(1g9k_%CnmET6;gSzfzsnh*x9psh>|l$nYD?=~g}7`2h%opNR z6n(lUAh7n*snx%i=Espw-gp~&Xl&|l*Z(Ty0%Kyuqw9vG1FiPX332{hXdYBOi3wu! z^@T&;O*0nmknvh~Mi!>f3eWE}d7|)ew(2$=beUBK!d)X+)!xI@&>?1=Y=!!M$5-4t zw8FhN4jD@bxLJD?y;xgh0F^^(MEv%B6RjH#(>;O5C$|=A$QXT_Uzz}m1x*A~FB}l^ zoYrNJ?+I>m1$`$~m+VD(GyS6>WlTG!=_dP*nlW|v%0^K6g++>7dr706<+S6wVmPz? zsZ`e7BK(s*jz-e^Xsdu$DBnesj-B?sqbxh0s7t~r)7Pu5HVXmbQ(1xb8#d+HUE`V3 zR#7*v+TsW}(Fpa>tg@8Ar{xA^>rL{KL0eh=q`uNx;g^;t0`56h<`IvgxkBvuW_63+ z!QE|7P)|qqJ|Tz3;Ie!Esjdyn2W50AVLCdnYTDYx1 zt*P9g^>%W$&_f4PL)w3A-a$+iQ+heiYbRPrRY0e^fe9n6!F%#ap)A(V!`yvN_bf>3 z^R2roX1V`UkJWaUF0!|bPfu>t%w(&`t?_di(< zH?_tXA;Z(>SW~6%ztKD)(pEYgONQ^4b!)_*_f)g~i&g_|n;_YVcxp9N%Lz{q5j9)2 zM<>X%E@p>G=b(brd;1-UAv`kTs(N)MKseu+U{tgT*j_nx$|m&msgvOCoP+_+hDz6X zwPuG5b+fSnxAzzq|24o_-bEJ+?7#IR)7F(1U4xLzYnhX81PchhzS(F!l5jr~DP6~2 z^{j^BM!>tRu5;aE#f93BN7H+8jrcyEK@+~G(-;|1CL~|QsaO^R*U#*le|m3`O5Z01 zNv15eSB}#v;1nlN-JjDl&K%eXYWa9VdDcrYe|@hV|LJ(y35BWLb)U49+3I&|Z<_ic zN}Yb!n>hIU!HJ^ump=3~$28?Y(s^%CSGGxF`JR6|#4f*yROGGnBYJv}#RwH1B|)OG z`hug;rA8~C#^J(FdnlPL@gIzT?W6Ntn!)?rI#4|W13yV#MmZhPV+h0lp- zX?m~1fBU{P*mJPGEsrJtUEy)#T={V(x@A#Or&;}7)`%m zWyoX8!5MMR!(Jo674PA3>8o`)xCm^pyWC(LYf>eDP&gn~$vR@{V-2Zuki3Ufnq@tX zMH!YXecTO6)rJu%Hz&%wn!`WGMl+6G@~)sAZ8f=1vGbQ+vvk>*t=ln_Tx=0!m(9`! zx_ySYB3*!SxViUm8QNz*z%b%&ui+^KU=I?OR~{*ps`4J*q ziO02cUavr-$`@S4F@dyZ!C`B!rQnA71AQd|yO1V#ICN`Swga2}RJ@C#RN2fS+1oV| zb^pYu%-ACYOXT?(+I{+%j2+G~`BJqNI9h$=tF4t)b{o-&DH_mhAqwdZHFQPwnhO*Y5cT}UH%5gNbJl5iLY2^am#$U2x`ex%m{H!jFtu1bcwK1Y#izB?ql{Ln z0!iZT(?u%i$^*T7iZyTY{s_3h5hP%pMb)|HGR=u_H$t@P!s&vkYvW`tVL_{bU7nb< z8=x@c_I1R!8Rs1}7`N7gaAMp@l7tvH1MuAiBo!95zcsB&+@fZx%)-^FNRuf7o_>QLQJ2v7^F=~X$22Mo5 zO@rn5!DdwE=-Oqm_+D&Xt4rm`F~NG!GjPfwj>YeYFl1MPUv=amHs?u59YPG2*nI3X z;=Ls$-$vS@$iZAejIpDu4C!}OvEq;TQym^BI)zo`0+bzVv>kw1-10yVvQJ!d&@(%a zFAyFI3Ht94Ha%BX3pJBjY6`g|BEslPcKHyn{C~J-cq2}bxBMtC#Lo&qc!N}ABLUu_A4IewpQj@&d6$zIOSNkCL3Mq4Oz`eMxL^BVWw~7eT{5c?8pHs zVfShFWx@%_6b9w|`T7?--4|cK3oscAl2+pjUsGCxXH`x8qwS>nFGGYW^cp6K6`HaXQPc z=HG)&g!07ct+EWt(9VkmeH_h;&?%z0V7ps>W!OXh5z2FQDaYI}3whUnml=U`i-uW> zq>PCXS-R|W5T7b?&Ua@Jvdue3pu0pwN9V>iQ8y=mU@rJhc~ixcjfzo_@(AIJXxG)I zYXIhak?V%D<4PB?Q2_|DPYDQM^NWZbb7JZ3qk(Lk%BgZFpqqrd_Y6;($z<4bQ8@p? z<^>#`64jL@C-&HgRs#YN=X)S~60GM13cn}JYgyreMPT95% zeDP#x3C~W|#ODId-rrZ?B7ZB)9g+#$Ywdf_+_t<776pB;m~09Q7f zNZsbVyYN-URPOPEd%Evhdm5I>axz)1k~s=Gdr{QhcTjcxosAzLJ?#KVj?0wvM{u;n z5R1sgh-gl$%wF!d<^~Ks<-(Wh2`RSAD%EdTOO=gK^{pI~$Cefa%bp{`T#8A!f3neP z@#F4cJPR-zsPlwGsZSTDmj1r=r~oTMzCb|g zCq`vYP1s66muZb$mSqTg5M@Qy*R9k?)-628@09Kl^F_81vyV43oC0r*v`j&7TP&gv zC}zcQ?wsBjVpnW+jmO`}RH)PSAhl&-(6`#1f7$avOc8WHB|S5;E!Uu#yL48StwIam zd;$ZgroO~SBn*JcplJJE1z6du6*YbRsTRG_W(@D_SGjNktYFPqfnx~)ly$?^8r`R` z^4jidv5>bO4PP^9*X&RitiA79v0>P=?7Zv+9Mc@;6bLtL9`j$CpZ)xGN;&CLBm)G} zJGX3gH)?$A?aSA$M4R-)@g>duYQ<95!>CK_tldeLp4!9?YO1vrA!dAa{NPl?Zx?i$U3=e)#OH zEy!}Y;Xd68x65R#cA#y2$^hy4#){j)Ars$K1%jt3f=Ox9)Z$n|ip8|nm$uG}a! zyOY$9vtO|u1C~1^V9$91h_p_DC9KgSWBr8qv1+R3NSZnj5tD88vJ6UZ_FQ`i-Uq&h z$c9w8>Wulewi{=PjF~XkoNy(V0Z`yW|)_t^FV?7YuqN_a? zsMg;>&?a(atgr4Nf5k-c(m~YvqleU41=R3cnPCmaC7S`v=*|n-6pu>8c}!)0>#3K7 zvV*zf<{P4mTxALDpt=;S3favO)OVL3^hJ*_$0#fJe10>l7ZID+VOF8=za)^AoetcB-!eIv+Ri14n!hLC#r5i+``#t?6GiuxRlT zU{r(cY0hL#!faVTf^vGcdgZ$aO>bM8N!j&x@{;x}Zab?R&ceHXIKPkp8nf+upX8^- zUMHA40MyQ$6lG)E;D57g7?}VDj)s)<@DGc|%mxR{)-=6+`EluSR3*CkMI3`U@_YjP zJ8-t+Vqyl7tC@9rwo?ETRm0-Rohy?cw1qD{U@rs%*cm zgGzxnpCiA9UsJryXNcR+#n5`y*y!QLRl`Ov?-8-8zGZiRwX-akm%+pVyhgW!rWTUB_;XvZn)^Sx(oj}F<7aH^z%EeOKqVlEf)0nB3jTjgorPbN z4cDz71VrhOPC)@_M7q068l+2dL^=kfK}s5=ySpSux;us*kj|lIMq=R1^L^)i&-oAL zcMsfa_S$P*o3h~L-gRkWVS4~~Noa zT%VGPqe+B4E%(j$W`+D_y+F-hIOG(|15cOT9G1&7nM%KXqbMY1x{3H(h!91mB@!9v z+JKxNc45fh69s#%vhdy1O4Wng=S_@xV#?{hbY+N~@lo=A&4$!QFzQPBUZuDe5h+=J z2>Hohsgm@jhk9z8=}9Re7w8#A zlk?JIrIC8K2jI_*dxWgVv^e)Be1!Vn{Ogdq@m=>!Wc~SM+GO(!YfD2ci+ zCz9HqG^eplCS+KdVq-?Hjk{IRathnnUwwblUAo^f)b4^4kmxN9cJt)fvSl64hoEj5 znA9*mLQ@W}Ee{;ax(uX?WYbmLb?AilNl3 z-KKfENmjPg*4)O$Y3Sh1mffcV%!QCvWiro#yFLPscIyKRTR~a!EWb74-VA|h;MM&%nE1Qo zos#Rczjit5GZMiYpusft6D?swVXJlsSfq&6u>^6f7EWg9U4)(+u zYjm?K!28EBS|Qw5T$IC@hp#U(aDil`E4~ET`B$O&r3;=yIewX!P|u28+eYzD?rkZt z(lUO=FMEqO=^Os=zeqc&Os()^lp?Lz)oW;uK+nCOb^Bk6khP+>bkZTZG1k83(f^GT z4j3@3p4<22F3{ST+5Z0*xx8<6hljxjST#$}zC^VUz20IUz zK$SHspfrDb>~T@+pCy;ILWNG5FVC!5W1u)~kb=U|n%gnoX&Xh}CmBqY-y)(fFV7U37=lYq|Bs)2cvxNH%R=4SdZ@wAwjSKtC2W5pZ8CI6QF=d=Erd7xcg-Zm$rlA!Mt zV(wAIewz9r0P84*TsB{;mD+)VAT!b^s|}&IOI&a*$7FTI7=b@tbseu4kT#PVEI}Xx zY^BAJo&%+1q5Bh1%I`$HH2(^wclYlbzkt_YG9+9CnAWZZcT$Ux6=eBny18&iz=OVW6Kn7QQX_&|hy)sbT(uYz2dCX!dOX6G*xfh z#<|ora6vW2_nPcz(e?GK0i}|0{lyc)_FLp7lelDSkbrgkeoX8#{b@Qct|CE!ILD9r zDNe1cyKt$7u zt8n`^-7!{ktp!N+-0ze(y~K5ztz8P8(!#?^$VtA1Jk>5*M-lg? zPr8GW(f)lW^gEz-n3_IMvYCHDqaDJ*7|Vo$*5zI#uh+>Eq~Dmetny8rPh|3|gnM5861wlenl4KYU*GD-;sQ3=Ab{N)XMdPFjS0 zYt=%I5)ay5F_cTGj(f{~~c3@vE z6V<*Jh&cQ}Lzb%5-CH$zLzru4;xp=;Ky@{Gllk6b`E!%8=Gn*qDh=ym40`=mxMhWFj_G2)V*ewgDYK`oV`J)pfkg9pi}0yg)c z>&mijs&n5T?2f6(^{qX_nF64bulEcONPpG#K_A2L#s1@~jeCu6>Y}4&GM@If-zbHS zdR8w;`9B~WkE-uf*0zL}KfT=8UO?wXV9^KCZ2Lu!{F9Alff~i<7~pj8%j+I3ViO9X zHUNN+1ByK_1Sgi}+p|KWkP0#Dn0YLzx*Y z3j)LYz&8}Aoa`a=H_t24FIztr0Lu%$Qv$XwSR!?^!i@KE-)9LWP_ZoCk}`NxFa$dR z69Kif;eF=1GeNcH@_y2TUZ*bVSaAVR&b9<#?GpVx!rMB62J;mb=#$0-*C73WJBz+5 z=m57wI#Ew2_5SRHToPCAP$_(n@qfj!0FVT=pY-~Zz2N-tVo;806F$eI@V@|P~DV(JBrA4TBYn(0v zWmDjOYyzz7R?y>+HIvsp-t4sC8K%V>ooi7v=vdYVhk|T?UI^ShyV^o{#Z5%ad`@&`87_Y*t==+=YYmFQ%7idWj|HDN;bN9Loa1D6$ z7ShA;`iB-R^fjR}ZSTBA9lt9B-eM=i+T-m3eG8|#X~H{8arjBkeSq|@AAnXWUt-9q zWs8$uI{es_D(=5Axc!$>tj0mh{I6Lt7VGpz-j&cPv%fq4zJ9dOJVjQ?bkVN+34>r$`|KwiQ?0j6L!DEjK*mkx! z9j8aAt`YQrW4KetxB&X&XBZOUpXr8u62G(JQI{7A8n6+zOljE1??P%Ab?FPT3C8x7 zSpb?Fta(9AqQs1DPN^uft``nbtTT0*VX{+AR&yYOrilzT3iW+$BIgFRDF`5a)t{mg zadSV$X z>aak@O58H$Mvd22!hXkHMzoe44>{jgGtt@igFuQRK#$1=|4ib1rk@hHKxMtXY^d!B zdJgmIz5wd^h}lBS{!IPh;6A@hvC%j?G3dpf_)|FOU*LzuKk<_&pcZ19nMp&1ooF zw65LEjmKq2C7`zXxGL2zgGIuQdF0|Fq88}r@cX-&s2C@lvi!pDypQJI@~io(pQW0Y ze8r^oq&y)+`+H;$_)vu!zo8Mku@o7``|mSHnj z(TMv>4{>eO4sL3b9$u-ro?V8N@1fg0Q8{>Z;z0nCY^s8{bX#f#xbKoj*h`vJ3d4G^ zUL>FA243z+-@*|=4@ny`Fe7tlsyQO}Vq9nM(&HmTCln1s=Ak$5sg$X9E%P{ilr8h) zt;mcp^#M!PVJK=ASa;Zq%iq4O~|(w@OD3k zC~X3Zv(?s=gWQ^;gN>*4#4sij>5g%U>veXKIW{vDE;Aufi(Sh#Gz{(MO*W&&RgL%2 zhc`M3YSc>qIN+2qk?0j_du5&WjFUYYR2yn+9__im`O4SZcm(PljQ`*q|L$t}nE;0( zIE3gK3hlvEe7RcdZ~)8o7l2AJYMT5eIb2>t!t=fFl`4`nefR};n^Dv8m%cvFU;^Bz zt1Mxi=cAR38x)~Z&GFyYT}+A$P8==;=DG%g&)xU8dSyR$?_Yb78auyu{c1vWoxBp2 zhy3$U#Q2+DGVl{JXC{cEWFR&+eiNj>+2nSAW1EsOB= z!l+CuicbjQcXQ05n$Cq_k9J9*=Hsvc*}U(M zey;JR^|kTga59U6(GnNQ*aHU)4V}?r?MwG$?rlS{+EFLKGDoz7f364V7Y@N&$7e=lO8llhn&vAdv8Q=-Q*R&A4(_V)J56SM9}O zkw4_pDSueT1NHc6BG4Ne6zPG6%o-GX-lhdXPB+FlwC$_Ap~<}2ahCted8`iFzU3E& z+D|YC(1?YSASfIaA^SD_$J?sWricDu1Tb-8_6qfNXh${Ok|0JFlHgb-=tSk8X*M03UQMOpCz=?atx=G#3M9tiKt}E== z5X&A!$_`fgGZ0-8dmPH!f;Wv%F*rz<*&n#nl;^JAjtV89<>cz>`U~k|I-Lh%X>cLd!PbXBqA860?jX+=`f8_H5<_ z5y|v?s3_O=*0cZg4^dbvl>Be{EcmU|Bcr;&<@I+nxdLNk;f%WG1%*GmVIXL6KGiBs zA=Uy%Ui{HT_?_vLi^kMuM0xAa+nmsoTgXpe8lh4 zs`UMhB_-|kXJ^VZpI#^jKIat)JM}^6$zVn+|6D+9yv($cEe}LBG#zFebEIzYsAoWJ zDY%zFk+8eZ?9Q;t62BXri5+j1mgDI|Om!f zbo54SV2io%!4TFX0N4~0*?6>%S&4b|?u{&jdaHWqzB1YXJ@A+OA@jV^UetZ;*Pr|@ zCQW`7BoxD{<@j#*CzHm)j4%bZ7yoQtcDgiBIZ*dvS|IOWDRU*c9`=buj&c>n#~TwQ zgE5CnCq(agg8!@H3aI|>+D@_)q-0Xzs^UeLrbM;^A*Qf_UmojvbyHcZ7H#4HZ=cpP zQR31u+*yaCS_yI5Fx32}>uDV&_9$02Xs7K=)RA0nCt=(myP4G~&q5k>7)YAgUY^;kMkwMpfgmLMz0=!O~|kyZXnT_6Ljv*3Ur>~ZY7Nmst}^5y7- zbAk|rI6Y&b2xHY6S*%v~c2u3s4t}25X}@3|Aq{)mij`Lu@0Dj>tFrvVW>HM_v5E4z zx>uz6C5b(k3WQQpxd*j0zbSHfn={uS4|XL*#pmtpm3-56PutbD)(OogICTk1Hoo9C zf zBMhLaq|Kl74@YI!NT@_X?bp+9$jWT_T*~^7(>oA3J#vM&JOX~R0+dCMGQ1|`Js-RI z9Eg#srF-67a9e)&#Q4tmszn#ero!O@y!;UNIJ~Jij!GGoBXR+*81{IA|D5 zi?V>7^0k~UPIb|W^Jxv(CR1{YTu5JU70CMCrBYR%Rn-OLViPv0-C0zRQfZw=Nm z7PdE7M~LhZHqa!FTk2Kmr_e3Ud=Z)5fwa1SRK?%oM@k>^pY248Foxui_Iq1XplU6l z_sSg}4rhyj*JmOgi}&_8#^72LZkILB#oNNWa!19?9&H(z6~QKpCTqbRZ8Y)7pz2e_ z=l!RVgwFU;H_znBREhT8X|Fo5A5(~=7oshizF5Ft0cG@9b(lG5z4ox?2t*wuHx>E%I*BS1Zi_D=ee_YV)pxih&CFLz$uL-0&~;c zshW8n8U;}1BdwsmSoXW{g?B%-4}?7)y3`E!{b%N08a$;=XDNKI967G{1kokxfoM89 zn8ir?*|l6+^TBjh{~|d)o>v@qWZYA^fiY)|SFRR48ac6P1p;E@S7S+Cc~d&^ObdWA<1( z`A=@d`=%ndrLqK_s*_OyF8droD%a44_h;HX@DeB_C30?VXG6j*ZB;Jg>2Hz|$@8K^g*|Z! z)Heu;(z~f_M~ZuU@$so!YfQV}gjh^fwNi;PTimP$-kgLG>^kUa}$DqOZMSA^=s>S)H ze!i_x_?GZL`+5XZyh4>*xd3VfL6yqdOzc$0ds>rq^d`GenjIAOY~A}5dHFLTUTXt5 z#iZh==Lz+qmaBm)QNoeaoHsXjz{tCZDuOJXGT^>JOM4k=iZ*W5Dw6De2r&AQ1=95pkfZ7sey-iFsKgN~#(PkV zwSjWBY4Y;&0znh1bEFivj zZe+#P(|p&W?YsEb9fuV@ep!J&}o(SJOUoxrtUWqi@%lt2nkFW`YaFU#H)Hdr8zD_uhAC-@X)~FiF z)v5(VIk+FU9p!Ai;??^u2TC(^wO|hO4wAvh)JA%<69PJIl?6npRb1 zmp(VJ5IZ+Cn}?z=xqb*QbBACy%=NC;Q@{zaR_HSgjy zFI3+3Upd}ldHCr*rF5x`d6^tXK@4sx4xPcKUWZ*Z?;UQva!$!AJFopX0V_Z?sOVBl z`Q4B2eo%T`ZnlCu%MucH6nda`mA$aLTb;y|uJ19`F)tRT!+4_!KAVf#Fdt#pBpA)|#&PN{Z9E~WWMcb^!a0mD4-#RnNG4Pt z3AI1?ZWW(CA*xqW4qg#GC9_B?+(i(w7(A1oqVU-ikyGF6yc*tR*Wp9g&Du6x|e=UA?1Q5nWG zDL;R^)W!}q6$H6&oQwIWRCZsNbc;+)3^!{bpHMvVr>8GJSsVTXBR|W*%zvdv9U*Bf zQY?*;Sl>X1{;otInBD%a%sh-(@|;Hz1>8+xCh6df`Ed6UvA0x z^zaF(3cn!RybtC;WLz_JMlTYNYT1A;AiqPiYb8VcKri#L&$+vOchdJ`xfU8pNjm5e z-dSyitaV2Dy(6+QyZf7kednGILUD5@|&<*=n8 zzWqbkyX0Y&l{Ek??WpzZ?g(VA+Sg>I4FHO#lk^Hh1w?ZKm9YpY-&JjzosiS9SzMRG zl0-b&e4SQQC?%|_H6*+yzO=VJn4&e+8nzopNbso)Yf=b){DLdHQXdY9R3X0pJ0`fB z+Nt9ItLVa^DkvHBC`{U%TXt;DUhy$HTf$vKf%BI4vvEqCh=n;olw({H*`Fn$6Y*gV z7MzqM5XZ*RtC1(p5=1Y_nfbmrHTGye!=gL;zSnD|1Cb$!JG?s@SvR|;sGB>=9&|aB znOcQolQ@KUHJh~tr%eWLLR<^G#{FwYIZ5jf%_y7$mJL$yzRRt_kaA{gHGeQ$)LUb0 zLr=b}SNOX-X)Ewv!(pa8+zhZ#pL=sUD_@6ocWqGt|zj#S!vXJ>5yL0Y_ySd8+Nwdu1e=Rv(Cbi9p|d)kyffsby!?bOH$gU z1+Hk^V>>EF=vA;XMM%0d`lbg9`I8v32d_2<46a>G)X(aVUFf@+4#0@K{$3C{ES4sp zZX(Of?LM(o>ee!(vTv}XU^7=S1f)DrSonLlIo+JoIA8bO%Bt^owwc#+pE3o2rT9Va zvrb>-w`BqytS;AZA`we9YbDyrX&sOFXC}&7OSzEFjeK=_Ajd`rVqSVWo~CeR`7+w{ z3EoLx?3pzsu`(P>$4q+Oy++*{^n~UccpO^~rRJn}Va^e4S-gd0Je9`g@eG=f>Fd`S zbF_cmyLs6Uq(k^y3!PIh)h%R6KHkJM`!sh)&#AWgCjbHOqtikB=2v^ypTLChe~V$j z+lQDswWR!UWfH~FoV~H*5BuxyDSv*b<=*HNw-Z37{bGTb*R*Q>&Cs4!3dcr_to!2F z%()-rk<^2r)xN4ISkOtb#CjYFi-yV*3l>fwOKZV8d8uX!s%N&`TYD0O^we?`yQtS( zUoaooxyGwQnr`sx`*^ zXZb%)d^QJ>1Fg4ppf`ixO^@)5>%TO_(h9D0=Afu$Mh(uv-l8*OPmgUz9f(sXNt{3J zxo_ffUeI~ss%Ms5l01a(Vj=+PnR~!!Cd1?Uz^ z*fhIEd54?m#%(b11N*5AM#0T5If5?bsal9K!*y?&mhH1e=*WDi;@>y@ojT|1>GxqP z)TxW&w?F4fcF(U6YrU3r5I?xF zc%DwWK7K*{y?K(At>T=i_q^9GoofI#wLt6K?hbZ6T4?V?Ai>3)rj=o0lD63p_XkmE z&w+a&6Y|0`bocRIYbzN0HSKwdL??lDsfUFA03{n3GWu`dqf;8#h^ zfpTvMW|zad{+Ax{)y7Z>@6*4j>}1Nh3}ANA8Y6ErZ#AEKTTqX9vDrpsK$6h7!*YJ^ z&GCvn!eC{(!6*F)T-GV3yVeFBTj$H3PVpi8&4>11m--t93$K_$F3fzKw{dC znt5qfS;Bc$bW65&?HY5p$*zmRL0V?QeW2v~qkc|E&8N2dAdT!afn>qa=^&cKYRdT| zKULDP^EBPSRiNCe#>$%!okk0<%*8#foMC>q*k=e@p+eQMthH|SM14MsEiDxK4w&PT zdfYaW$fQ^-|F>8XLVBkKuk0x^54_dWF9-Y+iSHX|O~MkJ)MyL1E=BogjU0aN72ch$ zIg!P7la(JUQ|_ix1$>_NQ7nQtC}h)J)ZNWFm*=tAAtwtN`{8vEY!U3KJ^0=19e3A7 zw#_K$Ru zeb$M@cX>wo?%%YIU!~*%#a%o#e}LgwYNsg|NbCzJNqPG1e}0Qf%@GQD+?bcZZgnIc zTlTuR+5UtrjsH4-kPI*ZISr zNk&JR7RhNr+)WUqUfuM$U)#E|*hN!t4%zg!kNr2!dbLXqxjHU+C2+LXa)A6h?U`<*NHFYRnTN@hqyTkf~qR@@K6=Dd+ifS?|e?y85Hrsi%? zn1}DhLz^0g#N(ggyNuv>%OWm2i2L0Ja)A?z-8wf^(~%e|U|4+@kiPl&#RhLQ?Ol$U z`TZjOod1;lrpI30I7{3)7hBsWU^~LlkIA~Z(LT>U4~IPJ0f?!x@boCkVxJOtzJJbc zwNUu?)%Dq~NXOPmXLgY0cX{cgVACcc?Tb4(GhVK;!fXsdEY%}d8{aLX=kkx`Ss&b#Dkyvc&qH3 z&FMY!7~mG9&Hq+$|0ZyI8{^wFo@oF-J37_o8})NeG9J-dOlTl764!Uf32EZRJRtm& z-RU{4nC)J|`?E9p9ObSx*{lr?0?5&E?vM-db;2?rrGV+zEBnPEMo`9OKy0a zGAW8dI=+;%dk;mY$2d4&_dK9|@7C8O(HlIFCK0`$z=L+!C$DNdv8+7B;U{W8MPpoS zHLwph52~5SJvu6v3ekcAmM;o!js%s`!wGW!ZbcI`!H)e0_*jEd?-;U})v0oZ&Iks6 zi2F$#kyc=mNUrqxv^72pcX_agE7r_23#uMg^v@uQ#Tc`Wu}o@0Ap)UVEx&e0&xLP6 ze~~{r+@2^uw|V$LI!fM}t}fikh+8Ed6mV)qP_@0%BCrIsQ&By6Rh)E&%BI09lt-c`Q&#(WZ6|FjFX(X=5forkkB3{PnZ-(Y5^kMb#wt;F zd*wz=NT^}dJGYhndkeGdg1|TXk3c64?t1?}5^H9;e5SSSr75(<;Ir!~x#u0sj1mnl zj^Lgcq4uB~khf_b`1B;&Avx>C)BvXOkW9I2Oo6(%?btdiMS$g6B)uy!uF!`F$ijT+ z-O*&y+gdpFOmvhXHqHjdekrG`Y8SfLqoIGV;`_DrF<$h*(|gP-sbVvRAc?#k$FL}h zLt;Qd2U1k|6ga%;-R60}vOX}ajXqkdN}*)empvZzD9omJjv#drna5Zi@;ppUH(!|5 zD6pTT(zCsoM=b1AGNhOw3 z(>tzr|D)igwB&#M?2qxAA5i?$y#_9EWbSJ>ybKA?LYwh@$>p15P094(&YP=ub96$- zBn1N5&`J1pG#_Ux?+?qF`F>;}&kOJ0I^C&C;w|Q%y4H3LEM=scWng^vQ%X60>cHnO zzfJ!}0|vm|)2Yr&v{IBLlxy6)WOrX#eTM0`IPw5gML&4PHm zhrrcV-vv*t@+KPhAgLhIyBgwgfrSKEOf)A6j*= zqw-4hL2TaZZk=irPt{!l-aTqL$4A$OAlKASUPjM-HH2Axtsfb49w+79OQeDy{D39L z_SCgBZ{;1A32uVV*V|2~_+5z{ypHBdlG`BDWR;>gKi~UiuNTr_U^Iotr1@Z8cy%xu zyh^*;gQndtNL_rige$Jywrl){F-%DRtV|;>RbBEt-8Szu1!giO*(t5N0^O$WN?nzK z?V(pGC9Y?7yTQkrVtNw6lIxYBC{IwQ4)~f~0`{T^Oi;y~&Jx9S)@29Wv+vv;H2}?I z6`5?ZExK|QgI@>K2rn>oIGa`cx~X)}$rb@>jKQy7q`bzBldt~s$Da83BAIVYY=Ag$8_*vL_DR7iRjTw84*g`2qq&?}267~4 zo?{EPVFbZ)nXTXE;hz9kYvWQbA>MxOc;99Q;H6dv-n9p#IVRoy&W2J&&`q7vbkly+>Tnl)S|G27}V9G6bNLaLHCsrBs zc$+?V)IjHzVm9nq*!9!*-tws_pFX0>wFB&{;Eh7eI@ShzPMuh@ z9wA^-kM})BL_>qQuZZ8L=$i}bMm+l93z{wFKdtkbo+;Pg`qu=*O1MEcA=A*oV$IVl z6si%GS!b9$=XthLX&q2is5=u7MaY6!o z$kqN*`$r_3Nzn@&i$y?}gxW#e4s3Yrz~1i+j!IZA3kCiO)2-e;X&IpN*q$K#Y~jz7 zC^8mhpOx*>+*U+dsmSLu*vvE|MJm>h3h+bKX+sgAlaCf-o?JO#+Nhz+E=OE^G%kZC zbIsUQxH|FQlmfL>tk2D2?8hcmv!gFEB&Zq@ z20}I>R%&rI_Sc#-i=D9Vm4`1fE?nfKv5ib=pCeQ6X$ak~GxFzc+hf1y?m=GAB9!|@ z_6N7v^}u`1kDy*AVUZ-@C!nyoy%IQF7#8v-$~Z}v^2~AHqn$7x6t=2yCLIw;|)4= z;&a2+bU()D{Ig3G*mVWXrW*wF5)eLfc+K{$_7|_!$CPru%6BPK$FAmg$CK+rU$bLv zlwl26ExlQO*d#4(zIwzh5W~2xS0CfMnoTY%Ii80eo@rUR=ZxH;OY?4OTI4vTB;hZr z8lh$*!dZR#(~9ADx{NCOFiW2jLLADim;PE}bj& zT=R?{z+OF_=TtZHT9_o8EbHc%{`#Ctd%}Sq_99-+MLJ4c);9TGFL0G9lw-a3Q619# z%u{C2EM=u?Zxk#>y7q_BM=bn6r%d|u%WX;#d(`jwA`TO!`~5=jZcUrMAHu$unp;_$ zU*43Vsf=7vu}|i02#x@4Yj@toLp)r;s`a0VN1+q_p&$0Ssj2MX!}47&T@d`c^T)bR zmK#grks4zY-snM}6$;^cbxB<--1A4|E~{@P&*4$ip5Jz+NeI$(brk&+cDw4~f-6A- zOmyKqbkBU3&qG;kraEfkvkwHv&9fBQKBX&SIYa8iv;oVdU~Vr|H7?9M9TDr-EIymV z;vR@cC$_ah5P|lVaJ_HFQbgIe;TtB&&Gtjhtp$4B;oDCIcc3!Oaq+#X<16%+wH`J< zBxlXa)Mgd_5~2u}oUZ3rhFA`pT@4iy%;VzzaEEEeA*Z7sy_za<$J+@3ajB@=S)gv5 zce>_XHtk}fj$PBd4dLLZjO#h4_bwgwQjyAk3xDFbOsESUQi^nVB78Ij+%o<&w@^h{ ziiOC$Fz=D^B&kVnAgh$ULBC9Jf#16HZQpJPkMzD+EE9VwMC3ZoX=aM)^T=273i5VN zj%S-N1BGNfKk2aP!vnf_ZhsR_3l1^V0!`GXoicu2XpNh8KKyMSWH~adi7hq9#uqJ^!tyr+oeWt{_ zu;Yeb(EN>Fjs_Xe6o=<~Kd&|dq0C$}bMJ2CMA|Y1*6kLJTRnQN!qNn-W)X#gkfd2_ z=DQCSiiqJ7x1z{yOA4U}tuqA)daz4DM`pvY%@_ZJuOv;1C)(n<2%;wL?H7w1wbZV| zl4)Skd5MF$8cwB9Gzi7b*1qxvSHCX@Q6vJ&j!oW}9KF^)S8geOR59>E!(9}vq+_6N z32DdAA4E*Um>hF~b*L-4sJk76)J*@yM92_Eq1azOO7xJ@>bn^_ zYPXP;RM^kvTfzsY;(I9uwn*83ZggtRpL)LP^XZnM{=-jRz_6gfAY`jv5Axjq z_D>Az!;nPoecy{&h*c5pmcAscl;zoIvJV2#_O70&zZ$}(2qtx&`5ovd+2IMTYBSFh zRE)WprH5}wh1Phy<($_4237R>b7woQKh^=G_AnNb$h>>NIHO@S%#0EZ z_**Y>E_oPyf0*7Te%khVQ&+_6=4_rok8THbpY4C2+#gMgg+Bn>&3ii9h0|K^@tQ$y za4Jd{=>M;+X1X-T!j1)FdsvNt*iIw?JXc3m*8QQLbltC>mDW8fM=J!)xe-=!-+u1Q zcWF0~;I)5}0;{V03j%t13P{gIzo*l|n>!v9nd7xctzEgq`J=wc#t1n6N)7n?t|^HiTW zR^OC`saD^9ZS&5O@#OwqZ}5jvH}Y5A5ITYX;4^rncw3tEvSF156YbusCI$9?S_T0p zn?_tlreZ(V=EbS&4oh>k7XUHlA{FW0K98a4iuOjOYE5B>6-L*sW|o{{qKEBpY&6%ui^01udm}1u&VHivZ4C9qc!; z5k|MS^l0LFl0GKV?@+O{xa)Mur^H)o@1Le_rmIKZ6%L=xj6sw9IcNN|Ofd>wzMJ=c zXN}>z5$xjRzqtb?ixrk{vGLEI)s5sR)79weVj+PK&G4T1IMnzN4-E6x_i+ec>C>jQ zKsI!XORRv(7Anq&G@T(mI#h2w@MV^N8AfZPj*|fPZmLDPy(2o#mocSgaJF%sdmqwE z%KLSqlw;g!>6YDcS2yYU+colW{qskY1P>eld8N)AaTjQ28rwBshwT?->bX)bjrPIc zqHyMyJ1^yg5A!E}a#pST^ux>m$A?{y^3e$>3ta!a;{@MeIy|pR14Xy(JSi3XRM$#; z>%ljP-5#5&MN2AwkJ`X_cZpSoil3Xe>S@!tL`w2$nNPcM0w4u3WDhG2`Wz+H|))aw)5Tc64X_C6>z`f@xwRAM}>jyS3&$8J^B zXGF;e)_O2V;J|=yehnwi+qE86Ps79kc3ZE3soh;O)lhHKM1hPKWS0r8pVbK zh4QpxL*Cc#J-VS)^Xh zdmf!u&aO!EV{H|NPM^#7DA9x+FD3=5bWv13chAu?dGg=!?lbcwL~3og{P^xr2jn=j_au>YAA02()H&rG z@o5!Nw$fBO1_PV!q_eEv$D0So|08&Lmc25+EAsXV&(<|GFqHMh!Z`ZzV{L2(?2Po3c3DGv6;owALX8}fYO^3`h@!^2f;MdbLU3wzFdop zy!|o+w<&brJM^)F5gy4y9Oiz$wQ4y6^UlX_yVkpTT#^JO<;YxC#m~Kg-cu78(tTmk zIuCYWsRD}i%_4ttWbM9A=C}gK+V00LC#_#Hp6iNf9Hy@``RtPv@Q#n%pJNWGmeYNn zK@E}8JjoR9X5N2Z>k(AnzB&+`9C90W?BW4tmmz!Xn`u^K+lD|Gmk_gMeb;=Is2%kDA)`zZ z1%HD3ef!q-gGXP3JyMyJxMy;+;BJs57V-2*Qb~boIt)9*7TVHDD!I#C)`q+2;Pig= z5jO_Nnna48+pe-6Qi|6-$=YvhdH;I|PUkUq=$+Zy_rs!t5^w)8zu%)z5|%ag4YKi6PG@dWCj07pd?WmB%_&^N+jf(q z@wDPMq#APPQ)WO2eO1|ia&Hf!o7tn7hE9#SK+jOVSJ2~{`P^Om(~(u@Vu$`rgdvsO z@%$n~u)*fNI{ArB?s5kgDna^OI_Sgd&hPrwt(Ha;hZjW+GGjPTKYQuyE4<-G6@q}L?&Fh+`Z0i4gZ@jS1-1X97 zk^d;>B>^h0T;Xx^od4SsYT@Lc{IUF8o(Qh;DeSmaso`shKV~k0ETvrB2v*kpu^Loy z;oq6XHy9)TVgcXs`Goq28!CO`rzH}uQGd1kc$GtUl=xn2$EMC%~|T`@~M{oXYZ z9bGBPE_e-PD=2Qjd8-T1E6I2@wwKwuU8CtWF1VJE!R(vvxRvw!#5Zkx?zkQga-JL~ z=|lIXE1CwCwD_eHkYox1w(@cl%#B&lai&M`OedVti{4e67{4r3qQbP(QVFGx^G_6Sqbw^4)U%Nj-x$hV`McY3)F+8vj)hOM~epZP^`^%}gntf33 z_#EWFeer)v`|7x;wzXjdq(o8#L_!)tDd`TSq`Og&PU)cq1f(0JySt=8N^(TH8)T>< z2Bg0|=iKX6&VBED-uwN2^T*n-_ljpdwVqmGKvC+?jnj_&WNHIf20?PmGo!*mccoP@ zD0;(>rPmxnNurX;WfB} znzH{Q|LSwFJ#tmn<&*UgiD|$Q!DW3R2|5COE1fpE98=c|`Ep)w@BLAi zXsF8l6fr!tw1odm*uW;qql{~*eRl#!I89j@ul-xDY?0@k)bpg?EgclRC-iL}lF(*%F1w%b zq4YkpTHm^RCwaQgq5!q#v;Fu1LD6k;J*z6PNS?uHc1P8SRoxsV5NiN+^D3c215xNTX9mFw-mKdvL>&G+$lu&fcA_`N8Y#n4 zMu7Q*!#p~tx&aT`7ySM$Qez{Z@(Ci8cc>4JOutzwfMY%IQW<3vG?!i5$Pmmw4_10D zkSXO3go5zFf{tT*?WY&sD;{+Zgk2${t)*Z|A|iicCQJLI$j(mG#@0u7hZ#I~3$-f!-8A zQsoZ`XWT%MrAp=j$M~)RB^Gj0IKKQ~fDIkDA&u=&E0$rCv5AhC>gFx@RvIZ%VvGfR zP50E@EHyS~uN8r12qZ4Dg{@?an?a z(Q-aIhMjEA=|b`~KU)IjOrL1C;BzCOch)O!SRVksy6=`Y1&R9ytG!l)?T$a)U_|&D z|8Vv7y39H}Bjd1qolAmlot39#PHf?b?AYjPs%(6b-&a_#DVb?+OWwR{I z?YKEDeO!sxL|mNW8=Esx?!%IK2;y>r2TwGm^T*Vk6_7MiB4wT+R% zXqk*Rwg9+ZdycDY3Z3Y2`TDqFdzw4wP3t9nB8tJ4sN>iq%_3Eb18c%*NT`cTD;q!AcdeY3c=>(&bC!Kj74 zxT;$DKqOF=IyFA^Q;+s6Icj+SC3+QdLR&6D={K_LL8ohVLG`_rUAcGr=k6sv&AbeK z4|0aK9JQ~WX~NjZfV6zDko$4d6{e$;>PA|Uh+oSq7suY>>TH}s@WLlmw+|9pE;4De zEy=3`%XU#)w6k1qu546fdn2c!u_lsgqrqOvxe9X%7+%DL8E56V3D%ae)?I+HM;fSo zD^~mE_{!XC0F$=1`p#Wygy%iIStY!X?C&~lF$*|K23nDOsJ)mS?R?;w-cvnuvY;;I!7^0DPkK$8 z#N`D!TsrL{OpRvanp=D_bZihVyv^Px@gU~za2oM51Gd}vEs4)Gu(VzDkY5MTIgyg} zFV#PETHp3!gYD?A*^G&pY4`VajfQe&VSN_s&ZiOjUX4btOP};{nXT-hD%BS?_p^Xh z-tJYa5^?Bld~qmFfxIRx7%Z7qN%K}}jO|qRZDPwh7Z3D=Vb5vTk~rJ2W_f-`7}3>5 z*+#J<|A1&q$~>>}o*!h=LfiDig59}O3EY`u-oCmXE~J{dqNx`)k|!IZ9b-DoiMjn9 z@LPquU?4_W7FJ=;H-{P!l5sk3Pv%s;pj44SaWUz1#q6lb6gwYRs$3m=d$uqleboHi z&Ex%-drmV}T>UCEUpemso~;IsUO5THT4q17CjK~>zumP6}7{Rhu^8gV;1#2>!0&F@Lt=|8KE$W z1h31k?)OZ)iOq_Gx#KtJ<-r95cYBhit6m2;+osrqa-FFsMy}^wotO1qKN9v@djl30 zQ7-ieWq;Kk2aP%}eB41+?Tc+*VUCZo&S5h=w86uo;f6Dz;F`TNRwa{fRJw27gZWts zjXw19@y_0RbEAB4Qe5|t9*ki{72>yK(<4sH*Z^ z3n&aNJTGs+2{5U>ZPP>v_|eCtb}S_Gn`p@7IZ?q_?Vi@(O|PF ze6sb_;GIz;<_3rfFmtwqbI*KlDqVI(*m2TgDsvuMc*X6Dx8v++G9zkbc>g{o1>5~E z?2SRrPur1^`nM17nQi+V4Dn~wPP8_PQoLokU&NVsAo`>OsKSwY@D6;)-&c*A>Q{)g zZ;eErlDa9&<6>?7t+-}Efa9CkR(WRf81N1%p&K>*VlHXt=>+Tq6}LsUv2|%lmWY zEUv!q2OV{QYlDp@*~uihcq!fqeK$0lTfg8MD%Ita0`8KaqJPwsZQIRZ`juTUs2y`V zB!jsW6v_*1YYL(VK92~@uEPwkSTQR=Ro@CV%~Qs2CS+f*;e`hsr$$CAlXkzv=LU9dPlzopYQ3)sb*{ zssuxESx)OKJdwh~3lbHR1ionnpAN^b+=IB?S;qJo={JBT{8iVi%~iLnT*5jI)u!=t z5hEKximF_aUgv;Rk=Hj7sNmHQyK1xOp{YMa?$OB#c1)a;s>cG=*Z1Sn$){s`sE#DO zD$F#1w~0;m=;_ivY3hR2xv;A=IF+H93+{)KzTLJEiEovAfbnEuBUZjW1x&@&3X|~4rL5OfJ!ydRtu2nj)f%dud_KqUo7G)XZz+F~6 zpo8lB?+g)~nwao1c&E$r^=Z;Han72ut98>{j~oL7PN1^VF?U~aVfxCa>YrwvOlKjD zrMdGwRYqDF3xNUw_!MRt{MCl*2s41CLE^LwMqlQ)PA1Vl=_&8Zv&XuHPu@&-{HCIT z>>fCcK&pDs?b>;-_#SZYuk!hs_X)`D$7HM0Qtz0w1;p;m^Z?V+A^O?VJy&wE$x&6I zzC%bFE8yu0g2uBF7N&9ADLtlkh)E|VZ)w$HGlDh?H*kROuP@TLjD2{1wkD7;`R!@X z)ekGThECLxR~MEm}XWPv1 z;@~}_+j`fJRk(#3*5dU&qm2h=PW+3`9#1}d)8Gewj)374v z&=ZuJBTj~;p9_#c z_RKh*bdG!UtbW-aQF-qP0bb8 zZd&5nO4H?NezTyiv|k1K%=7sb$Ri#`2-pn_sBCW%RfG- z21183qE0(|wDQRY|A@o5S11;7Co=L>_T0OY(-xe3e1Rq3f-uxnzbXBs#i3wzqWH{;H)Vcow*T$}dsrodj6u_T6kI zKlwXsFZ1f=bt2=eEbL#zw5wqA3m+O z_%Hd=YO?D05{^-{cyE7}BrKJ1%~d{!iDuT zi}c9vZSq8l3;LL%`iR8z4}QWEwNxsS(G!B=NwCtFLyZlm1JmHcOJTIENQ9pZmK%AQ zL8Ye}hEud6#wWfu3=-nfo37BO$9@fy83g`iGhQ8Oq{yy%yDCXl=&9dexnN0wLpmpRt~V zE~RTSgJYG+LJY>$l!;mxREu`cU$)BKYCkcRN0F}RjiqS5DGKsu7Lfz3@=aLd;G|L<`XpTbw(35K%0St z`hLAyXX7fciM{RxLNpjG#+$YTXo;SAw*Gpx z?lbQTbZ})rA8XJ3zh~5pE9@;2xFD! zqv;frxMevzxukSOwh*l@L46UVmLK+d@d?>H+gzs`v>UVi6_DIlQv}nLxH4lN_(nFl zgNEjoO3WsFrHI&lOxgg+w?#&i1TM6N(6h&XG|w3HP`{mghHPeF5hHmyf*i?P`^aEV zv+moB3R5hT@&(SO z3NXmIs73hW7n$ezVV7O^4$E4O8+Zv9pnTZ-Nfr~eZ@x?sQYg$G4fh=M(xnv*H3&p8 z*uR)V|FFQ*S1w@u0w_I7@@Nrcwd)RqH$9&xzJr71J6UKJefBNe&O?Zqu;P=Pt2yo| zkmVE86U{1^*$b%o)X#(Uh}pv-xuut=S5Z8Lhj>-=+;I&t|bkt>H`L7qZU*em(EoJ7g8E;dQlHLKpL0{3@3>eS&VgsTBwuCZg zf)iP%tF1F8c7%QmI&IC%qlS|6iSE{K$no*6o)xNEys3wzI}JJ93LoPtNMvE@GWWSS zz36Li-UHI!A`3=L&H@j=N_o^BJV3JPAhLzV9;Dk~R*_a)txTcj;oLP#CKJcyw7xJ( zY&Bp7fURQ(viGN((5%u^+l>2>e2uf{z4}#{4npl5$zc0iu%qbcR z@!0^kcY*a@ecea&@qROK_zCE}-Mqb(NQ*pe{9T7pXHao~{y@?leO2<;80Y?|cLHDJ z&lkR7_u(cp#@=Oz`5)wlVY935mc5C(BcAAS?r><`SRzh^flciffaA8qw>8Q>Wl_4U zhE_PtspDlE?x4j#?YBT!Dqsx`$|v__XrRZIicD=BswL-j&?p?s-@*qj#tD<;za#cF z{OCt0P*IG2d8+`>fPN=X$mD6sb92S@Yfr-bHE(3Rdi>C2BLs0d`KBR6UF~Hb{Y@9H;qWhE`cF|4kO{ z6OY}D?<3xI4l@+#-$$GyPBiCuM*LDZzcwT(c;vjLkDxnol_#KOHg>nilI|RM@+nu` zaA->o2-%dgYn{PlU{nL@ONtNAJD5l8ZrPihHlOhLLv%;&E$toeX8a|MX$RE7{mnUZn~pAdDxjGl{E5zmosd!^bGC0n&wqHUF)$|mqKHmV9>F38COo%k=+ zH*VoKH(%mepAMVAvjn~aSD1x)%O(M#!Sks$pR8SFCjloz&Wq14%V;tCZx@ogEN34M zwcyn+=;k>oGRo3fLAK6%#v1j!M7=;q(bax0Z{f+dVEPMO2hnN1ylKJCY&+bU+Nh$?D;R6OTS8Yhfb3#;v(1DOZ?N zRdk=-25B?+j((cU_XlPkX|2ZDE2H77S!w)3{(W%+J9HtAjC=}{STu57!n$ZLk*3nS zA;cS@WscQ=TmT>AM37W8Y7^JpYn^2rwJ9?$0TmmYr5QoHXKjzpJ*~WP?q|L=bSX1u zwadC_*&xSXZ72rWi|pXe-Cy42w|%+s+|5^W1Vf!6WwvIT&#ByDsZ-Zn)RBdiY`CID z?yiHkGi=U_w8vPOF&l-hE%LDo&Uzk~#iN)K9xXVZsJnX~Gmw?jwF}#m zY{X(Aqv>-IF_}`H^qZ*LI@ZdF#~`YO5m8%{Ot`ivAM|btc|$$jB69A&PW*$gd5Tt^ zA->h;UQ(&s@l(CJ6Lw*S3Yfqt6=Tfm!BR<&PCl7l4IwQ7FM<KtlvxX2ccjL8Fmhja9yDMWtCgx>|3xs$~ z;%_qTh^Lo=-S7KsdV0k2!w%T9WuAoYF;Je`>(OqG-n&~%D&(j(M{(RYF@rVJ4r<