From 883af7008934bc7d9bf26fc7c5663ff6a2ab8355 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 9 Apr 2020 09:39:33 -0400 Subject: [PATCH 001/121] [Remote clusters] Fix flaky jest tests (#58768) --- .../remote_clusters_add.test.js | 2 - .../remote_clusters_edit.test.js | 44 ++++++++----------- .../remote_clusters_list.test.js | 18 ++++---- .../remote_cluster_form.test.js.snap | 6 ++- .../remote_cluster_form.js | 2 +- .../remote_cluster_add/remote_cluster_add.js | 6 ++- 6 files changed, 40 insertions(+), 38 deletions(-) diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js index 78482198b1a5d..569c9a6c56c5a 100644 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_add.test.js @@ -7,8 +7,6 @@ import { pageHelpers, nextTick, setupEnvironment } from './helpers'; import { NON_ALPHA_NUMERIC_CHARS, ACCENTED_CHARS } from './helpers/constants'; -jest.mock('ui/new_platform'); - const { setup } = pageHelpers.remoteClustersAdd; describe('Create Remote cluster', () => { diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js index f7625d9eec090..a5905227f49b8 100644 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_edit.test.js @@ -4,29 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('ui/new_platform'); +import { act } from 'react-dom/test-utils'; + import { RemoteClusterForm } from '../../public/application/sections/components/remote_cluster_form'; -// import { pageHelpers, setupEnvironment, nextTick } from './helpers'; -import { pageHelpers, nextTick } from './helpers'; +import { pageHelpers, setupEnvironment } from './helpers'; import { REMOTE_CLUSTER_EDIT, REMOTE_CLUSTER_EDIT_NAME } from './helpers/constants'; -// const { setup } = pageHelpers.remoteClustersEdit; +const { setup } = pageHelpers.remoteClustersEdit; const { setup: setupRemoteClustersAdd } = pageHelpers.remoteClustersAdd; -// FLAKY: https://github.com/elastic/kibana/issues/57762 -// FLAKY: https://github.com/elastic/kibana/issues/57997 -// FLAKY: https://github.com/elastic/kibana/issues/57998 -describe.skip('Edit Remote cluster', () => { - // let server; - // let httpRequestsMockHelpers; +describe('Edit Remote cluster', () => { + let server; + let httpRequestsMockHelpers; let component; let find; let exists; - - /** - * - * commented out due to hooks being called regardless of skip - * https://github.com/facebook/jest/issues/8379 + let waitFor; beforeAll(() => { ({ server, httpRequestsMockHelpers } = setupEnvironment()); @@ -39,13 +32,12 @@ describe.skip('Edit Remote cluster', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadRemoteClustersResponse([REMOTE_CLUSTER_EDIT]); - ({ component, find, exists } = setup()); - await nextTick(100); // We need to wait next tick for the mock server response to kick in - component.update(); + await act(async () => { + ({ component, find, exists, waitFor } = setup()); + await waitFor('remoteClusterForm'); + }); }); - */ - test('should have the title of the page set correctly', () => { expect(exists('remoteClusterPageTitle')).toBe(true); expect(find('remoteClusterPageTitle').text()).toEqual('Edit remote cluster'); @@ -60,14 +52,16 @@ describe.skip('Edit Remote cluster', () => { * the "create" remote cluster, we won't test it again but simply make sure that * the form component is indeed shared between the 2 app sections. */ - test('should use the same Form component as the "" component', async () => { - const { component: addRemoteClusterComponent } = setupRemoteClustersAdd(); + test('should use the same Form component as the "" component', async () => { + let addRemoteClusterTestBed; - await nextTick(); - addRemoteClusterComponent.update(); + await act(async () => { + addRemoteClusterTestBed = setupRemoteClustersAdd(); + addRemoteClusterTestBed.waitFor('remoteClusterAddPage'); + }); const formEdit = component.find(RemoteClusterForm); - const formAdd = addRemoteClusterComponent.find(RemoteClusterForm); + const formAdd = addRemoteClusterTestBed.component.find(RemoteClusterForm); expect(formEdit.length).toBe(1); expect(formAdd.length).toBe(1); diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js index 954deb8b98d3e..bc73387831c9d 100644 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/remote_clusters_list.test.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 { act } from 'react-dom/test-utils'; import { pageHelpers, @@ -17,8 +18,6 @@ import { getRemoteClusterMock } from '../../fixtures/remote_cluster'; import { PROXY_MODE } from '../../common/constants'; -jest.mock('ui/new_platform'); - const { setup } = pageHelpers.remoteClustersList; describe('', () => { @@ -78,6 +77,7 @@ describe('', () => { let actions; let tableCellsValues; let rows; + let waitFor; // For deterministic tests, we need to make sure that remoteCluster1 comes before remoteCluster2 // in the table list that is rendered. As the table orders alphabetically by index name @@ -110,11 +110,11 @@ describe('', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadRemoteClustersResponse(remoteClusters); - // Mount the component - ({ component, find, exists, table, actions } = setup()); + await act(async () => { + ({ component, find, exists, table, actions, waitFor } = setup()); - await nextTick(100); // Make sure that the Http request is fulfilled - component.update(); + await waitFor('remoteClusterListTable'); + }); // Read the remote clusters list table ({ rows, tableCellsValues } = table.getMetaData('remoteClusterListTable')); @@ -241,8 +241,10 @@ describe('', () => { actions.clickBulkDeleteButton(); actions.clickConfirmModalDeleteRemoteCluster(); - await nextTick(600); // there is a 500ms timeout in the api action - component.update(); + await act(async () => { + await nextTick(600); // there is a 500ms timeout in the api action + component.update(); + }); ({ rows } = table.getMetaData('remoteClusterListTable')); diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap index 1e6c2c4d289aa..35c566548f158 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap @@ -118,9 +118,12 @@ exports[`RemoteClusterForm proxy mode renders correct connection settings when u } save={[Function]} > - +
{this.renderSaveErrorFeedback()} - + diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js index 0531310bd097b..4f9c5dcd38254 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js @@ -57,7 +57,11 @@ export class RemoteClusterAdd extends PureComponent { const { isAddingCluster, addClusterError } = this.props; return ( - + Date: Thu, 9 Apr 2020 09:41:38 -0400 Subject: [PATCH 002/121] [Endpoint][EPM] Endpoint depending on ingest manager to initialize (#62871) * Endpoint successfully depending on ingest manager to initialize * Moving the endpoint functional tests to their own directory to avoid enabling ingest in the base tests * Removing page objects and other endpoint fields from base functional * Updating code owners with new functional location * Pointing resolver tests at endpoint functional tests * Pointing space tests at the endpoint functional directory * Adding jest test names --- .github/CODEOWNERS | 3 +- x-pack/plugins/endpoint/kibana.json | 2 +- .../public/applications/endpoint/index.tsx | 2 + .../endpoint/mocks/dependencies_start_mock.ts | 3 ++ .../applications/endpoint/view/setup.tsx | 52 +++++++++++++++++++ x-pack/plugins/endpoint/public/plugin.ts | 2 + .../ingest_manager/common/types/models/epm.ts | 1 + x-pack/plugins/ingest_manager/public/index.ts | 2 + .../plugins/ingest_manager/public/plugin.ts | 20 ++++++- x-pack/scripts/functional_tests.js | 2 + x-pack/test/functional/config.js | 5 -- .../endpoint/alerts/api_feature/mappings.json | 3 +- x-pack/test/functional/page_objects/index.ts | 4 -- .../apps/endpoint/alerts.ts | 0 .../feature_controls/endpoint_spaces.ts | 0 .../apps/endpoint/feature_controls/index.ts | 0 .../apps/endpoint/header_nav.ts | 0 .../apps/endpoint/host_list.ts | 0 .../apps/endpoint/index.ts | 0 .../apps/endpoint/landing_page.ts | 7 ++- .../apps/endpoint/policy_list.ts | 0 x-pack/test/functional_endpoint/config.ts | 37 +++++++++++++ .../ftr_provider_context.d.ts | 12 +++++ .../page_objects/endpoint_alerts_page.ts | 0 .../page_objects/endpoint_page.ts | 0 .../functional_endpoint/page_objects/index.ts | 15 ++++++ .../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 | 4 +- 31 files changed, 238 insertions(+), 16 deletions(-) create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/setup.tsx rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/alerts.ts (100%) rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/feature_controls/endpoint_spaces.ts (100%) rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/feature_controls/index.ts (100%) rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/header_nav.ts (100%) rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/host_list.ts (100%) rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/index.ts (100%) rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/landing_page.ts (72%) rename x-pack/test/{functional => functional_endpoint}/apps/endpoint/policy_list.ts (100%) create mode 100644 x-pack/test/functional_endpoint/config.ts create mode 100644 x-pack/test/functional_endpoint/ftr_provider_context.d.ts rename x-pack/test/{functional => functional_endpoint}/page_objects/endpoint_alerts_page.ts (100%) rename x-pack/test/{functional => functional_endpoint}/page_objects/endpoint_page.ts (100%) create mode 100644 x-pack/test/functional_endpoint/page_objects/index.ts create mode 100644 x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/index.ts create mode 100644 x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/landing_page.ts create mode 100644 x-pack/test/functional_endpoint_ingest_failure/config.ts create mode 100644 x-pack/test/functional_endpoint_ingest_failure/ftr_provider_context.d.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index feaf47e45fd69..e707250ff3261 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -202,7 +202,8 @@ # Endpoint /x-pack/plugins/endpoint/ @elastic/endpoint-app-team /x-pack/test/api_integration/apis/endpoint/ @elastic/endpoint-app-team -/x-pack/test/functional/apps/endpoint/ @elastic/endpoint-app-team +/x-pack/test/functional_endpoint/ @elastic/endpoint-app-team +/x-pack/test/functional_endpoint_ingest_failure/ @elastic/endpoint-app-team /x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team # SIEM diff --git a/x-pack/plugins/endpoint/kibana.json b/x-pack/plugins/endpoint/kibana.json index 5b8bec7777406..4b48c83fb0e7c 100644 --- a/x-pack/plugins/endpoint/kibana.json +++ b/x-pack/plugins/endpoint/kibana.json @@ -3,7 +3,7 @@ "version": "1.0.0", "kibanaVersion": "kibana", "configPath": ["xpack", "endpoint"], - "requiredPlugins": ["features", "embeddable", "data", "dataEnhanced"], + "requiredPlugins": ["features", "embeddable", "data", "dataEnhanced", "ingestManager"], "server": true, "ui": true } diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx index 89a6302351a54..82ac95160519c 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx @@ -18,6 +18,7 @@ import { PolicyList } from './view/policy'; import { PolicyDetails } from './view/policy'; import { HeaderNavigation } from './components/header_nav'; import { AppRootProvider } from './view/app_root_provider'; +import { Setup } from './view/setup'; /** * This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle. @@ -48,6 +49,7 @@ const AppRoot: React.FunctionComponent = React.memo( ({ history, store, coreStart, depsStart }) => { return ( + & { */ export interface DepsStartMock { data: DataMock; + ingestManager: IngestManagerStart; } /** @@ -54,5 +56,6 @@ export const depsStartMock: () => DepsStartMock = () => { return { data: dataMock, + ingestManager: { success: true }, }; }; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/setup.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/setup.tsx new file mode 100644 index 0000000000000..a826e1f30f75d --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/setup.tsx @@ -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 * as React from 'react'; +import { i18n } from '@kbn/i18n'; +import { NotificationsStart } from 'kibana/public'; +import { IngestManagerStart } from '../../../../../ingest_manager/public'; + +export const Setup: React.FunctionComponent<{ + ingestManager: IngestManagerStart; + notifications: NotificationsStart; +}> = ({ ingestManager, notifications }) => { + React.useEffect(() => { + const defaultText = i18n.translate('xpack.endpoint.ingestToastMessage', { + defaultMessage: 'Ingest Manager failed during its setup.', + }); + + const title = i18n.translate('xpack.endpoint.ingestToastTitle', { + defaultMessage: 'App failed to initialize', + }); + + const displayToastWithModal = (text: string) => { + const errorText = new Error(defaultText); + // we're leveraging the notification's error toast which is usually used for displaying stack traces of an + // actually Error. Instead of displaying a stack trace we'll display the more detailed error text when the + // user clicks `See the full error` button to see the modal + errorText.stack = text; + notifications.toasts.addError(errorText, { + title, + }); + }; + + const displayToast = () => { + notifications.toasts.addDanger({ + title, + text: defaultText, + }); + }; + + if (!ingestManager.success) { + if (ingestManager.error) { + displayToastWithModal(ingestManager.error.message); + } else { + displayToast(); + } + } + }, [ingestManager, notifications.toasts]); + + return null; +}; diff --git a/x-pack/plugins/endpoint/public/plugin.ts b/x-pack/plugins/endpoint/public/plugin.ts index ee5bbe71ae8aa..9964454add801 100644 --- a/x-pack/plugins/endpoint/public/plugin.ts +++ b/x-pack/plugins/endpoint/public/plugin.ts @@ -8,6 +8,7 @@ import { Plugin, CoreSetup, AppMountParameters, CoreStart } from 'kibana/public' import { EmbeddableSetup } from 'src/plugins/embeddable/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; import { i18n } from '@kbn/i18n'; +import { IngestManagerStart } from '../../ingest_manager/public'; import { ResolverEmbeddableFactory } from './embeddables/resolver'; export type EndpointPluginStart = void; @@ -18,6 +19,7 @@ export interface EndpointPluginSetupDependencies { } export interface EndpointPluginStartDependencies { data: DataPublicPluginStart; + ingestManager: IngestManagerStart; } /** diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index efa6621001038..5524e7505d74b 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -252,6 +252,7 @@ export enum IngestAssetType { export enum DefaultPackages { base = 'base', system = 'system', + endpoint = 'endpoint', } export interface IndexTemplate { diff --git a/x-pack/plugins/ingest_manager/public/index.ts b/x-pack/plugins/ingest_manager/public/index.ts index aa1e0e79e548b..c11ad60dffee4 100644 --- a/x-pack/plugins/ingest_manager/public/index.ts +++ b/x-pack/plugins/ingest_manager/public/index.ts @@ -6,6 +6,8 @@ import { PluginInitializerContext } from 'src/core/public'; import { IngestManagerPlugin } from './plugin'; +export { IngestManagerStart } from './plugin'; + export const plugin = (initializerContext: PluginInitializerContext) => { return new IngestManagerPlugin(initializerContext); }; diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/ingest_manager/public/plugin.ts index d7be1c1f1fe6e..77bba0bb0f990 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/ingest_manager/public/plugin.ts @@ -17,11 +17,20 @@ import { LicensingPluginSetup } from '../../licensing/public'; import { PLUGIN_ID } from '../common/constants'; import { IngestManagerConfigType } from '../common/types'; +import { setupRouteService } from '../common'; export { IngestManagerConfigType } from '../common/types'; export type IngestManagerSetup = void; -export type IngestManagerStart = void; +/** + * Describes public IngestManager plugin contract returned at the `start` stage. + */ +export interface IngestManagerStart { + success: boolean; + error?: { + message: string; + }; +} export interface IngestManagerSetupDeps { licensing: LicensingPluginSetup; @@ -61,7 +70,14 @@ export class IngestManagerPlugin }); } - public start(core: CoreStart) {} + public async start(core: CoreStart): Promise { + try { + const { isInitialized: success } = await core.http.post(setupRouteService.getSetupPath()); + return { success }; + } catch (error) { + return { success: false, error: { message: error.body?.message || 'Unknown error' } }; + } + } public stop() {} } diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index 7943da07716a1..061c9e4a0d921 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -43,6 +43,8 @@ const onlyNotInCoverageTests = [ require.resolve('../test/licensing_plugin/config.ts'), require.resolve('../test/licensing_plugin/config.public.ts'), require.resolve('../test/licensing_plugin/config.legacy.ts'), + require.resolve('../test/functional_endpoint_ingest_failure/config.ts'), + require.resolve('../test/functional_endpoint/config.ts'), ]; require('@kbn/plugin-helpers').babelRegister(); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index cff555feace18..bc9a67da731cc 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -57,7 +57,6 @@ export default async function({ readConfigFile }) { resolve(__dirname, './apps/cross_cluster_replication'), resolve(__dirname, './apps/remote_clusters'), resolve(__dirname, './apps/transform'), - resolve(__dirname, './apps/endpoint'), // This license_management file must be last because it is destructive. resolve(__dirname, './apps/license_management'), ], @@ -88,7 +87,6 @@ export default async function({ readConfigFile }) { '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', '--telemetry.banner=false', '--timelion.ui.enabled=true', - '--xpack.endpoint.enabled=true', ], }, uiSettings: { @@ -199,9 +197,6 @@ export default async function({ readConfigFile }) { pathname: '/app/kibana/', hash: '/management/elasticsearch/transform', }, - endpoint: { - pathname: '/app/endpoint', - }, }, // choose where esArchiver should load archives from diff --git a/x-pack/test/functional/es_archives/endpoint/alerts/api_feature/mappings.json b/x-pack/test/functional/es_archives/endpoint/alerts/api_feature/mappings.json index 64dc395ab69a4..7068c24a4b26c 100644 --- a/x-pack/test/functional/es_archives/endpoint/alerts/api_feature/mappings.json +++ b/x-pack/test/functional/es_archives/endpoint/alerts/api_feature/mappings.json @@ -389,7 +389,8 @@ "type": "nested" }, "file_extension": { - "type": "long" + "ignore_above": 1024, + "type": "keyword" }, "project_file": { "properties": { diff --git a/x-pack/test/functional/page_objects/index.ts b/x-pack/test/functional/page_objects/index.ts index 07c5719ae53c5..782d57adea770 100644 --- a/x-pack/test/functional/page_objects/index.ts +++ b/x-pack/test/functional/page_objects/index.ts @@ -46,8 +46,6 @@ import { LensPageProvider } from './lens_page'; import { InfraMetricExplorerProvider } from './infra_metric_explorer'; import { RoleMappingsPageProvider } from './role_mappings_page'; import { SpaceSelectorPageProvider } from './space_selector_page'; -import { EndpointPageProvider } from './endpoint_page'; -import { EndpointAlertsPageProvider } from './endpoint_alerts_page'; // just like services, PageObjects are defined as a map of // names to Providers. Merge in Kibana's or pick specific ones @@ -81,6 +79,4 @@ export const pageObjects = { copySavedObjectsToSpace: CopySavedObjectsToSpacePageProvider, lens: LensPageProvider, roleMappings: RoleMappingsPageProvider, - endpoint: EndpointPageProvider, - endpointAlerts: EndpointAlertsPageProvider, }; diff --git a/x-pack/test/functional/apps/endpoint/alerts.ts b/x-pack/test/functional_endpoint/apps/endpoint/alerts.ts similarity index 100% rename from x-pack/test/functional/apps/endpoint/alerts.ts rename to x-pack/test/functional_endpoint/apps/endpoint/alerts.ts diff --git a/x-pack/test/functional/apps/endpoint/feature_controls/endpoint_spaces.ts b/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/endpoint_spaces.ts similarity index 100% rename from x-pack/test/functional/apps/endpoint/feature_controls/endpoint_spaces.ts rename to x-pack/test/functional_endpoint/apps/endpoint/feature_controls/endpoint_spaces.ts diff --git a/x-pack/test/functional/apps/endpoint/feature_controls/index.ts b/x-pack/test/functional_endpoint/apps/endpoint/feature_controls/index.ts similarity index 100% rename from x-pack/test/functional/apps/endpoint/feature_controls/index.ts rename to x-pack/test/functional_endpoint/apps/endpoint/feature_controls/index.ts diff --git a/x-pack/test/functional/apps/endpoint/header_nav.ts b/x-pack/test/functional_endpoint/apps/endpoint/header_nav.ts similarity index 100% rename from x-pack/test/functional/apps/endpoint/header_nav.ts rename to x-pack/test/functional_endpoint/apps/endpoint/header_nav.ts diff --git a/x-pack/test/functional/apps/endpoint/host_list.ts b/x-pack/test/functional_endpoint/apps/endpoint/host_list.ts similarity index 100% rename from x-pack/test/functional/apps/endpoint/host_list.ts rename to x-pack/test/functional_endpoint/apps/endpoint/host_list.ts diff --git a/x-pack/test/functional/apps/endpoint/index.ts b/x-pack/test/functional_endpoint/apps/endpoint/index.ts similarity index 100% rename from x-pack/test/functional/apps/endpoint/index.ts rename to x-pack/test/functional_endpoint/apps/endpoint/index.ts diff --git a/x-pack/test/functional/apps/endpoint/landing_page.ts b/x-pack/test/functional_endpoint/apps/endpoint/landing_page.ts similarity index 72% rename from x-pack/test/functional/apps/endpoint/landing_page.ts rename to x-pack/test/functional_endpoint/apps/endpoint/landing_page.ts index 65af91feae407..b4da4631aa60b 100644 --- a/x-pack/test/functional/apps/endpoint/landing_page.ts +++ b/x-pack/test/functional_endpoint/apps/endpoint/landing_page.ts @@ -7,8 +7,9 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; -export default ({ getPageObjects }: FtrProviderContext) => { +export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['common', 'endpoint']); + const testSubjects = getService('testSubjects'); describe('Endpoint landing page', function() { this.tags('ciGroup7'); @@ -20,5 +21,9 @@ export default ({ getPageObjects }: FtrProviderContext) => { 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/apps/endpoint/policy_list.ts b/x-pack/test/functional_endpoint/apps/endpoint/policy_list.ts similarity index 100% rename from x-pack/test/functional/apps/endpoint/policy_list.ts rename to x-pack/test/functional_endpoint/apps/endpoint/policy_list.ts diff --git a/x-pack/test/functional_endpoint/config.ts b/x-pack/test/functional_endpoint/config.ts new file mode 100644 index 0000000000000..37bf57b67b47e --- /dev/null +++ b/x-pack/test/functional_endpoint/config.ts @@ -0,0 +1,37 @@ +/* + * 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 { resolve } from 'path'; +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; +import { pageObjects } from './page_objects'; + +export default async function({ readConfigFile }: FtrConfigProviderContext) { + const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + + return { + ...xpackFunctionalConfig.getAll(), + pageObjects, + testFiles: [resolve(__dirname, './apps/endpoint')], + junit: { + reportName: 'X-Pack Endpoint Functional Tests', + }, + apps: { + ...xpackFunctionalConfig.get('apps'), + endpoint: { + pathname: '/app/endpoint', + }, + }, + kbnTestServer: { + ...xpackFunctionalConfig.get('kbnTestServer'), + serverArgs: [ + ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + '--xpack.endpoint.enabled=true', + '--xpack.ingestManager.enabled=true', + '--xpack.ingestManager.fleet.enabled=true', + ], + }, + }; +} diff --git a/x-pack/test/functional_endpoint/ftr_provider_context.d.ts b/x-pack/test/functional_endpoint/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..21ab5d5a4e554 --- /dev/null +++ b/x-pack/test/functional_endpoint/ftr_provider_context.d.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; + +import { pageObjects } from './page_objects'; +import { services } from '../functional/services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/functional/page_objects/endpoint_alerts_page.ts b/x-pack/test/functional_endpoint/page_objects/endpoint_alerts_page.ts similarity index 100% rename from x-pack/test/functional/page_objects/endpoint_alerts_page.ts rename to x-pack/test/functional_endpoint/page_objects/endpoint_alerts_page.ts diff --git a/x-pack/test/functional/page_objects/endpoint_page.ts b/x-pack/test/functional_endpoint/page_objects/endpoint_page.ts similarity index 100% rename from x-pack/test/functional/page_objects/endpoint_page.ts rename to x-pack/test/functional_endpoint/page_objects/endpoint_page.ts diff --git a/x-pack/test/functional_endpoint/page_objects/index.ts b/x-pack/test/functional_endpoint/page_objects/index.ts new file mode 100644 index 0000000000000..8138ce2eeccb3 --- /dev/null +++ b/x-pack/test/functional_endpoint/page_objects/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 { pageObjects as xpackFunctionalPageObjects } from '../../functional/page_objects'; +import { EndpointPageProvider } from './endpoint_page'; +import { EndpointAlertsPageProvider } from './endpoint_alerts_page'; + +export const pageObjects = { + ...xpackFunctionalPageObjects, + endpoint: EndpointPageProvider, + endpointAlerts: EndpointAlertsPageProvider, +}; diff --git a/x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/index.ts b/x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/index.ts new file mode 100644 index 0000000000000..ae35f3e525461 --- /dev/null +++ b/x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * 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('endpoint when the ingest manager fails to setup correctly', function() { + this.tags('ciGroup7'); + + loadTestFile(require.resolve('./landing_page')); + }); +} diff --git a/x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/landing_page.ts b/x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/landing_page.ts new file mode 100644 index 0000000000000..d29250ca3bed4 --- /dev/null +++ b/x-pack/test/functional_endpoint_ingest_failure/apps/endpoint/landing_page.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + describe('home page', function() { + const pageObjects = getPageObjects(['common']); + const testSubjects = getService('testSubjects'); + + before(async () => { + await pageObjects.common.navigateToApp('endpoint'); + }); + + it('displays an error toast', async () => { + await testSubjects.existOrFail('euiToastHeader'); + }); + }); +}; diff --git a/x-pack/test/functional_endpoint_ingest_failure/config.ts b/x-pack/test/functional_endpoint_ingest_failure/config.ts new file mode 100644 index 0000000000000..a2055a4bbdc18 --- /dev/null +++ b/x-pack/test/functional_endpoint_ingest_failure/config.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 { resolve } from 'path'; +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; + +export default async function({ readConfigFile }: FtrConfigProviderContext) { + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional_endpoint/config.ts') + ); + + return { + ...xpackFunctionalConfig.getAll(), + testFiles: [resolve(__dirname, './apps/endpoint')], + junit: { + reportName: 'X-Pack Endpoint Without Ingest Functional Tests', + }, + kbnTestServer: { + ...xpackFunctionalConfig.get('kbnTestServer'), + serverArgs: [ + ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + // use a bogus port so the ingest manager setup will fail + '--xpack.ingestManager.epm.registryUrl=http://127.0.0.1:12345', + ], + }, + }; +} diff --git a/x-pack/test/functional_endpoint_ingest_failure/ftr_provider_context.d.ts b/x-pack/test/functional_endpoint_ingest_failure/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..0e4b47471d419 --- /dev/null +++ b/x-pack/test/functional_endpoint_ingest_failure/ftr_provider_context.d.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; + +import { pageObjects } from '../functional_endpoint/page_objects'; +import { services } from '../functional/services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/plugin_functional/config.ts b/x-pack/test/plugin_functional/config.ts index 6c3c496da71f6..aa3c9bd24842a 100644 --- a/x-pack/test/plugin_functional/config.ts +++ b/x-pack/test/plugin_functional/config.ts @@ -14,7 +14,9 @@ import { pageObjects } from './page_objects'; /* eslint-disable import/no-default-export */ export default async function({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional_endpoint/config.ts') + ); // Find all folders in ./plugins since we treat all them as plugin folder const allFiles = fs.readdirSync(resolve(__dirname, 'plugins')); From abe3ccf1cc45213c2991af83e261a12ce19e91d1 Mon Sep 17 00:00:00 2001 From: Daniil Suleiman <31325372+sulemanof@users.noreply.github.com> Date: Thu, 9 Apr 2020 17:00:45 +0300 Subject: [PATCH 003/121] [Table Vis] Fix visualization overflow (#62630) * Fix data table vis overflowing * Change overflow to hidden --- src/plugins/vis_default_editor/public/_default.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/vis_default_editor/public/_default.scss b/src/plugins/vis_default_editor/public/_default.scss index 985381eeb56a5..2187baea547da 100644 --- a/src/plugins/vis_default_editor/public/_default.scss +++ b/src/plugins/vis_default_editor/public/_default.scss @@ -72,6 +72,7 @@ display: flex; flex-basis: 100%; flex: 1; + overflow: hidden; @include euiBreakpoint('xs', 's', 'm') { // If we are on a small screen we force the visualization to take 100% width. From f9ba963af90d41b74e8d7dde9981c9a5cee53127 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Thu, 9 Apr 2020 10:33:55 -0400 Subject: [PATCH 004/121] [ML] DF Analytics: update memory estimate after adding exclude fields (#62850) * update mml estimate when excludes changes * ensure manually input mml is validated once estimated mml loads --- .../create_analytics_form.tsx | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) 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 index 0c83dfb6a2346..199100d8b5ab0 100644 --- 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 @@ -55,7 +55,14 @@ export const CreateAnalyticsForm: FC = ({ actions, sta const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; const { setFormState, setEstimatedModelMemoryLimit } = actions; const mlContext = useMlContext(); - const { form, indexPatternsMap, isAdvancedEditorEnabled, isJobCreated, requestMessages } = state; + const { + estimatedModelMemoryLimit, + form, + indexPatternsMap, + isAdvancedEditorEnabled, + isJobCreated, + requestMessages, + } = state; const forceInput = useRef(null); const firstUpdate = useRef(true); @@ -152,6 +159,9 @@ export const CreateAnalyticsForm: FC = ({ actions, sta const debouncedGetExplainData = debounce(async () => { const shouldUpdateModelMemoryLimit = !firstUpdate.current || !modelMemoryLimit; + const shouldUpdateEstimatedMml = + !firstUpdate.current || !modelMemoryLimit || estimatedModelMemoryLimit === ''; + if (firstUpdate.current) { firstUpdate.current = false; } @@ -167,13 +177,12 @@ export const CreateAnalyticsForm: FC = ({ actions, sta const jobConfig = getJobConfigFromFormState(form); delete jobConfig.dest; delete jobConfig.model_memory_limit; - delete jobConfig.analyzed_fields; const resp: DfAnalyticsExplainResponse = await ml.dataFrameAnalytics.explainDataFrameAnalytics( jobConfig ); const expectedMemoryWithoutDisk = resp.memory_estimation?.expected_memory_without_disk; - if (shouldUpdateModelMemoryLimit) { + if (shouldUpdateEstimatedMml) { setEstimatedModelMemoryLimit(expectedMemoryWithoutDisk); } @@ -340,7 +349,14 @@ export const CreateAnalyticsForm: FC = ({ actions, sta return () => { debouncedGetExplainData.cancel(); }; - }, [jobType, sourceIndex, sourceIndexNameEmpty, dependentVariable, trainingPercent]); + }, [ + jobType, + sourceIndex, + sourceIndexNameEmpty, + dependentVariable, + trainingPercent, + JSON.stringify(excludes), + ]); // Temp effect to close the context menu popover on Clone button click useEffect(() => { From 90d2b18bc5c4db75311733aea305c87b06d43675 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Thu, 9 Apr 2020 07:43:36 -0700 Subject: [PATCH 005/121] Add Data - Adding cloud reset password link to cloud instructions (#62835) * Adding cloud reset password link to cloud filebeat instructions * Auditbeat gets the cool reset password link * And the other beats instructions get the awesome password reset link * Changing the i18n id to more closely match the on-prem cloud id * Changing text for forgot password * Removing now unused translations * "Forgot your password" -> "Forgot the password" * "Elastic Cloud UI" -> "Elastic Cloud" Co-authored-by: Elastic Machine --- .../instructions/auditbeat_instructions.ts | 33 +++---------------- .../instructions/cloud_instructions.ts | 31 +++++++++++++++++ .../instructions/filebeat_instructions.ts | 33 +++---------------- .../instructions/functionbeat_instructions.ts | 17 ++-------- .../instructions/heartbeat_instructions.ts | 33 +++---------------- .../instructions/metricbeat_instructions.ts | 33 +++---------------- .../instructions/winlogbeat_instructions.ts | 9 ++--- x-pack/plugins/cloud/public/plugin.ts | 5 +-- x-pack/plugins/cloud/server/config.ts | 2 ++ .../translations/translations/ja-JP.json | 19 ----------- .../translations/translations/zh-CN.json | 19 ----------- 11 files changed, 61 insertions(+), 173 deletions(-) create mode 100644 src/plugins/home/server/tutorials/instructions/cloud_instructions.ts diff --git a/src/plugins/home/server/tutorials/instructions/auditbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/auditbeat_instructions.ts index 4c85ad3985b3d..2a6cfa0358709 100644 --- a/src/plugins/home/server/tutorials/instructions/auditbeat_instructions.ts +++ b/src/plugins/home/server/tutorials/instructions/auditbeat_instructions.ts @@ -22,6 +22,7 @@ import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; +import { cloudPasswordAndResetLink } from './cloud_instructions'; export const createAuditbeatInstructions = (context?: TutorialContext) => ({ INSTALL: { @@ -305,13 +306,7 @@ export const createAuditbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.auditbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, DEB: { title: i18n.translate('home.tutorials.common.auditbeatCloudInstructions.config.debTitle', { @@ -327,13 +322,7 @@ export const createAuditbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.auditbeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, RPM: { title: i18n.translate('home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle', { @@ -349,13 +338,7 @@ export const createAuditbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, WINDOWS: { title: i18n.translate( @@ -374,13 +357,7 @@ export const createAuditbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, }, }); diff --git a/src/plugins/home/server/tutorials/instructions/cloud_instructions.ts b/src/plugins/home/server/tutorials/instructions/cloud_instructions.ts new file mode 100644 index 0000000000000..a18e21d2b43dd --- /dev/null +++ b/src/plugins/home/server/tutorials/instructions/cloud_instructions.ts @@ -0,0 +1,31 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const cloudPasswordAndResetLink = i18n.translate( + 'home.tutorials.common.cloudInstructions.passwordAndResetLink', + { + defaultMessage: + 'Where {passwordTemplate} is the password of the `elastic` user.' + + `\\{#config.cloud.resetPasswordUrl\\} + Forgot the password? [Reset in Elastic Cloud](\\{config.cloud.resetPasswordUrl\\}). + \\{/config.cloud.resetPasswordUrl\\}`, + values: { passwordTemplate: '``' }, + } +); diff --git a/src/plugins/home/server/tutorials/instructions/filebeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/filebeat_instructions.ts index 66efa36ec9bcd..0e99033b2ea69 100644 --- a/src/plugins/home/server/tutorials/instructions/filebeat_instructions.ts +++ b/src/plugins/home/server/tutorials/instructions/filebeat_instructions.ts @@ -22,6 +22,7 @@ import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; +import { cloudPasswordAndResetLink } from './cloud_instructions'; export const createFilebeatInstructions = (context?: TutorialContext) => ({ INSTALL: { @@ -299,13 +300,7 @@ export const createFilebeatCloudInstructions = () => ({ }, }), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.filebeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, DEB: { title: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.debTitle', { @@ -318,13 +313,7 @@ export const createFilebeatCloudInstructions = () => ({ }, }), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.filebeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, RPM: { title: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.rpmTitle', { @@ -337,13 +326,7 @@ export const createFilebeatCloudInstructions = () => ({ }, }), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.filebeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, WINDOWS: { title: i18n.translate('home.tutorials.common.filebeatCloudInstructions.config.windowsTitle', { @@ -359,13 +342,7 @@ export const createFilebeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.filebeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, }, }); diff --git a/src/plugins/home/server/tutorials/instructions/functionbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/functionbeat_instructions.ts index ee13b9c5eefd8..06ff84146b5d8 100644 --- a/src/plugins/home/server/tutorials/instructions/functionbeat_instructions.ts +++ b/src/plugins/home/server/tutorials/instructions/functionbeat_instructions.ts @@ -22,6 +22,7 @@ import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; +import { cloudPasswordAndResetLink } from './cloud_instructions'; export const createFunctionbeatInstructions = (context?: TutorialContext) => ({ INSTALL: { @@ -200,13 +201,7 @@ export const createFunctionbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.functionbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, WINDOWS: { title: i18n.translate( @@ -225,13 +220,7 @@ export const createFunctionbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, }, }); diff --git a/src/plugins/home/server/tutorials/instructions/heartbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/heartbeat_instructions.ts index 33f5defc0273f..fa5bf5df13b6b 100644 --- a/src/plugins/home/server/tutorials/instructions/heartbeat_instructions.ts +++ b/src/plugins/home/server/tutorials/instructions/heartbeat_instructions.ts @@ -22,6 +22,7 @@ import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; import { Platform, TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; +import { cloudPasswordAndResetLink } from './cloud_instructions'; export const createHeartbeatInstructions = (context?: TutorialContext) => ({ INSTALL: { @@ -280,13 +281,7 @@ export const createHeartbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.heartbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, DEB: { title: i18n.translate('home.tutorials.common.heartbeatCloudInstructions.config.debTitle', { @@ -302,13 +297,7 @@ export const createHeartbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.heartbeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, RPM: { title: i18n.translate('home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle', { @@ -324,13 +313,7 @@ export const createHeartbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, WINDOWS: { title: i18n.translate( @@ -349,13 +332,7 @@ export const createHeartbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, }, }); diff --git a/src/plugins/home/server/tutorials/instructions/metricbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/metricbeat_instructions.ts index 9fdc70e0703a4..651405941610f 100644 --- a/src/plugins/home/server/tutorials/instructions/metricbeat_instructions.ts +++ b/src/plugins/home/server/tutorials/instructions/metricbeat_instructions.ts @@ -22,6 +22,7 @@ import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; import { TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; +import { cloudPasswordAndResetLink } from './cloud_instructions'; export const createMetricbeatInstructions = (context?: TutorialContext) => ({ INSTALL: { @@ -295,13 +296,7 @@ export const createMetricbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.metricbeatCloudInstructions.config.osxTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, DEB: { title: i18n.translate('home.tutorials.common.metricbeatCloudInstructions.config.debTitle', { @@ -317,13 +312,7 @@ export const createMetricbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.metricbeatCloudInstructions.config.debTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, RPM: { title: i18n.translate('home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle', { @@ -339,13 +328,7 @@ export const createMetricbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, WINDOWS: { title: i18n.translate( @@ -364,13 +347,7 @@ export const createMetricbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, }, }); diff --git a/src/plugins/home/server/tutorials/instructions/winlogbeat_instructions.ts b/src/plugins/home/server/tutorials/instructions/winlogbeat_instructions.ts index 9d7d0660d3d6c..27d7822e080a3 100644 --- a/src/plugins/home/server/tutorials/instructions/winlogbeat_instructions.ts +++ b/src/plugins/home/server/tutorials/instructions/winlogbeat_instructions.ts @@ -22,6 +22,7 @@ import { INSTRUCTION_VARIANT } from '../../../common/instruction_variant'; import { createTrycloudOption1, createTrycloudOption2 } from './onprem_cloud_instructions'; import { getSpaceIdForBeatsTutorial } from './get_space_id_for_beats_tutorial'; import { TutorialContext } from '../../services/tutorials/lib/tutorials_registry_types'; +import { cloudPasswordAndResetLink } from './cloud_instructions'; export const createWinlogbeatInstructions = (context?: TutorialContext) => ({ INSTALL: { @@ -130,13 +131,7 @@ export const createWinlogbeatCloudInstructions = () => ({ } ), commands: ['cloud.id: "{config.cloud.id}"', 'cloud.auth: "elastic:"'], - textPost: i18n.translate( - 'home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPost', - { - defaultMessage: 'Where {passwordTemplate} is the password of the `elastic` user.', - values: { passwordTemplate: '``' }, - } - ), + textPost: cloudPasswordAndResetLink, }, }, }); diff --git a/x-pack/plugins/cloud/public/plugin.ts b/x-pack/plugins/cloud/public/plugin.ts index 2b8247066bfc3..62e21392f7110 100644 --- a/x-pack/plugins/cloud/public/plugin.ts +++ b/x-pack/plugins/cloud/public/plugin.ts @@ -11,6 +11,7 @@ import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; interface CloudConfigType { id?: string; + resetPasswordUrl?: string; } interface CloudSetupDependencies { @@ -26,13 +27,13 @@ export class CloudPlugin implements Plugin { constructor(private readonly initializerContext: PluginInitializerContext) {} public async setup(core: CoreSetup, { home }: CloudSetupDependencies) { - const { id } = this.initializerContext.config.get(); + const { id, resetPasswordUrl } = this.initializerContext.config.get(); const isCloudEnabled = getIsCloudEnabled(id); if (home) { home.environment.update({ cloud: isCloudEnabled }); if (isCloudEnabled) { - home.tutorials.setVariable('cloud', { id }); + home.tutorials.setVariable('cloud', { id, resetPasswordUrl }); } } diff --git a/x-pack/plugins/cloud/server/config.ts b/x-pack/plugins/cloud/server/config.ts index 77e493dc3b7dc..d899b45aebdfe 100644 --- a/x-pack/plugins/cloud/server/config.ts +++ b/x-pack/plugins/cloud/server/config.ts @@ -21,6 +21,7 @@ const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), id: schema.maybe(schema.string()), apm: schema.maybe(apmConfigSchema), + resetPasswordUrl: schema.maybe(schema.string()), }); export type CloudConfigType = TypeOf; @@ -28,6 +29,7 @@ export type CloudConfigType = TypeOf; export const config: PluginConfigDescriptor = { exposeToBrowser: { id: true, + resetPasswordUrl: true, }, schema: configSchema, }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e63e1c8ad2c91..16c4b11bb6a6e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1196,16 +1196,12 @@ "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.auditbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.auditbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.auditbeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.auditbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.auditbeatCloudInstructions.config.windowsTitle": "構成を編集する", "home.tutorials.common.auditbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", @@ -1247,16 +1243,12 @@ "home.tutorials.common.filebeat.cloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.filebeat.premCloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.filebeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.filebeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.filebeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.filebeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.filebeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.filebeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.filebeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.filebeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.filebeatCloudInstructions.config.windowsTitle": "構成を編集する", "home.tutorials.common.filebeatEnableInstructions.debTextPost": "「/etc/filebeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", @@ -1311,10 +1303,8 @@ "home.tutorials.common.functionbeatAWSInstructions.textPost": "「」と「」がアカウント資格情報、「us-east-1」がご希望の地域です。", "home.tutorials.common.functionbeatAWSInstructions.textPre": "環境で AWS アカウント認証情報を設定します。", "home.tutorials.common.functionbeatAWSInstructions.title": "AWS 認証情報の設定", - "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.functionbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.functionbeatCloudInstructions.config.windowsTitle": "構成を編集する", "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTextPost": "「」が投入するロググループの名前で、「」が Functionbeat デプロイのステージングに使用されるが有効な S3 バケット名です。", @@ -1345,16 +1335,12 @@ "home.tutorials.common.heartbeat.cloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.heartbeat.premCloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.heartbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.heartbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.heartbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.heartbeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.heartbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.heartbeatCloudInstructions.config.windowsTitle": "構成を編集する", "home.tutorials.common.heartbeatEnableCloudInstructions.debTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", @@ -1414,16 +1400,12 @@ "home.tutorials.common.metricbeat.cloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.metricbeat.premCloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.metricbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.metricbeatCloudInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.metricbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.metricbeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.metricbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.metricbeatCloudInstructions.config.windowsTitle": "構成を編集する", "home.tutorials.common.metricbeatEnableInstructions.debTextPost": "「/etc/metricbeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", @@ -1478,7 +1460,6 @@ "home.tutorials.common.winlogbeat.cloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.winlogbeat.premCloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.winlogbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワードです。", "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTitle": "構成を編集する", "home.tutorials.common.winlogbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index cc75ceb988d97..c81fad386ac2f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1197,16 +1197,12 @@ "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "入门", - "home.tutorials.common.auditbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.auditbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.auditbeatCloudInstructions.config.debTitle": "编辑配置", - "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.auditbeatCloudInstructions.config.osxTitle": "编辑配置", - "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle": "编辑配置", - "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.auditbeatCloudInstructions.config.windowsTitle": "编辑配置", "home.tutorials.common.auditbeatInstructions.config.debTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", @@ -1248,16 +1244,12 @@ "home.tutorials.common.filebeat.cloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.filebeat.premCloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.filebeat.premInstructions.gettingStarted.title": "入门", - "home.tutorials.common.filebeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.filebeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.filebeatCloudInstructions.config.debTitle": "编辑配置", - "home.tutorials.common.filebeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.filebeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.filebeatCloudInstructions.config.osxTitle": "编辑配置", - "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.filebeatCloudInstructions.config.rpmTitle": "编辑配置", - "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.filebeatCloudInstructions.config.windowsTitle": "编辑配置", "home.tutorials.common.filebeatEnableInstructions.debTextPost": "在 `/etc/filebeat/modules.d/{moduleName}.yml` 文件中修改设置。", @@ -1312,10 +1304,8 @@ "home.tutorials.common.functionbeatAWSInstructions.textPost": "其中 `` 和 `` 是您的帐户凭据,`us-east-1` 是所需的地区。", "home.tutorials.common.functionbeatAWSInstructions.textPre": "在环境中设置您的 AWS 帐户凭据:", "home.tutorials.common.functionbeatAWSInstructions.title": "设置 AWS 凭据", - "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.functionbeatCloudInstructions.config.osxTitle": "编辑配置", - "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.functionbeatCloudInstructions.config.windowsTitle": "编辑配置", "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTextPost": "其中 `` 是要采集的日志组名称,`` 是将用于暂存 Functionbeat 部署的有效 S3 存储桶名称。", @@ -1346,16 +1336,12 @@ "home.tutorials.common.heartbeat.cloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.heartbeat.premCloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.heartbeat.premInstructions.gettingStarted.title": "入门", - "home.tutorials.common.heartbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.heartbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.heartbeatCloudInstructions.config.debTitle": "编辑配置", - "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.heartbeatCloudInstructions.config.osxTitle": "编辑配置", - "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle": "编辑配置", - "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.heartbeatCloudInstructions.config.windowsTitle": "编辑配置", "home.tutorials.common.heartbeatEnableCloudInstructions.debTextPre": "在 `heartbeat.yml` 文件中编辑 `heartbeat.monitors` 设置。", @@ -1415,16 +1401,12 @@ "home.tutorials.common.metricbeat.cloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.metricbeat.premCloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.metricbeat.premInstructions.gettingStarted.title": "入门", - "home.tutorials.common.metricbeatCloudInstructions.config.debTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.metricbeatCloudInstructions.config.debTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.metricbeatCloudInstructions.config.debTitle": "编辑配置", - "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.metricbeatCloudInstructions.config.osxTitle": "编辑配置", - "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle": "编辑配置", - "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.metricbeatCloudInstructions.config.windowsTitle": "编辑配置", "home.tutorials.common.metricbeatEnableInstructions.debTextPost": "在 `/etc/metricbeat/modules.d/{moduleName}.yml` 文件中修改设置。", @@ -1479,7 +1461,6 @@ "home.tutorials.common.winlogbeat.cloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.winlogbeat.premCloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.winlogbeat.premInstructions.gettingStarted.title": "入门", - "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPost": "其中 {passwordTemplate} 是 `elastic` 用户的密码。", "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPre": "修改 {path} 以设置 Elastic Cloud 的连接信息:", "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTitle": "编辑配置", "home.tutorials.common.winlogbeatInstructions.config.windowsTextPost": "其中,{passwordTemplate} 是 `elastic` 用户的密码,{esUrlTemplate} 是 Elasticsearch 的 URL,{kibanaUrlTemplate} 是 Kibana 的 URL。", From 80384c3209d8b49ed43fd2b505cd37f8cbf38ac7 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Thu, 9 Apr 2020 07:50:11 -0700 Subject: [PATCH 006/121] Exposed AddMessageVariables as separate component (#63007) * Exposed AddMessageVariables as separate component and added styles to allow to handle bigger list of messageVariables * Fixed failing tests and styles * Fixed due to comments --- .../translations/translations/ja-JP.json | 15 -- .../translations/translations/zh-CN.json | 15 -- .../components/add_message_variables.scss | 4 + .../components/add_message_variables.tsx | 69 +++++++ .../components/builtin_action_types/email.tsx | 62 +++--- .../builtin_action_types/es_index.test.tsx | 4 +- .../builtin_action_types/es_index.tsx | 62 ++---- .../builtin_action_types/pagerduty.tsx | 182 ++++++------------ .../builtin_action_types/server_log.tsx | 63 ++---- .../components/builtin_action_types/slack.tsx | 66 ++----- .../builtin_action_types/webhook.test.tsx | 2 +- .../builtin_action_types/webhook.tsx | 54 +----- 12 files changed, 211 insertions(+), 387 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.scss create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 16c4b11bb6a6e..d357e40c02934 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -15846,7 +15846,6 @@ "xpack.triggersActionsUI.common.expressionItems.threshold.descriptionLabel": "タイミング", "xpack.triggersActionsUI.common.expressionItems.threshold.popoverTitle": "タイミング", "xpack.triggersActionsUI.components.builtinActionTypes.emailAction.actionTypeTitle": "メールに送信", - "xpack.triggersActionsUI.components.builtinActionTypes.emailAction.addVariablePopoverButton": "変数を追加", "xpack.triggersActionsUI.components.builtinActionTypes.emailAction.selectMessageText": "サーバーからメールを送信します。", "xpack.triggersActionsUI.components.builtinActionTypes.error.formatFromText": "送信元は有効なメールアドレスではありません。", "xpack.triggersActionsUI.components.builtinActionTypes.error.requiredEntryText": "To、Cc、または Bcc のエントリーがありません。 1 つ以上のエントリーが必要です。", @@ -15875,14 +15874,6 @@ "xpack.triggersActionsUI.components.builtinActionTypes.indexAction.refreshTooltip": "このチェックボックスは更新インデックス値を設定します。", "xpack.triggersActionsUI.components.builtinActionTypes.indexAction.selectMessageText": "データを Elasticsearch にインデックスしてください。", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.actionTypeTitle": "PagerDuty に送信", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton1": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton2": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton3": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton4": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton5": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton6": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton7": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariableTitle": "アラート変数を追加", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.apiUrlTextFieldLabel": "API URL", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.classFieldLabel": "クラス (任意)", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.componentTextFieldLabel": "コンポーネント(任意)", @@ -15906,14 +15897,10 @@ "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.summaryFieldLabel": "まとめ", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.timestampTextFieldLabel": "タイムスタンプ (任意)", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.actionTypeTitle": "サーバーログに送信", - "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.addVariablePopoverButton": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.addVariableTitle": "変数を追加", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.logLevelFieldLabel": "レベル", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.logMessageFieldLabel": "メッセージ", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.selectMessageText": "Kibana ログにメッセージを追加します。", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.actionTypeTitle": "Slack に送信", - "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.addVariablePopoverButton": "アラート変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.addVariableTitle": "アラート変数を追加", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.error.requiredWebhookUrlText": "Web フック URL が必要です。", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.messageTextAreaFieldLabel": "メッセージ", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.selectMessageText": "Slack チャネルにメッセージを送信します。", @@ -15922,8 +15909,6 @@ "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.actionTypeTitle": "Web フックデータ", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addHeader": "ヘッダーを追加", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addHeaderButton": "追加", - "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addVariablePopoverButton": "変数を追加", - "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addVariableTitle": "変数を追加", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.bodyCodeEditorAriaLabel": "コードエディター", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.bodyFieldLabel": "本文", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.deleteHeaderButton": "削除", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c81fad386ac2f..839c89f3b1cae 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -15850,7 +15850,6 @@ "xpack.triggersActionsUI.common.expressionItems.threshold.descriptionLabel": "当", "xpack.triggersActionsUI.common.expressionItems.threshold.popoverTitle": "当", "xpack.triggersActionsUI.components.builtinActionTypes.emailAction.actionTypeTitle": "发送到电子邮件", - "xpack.triggersActionsUI.components.builtinActionTypes.emailAction.addVariablePopoverButton": "添加变量", "xpack.triggersActionsUI.components.builtinActionTypes.emailAction.selectMessageText": "从您的服务器发送电子邮件。", "xpack.triggersActionsUI.components.builtinActionTypes.error.formatFromText": "发送者电子邮件地址无效。", "xpack.triggersActionsUI.components.builtinActionTypes.error.requiredEntryText": "未输入收件人、抄送、密送。 至少需要输入一个。", @@ -15879,14 +15878,6 @@ "xpack.triggersActionsUI.components.builtinActionTypes.indexAction.refreshTooltip": "此复选框设置刷新索引值。", "xpack.triggersActionsUI.components.builtinActionTypes.indexAction.selectMessageText": "将数据索引到 Elasticsearch 中。", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.actionTypeTitle": "发送到 PagerDuty", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton1": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton2": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton3": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton4": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton5": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton6": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariablePopoverButton7": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariableTitle": "添加告警变量", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.apiUrlTextFieldLabel": "API URL", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.classFieldLabel": "类(可选)", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.componentTextFieldLabel": "组件(可选)", @@ -15910,14 +15901,10 @@ "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.summaryFieldLabel": "摘要", "xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.timestampTextFieldLabel": "时间戳(可选)", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.actionTypeTitle": "发送到服务器日志", - "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.addVariablePopoverButton": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.addVariableTitle": "添加变量", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.logLevelFieldLabel": "级别", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.logMessageFieldLabel": "消息", "xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.selectMessageText": "将消息添加到 Kibana 日志。", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.actionTypeTitle": "发送到 Slack", - "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.addVariablePopoverButton": "添加告警变量", - "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.addVariableTitle": "添加告警变量", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.error.requiredWebhookUrlText": "Webhook URL 必填。", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.messageTextAreaFieldLabel": "消息", "xpack.triggersActionsUI.components.builtinActionTypes.slackAction.selectMessageText": "向 Slack 频道或用户发送消息。", @@ -15926,8 +15913,6 @@ "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.actionTypeTitle": "Webhook 数据", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addHeader": "添加标头", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addHeaderButton": "添加", - "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addVariablePopoverButton": "添加变量", - "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addVariableTitle": "添加变量", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.bodyCodeEditorAriaLabel": "代码编辑器", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.bodyFieldLabel": "正文", "xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.deleteHeaderButton": "删除", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.scss b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.scss new file mode 100644 index 0000000000000..996f21c4b6b09 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.scss @@ -0,0 +1,4 @@ +.messageVariablesPanel { + @include euiYScrollWithShadows; + max-height: $euiSize * 20; +} \ No newline at end of file diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx new file mode 100644 index 0000000000000..ab9b5c2586c17 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiPopover, EuiButtonIcon, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui'; +import './add_message_variables.scss'; + +interface Props { + messageVariables: string[] | undefined; + paramsProperty: string; + onSelectEventHandler: (variable: string) => void; +} + +export const AddMessageVariables: React.FunctionComponent = ({ + messageVariables, + paramsProperty, + onSelectEventHandler, +}) => { + const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState(false); + + const getMessageVariables = () => + messageVariables?.map((variable: string) => ( + { + onSelectEventHandler(variable); + setIsVariablesPopoverOpen(false); + }} + > + {`{{${variable}}}`} + + )); + + const addVariableButtonTitle = i18n.translate( + 'xpack.triggersActionsUI.components.addMessageVariables.addVariableTitle', + { + defaultMessage: 'Add alert variable', + } + ); + + return ( + setIsVariablesPopoverOpen(true)} + iconType="indexOpen" + aria-label={i18n.translate( + 'xpack.triggersActionsUI.components.addMessageVariables.addVariablePopoverButton', + { + defaultMessage: 'Add variable', + } + )} + /> + } + isOpen={isVariablesPopoverOpen} + closePopover={() => setIsVariablesPopoverOpen(false)} + panelPaddingSize="none" + anchorPosition="downLeft" + > + + + ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email.tsx index b4bbb8af36a19..dff697297f3e4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email.tsx @@ -16,10 +16,6 @@ import { EuiButtonEmpty, EuiSwitch, EuiFormRow, - EuiContextMenuItem, - EuiButtonIcon, - EuiContextMenuPanel, - EuiPopover, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { @@ -29,6 +25,7 @@ import { ActionParamsProps, } from '../../../types'; import { EmailActionParams, EmailActionConnector } from './types'; +import { AddMessageVariables } from '../add_message_variables'; export function getActionType(): ActionTypeModel { const mailformat = /^[^@\s]+@[^@\s]+$/; @@ -368,25 +365,21 @@ const EmailParamsFields: React.FunctionComponent(false); const [addBCC, setAddBCC] = useState(false); - const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState(false); useEffect(() => { if (!message && defaultMessage && defaultMessage.length > 0) { editAction('message', defaultMessage, index); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const messageVariablesItems = messageVariables?.map((variable: string) => ( - { - editAction('message', (message ?? '').concat(` {{${variable}}}`), index); - setIsVariablesPopoverOpen(false); - }} - > - {`{{${variable}}}`} - - )); + + const onSelectMessageVariable = (paramsProperty: string, variable: string) => { + editAction( + paramsProperty, + ((actionParams as any)[paramsProperty] ?? '').concat(` {{${variable}}}`), + index + ); + }; + return ( + onSelectMessageVariable('subject', variable) + } + paramsProperty="subject" + /> + } > setIsVariablesPopoverOpen(true)} - iconType="indexOpen" - aria-label={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.emailAction.addVariablePopoverButton', - { - defaultMessage: 'Add variable', - } - )} - /> + + onSelectMessageVariable('message', variable) } - isOpen={isVariablesPopoverOpen} - closePopover={() => setIsVariablesPopoverOpen(false)} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - + paramsProperty="message" + /> } > { ).toBe(`{ "test": 123 }`); - expect( - wrapper.find('[data-test-subj="indexDocumentAddVariableButton"]').length > 0 - ).toBeTruthy(); + expect(wrapper.find('[data-test-subj="documentsAddVariableButton"]').length > 0).toBeTruthy(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx index 56d9f40e40021..9bd6a39d216e3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx @@ -14,10 +14,6 @@ import { EuiSelect, EuiTitle, EuiIconTip, - EuiPopover, - EuiButtonIcon, - EuiContextMenuPanel, - EuiContextMenuItem, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -36,6 +32,7 @@ import { getIndexPatterns, } from '../../../common/index_controls'; import { useXJsonMode } from '../../lib/use_x_json_mode'; +import { AddMessageVariables } from '../add_message_variables'; export function getActionType(): ActionTypeModel { return { @@ -282,23 +279,13 @@ const IndexParamsFields: React.FunctionComponent 0 ? documents[0] : null ); - const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState(false); - const messageVariablesItems = messageVariables?.map((variable: string, i: number) => ( - { - const value = (xJson ?? '').concat(` {{${variable}}}`); - setXJson(value); - // Keep the documents in sync with the editor content - onDocumentsChange(convertToJson(value)); - setIsVariablesPopoverOpen(false); - }} - > - {`{{${variable}}}`} - - )); + const onSelectMessageVariable = (variable: string) => { + const value = (xJson ?? '').concat(` {{${variable}}}`); + setXJson(value); + // Keep the documents in sync with the editor content + onDocumentsChange(convertToJson(value)); + }; + function onDocumentsChange(updatedDocuments: string) { try { const documentsJSON = JSON.parse(updatedDocuments); @@ -317,34 +304,11 @@ const IndexParamsFields: React.FunctionComponent setIsVariablesPopoverOpen(true)} - iconType="indexOpen" - title={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.indexAction.addVariableTitle', - { - defaultMessage: 'Add variable', - } - )} - aria-label={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.indexAction.addVariablePopoverButton', - { - defaultMessage: 'Add variable', - } - )} - /> - } - isOpen={isVariablesPopoverOpen} - closePopover={() => setIsVariablesPopoverOpen(false)} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - + onSelectMessageVariable(variable)} + paramsProperty="documents" + /> } > >({ - dedupKey: false, - summary: false, - source: false, - timestamp: false, - component: false, - group: false, - class: false, - }); - // TODO: replace this button with a proper Eui component, when it will be ready - const getMessageVariables = (paramsProperty: string) => - messageVariables?.map((variable: string) => ( - { - editAction( - paramsProperty, - ((actionParams as any)[paramsProperty] ?? '').concat(` {{${variable}}}`), - index - ); - setIsVariablesPopoverOpen({ ...isVariablesPopoverOpen, [paramsProperty]: false }); - }} - > - {`{{${variable}}}`} - - )); - - const addVariableButtonTitle = i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.pagerDutyAction.addVariableTitle', - { - defaultMessage: 'Add alert variable', - } - ); - const getAddVariableComponent = (paramsProperty: string, buttonName: string) => { - return ( - - setIsVariablesPopoverOpen({ ...isVariablesPopoverOpen, [paramsProperty]: true }) - } - iconType="indexOpen" - aria-label={buttonName} - /> - } - isOpen={isVariablesPopoverOpen[paramsProperty]} - closePopover={() => - setIsVariablesPopoverOpen({ ...isVariablesPopoverOpen, [paramsProperty]: false }) - } - panelPaddingSize="none" - anchorPosition="downLeft" - > - - + const onSelectMessageVariable = (paramsProperty: string, variable: string) => { + editAction( + paramsProperty, + ((actionParams as any)[paramsProperty] ?? '').concat(` {{${variable}}}`), + index ); }; + return ( @@ -359,15 +305,15 @@ const PagerDutyParamsFields: React.FunctionComponent + onSelectMessageVariable('dedupKey', variable) } - ) - )} + paramsProperty="dedupKey" + /> + } > + onSelectMessageVariable('timestamp', variable) } - ) - )} + paramsProperty="timestamp" + /> + } > + onSelectMessageVariable('component', variable) } - ) - )} + paramsProperty="component" + /> + } > onSelectMessageVariable('group', variable)} + paramsProperty="group" + /> + } > onSelectMessageVariable('source', variable)} + paramsProperty="source" + /> + } > + onSelectMessageVariable('summary', variable) } - ) - )} + paramsProperty="summary" + /> + } > onSelectMessageVariable('class', variable)} + paramsProperty="class" + /> + } > (false); useEffect(() => { editAction('level', 'info', index); @@ -80,18 +72,11 @@ export const ServerLogParamsFields: React.FunctionComponent ( - { - editAction('message', (message ?? '').concat(` {{${variable}}}`), index); - setIsVariablesPopoverOpen(false); - }} - > - {`{{${variable}}}`} - - )); + + const onSelectMessageVariable = (paramsProperty: string, variable: string) => { + editAction(paramsProperty, (message ?? '').concat(` {{${variable}}}`), index); + }; + return ( setIsVariablesPopoverOpen(true)} - iconType="indexOpen" - title={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.addVariableTitle', - { - defaultMessage: 'Add variable', - } - )} - aria-label={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.serverLogAction.addVariablePopoverButton', - { - defaultMessage: 'Add variable', - } - )} - /> + + onSelectMessageVariable('message', variable) } - isOpen={isVariablesPopoverOpen} - closePopover={() => setIsVariablesPopoverOpen(false)} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - + paramsProperty="message" + /> } > { const { message } = actionParams; - const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState(false); useEffect(() => { if (!message && defaultMessage && defaultMessage.length > 0) { editAction('message', defaultMessage, index); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const messageVariablesItems = messageVariables?.map((variable: string, i: number) => ( - { - editAction('message', (message ?? '').concat(` {{${variable}}}`), index); - setIsVariablesPopoverOpen(false); - }} - > - {`{{${variable}}}`} - - )); + + const onSelectMessageVariable = (paramsProperty: string, variable: string) => { + editAction(paramsProperty, (message ?? '').concat(` {{${variable}}}`), index); + }; + return ( setIsVariablesPopoverOpen(true)} - iconType="indexOpen" - title={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.slackAction.addVariableTitle', - { - defaultMessage: 'Add alert variable', - } - )} - aria-label={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.slackAction.addVariablePopoverButton', - { - defaultMessage: 'Add alert variable', - } - )} - /> + + onSelectMessageVariable('message', variable) } - isOpen={isVariablesPopoverOpen} - closePopover={() => setIsVariablesPopoverOpen(false)} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - + paramsProperty="message" + /> } > { .first() .prop('value') ).toStrictEqual('test message'); - expect(wrapper.find('[data-test-subj="webhookAddVariableButton"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="bodyAddVariableButton"]').length > 0).toBeTruthy(); }); test('params validation fails when body is not valid', () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook.tsx index f611c3715e56a..daa5a6caeabe9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook.tsx @@ -22,9 +22,6 @@ import { EuiCodeEditor, EuiSwitch, EuiButtonEmpty, - EuiContextMenuItem, - EuiPopover, - EuiContextMenuPanel, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { @@ -34,6 +31,7 @@ import { ActionParamsProps, } from '../../../types'; import { WebhookActionParams, WebhookActionConnector } from './types'; +import { AddMessageVariables } from '../add_message_variables'; const HTTP_VERBS = ['post', 'put']; @@ -467,20 +465,9 @@ const WebhookParamsFields: React.FunctionComponent { const { body } = actionParams; - const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState(false); - const messageVariablesItems = messageVariables?.map((variable: string, i: number) => ( - { - editAction('body', (body ?? '').concat(` {{${variable}}}`), index); - setIsVariablesPopoverOpen(false); - }} - > - {`{{${variable}}}`} - - )); + const onSelectMessageVariable = (paramsProperty: string, variable: string) => { + editAction(paramsProperty, (body ?? '').concat(` {{${variable}}}`), index); + }; return ( setIsVariablesPopoverOpen(true)} - iconType="indexOpen" - title={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addVariableTitle', - { - defaultMessage: 'Add variable', - } - )} - aria-label={i18n.translate( - 'xpack.triggersActionsUI.components.builtinActionTypes.webhookAction.addVariablePopoverButton', - { - defaultMessage: 'Add variable', - } - )} - /> - } - isOpen={isVariablesPopoverOpen} - closePopover={() => setIsVariablesPopoverOpen(false)} - panelPaddingSize="none" - anchorPosition="downLeft" - > - - + onSelectMessageVariable('body', variable)} + paramsProperty="body" + /> } > Date: Thu, 9 Apr 2020 08:22:00 -0700 Subject: [PATCH 007/121] docs: fix rendering of bulleted list (#62855) --- docs/user/alerting/index.asciidoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/user/alerting/index.asciidoc b/docs/user/alerting/index.asciidoc index b4f7e6af3d61c..c7cf1186a44be 100644 --- a/docs/user/alerting/index.asciidoc +++ b/docs/user/alerting/index.asciidoc @@ -163,7 +163,8 @@ If you are using an *on-premises* Elastic Stack deployment with <> * <> * <> From a0c247b9cc165638c3c01c87ce02c13ac2a4a698 Mon Sep 17 00:00:00 2001 From: Sandra Gonzales Date: Thu, 9 Apr 2020 11:42:10 -0400 Subject: [PATCH 008/121] [EPM] Change PACKAGES_SAVED_OBJECT_TYPE id (#62818) * changed PACKAGES_SAVED_OBJECT_TYPE id from packageName-version to packageName * change references to keys to package and version Co-authored-by: Elastic Machine --- .../server/routes/epm/handlers.ts | 4 +- .../server/services/datasource.ts | 10 ++-- .../services/epm/elasticsearch/ilm/install.ts | 12 +++-- .../elasticsearch/ingest_pipeline/install.ts | 23 +++++---- .../epm/elasticsearch/template/install.ts | 17 +++++-- .../epm/kibana/index_pattern/install.ts | 27 +++++++---- .../server/services/epm/packages/assets.ts | 2 +- .../server/services/epm/packages/get.ts | 40 +++++----------- .../services/epm/packages/get_objects.ts | 40 ---------------- .../server/services/epm/packages/index.ts | 1 - .../server/services/epm/packages/install.ts | 47 ++++++++++++------- .../server/services/epm/packages/remove.ts | 6 ++- .../server/services/epm/registry/index.ts | 25 +++++----- .../ingest_manager/server/services/setup.ts | 3 +- 14 files changed, 118 insertions(+), 139 deletions(-) diff --git a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts index 48f37a4d65ac6..ad16e1dde456b 100644 --- a/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/epm/handlers.ts @@ -102,7 +102,9 @@ export const getInfoHandler: RequestHandler { - const pkgInstall = await findInstalledPackageByName({ - savedObjectsClient: soClient, - pkgName, - }); + const pkgInstall = await getInstallation({ savedObjectsClient: soClient, pkgName }); if (pkgInstall) { const [pkgInfo, defaultOutputId] = await Promise.all([ getPackageInfo({ savedObjectsClient: soClient, - pkgkey: `${pkgInstall.name}-${pkgInstall.version}`, + pkgName: pkgInstall.name, + pkgVersion: pkgInstall.version, }), outputService.getDefaultOutputId(soClient), ]); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ilm/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ilm/install.ts index c56322239f27b..60a85e367079f 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ilm/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ilm/install.ts @@ -7,9 +7,15 @@ import { CallESAsCurrentUser, ElasticsearchAssetType } from '../../../../types'; import * as Registry from '../../registry'; -export async function installILMPolicy(pkgkey: string, callCluster: CallESAsCurrentUser) { - const ilmPaths = await Registry.getArchiveInfo(pkgkey, (entry: Registry.ArchiveEntry) => - isILMPolicy(entry) +export async function installILMPolicy( + pkgName: string, + pkgVersion: string, + callCluster: CallESAsCurrentUser +) { + const ilmPaths = await Registry.getArchiveInfo( + pkgName, + pkgVersion, + (entry: Registry.ArchiveEntry) => isILMPolicy(entry) ); if (!ilmPaths.length) return; await Promise.all( diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts index 4b65e5554567e..2bbb555ef7393 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/ingest_pipeline/install.ts @@ -30,11 +30,10 @@ export const installPipelines = async ( if (dataset.ingest_pipeline) { acc.push( installPipelinesForDataset({ - pkgkey: Registry.pkgToPkgKey(registryPackage), dataset, callCluster, - packageName: registryPackage.name, - packageVersion: registryPackage.version, + pkgName: registryPackage.name, + pkgVersion: registryPackage.version, }) ); } @@ -68,19 +67,19 @@ export function rewriteIngestPipeline( export async function installPipelinesForDataset({ callCluster, - pkgkey, + pkgName, + pkgVersion, dataset, - packageName, - packageVersion, }: { callCluster: CallESAsCurrentUser; - pkgkey: string; + pkgName: string; + pkgVersion: string; dataset: Dataset; - packageName: string; - packageVersion: string; }): Promise { - const pipelinePaths = await Registry.getArchiveInfo(pkgkey, (entry: Registry.ArchiveEntry) => - isDatasetPipeline(entry, dataset.path) + const pipelinePaths = await Registry.getArchiveInfo( + pkgName, + pkgVersion, + (entry: Registry.ArchiveEntry) => isDatasetPipeline(entry, dataset.path) ); let pipelines: any[] = []; const substitutions: RewriteSubstitution[] = []; @@ -90,7 +89,7 @@ export async function installPipelinesForDataset({ const nameForInstallation = getPipelineNameForInstallation({ pipelineName: name, dataset, - packageVersion, + packageVersion: pkgVersion, }); const content = Registry.getAsset(path).toString('utf-8'); pipelines.push({ diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts index de4ba25590c98..560ddfc1f6885 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/install.ts @@ -20,11 +20,12 @@ import * as Registry from '../../registry'; export const installTemplates = async ( registryPackage: RegistryPackage, callCluster: CallESAsCurrentUser, - pkgkey: string + pkgName: string, + pkgVersion: string ) => { // install any pre-built index template assets, // atm, this is only the base package's global template - installPreBuiltTemplates(pkgkey, callCluster); + installPreBuiltTemplates(pkgName, pkgVersion, callCluster); // build templates per dataset from yml files const datasets = registryPackage.datasets; @@ -45,9 +46,15 @@ export const installTemplates = async ( }; // this is temporary until we update the registry to use index templates v2 structure -const installPreBuiltTemplates = async (pkgkey: string, callCluster: CallESAsCurrentUser) => { - const templatePaths = await Registry.getArchiveInfo(pkgkey, (entry: Registry.ArchiveEntry) => - isTemplate(entry) +const installPreBuiltTemplates = async ( + pkgName: string, + pkgVersion: string, + callCluster: CallESAsCurrentUser +) => { + const templatePaths = await Registry.getArchiveInfo( + pkgName, + pkgVersion, + (entry: Registry.ArchiveEntry) => isTemplate(entry) ); templatePaths.forEach(async path => { const { file } = Registry.pathParts(path); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts index 0657fb7759b49..05e64c6565dc6 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts @@ -68,25 +68,32 @@ export enum IndexPatternType { metrics = 'metrics', events = 'events', } - +// TODO: use a function overload and make pkgName and pkgVersion required for install/update +// and not for an update removal. or separate out the functions export async function installIndexPatterns( savedObjectsClient: SavedObjectsClientContract, - pkgkey?: string + pkgName?: string, + pkgVersion?: string ) { // get all user installed packages const installedPackages = await getPackageKeysByStatus( savedObjectsClient, InstallationStatus.installed ); - // add this package to the array if it doesn't already exist - // this should not happen because a user can't "reinstall" a package - // if it does because the install endpoint is called directly, the install continues - if (pkgkey && !installedPackages.includes(pkgkey)) { - installedPackages.push(pkgkey); + if (pkgName && pkgVersion) { + // add this package to the array if it doesn't already exist + const foundPkg = installedPackages.find(pkg => pkg.pkgName === pkgName); + // this may be removed if we add the packged to saved objects before installing index patterns + // otherwise this is a first time install + // TODO: handle update case when versions are different + if (!foundPkg) { + installedPackages.push({ pkgName, pkgVersion }); + } } - // get each package's registry info - const installedPackagesFetchInfoPromise = installedPackages.map(pkg => Registry.fetchInfo(pkg)); + const installedPackagesFetchInfoPromise = installedPackages.map(pkg => + Registry.fetchInfo(pkg.pkgName, pkg.pkgVersion) + ); const installedPackagesInfo = await Promise.all(installedPackagesFetchInfoPromise); // for each index pattern type, create an index pattern @@ -97,7 +104,7 @@ export async function installIndexPatterns( ]; indexPatternTypes.forEach(async indexPatternType => { // if this is an update because a package is being unisntalled (no pkgkey argument passed) and no other packages are installed, remove the index pattern - if (!pkgkey && installedPackages.length === 0) { + if (!pkgName && installedPackages.length === 0) { try { await savedObjectsClient.delete(INDEX_PATTERN_SAVED_OBJECT_TYPE, `${indexPatternType}-*`); } catch (err) { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts index d7a5c5569986e..7026d9eae24c3 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/assets.ts @@ -58,7 +58,7 @@ export async function getAssetsData( ): Promise { // TODO: Needs to be called to fill the cache but should not be required const pkgkey = packageInfo.name + '-' + packageInfo.version; - if (!cacheHas(pkgkey)) await Registry.getArchiveInfo(pkgkey); + if (!cacheHas(pkgkey)) await Registry.getArchiveInfo(packageInfo.name, packageInfo.version); // Gather all asset data const assets = getAssets(packageInfo, filter, datasetName); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts index e963ea138dfd5..0e2c2a3d26073 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts @@ -41,7 +41,7 @@ export async function getPackages( .map(item => createInstallableFrom( item, - savedObjectsVisible.find(({ attributes }) => attributes.name === item.name) + savedObjectsVisible.find(({ id }) => id === item.name) ) ) .sort(sortByName); @@ -53,9 +53,9 @@ export async function getPackageKeysByStatus( status: InstallationStatus ) { const allPackages = await getPackages({ savedObjectsClient }); - return allPackages.reduce((acc, pkg) => { + return allPackages.reduce>((acc, pkg) => { if (pkg.status === status) { - acc.push(`${pkg.name}-${pkg.version}`); + acc.push({ pkgName: pkg.name, pkgVersion: pkg.version }); } return acc; }, []); @@ -63,13 +63,14 @@ export async function getPackageKeysByStatus( export async function getPackageInfo(options: { savedObjectsClient: SavedObjectsClientContract; - pkgkey: string; + pkgName: string; + pkgVersion: string; }): Promise { - const { savedObjectsClient, pkgkey } = options; + const { savedObjectsClient, pkgName, pkgVersion } = options; const [item, savedObject] = await Promise.all([ - Registry.fetchInfo(pkgkey), - getInstallationObject({ savedObjectsClient, pkgkey }), - Registry.getArchiveInfo(pkgkey), + Registry.fetchInfo(pkgName, pkgVersion), + getInstallationObject({ savedObjectsClient, pkgName }), + Registry.getArchiveInfo(pkgName, pkgVersion), ] as const); // adding `as const` due to regression in TS 3.7.2 // see https://github.com/microsoft/TypeScript/issues/34925#issuecomment-550021453 @@ -86,37 +87,22 @@ export async function getPackageInfo(options: { export async function getInstallationObject(options: { savedObjectsClient: SavedObjectsClientContract; - pkgkey: string; + pkgName: string; }) { - const { savedObjectsClient, pkgkey } = options; + const { savedObjectsClient, pkgName } = options; return savedObjectsClient - .get(PACKAGES_SAVED_OBJECT_TYPE, pkgkey) + .get(PACKAGES_SAVED_OBJECT_TYPE, pkgName) .catch(e => undefined); } export async function getInstallation(options: { savedObjectsClient: SavedObjectsClientContract; - pkgkey: string; + pkgName: string; }) { const savedObject = await getInstallationObject(options); return savedObject?.attributes; } -export async function findInstalledPackageByName(options: { - savedObjectsClient: SavedObjectsClientContract; - pkgName: string; -}): Promise { - const { savedObjectsClient, pkgName } = options; - - const res = await savedObjectsClient.find({ - type: PACKAGES_SAVED_OBJECT_TYPE, - search: pkgName, - searchFields: ['name'], - }); - if (res.saved_objects.length) return res.saved_objects[0].attributes; - return undefined; -} - function sortByName(a: { name: string }, b: { name: string }) { if (a.name > b.name) { return 1; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get_objects.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/get_objects.ts index b924c045870f3..b623295c5e060 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/get_objects.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/get_objects.ts @@ -11,46 +11,6 @@ import * as Registry from '../registry'; type ArchiveAsset = Pick; type SavedObjectToBe = Required & { type: AssetType }; -export async function getObjects( - pkgkey: string, - filter = (entry: Registry.ArchiveEntry): boolean => true -): Promise { - // Create a Map b/c some values, especially index-patterns, are referenced multiple times - const objects: Map = new Map(); - - // Get paths which match the given filter - const paths = await Registry.getArchiveInfo(pkgkey, filter); - - // Get all objects which matched filter. Add them to the Map - const rootObjects = await Promise.all(paths.map(getObject)); - rootObjects.forEach(obj => objects.set(obj.id, obj)); - - // Each of those objects might have `references` property like [{id, type, name}] - for (const object of rootObjects) { - // For each of those objects, if they have references - for (const reference of object.references) { - // Get the referenced objects. Call same function with a new filter - const referencedObjects = await getObjects(pkgkey, (entry: Registry.ArchiveEntry) => { - // Skip anything we've already stored - if (objects.has(reference.id)) return false; - - // Is the archive entry the reference we want? - const { type, file } = Registry.pathParts(entry.path); - const isType = type === reference.type; - const isJson = file === `${reference.id}.json`; - - return isType && isJson; - }); - - // Add referenced objects to the Map - referencedObjects.forEach(ro => objects.set(ro.id, ro)); - } - } - - // return the array of unique objects - return Array.from(objects.values()); -} - export async function getObject(key: string) { const buffer = Registry.getAsset(key); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts index 79259ce79ff41..d49e0e661440f 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/index.ts @@ -21,7 +21,6 @@ export { getPackageInfo, getPackages, SearchParams, - findInstalledPackageByName, } from './get'; export { installKibanaAssets, installPackage, ensureInstalledPackage } from './install'; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts index 82523e37509d1..e250b4f176819 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts @@ -16,7 +16,7 @@ import { import { installIndexPatterns } from '../kibana/index_pattern/install'; import * as Registry from '../registry'; import { getObject } from './get_objects'; -import { getInstallation, findInstalledPackageByName } from './index'; +import { getInstallation } from './index'; import { installTemplates } from '../elasticsearch/template/install'; import { installPipelines } from '../elasticsearch/ingest_pipeline/install'; import { installILMPolicy } from '../elasticsearch/ilm/install'; @@ -63,7 +63,7 @@ export async function ensureInstalledPackage(options: { callCluster: CallESAsCurrentUser; }): Promise { const { savedObjectsClient, pkgName, callCluster } = options; - const installedPackage = await findInstalledPackageByName({ savedObjectsClient, pkgName }); + const installedPackage = await getInstallation({ savedObjectsClient, pkgName }); if (installedPackage) { return installedPackage; } @@ -74,7 +74,7 @@ export async function ensureInstalledPackage(options: { pkgName, callCluster, }); - return await findInstalledPackageByName({ savedObjectsClient, pkgName }); + return await getInstallation({ savedObjectsClient, pkgName }); } catch (err) { throw new Error(err.message); } @@ -86,22 +86,30 @@ export async function installPackage(options: { callCluster: CallESAsCurrentUser; }): Promise { const { savedObjectsClient, pkgkey, callCluster } = options; - const registryPackageInfo = await Registry.fetchInfo(pkgkey); - const { name: pkgName, version: pkgVersion, internal = false } = registryPackageInfo; + // TODO: change epm API to /packageName/version so we don't need to do this + const [pkgName, pkgVersion] = pkgkey.split('-'); + const registryPackageInfo = await Registry.fetchInfo(pkgName, pkgVersion); + const { internal = false } = registryPackageInfo; const installKibanaAssetsPromise = installKibanaAssets({ savedObjectsClient, - pkgkey, + pkgName, + pkgVersion, }); const installPipelinePromises = installPipelines(registryPackageInfo, callCluster); - const installTemplatePromises = installTemplates(registryPackageInfo, callCluster, pkgkey); + const installTemplatePromises = installTemplates( + registryPackageInfo, + callCluster, + pkgName, + pkgVersion + ); // index patterns and ilm policies are not currently associated with a particular package // so we do not save them in the package saved object state. at some point ILM policies can be installed/modified // per dataset and we should then save them - await installIndexPatterns(savedObjectsClient, pkgkey); + await installIndexPatterns(savedObjectsClient, pkgName, pkgVersion); // currenly only the base package has an ILM policy - await installILMPolicy(pkgkey, callCluster); + await installILMPolicy(pkgName, pkgVersion, callCluster); const res = await Promise.all([ installKibanaAssetsPromise, @@ -126,14 +134,15 @@ export async function installPackage(options: { // e.g. switch statement with cases for each enum key returning `never` for default case export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; - pkgkey: string; + pkgName: string; + pkgVersion: string; }) { - const { savedObjectsClient, pkgkey } = options; + const { savedObjectsClient, pkgName, pkgVersion } = options; // Only install Kibana assets during package installation. const kibanaAssetTypes = Object.values(KibanaAssetType); const installationPromises = kibanaAssetTypes.map(async assetType => - installKibanaSavedObjects({ savedObjectsClient, pkgkey, assetType }) + installKibanaSavedObjects({ savedObjectsClient, pkgName, pkgVersion, assetType }) ); // installKibanaSavedObjects returns AssetReference[], so .map creates AssetReference[][] @@ -149,8 +158,8 @@ export async function saveInstallationReferences(options: { internal: boolean; toSave: AssetReference[]; }) { - const { savedObjectsClient, pkgkey, pkgName, pkgVersion, internal, toSave } = options; - const installation = await getInstallation({ savedObjectsClient, pkgkey }); + const { savedObjectsClient, pkgName, pkgVersion, internal, toSave } = options; + const installation = await getInstallation({ savedObjectsClient, pkgName }); const savedRefs = installation?.installed || []; const mergeRefsReducer = (current: AssetReference[], pending: AssetReference) => { const hasRef = current.find(c => c.id === pending.id && c.type === pending.type); @@ -162,7 +171,7 @@ export async function saveInstallationReferences(options: { await savedObjectsClient.create( PACKAGES_SAVED_OBJECT_TYPE, { installed: toInstall, name: pkgName, version: pkgVersion, internal }, - { id: pkgkey, overwrite: true } + { id: pkgName, overwrite: true } ); return toInstall; @@ -170,16 +179,18 @@ export async function saveInstallationReferences(options: { async function installKibanaSavedObjects({ savedObjectsClient, - pkgkey, + pkgName, + pkgVersion, assetType, }: { savedObjectsClient: SavedObjectsClientContract; - pkgkey: string; + pkgName: string; + pkgVersion: string; assetType: KibanaAssetType; }) { const isSameType = ({ path }: Registry.ArchiveEntry) => assetType === Registry.pathParts(path).type; - const paths = await Registry.getArchiveInfo(pkgkey, isSameType); + const paths = await Registry.getArchiveInfo(pkgName, pkgVersion, isSameType); const toBeSavedObjects = await Promise.all(paths.map(getObject)); if (toBeSavedObjects.length === 0) { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts index 2e73160453c2b..a30acb97b99cf 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts @@ -17,12 +17,14 @@ export async function removeInstallation(options: { callCluster: CallESAsCurrentUser; }): Promise { const { savedObjectsClient, pkgkey, callCluster } = options; - const installation = await getInstallation({ savedObjectsClient, pkgkey }); + // TODO: the epm api should change to /name/version so we don't need to do this + const [pkgName] = pkgkey.split('-'); + const installation = await getInstallation({ savedObjectsClient, pkgName }); const installedObjects = installation?.installed || []; // Delete the manager saved object with references to the asset objects // could also update with [] or some other state - await savedObjectsClient.delete(PACKAGES_SAVED_OBJECT_TYPE, pkgkey); + await savedObjectsClient.delete(PACKAGES_SAVED_OBJECT_TYPE, pkgName); // recreate or delete index patterns when a package is uninstalled await installIndexPatterns(savedObjectsClient); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts index 36a04b88bba29..a96afc5eb7fa5 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/registry/index.ts @@ -56,10 +56,9 @@ export async function fetchFindLatestPackage( } } -export async function fetchInfo(pkgkey: string): Promise { +export async function fetchInfo(pkgName: string, pkgVersion: string): Promise { const registryUrl = appContextService.getConfig()?.epm.registryUrl; - // change pkg-version to pkg/version - return fetchUrl(`${registryUrl}/package/${pkgkey.replace('-', '/')}`).then(JSON.parse); + return fetchUrl(`${registryUrl}/package/${pkgName}/${pkgVersion}`).then(JSON.parse); } export async function fetchFile(filePath: string): Promise { @@ -73,7 +72,8 @@ export async function fetchCategories(): Promise { } export async function getArchiveInfo( - pkgkey: string, + pkgName: string, + pkgVersion: string, filter = (entry: ArchiveEntry): boolean => true ): Promise { const paths: string[] = []; @@ -87,7 +87,7 @@ export async function getArchiveInfo( } }; - await extract(pkgkey, filter, onEntry); + await extract(pkgName, pkgVersion, filter, onEntry); return paths; } @@ -123,21 +123,22 @@ export function pathParts(path: string): AssetParts { } async function extract( - pkgkey: string, + pkgName: string, + pkgVersion: string, filter = (entry: ArchiveEntry): boolean => true, onEntry: (entry: ArchiveEntry) => void ) { - const archiveBuffer = await getOrFetchArchiveBuffer(pkgkey); + const archiveBuffer = await getOrFetchArchiveBuffer(pkgName, pkgVersion); return untarBuffer(archiveBuffer, filter, onEntry); } -async function getOrFetchArchiveBuffer(pkgkey: string): Promise { +async function getOrFetchArchiveBuffer(pkgName: string, pkgVersion: string): Promise { // assume .tar.gz for now. add support for .zip if/when we need it - const key = `${pkgkey}.tar.gz`; + const key = `${pkgName}-${pkgVersion}.tar.gz`; let buffer = cacheGet(key); if (!buffer) { - buffer = await fetchArchiveBuffer(pkgkey); + buffer = await fetchArchiveBuffer(pkgName, pkgVersion); cacheSet(key, buffer); } @@ -148,8 +149,8 @@ async function getOrFetchArchiveBuffer(pkgkey: string): Promise { } } -async function fetchArchiveBuffer(key: string): Promise { - const { download: archivePath } = await fetchInfo(key); +async function fetchArchiveBuffer(pkgName: string, pkgVersion: string): Promise { + const { download: archivePath } = await fetchInfo(pkgName, pkgVersion); const registryUrl = appContextService.getConfig()?.epm.registryUrl; return getResponseStream(`${registryUrl}${archivePath}`).then(streamToBuffer); } diff --git a/x-pack/plugins/ingest_manager/server/services/setup.ts b/x-pack/plugins/ingest_manager/server/services/setup.ts index 224355ced7cb1..bbaf083fb8396 100644 --- a/x-pack/plugins/ingest_manager/server/services/setup.ts +++ b/x-pack/plugins/ingest_manager/server/services/setup.ts @@ -120,7 +120,8 @@ async function addPackageToConfig( ) { const packageInfo = await getPackageInfo({ savedObjectsClient: soClient, - pkgkey: `${packageToInstall.name}-${packageToInstall.version}`, + pkgName: packageToInstall.name, + pkgVersion: packageToInstall.version, }); await datasourceService.create( soClient, From fddf6cbee5ca1e486f6bc2724d55b2143e93fe74 Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Thu, 9 Apr 2020 08:52:06 -0700 Subject: [PATCH 009/121] [APM] docs: add alerting examples for APM (#62864) --- docs/apm/apm-alerts.asciidoc | 97 +++++++++++++++++++++++++++++ docs/apm/images/apm-alert.png | Bin 0 -> 658181 bytes docs/apm/using-the-apm-ui.asciidoc | 3 + 3 files changed, 100 insertions(+) create mode 100644 docs/apm/apm-alerts.asciidoc create mode 100644 docs/apm/images/apm-alert.png diff --git a/docs/apm/apm-alerts.asciidoc b/docs/apm/apm-alerts.asciidoc new file mode 100644 index 0000000000000..b8552c007b13d --- /dev/null +++ b/docs/apm/apm-alerts.asciidoc @@ -0,0 +1,97 @@ +[role="xpack"] +[[apm-alerts]] +=== Create an alert + +beta::[] + +The APM app is integrated with Kibana's {kibana-ref}/alerting-getting-started.html[alerting and actions] feature. +It provides a set of built-in **actions** and APM specific threshold **alerts** for you to use, +and allows all alerts to be centrally managed from <>. + +[role="screenshot"] +image::apm/images/apm-alert.png[Create an alert in the APM app] + +There are two different types of threshold alerts: transaction duration, and error rate. +Below, we'll create one of each. + +[float] +[[apm-create-transaction-alert]] +=== Create a transaction duration alert + +This guide creates an alert for the `opbeans-java` service based on the following criteria: + +* Transaction type: `transaction.type:request` +* Average request is above `1500ms` for the last 5 minutes +* Check every 10 minutes, and repeat the alert every 30 minutes +* Send the alert via Slack + +From the APM app, navigate to the `opbeans-java` service and select +**Alerts** > **Create threshold alert** > **Transaction duration**. + +The name of your alert will automatically be set as `Transaction duration | opbeans-java`, +and the alert will be tagged with `apm` and `service.name:opbeans-java`. +Feel free to edit either of these defaults. + +Based on the alert criteria, define the following alert details: + +* **Check every** - `10 minutes` +* **Notify every** - `30 minutes` +* **TYPE** - `request` +* **WHEN** - `avg` +* **IS ABOVE** - `1500ms` +* **FOR THE LAST** - `5 minutes` + +Select an action type. +Multiple action types can be selected, but in this example we want to post to a slack channel. +Select **Slack** > **Create a connector**. +Enter a name for the connector, +and paste the webhook URL. +See Slack's webhook documentation if you need to create one. + +Select **Save**. The alert has been created and is now active! + +[float] +[[apm-create-error-alert]] +=== Create an error rate alert + +This guide creates an alert for the `opbeans-python` service based on the following criteria: + +* Error rate is above 25 for the last minute +* Check every 1 minute, and repeat the alert every 10 minutes +* Send the alert via email to the `opbeans-python` team + +From the APM app, navigate to the `opbeans-python` service and select +**Alerts** > **Create threshold alert** > **Error rate**. + +The name of your alert will automatically be set as `Error rate | opbeans-python`, +and the alert will be tagged with `apm` and `service.name:opbeans-python`. +Feel free to edit either of these defaults. + +Based on the alert criteria, define the following alert details: + +* **Check every** - `1 minute` +* **Notify every** - `10 minutes` +* **IS ABOVE** - `25 errors` +* **FOR THE LAST** - `1 minute` + +Select the **Email** action type and click **Create a connector**. +Fill out the required details: sender, host, port, etc., and click **save**. + +Select **Save**. The alert has been created and is now active! + +[float] +[[apm-alert-manage]] +=== Manage alerts and actions + +From the APM app, select **Alerts** > **View active alerts** to be taken to the Kibana alerts and actions management page. +From this page, you can create, edit, disable, mute, and delete alerts, and create, edit, and disable connectors. + +[float] +[[apm-alert-more-info]] +=== More information + +See {kibana-ref}/alerting-getting-started.html[alerting and actions] for more information. + +NOTE: If you are using an **on-premise** Elastic Stack deployment with security, +TLS must be configured for communication between Elasticsearch and Kibana. +More information is in the alerting {kibana-ref}/alerting-getting-started.html#alerting-setup-prerequisites[prerequisites]. \ No newline at end of file diff --git a/docs/apm/images/apm-alert.png b/docs/apm/images/apm-alert.png new file mode 100644 index 0000000000000000000000000000000000000000..4cee7214637f8e235db2f9ee1201c603cfdb8aa7 GIT binary patch literal 658181 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


#q|^Hy8wAq!HGKrX@3GsH68Pm$O( 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 z zhNeU1mezGeL-u?jn+oiQK#7)W13o)dWe?r^goessW=&Y{G_l4hlpDW!M?TWXI>Qp8 z$YuYdLF!fl!fMLn8Yq5zsI&jv{C&ZQ^gLhOXwAVV_gdkIlbZa5br3^*bKVUM-#9KW zlRGmOf*z7kd-kJ%Fi31{xy&;?k+$V4D~IGrKT&o&cE*KX`lo-w8AV1x%j*Scff#89 za#CCOmQ2~7HmIvPjp$Zdurgfd)>S%#|>Q&Q^zZ&YKTv z?LTLsDfelrm6~3;ew~M67RKJ`@5ot7G&jJ77Bz_;at94;Cd6eH^VcFAFIW4wO5}Xb8*+E-abipexp?m7n+(&DUoT!VEU=YK^IhJ-HO9lnw@Pg zs0ETqG>$C(ZJX&@`lt(S(8(5R^14~>UggqEb&E``HQ2d#>Z&d{;a8v_jS17Lz$2ys zB>O{5J?r@ym0a_$KxN1s82AVfR+|@uqTYHbmek1<^G3`@d6TP@A z({;vjZ-z3_#6&wQr^X2)nT=_?E6qZQzezZ8+u!|KJejT(tPQ4BsgGE~gU{t=tM}r7 zkZ6sG(cm<+aq-Mbosf_zTf8Ua9c&X*am{u9H;{?{>Ha0dBYG5H{ zOUrCmIx5-vhMHPv5%m-f#g?Ke8ZsPXs_K5!^!gR?$Kyn^2}LooPxr)U$lbwXQIFNtMD`Li?@E_H z)YY53$uWiN%2MUsGDutrzlJ^J6cRD(mS4u8X2R{UW8+V>0;X(oBGT|>-W8XE9!c}=#~ zv?XPnPSTW!Eb2$d6z@%j!Y{k>_a4e&5Cjim&QUmQ^)3a!DXhL@?5lZAf6rla(xWDd zqc&#lUsKhKmE_=#b(WMH542%M&8ySLCma?B21$skVlN7ISKKDS$L1s?AN4X_ zWq4YstK_E*J!~hd-iY&r!(e=IDOww`)w|6Utn4aH)|NJ&Y&)~7A9E!MZ+YgbpUduaYjoF_EHm&iKpY5Z1l zHQ%9Y`66;!@7{`Z;;iWGFh)JIu2ZHy6IcpA=MM`i`A9#PO!X)SlFlBIpYU8Px4=Ch ze?*wDHLQ>3XjmtesV_Oq3aMCmahHWeT!$gu-nrq6geN7%wGEc_Hhka(;yy4l&={1U zdQCYTUJGI)2Mg6($o^Udif`@kf5am>Fit>C9i>iZCEPuf5zHa*CvL|BoP%>b&pw$^ zW=XevW|30*>;!eI7$X^0z{OX9U7a19&D%E zA3wJSjy`q1)#=N7QNr$|6Ju-a_-?#OYL2T_= z+Y4CMCK;TyzZFvh)m-hBZP6a?B7$Kvy~*x(_C(x|N+5VA_o!z_*Zxt0)*@~Xb1j=0 z`xW!ozQxFym8oyUACftw#u? z?q`vb)F@EA3vRcbygT^Vi4pdyC|5;pB`%~?a+=0p%}>bQ010yauj$G)@>JL;< zUG^_VsnCXh$J8VWPt;bPD;KPKRS7@$O&RuT>&^5vLWVYJm9Zsr_oc;Md_&~b9``z$ z1#YOHoA2T5Il)pQvV-B}(=6|-V4{61=ar^Y`EOw*A4ed%XF=<(;V z=FmJtBm_bl=x8VSrmEhqFY({6Gqr33HbrdCh_r3|HM>OpfBHWPt|+PINGlZE`G}@W zmHIL1+b^j%Uz6UUP|(2J#J40+d|nHfzH`ttk;8o~Fw`|O#aK3O7iDd3*t3VdUUC2* z5opQmy*dPgRN)ySJ9H6tquyhaM&eE$ZTpc~sZV)!f*#?#stA;@G zL{)Rm!!;q(v-Z?~dw4JJ?lZ^kqRw?Cg8PWGzWpU>WJiIN+P@}Qk$-Cumt^(@AQC90 zHAl!3R_-X!*Pfr9aN8mb$d0vnvVR{KYS?}Ek94N(v$3)?7B=wW=6K#3CqfoXMH%2 ztfgc%I>O)MnQd%m$iUL>AU1ALwlV4$)4cQ=>rB`0>@51Ef-e>1XK^Q$byqCn^f)k~ z&>hD)S(%)=mvssb7n<+L-?AWd40p27AcX|i4GN(x7q>i6-D>96UcrKWyxF#^2gnsl z37CchoopJmL}eLVeitN7MVxD1=-LY{mQt9;-)r8#?0^bZ*?t-ltgz9Q9$;;E^nPqd z7PK{V3P6v3F@i61B~gb~^0h%9_d0WTWvKkhj5Op+mt;K?viR&(`R*+?)l2=jJnVA& zf_3w0f;98SdBsK)r93h&7-e+y{73Em0~6xmnd;~EqV3)C-z z$uwOn_%jLEHZ^Bh2H`0heex{5-}F##>GlVXz`Lfw@fC&H`m7j@*MT)+IVa;mjdw4HRltw- zY5~WtnYdUpSHmzd)@z!B#e<)?Nj;Vk(R|UGn)8phsF~b#&19D#3QLA zf)=T^^6$~P-Is*65p}Qc(a}@jZ}s2Xjjh^ihn=||AATGd8WP%ZlxK7q%1}wDsWs0I zlYP4=^`WM`nBZTtVgIL&4T=G#0&A#J|I58_P7$Hbf^%#IUoA4p$jXj&+*hDwu66je z{%mpc0osnKsi}FvIe~UI(Bd@y+$?l+P_i%`vrt9OTm6c7!v>A4b|K$~YRj=QUeK}s z2vIcRryaM<`~Xk!1wQ5TaG@=fIQ@|-o_P2zv@X>o>&u_$Gco{RvhlabMcF=*l+a7| z&KfQ?#a*&_oE8qS`8^f!&;o@R`cfl-6EkJWfbX~%yckh_h`m5wKfa{o^h-&z;qJ;D z+VE0T4mRqGUD>;1`C;XA+# zyO+M(=snOyRUYT=9-?K^Uc7b^GyFip+2}=qna|SbwNGcWNUid{;1qTf*muC?oU6F7 zJZ=ZF*!^BOmZKZTixZo$Y2$3|J4+`c7@W|N_dIU<-)>@&xD_zGqZ>aCN6&=y<>#N< zd8Yx;X?{x|1V*37kcfHh>OO1&jtZa(l0@W|+}$&Geq`kYz-eIWJIE@#eN0Wah49zT zvwh|9amKT8>HCEWn~{OorptNIvDA{`iF4rF4nmg^mc~ErAdgr2Rte+C!cG2uu=~R6 zfsYcrH(nMZ6|fnz$cLOJNXOUoKW69*whj$=GPXhAK4{?uQVq*wQm~Dt(cas~+4A5vS(FW=LrV{g&MY@H0QriU;P?CGrxY?3zSfx3oOJ zhGG94-u?5uxB6RIn2j?v7o|`FBmKw9b7@J<0VNIJnmt188KFE?uy-J*T8Y+5a*-U4w#E89nUz!3Gu`6V7W8n*5YW$vBEW5leW5joLp`*Y!UYIq6p)Ra1kIAWwsh zr!&lotaTPc^H*aL09+1eG);Bb7HDz*77x+;8R!Z}pWfp1kKG3706ASl)%{GQn`1G7d3+x<(moj`+b`* z`-z&>QKmV?REWRW?R5Yge=2X7WwpNjR2_jfuzLpomql)be29I1lyz)EAfuDf6NsH( z&@PtaX>@Efyl@kqi=U~WK(5YwhqLvqK)1ZTh{HcIR+A#nG)sZV|D{61S_FNp zBiGnq#JqI7H^;e1md0NAP9?6H%o!&GacU2^v$0c;b|p~=sjso!{66!v-IJh7#MoEd zkm$GD;ScL@-9z8Cmj8s> z{{fx4)Xhb+q&atLJ!GU?&*(k;kUR z$s5ZL15a_@6y+HgKeeNG6ldx-Ea7Wr7j*15;GSJUXEE=5`=;uHLm^-DTyA`)@@q_} z$~i1@pU=&&RGc@PGrkXr@zSk?)Vq37<_eo>C$}7WrorW#MoqJ`LCBh9Lb8sed~O=% zImq6(m#o@$vT!5!;!^iv=q>vZVY!4r$@+iJhkvpjL1d>vuq`Q@2fQF+e&(n&|zM-HuE zbW{Zy-D4l$jFgl(D?MR?h&`I*Gcsago}>BtkR%7f6l+k8Md_sq@aSgJqa!=8 ztIGM2Xvk``z2L$>bKN{O!aY;C0>)RRDHnx(C=*VLO&o>5`pJtvs}zRxjYnAci#i9C zu;u(+K+u(zT_kwQ6Yi!b#WlBHOwUkyx^<~9=*~``b6p0m$U}rYo7cXiR znVt711}!^Lqs=!;B;R}^I^e?6ZH9;vsN?q$lPxiWZ@>O{5zzKwq~}ue>StSy6W)F4 zo2^(yn+a$8Lcwfpi=*#u(^kr<9U!RdX_m8lb$@Ze2QOf>k8244ZU8V4i8I&y;HQ?i zE1(!D2$f+cEcvPY>!s=Ky?n^`+5t+Jbi_dN9V>U|##9iG1?52QtpFE|@o~TN^1Qma z%ds>WO4Sz8Lyj*ojgWq_ozqI(B0GB&?7i_9%nUoEA8Y@3WS&(yrfJ~F3<*J&8P=sy z!-Wrvd}O@Kg0;&okBAjQC2FW+g?mg=RnS^Jl+%bE+c@wTrd;nKodMfwd4QuNAK!{= z0$t=X;2yC=@?jm?QY9yz`QY*Gdg{@nB*tmJ*PneNMbE8fNrQ_ssp}&Mzi67xhr*$w z#Ms%bp&lLAI#!n2eQ%BMtoyowc^;PI{r={pkj6KGDZk3vem~te7jlBPP~mh0N!*)^ znFn2+!lbyc6VQ|yII9sG8TZ!~>pO{}WU3(9F0mYi;YV~3JL9VfB^oLPD=#4$vbcbG zZPbd(aYdeUClMh82g7%E(KU!Wz|`R2aC;daQRgU)&j)k`= z&DOo)PX$*}ndg_O$#9%Jf&EdPT=aXq#O$d``S*aRjz$j+-+D#1*9fOSn@kB z`5=sU7rJo`m-iw|rGt-TbIB<2`;W<%u>lh|SBxe&foN*g3@p&nP1nsJt8)IA-ighf zA27_?Tp%3#;c=Es(;8DJPPaEudee*BYxqx#=CNGX+E$|e*(!1jZ}#AIRiPjC?~U_+ zN9mqFbXYoyIKDl<|2SW|!B|<1!`vTL6qpsk9v&puBW`APeW|T^CAG3We74+9^vOlgdAX>G{E(~b6MZh}5(q3QsW4EsO}XN-l#iJMQ-0SG zUq7)Vny6uUo-wb`?$#&*N&|n}VmQR%NtRtP&UI&vixnl8m~hr${%#cQU(G~d#gU9Q zB-F8FG@teAZ0g#mJYjXKNXwv|om(neOowVI%cbIngNEo*_62Ew2lYs+wVgf{F=L&o z6=?spUgG=uMC;#1Bv-49dB>`xTZf@ zz8=38CbY8JR`}q89nJQ!^vUeK7J^&fE1`~Y2J*|K-&$HT7yJ>hpgjx3QoQw+{(63g zv;f}KLo;r8YR#wp z=9AMCvFinuNU;F^D^i1gyJ(Wv>tIe5s^G>~w}|b(CD35nDkhSoE=I|^KLs9@2(`kldH3ro2}{Dpu5 z7abjWXdI#2m5aEn_I8A_hK}(nEBDqwY-jR=z8kDm0>=xh)T{#+m#M%%SmDElDO8S=)*<~JG1S6VvwjJMOW z5D$3PvwCgkc3&TvE4*;6I)$16N47?YUXHFw>dk4P=|r$~pns_#)SDixeE-%@1HGG% zh_|Dr%Ng-cjF+(N!mq^HQo>(>+U-Xb4?acvILYQnvhzmxb&PlWnGW2}pG#!Zo(GDb zEgQq1b*G?A!j%%}_*lL!T5rZ~u#)MA!bgz0XU#FrHL97rcQthurg=Msr{+r)HGEEDUC%x9N z#mpy^##VmlbkU!@09VoI4cxOfEOB%QxBMe}ar@?l(^|l;eL!l>ulcr%Z(g@OXu&bm zO#x7fT2lcRev$)`@qTc>g5%%8-X)2yt;cg$8?6duS1L;?45=?+ZGG`;h#sz0yrKpv zaFZo^H!dlx-fkP8xMQ4ks|{^-tKYR{$6~l)fa~krItOOoTb`qX=uYm7S0NFP>>(l+ z=cn01cxj2ETzfHQ9GA}blpXs#{Ii|`v7{L7zLxY>L=YLyj?v*(*40=R;e)78r+3VY zR?hh=JCBBE4PaXK_0jQ_T#wH$mm?c~59&}rObLp>H^+-19OIBr`|rDJji+tff5F7~ zPLhM0SRw0Gb|5Pi7Do|TrNHeP9BhZ5r+=`Z4y()|YTKxd?^}cgO)8W%oj#_tc8gK7LF`-fR zBW(u=%lqZN{x6M)y?3xpBym>zVf|8iTrA0_VTB`{(Cid2ba#`Lsug}=n<{iy4=#Ai zaaML8DsJ2Av3CSB4NN zMPtFYZoC8bXWJa%i|WGrBGG4lh8)Q@>$B>DN(^ zA(RhMm$M9Cb5|0Mi%X0&xATFlyjdjv4U=A;ytAE|o7vtVRD_klEH^*uIuvB&uvWiL zL(x2VS~wQ~wEz=bVGAUTh(ocf4x1|<_{8IyT51>qkLuq=9$H`wJQ6s5D(EfcWbbd6 z*$&&-J8siG7Y&t-S@MD5(7EuB;uPGZOr=F%0TUi-${aa19ThCSErXt$kSFy}5vN-z zFA^EOy3CkT_V&-G&7Xa%xEp+aTM`bG9DahT*qG9R6<#lHRB0`1;ZB-E4=K54?yiOd zA=D_=BCc27XY}D?A@q%`wt33P-tO0icy^SBA)2IDyS}U(-92X-BJ*oFX!>{$XY5-A zc387X1G9!&i!vY@6TR+^fFLggpzLl1Y?v3_W;B3NH8GSI4S4DqEJxWCnZi-Z&I z1u`#|rf$kt=P9c`1UqPx&&UnSGKN)5?s=cjluXW(kE*0aq2f**QH&9=F>YoQ{g9MO zR+s-8>G{9C)D-Cedapf5OtS^tbgIn{>KBZN_hGHi0C%@mUy9X-*($GoV=My^+0BdR z&6Ssl-%?53E>!WPCe4_oTb#CJM7TeZI9K_iwsXA3ml{Uzibo^ng;Rarxl%Pj`ix7& zS5Ow^(eFz+QYAmsIQ;No3J~6dlC03JjSZ!oW1^u8hd6(QU5ffqi#B3Ez_PRA{+dgo zQos6Lvu?fZH(_!ty%&BMF}QZo#BTC$VZqaEg*w6a3K#UA_KGB2rbA!DivEVAFgbNr0~y)vkG=ImM^g?s;1AJGyd zFrNh^lFDyk&QwKM5r*JcYQJ7|8`fI)UXs4#?`EI z-zUMCyiOqrf-hY^32=e(no)cx#Fq8QkGNt>^FQm61MmnEnWpsEP|t?_*wZ$2i43y4 zKk%^#k8DL^LA~2>!&)!s*lRt&@w78vtMYUI>iObp3+k?Q*hf7$et{Q`30Oo6yy7GM zJmqWr3pY0X^6o$%YQ9k`!|d9H`g!D3lN2tGmJcQStv?(;@d0e9qGE&1|36S zc;AHkwD%Rr!m>TY_-#s5510MKW9UJ$+{dku4w$Smn-I23-{s_W^9;@?U|~THHjsLb zKMt=j!6xViVsS*mE5{yk$g;HTBwxDM9Cg87W32l}gFM#UEH#pIU3$wKS1sE=m+3e1 zo=-2ev|U$uVlD;z_G6(yPOpN?V0{@w+q(hA8ki4>)VGd#eD0Y^VMSqV!7eY7!L5o} zD!}fMrvGi4?hW@jZIKm5^foZ%lA9iTv>nG)!mzuEVUS_m2wzkpjTw9ZLwS{!@ykAg zMcOp7>0#NkUYF<4t!c2{@OtL1@%wqB-gVw}TQ+&jWrs=}jY4O{uq@3PwePBw<1(w>*2+GJ-8ng7P{`m(Rx#%W4QY8 zYqXE2^_%vsghUHi85$x@-~K_t>3XN~+#pciq|-IzcMWPpLkN;;bq8~T8tpM=1&VjF0*2T zC(q_{Us;bevXmPR@5eR9_OJJA-+qibp1#$^O_K|(cxLtnvH$#wR~k@Sd}(N7cwCnS2SOUpEak4;Ya^^ z`QA`94_fRsC5yx^ zu*N%L1-Vlt0#G z5%D1$a6l(I<^8EQuM2$IR~ZpI&DC!k5e!>=e0`Ti)uG?BzGRcUAHt^`{@BtzBpjFL zO+PEY{VEp`KVy`akVH$9UVE;gXviL(&~yBhY zS#tT>=C5}ud~R|x#U_-I`*Muv%gKG2mqya~<2&TDGAvJEDp=sf{MEdV$m1iE6cz7l zNw2k~6)3Drff!z*;dMVAV5(8?SpS#HyH`;3Zp{vSnGh#u=X}p%ICjQ>+KuHD&ve)K zvrWll^e(RdkF&P`%BtVOM*%?zr9(QTQ%YXCrC++c1*E$}QV@`rl$Y-AZUjl`?(UFo zyc@rB&OLX|_uZNQe`XIe#%%U4)>_YcR*_TxlT-^0KZWQrspphC`Uv5n3!1=uJ8GEw z3X5@Sc2?F5#SErq1rmo}9cH^@Cko9Z=uj1^Ck>HK_;h^1dnqhfBs5&sb4F%nW*=8y zkvVh$vlQsz8;!5<>nqHJj?WxlwE?|f`0o} znb6Th1q1d<%8<<`fCe%hIrwVAvLUEC#nkj8napf}pPSbpO z)Pg^rwVPW;c~}q3=e9<=3&}C@T58u#&GmR7y$u^9ryqI&%Di=*aIT<>-urhi0D|p0 z%_Yy5-li_oHp#@7XP5XjZ!C)rW4evM%}Ye9>k()64`b!kx-_9RJdm>_#^$vyf{Q#} ztR(p@em}jUx%Kzb?tIzj*s^D?Shuf}?KLTNXUZe1njL#OU7!AFbW~TWblZyX!B^-} zsGzZJZ)Qox`ncBd>#e1)8mOG`ZGNk=+D)=Ma zC^wXCE}GA!$)dv6dbw7nSx)-qlPL8oC^RK8mSsXVN%-U)H;5)x>xv-m#5ZEa#A*EP zzuGAOM@au;m&4x!94ZdyrV%X7beOt?5SdTA(ju?x(aX%q^$n)F{?qwNv4Y^NC;|FY z59shW+_(Lux>#mSFiG>Z{dFxV(HoO7E7@H*-$%j~X>(q%%_EV0&reX$V1 zX7j$C)bGouPlv;^`RDFyD~p(dfJSDjLbV%9i3O)QS!*a=Q958GtGxNBn@*3^+l%tL z5k^RD$F?WIEC)C4U^gS*$0mK|@&SDcpQ+{DDSPaiszBPE9p_@5_Dlve8GsZMMS@ z)$@+RgF`ieLdfMn@$dzBu8HPCTU}jO58vK7Lepn{-rRgJL0h+JZ>}ser3QQ}E9t4G zs*Cq~5%ETyf2dx;Q19*{sldRZQed^sv3jBJ%a`F-uwcu!mw6Gj(q&NsgptnUdyg9_ z^B*bh#F1{AUe)e%dv>xKdCY^^S!6t;dY9cK*=ucb(z4x|_`$((+Zg{;KYaT%!2qXb z891aUp1o8!r6DdU64u@Q>B{zs)Y*PS72(e2dqcsl!(LQR2lxo1!h=s-s zK!e-l53%hlrGxD-A!E-fp&)8zNPu8iF{D^(dV@a?tAj@|6<%I^^Hn-BETmm(M0d$S zM}dKEnKqdRKcP;qTyCDTPsUt_xVo894{rU`ZoSBlY2kkDa`GF zt5!`)9|5^igKQ?Uj@X(OfnJ(<4{B*#;VsLz9tK|B zP0GX>kt}T3HOhcp9L+pjDB;<4e14&B8zG+7AVm;t(2*U8v3;&d5)lG-+|$;>OPRTm zvkBA`y&Jm?QhtwpphN2Yj;P3#TV za>ZsjR3=@c<-@N(YO21nbVwBu`~KDb=zm=;gRf5sOqsz8%0QP?evd`xX$1O67G29D zpB-}Rr8=))4u^9!W^E6bH8SCPp4R&wZp{k-o)z|)nQb-=Z@7rp{#5@7m8Z8@r-1@A zMGVC8;Gg1nPNKkdSyV_doyrj+Udaxi?daN^n+)5!!&>F(`{t%N1aY?pT2>*0_5!P> z_+LRqTOT(n^<7wq?rw7?QQkG_@z_IqvSNVO8S9PUY&LWp8;cvFa1G~sTl-!N26LEN zN73i?gC^hmXYn0w%x65npCIdATiCr+!0ZU2!nyBoNNTjjiof2hlhRpMC2sT)YIB(l^d)Nk#BsM;;b5MS=p+3efe})91B=?*59aAQ>JUx(E=B}a(6+xm+m>v zW3Cb4FI98$`#wXok{Z=$`2urWC%5&9hR+PD?RIL30lm2zI~uR^dTA29dNe@E0DQ$ZUj+W@nfs+S@3jyN<9e{Q@ zLy0BYwch~$H855HXlV5l$N;>_tz&Hi26u{XqY7LbRDGOfV<(eI0?UEFCEGO4!o`0J zC81G8ddid7p#t81sbn=0Ux_>c3pPWDGiU+_>{GI>?fI!j$3JpAdBBg<-IU{3CtE-&HD*t&_673)8mr-yqZr@PK}V1Y$f1 zg90E7#MsH=lcj(#P)4{2=VVK{q`*&yZBWuyM7%Z?;`6Q4rtx1tQ0yhMF3|lsou(5x zP?vnd6IKctwf~i5WsDCqz`|01)?oVMFrk8qc{tnc+!r1}u5u?XHq8^&Zu+2f5%*N2 zxl{K$#@lpH-31@w_ODB}K1s+@6eI@U9ttenHR}!-ud*Y>7oXD@)>*Mcp7||F>T~QQ zs$9A00A=9Qx(H4>GM=^0bJCad9yrt66(UZiX+5UJ-Dk)dy?AW*4$jcYZKsrrF#%-T z0o*Ap+M%r`z*`8J0$^6XD{9JItfUczI2 z7bpSAyEhEPAk~NuGhC)^6RaF8hvWlJXkVg$iJUf=KmLghG8lcTW5}dlgmg$rf>>D% zZJJN0*?D=B^J(K(^%w^1n@FRF23{0!>G*#7`R2rk+kIv=B&kC228Nvis7gT(QhYiD z*{4H*d_!;+@^5UHa_!_qB^VDg335_cY;10hOS--~l&waN72yS@JHX`SqSu!3qj6MTa#9FA47e({*IBEe~ojvvDzOMk@>B~ z8=m`tHkvGXuzR(>oO<7RO)qhlKgeG`m+dTufaEpMRAgF$~^J zp0k1BXaE4fr)mMA28T`QswlT49qIu$2?Vd}dguLjj@v1&!SS2#wcJt{JTELylp20S zgyMax_uFiTmA3=|Q&^l6{>)MmdTPf}tZRfjB8&iZSY@^6E;s2CG4`o>+wfTduX-~+ z533!yauZfy0!vpdk=9C+C+Wx&s0uvF@eVSpbR#@VAZLL?+Mr{RqM78jx}(~R+lF@9 z&TZRSr~2fX-jGnk>c3cl? z59uHF93mCX^p9%>#*$96;y+~c@+a%TDW6xtE$$^)d~0}^LZ}%lUB5X%R=MCC(lhdu z_SRFq8OpzKNXvRW%UFy#V6}9l$&k{RhC`~FCx{!nU<*GxoCAyn3Y3WB?1zVAEK9+P zW&k?aB5Tg)$z;sWk-l|-I>hgjXjZ8I0&_HZ)_EDiFHsw&xgF^7So$7Z06p91K0T=s zh5sPt|N4VQ1oAm22#F;`##pEs%%#=_1R-`g7_h9WPQM&wWC+7DN>C(BMKTbQDh&13 zoSmJ)Nk`7`t&OpzKD}>*;mI?Ki%%z3rB%QK75Ir0feIjfs$f5w-Hc1xF0+jE2pK{K z5KshXUjC1fNodquc8Fpy8>4yJ7u{o_fY0p@O=3OmQ@vzU$RU4Y`2SK`V{i1lWyT~P5 zpx`1QkKlvg8<1vAXZV{o#^GAr!D$ zue|lqMEx8blA^~+x;~GB_1rQ`Cun1^6zL8;CTE9PQ}duIVBUr2{X95i5GX(?L4+hv z%x^%6&=M9*?J5+|P!s-iF&bl}7`d(l1~W?HDb@&>JW%cH8FXZKL_xy?fjg6;<< zt5y$du38@dQZjXwlnG|*b+*)(HGC=MEO2Ze=AE&gkGG~@_`SDykiQVsTA(Qnk!mZW z#SX33de6JySG8K62P+|U)wZXb+ZH^@o-6M$AB4Ho*_d+Gn75xbZ-4eB{ ze9fG(#W*2#M_;Xr!9P~);8wwTBZ28T3SLz?Y$8_y`7gVM>b3ARO%%K+fBgOP2tfUK z=F)wTL_nSZs_i*s#fHOr5@v-@E-Nh?E+X^Fafe(z*k)7ie?B9}fhEGZl?jlEw&n5{ zs1{C5UkMCAn9EgkuV3P@UrOPNk|xE;+oS`Tk!d_>TfubFxu8>)dENR%3Tckwh}C)R)k_qocbFi$6~tS zk(%Nkm3!+6Q#He92CN#h`~;cvzOXxM&)N=;HeTej{{}}&C|=n0Ms;|!^1v?5ZuUHYI4f}l1 zsthgR8glH@`T$dM<17t_uZv#tas@^~w4?8riMN=syCSoRzq0s>9Ls=Gh=(8<76SSj zo0C6EcHfv_wRg1Mnf#dSY9xQRa`Mt|WcH#SmEU>?8;OCn(#WkprLJ_81T40_LTeK^ zB&$-kdCUARWiEvBu9Wm-u(5lbXQGf_e~*DH9p840w`ZecNtIC(n%C_aY5b7|V&H-8 zvn0O2N7jBz(x`72S|xwSUh5W&Hat9^z4%&Qo6HbebF-$Ja9NAC9^J(C(PkkkzilU& z^wnxC0pZfW8m`6}EjO$Y}6Fb{=oPRib0J_=bC z7FB%i<>mF^mi&su>_Qj_FICLlj~yM?giZ>cvG2=U15ysS*Ws>G=MBZe$K2WK?c}8? zg_c>xwa&aLmRajxMFi*6Jx=t_t-)}H13OK5!qukLYc+7(pUt%+ep(pILe-cJaxH$@ zq#Ftg3zbvuh`#ko3If-X<>2?X0w>rw0)SD4CeS#HxxAB!+ zXYkX7J|%BG)V`vhLnNWGCcJQNudDv!(&z_kRBqbo*cL(+~Lo z3E7Dl3bb2d#e(A>8VDr2oMzNF{9$6j!&N^*xzg*r5AniH+^c9kw+ntxuOo`(ZWGaUaZy6!-)Km$Tjc7oG_t;o1}PV^NI zaX_=Acf&Fq9B6(Lqx!s1nqL0wkjvIr>TUjKJ*t)H?2PzrTUBiY#>UZUujG4U()9D; z?_2ez4G-0i70Gp%&ZMd5oc+(>?=~;SD^MP9S16CV^$r+3&|)u+@TS44OJ(+^Z+%Ya zR+ePkVR%U2K4UCRcO!{|IVNA3(`&XRoMLKS<{{aw67Lypv??5CL|EAOF>4rBoW9G} zmcI!8%&PKfE@a)Nvsv{MBtL5T@^@MbyMI-M$NIJLkGHiE-peAhW2aI1*wVeYB42Yx zL>}g=LJpK9^CdG>VpODKs1BR%srqBQm#0}He!CBO4towaEdV^)0WD{S;B{n`NJ1d|+4&b$GNk@?C^YWxq(A1F#j8@h zxD#C#3WP{+WRL{UlfoA{J7~`_o$tUs^J(`I<{LCskJP-eTLh+koH_+_J5V87g(475 z#w@c1*&|F*EV1V--p2+0PThYc{E%d?E0j4KsE}RP*_ItJ6vL z8g_wEM?`T`TdmEVZMOE3N{>)|ptPmFLXQ|MnQ8U@ZSVn2DnhAs;1`(JGnb=o))vG9v56)(}Wh=_RS;)fSm54X^g`<7vF1 zvCyQkA6cDgFFH9A=4F3%EFtGVo7(qSA5v^KHDZ)u4TPxOO8Ubf`u*=C^bx%mbCps% ze!=ILUp1TNTY0_yG#WIjE!p%yXe;S+5?&WsL>iQD+TG014LDr+R6h4HrQwh0TZn-W z!{-r4f6k`!>1)Sd%cxawI_b#qEO$s?0v^ zvfD!#+A9&%88Nzy>pv8bhypN@Et3Z#_Fg`OIZo6sD10H7`}h+FRZ;BlSbBw`0Z~0m z`Xy$#2shQe0&bVvZv(KUZ{JH+um@M!x2n0w3|#sOyI4^(Wl8<6reBA(gfvPrxsBlFb7zD%+ zA{`OFGT~;*-sd^+e|0_S6z5^_dA1GuO_CA=73pUbZsDmhO}mDHMgQ9eF+wOFk;dJU zF*O2D4e>sV>Y*ec*=|h#!7f1CFoUGlK-kJ>)B}sG`I&bG? zO3Ym}3%ygPC9K&atAZG7UHZwh<|SM(#YruFjlwkt8B0A z491R=D);!h_e+X1PGiRR#M2ct!%=aX?2u^OefB&|h^|f?`n{M;skw&<)eNy@D7n?T z(b0G+neca$>hz`wT_e|+fJu*^`H}2xVx0M;T0W1)BSfFhw;7j0ZE?eb3rTHx5owr4 zqW^YZVf+!vqAfb5aHXlKDFZ*okwahNOFO~Ck-@-`p~JzUgM(ox8be>hRZv1z(C*@T z-zcnRV3>!TCynm0 zj0;1U3^xek|2azJqFfJ2CN`)EdUGm?0n-GHcn|A$#G^f=U-k9}uQP~Ibl14@I`&zU z?`HeFRGk?vaz*X|h|rss94q{}YUmGd`Jen*GS0GvKAHYOJ}(11b?Y#RL?f~<;TS)W zr-$dqx+z^`r6q8);0Dco7I)F6hi&x0=swgVQ`s*bQXRdnl*)gdT}K+O@wVm5v;1TJ zqgN*x9^`KXY;C?fREej5aN3F4d`~HK5u*^z!e_0Ih5w}BP zWD2*OIEoI%Z&6t6&OQYNG19-bErS9ENVk&AOp_!-AL#6>COIz(xscYtF5dah{MKL; zD+So^f=*or_@)<^HNNztNtglj(eGhhu8lH9{fR2X#RYDUpy$RbG7?K9o9LUlHZGjmDtvU3IeW@c=%h*pZEjqNHfDy8Rdcd?|8zSXFV*ytBcRK>A6IP z_yEIEon(&MdqT>nf~s7$;uiJ7NF7`y1d1w-I3!2s9y!v3u~_W$^2AHLJb zk36pT$$D93mk z6paxozDoJsu`2#UNMVX?w(;J<7aezbg_({6ou+}wKTy9e+Ll&&>%zx-^mOGAOcK^ zK!R*sctUm{v=hP5PdJPkGEA-95s;uzphU&QL=LT95rX?8Y-Hg8C`jrig!vv4D^!d` zGb#EAz_jhi)aX(#O%OgZVAJh-3EyHr1UX4aN|;Nx@0i_yk!VD_2d%XR6&rc4?3{`| z@uBxd0>(xrEdG=IbV;Nl;@8S`k^pBo|3RwsqZe)}tz~QIgYHuAoNg4hi|m>sR@roF z`vUC7n&_Aq8F}R8MMAMmiRG2bjH*pxv+pmD4^_HA!`D|P;lY)uTF9J~fe>61$-hBG zPfHdBc{9+CN4s@g9FvD#Be?QdQSy_}4@BCpF_=s*jGZy3sM%{@jS#>KwMz@N zU^|dAzsT7Ng|NK)&|W;JaX>%?t|#wbz1b#3ND&-1ojiEU{Fjv1KS4VHg$S}EbyWg$$ffseat{|) zNyflk$!hV(2l2ceg9C`H=!h?1ahV*;Nj?1|a>OLd-{B)NO#m{680*(agIME+d4=t7 z18c<($f*|gTI@xFf}@UAEzvmD04rWqOIBA>#`MLHlq|OaG17P=dALp~8l8=QIG16s`}5R?`+C^D%`g-Pp*<$;n13>wu0CFH!`&pLa?TQ?LDH zxisGc_M1^O%Ky6%nOYEJucMV^HG7dwyEOa0>!=aqC7eq_$Dkssal$tuGKaSst61>!zQSc-a)U zBK_EsoVEfP=cj$itOF5nKd=99RIU_N1fyypJPxDA2o6;^!_~no%>XiPbD(q_{jQe0 zX=P2n@8hhjy}iBDtf{JsOFXloJ)6vlvE9>g_BsH^X?8>14lg44bezCaJ@StSw30FL zJ3KOvQ@-dv*T)`C8Sd$pDRTWtyw};s9?Q--S8>3GhBZq*VXWq7Lk%;S6|Mxq7w6i_Xb%O7@D8_U7480==#kTV^t_ZN;mmn z1ucf5eaw}uf7c4j*|NV3k&}ZQ{*!gY@`L00;MjGk^kVN!Zteyj* z_8_5RWE$rVQf-mS7gW%|3o%}NTdlA(VA1W~q=(Zi_CNb+EVImgM%}sQn%>TLK?XgCt12(w;p0al2gm*gv8S>; zF4>rpY$uCnX6*IMqjpNY!q5C0RQmL_7*BR)qejK1W+0YM4gq;%c;s_cP2W%LTBW@p zl|r3{7^mZu3{=sH*MEW2KTFJkCxb?ey$Z2t!t}GNglRyc(S+}{q0$8Pp&e-=h8j>A z;Mv;KxoP5)BfzavwBzb?(-uL(x{(`DbHpGzh~)JQ6ea;Mh=E}+D74%&i%w08uDi+# zn_jZNql!T_}*sbOPtErjIiu$B}#i(HsY2G+C z8K`w&gmSJ@Dv#;P-c?Tgu(6)ap=?SC1_qq9<`jb~-DLQ*a<5f7Wb1dfeBsey{C{C6 z^rTku><;MGIgGxtf~?Nt?%+RJEs8KdamLqEVY_Uih%{8L{#^|9f!%%OKq3dA&;E|J z2_Sp=;?(JmPazw=A|h}Vn|)nf3%jYMm~vY~Dcbc9%rYmP2nN~kz=xX37?3<2NHiyK zAcF))uQ~bPjZ{H>9JAfkf~%B)?=6lU`}eX7kw&vA{HYKF0lwtmq#=T-y24Eft$!|? zCqWp#bX@q)msHXKOK+KJk^>y)}v69sH847^b|0M{yNTB`2meq`DyX!kJm!(zar2#xKFAm+SKZGvLBTkBRf`iKg05|L3KKmfCX$g%A&kE;ukUXK(&N6`og+L4NXhZ7l{b6+0 z+Fv}q!o(8}x57YUdWv3!qo>Af0KeXZ+sv%iH5SBv{)h9kP1^bXmqQU4PW1PO()$CR zO&8S1I2%CObR^(%P#+dwqCky|xA6YPT~h+5GOiDk>NAqRsa_n8y$o=5Y#;_Af38l! z)74Q~c+EHnZv+UiNET58rdMN~YCu-knv~%Z@(#(<0S3HD*KyIuCWt<>KQW`}H)1vy z;;=9hhJX6EO8!4bVP&OA(Yf|_sCc#=M!k*pG2)$0H2tYNd4HEL{WO+49*a))S?3B& z&&}0N>;|@UJU_-{k@7s&_rKum|H=lyB4|=TRj`ad=r_A~FC(3j@EEtP?Tckw89t(WM8e0zo@z17D%B^KJC(rv zllu#%PK(>z{EVF?wh9~my#uRfx3>VoR_fce8JaZ~gshyZ({TP#20CwlCnTbEhLVjo z0qbvv4x)+-UtGKHC4Vf8Wi&<2h)j|>-N?a2Xkm$Xta7a@Rz8Rch>hhUJ>>TY1Vi~n z-7y^$XDP&gUU~!$`zBu<#%2Dh3( zNd)qD%ay)mgY?ig7#xh>h+pMb7H-af(GZV*)ZhMcRDWq+&FqdFEzgTKr)>_WNaBPi zq@Rk1D>l1n@+=7JM@bt+a(C-^2R-YF8XXadgof!4?~`FvHM3nu zJR{%yTb))7S{O?!-q3Y1Mlz9jX}qi#H9i=vzt9`U?oW^CL!a*zcUiaLzJX}Re}A!F zcF;WIib~AG`0_2zmHHQO3Xfcq>+y+p2+9DEAy_PLhhjcVJ-)@HZE?0$5-aaEUaXYE z7RR6-yaqQ@$2K-)&D_h5cmQ%zSWr(zL42W)c0J>O;$>Useylg=cz}q*q7co@q!=Sj z?Oyij^4%WKhv98cK@u9GyN3)2%})8Xy!^;;f|vD%V_=(AmQR$8pikA_jQV~GdYUry z?tygMqJrCJi{p^jCDw`AqGr`$t8;(&j&OPT7vD9{#$}3OUcMuBySLI8>$YR1n+|5z zgBdBWp%c8*?O__ehxl`Ks)7C?fZ|y8zREh+(J4~;st zwWk_Uiw@@5eUVUQKg_)M&e^DuFsikPK@}4&u}S|M*}NKyZsgLzS-zDZW4Yx!m)9w{ zKL}2dVY_U8j7NOt{}2 zDnaXCGygkhsjP))3Gr8+&8-<6h;4fzovdTHP`>&4=j$jy?P((ECwC0Wjac-Pp1mo|bPqi|J@~i*_4ObxpkT(1Dgu z_7M>;PEQVh+52>7`Jb;A4b@un?o?69Sd2=97wEM#a(L|s>8qMPo^BR>Xiqov*|%G5 zI$O$?VJX?k?^%x^F<$W92{P@E&D`$!f=MBL%nfGQc6&cJcPBC@Eu>pl+;CJ7l3bf! z`iejkc^DDncf_Xt$o#U8Y2UWk{_lyL*34IJZw=7C<2H-ROx;@!zZ?HzIhCuoMxx-$ z-NE>hZA|_kxoE0PM%_x_%KLf)X7;_VCuw~R{^Im6wP_!Ln+qC(n^iB(%SFd^xej+V zlDmiHBvFRnIt)YVN83KrI457ZcdMd)T6HCSdY`!b%1b37{!tKnd(dJ)0J2PX?s5OH zCfre}ySSf&t{kV!bxnu!%FTV-d3t<&4N6>SXWrxa;qEfUr>SW({ym4;ghHEhW#O+c zT+5leWrMNbhf~-;F}D?4s>va&|3C-KxoC9-z+PiWIz4-mG(~B^v7=qIORQz^*T4l= zn%1fqno_FAxK(K*MyP;1S3=9DT)sMdu46MSkyGpd$OOI<&KyXBaRFHqh2p@7r1~ow*#bcv~nlKbzwY`gbhZJr=|BL&6q;DO!B0SkndJ?T$ z2~WAENIUJe#^$(c{)HJhhx511g=Q&o@S-~xXWO12y#=!-N8g%^uc1kvXMP`!dXnn7 z@$X$V>)oM!o3{h!p+2vO#|sEKTQh4J&15VOX(A_!ZohJXySYM-|AS&Vfa5GJTAaCR6h?`rzcKOJ^*K0w{CluTm`k*TyWRcW((`r2FI}zMp5v|~xov^_ zz?PZntxAhylD*SYl*;?uJdtGDRfd<&f@VPD&31RVxX{ zj+h-~>kymN)tJMb!y!7;a*01mqmm=vG17LdWfP9}4z8b-9obw(*p1H`LG2@3_HUmn z!IYT|-F-T`O*zxt`5r)u>cU{(_SxHQrO7tQ2)_wIWtJA6^dPsXqx{iK-YaEgKZ*r! zRT|Vc1u^IQRsOMOTEYeYesS4%bb_TBcWBA;+#=lb6e3bRy?29=tGelL&7<)Bn|iPD zW{>Yph1nQV~V;TtXL7TNHPEKi3cY>nk-Z6?7u% zjsBN|E7L0VvUH0z(E5mwMwWM>DerD-a>;aS^SSbPXMJ+M9N_0m*43xE`mWV3+uVoe zdOa4n4=GM->YpKVqzyy7qKZNe*IH}Nu-8))#fM&fR5QErDi{*ZzyzCJR+J4%;NyTF z8ytBTuRg2u{Z#XoK(e}Qh115~JRJ1DD$8(PqGDQh{KjN=dWB2nZ%-gJ@`~%)+P%4pP0krS&ZYK;xpo;M zK1`d9@A|U`$2&c))r;DwQjHfIe^)@&*)5QF38mfeG{=~U8Rk{)m?P@?x2n6!r}Da+#$Nl9}iBV ziWcKl!t_5Wcm@)&exB6qrB9={rH#ad^j-L(c!OEP)A#RHrDHSeNZrS5kDmoj_Ti8e zLC#3`C2&6DvhVNX)_8EXe(?zR<-f)R?>VRX+`ZCzm`-Dp(cD-M1pWs1=G-OJoCR+7 zLOB1(CpoBt5&h9-{kex%=_>Bmx;3lL&Z#&YdMWj6Y0$4Pc1;5!`3guhwr#gs1anJm zc1p`x2c1&PcS7}q%tZ}^W~0(otlv%80j?rA{~nYAmHqPmWsKvoi}IU2&t!5qdu{yI z_gp008lMqoc@~n<`1jCDev|8rEVJm0IvN;mrq>cLHufu|KD=HV(%XM12Sw61UKRyH zI0w|yHPHmt^1s9N{vPs?+nO(#YPq8C|k?W%yR*lUp^tm8I zSC)tYR;ZoB&acsGlRi9^CKsk}`03hish2Y+SQe|DQ5yt|4_+8J($ba1KPy?($I?5# zn=TEAw5!!cPV;#di+N7e)V$61> z@bD;=`)OfjG)tZJyf85je!xh9vfeoz^yN)E>w=*R(EZ0M83>`GTc3Qu0tbJn8GZEx z`ThJtU>Lzh>b>AUZv8x~I3Ikp8r2!W(acbqfatb-3XV-93!>|ySXg(7V6!HUJ1mR#so*j=qg}M%An=kf2i=t*f;?Xu=?_z)fPnB!&>@?iL&Bebr z6B8%)b_;U@|WYWPd24`GC!)cKsSq5f@7}B4`NbM2nFiH zHr2krVb_}VeYHh@KQ?{A?E1b8jIhgianzFE zb&qb%)4s|b8p+o%Kk9K9jN)mx8V@84yolmps$k15xL+@YyN%GjQmma@ra?jF@W5>*T|E1^;OxS6n=ANFBb?ai}S zDaQ@+jT@JnQU^7bz(Lms}qztI< z;>gn!`Jurv8QW}V_paWOV2mmd;=lg!uJiSr_XfJIuO_E5`rR5o|8B75q%N-ow@n~l z)LoU+lXtY6avX7|vDjGF@_i5+3^YxNKf)6+Ks|0@Po`HbG)MzWj`O-6<^pmgbUAw& z8Go8;@{`nRvteta6^J>UvSQSez zk)o*9ax#Mcv**34zPD&wD9}5d@SQ>!Ce=oZQXcq_F+Nar*>d6BM;>YO3gHp;>fuVT z?^xZw6N{vYs?1wluJLAzaFWBDx$5p_ar<*f0pM4m`v(Cqm+UX4B}ND9Q`#{M+7RK} z1fnO2#>0@E$J!W0tTZz8q$g$@AULF?`Cawu_ad{d@7-zh0A#*mUj;BBCP#INIDZr$ zp!=TGAH(C3NYsGOma;bc!R^JMRF75jI7LMxD;5O~eZvhNn-fs@6= z2)bV(`i zrnoNCxNzQfo@MQ>{uZDru|8Q)F;LHBK|%ptwxewYqY_ee$6vC!i1VABzb#~$n|l_H zHru^Bf3{SG*XIO;g-z1#4dO{h_A(6D=Qr=?sx8DnJ?AUH>$|=~!5uxrqVBt1i&~~R zl0gHwt_;KBFXTRm2e>4=cVy1HV^SIk<53z}TmGLyb}|H_#x4(e7r#jdLuexFLgh5P zrfOT%&)4P@2JUx5RJG_EGj#(^tL5%4C8uK!jFiHJG=Nkppu^{Ww>;jc=d!P;x@xgl z+2tOCIvZvngz@$Ijbq|fud+&mm=r!*p4}aU zq<7EwJzAbN!ScaWtjFT-wp1^%bpAF@;GC__f8Bh ziS|AnGzdwLe<3RaYPj0LAV(yo+RoKpoVc=Iv?ckap z*I)7w*h#!dDifGs9o`-8s;LRBuPuy@>y+Yr;hjXXN|`o)L$rL6+O+#Mgmk3ogs@Dz zEQ9fQs)n6^;mSus_kqVH1f31-0NxrQ_20b!j$5V>=3RysT)UjFRC_d_9n-!puWZoL zd@9>1>bI<}R?H>FPB$42RezpGcRXy!z?;3tejk7X-V3NJ3;B|x!|m8u+EO|8!F9j5 zH0hD?75)CEm#!{%7bsr$MW0ZvPurdhOktz?{%L#3&z;uby26hGN_f}aR|{_AKV1Qe zWY1?g&2O|4lNsqDsHotIUlL2;Mge*EFw?1}V9p16)yFRSluvVEgfHlI3V(>PZHbzI z%OdRVpsC;c6=6+uo4_U=sZR_=MHk6-eIaGABN zp&LBErQWtYX^n^!zW3(F5AOb*J*Q>qOeUtXZP5&%j70|=e` zml7yQiX{~hL|Qe8wGo%qexmOq9X6!Xb)D$^3U_QRs8H z;1w2jGfNz%q;;*TO);HHA}o%1UTG-4hpz1c_vbpL}XSMygH^)QNwIT&CYBAYw zaxB=w5#n8I+ddVll`t~d?OKa60nCctfn{`wrNf8OOm1E8O&ljNjRfuUQ5q$f?>C=b z2#A(wFApio?2wa0lzkPYbmkAHsuUlJbFkP|qh2wXKZN5v;XAaSN{G;DPL|Ql7 zTDvg`OoR5J@PHTH@9D8b=pb-l3Du2sG{6u&tN3op7hBp0^v#iWb!||;9O!}7Rxbf! z!{zxNfw*4fk{UjD67e-w)4{h^chaA)`3p?bzd>-~coQi$VDJ(v?nW=EZt7#iA zpXxVSDb+1G8c1`qB=dgL1w(YL(RLC4V+@lR1>Ofe-as`}b(ONL&F5(QVHMwy7>svM z_kLCDvC$Ok0weP!>H+;dkS=$1kv%&`)C5=i!nd<8D^I>J;n~!Elj=Lq2Y-otHSYC= z;wG3&bEZQUL#DEj9<5Yeg^O!w(%2e-c8o5YLB7S8nBzFDFQjxO#RZOj0>{PJ^1EjW zCjgj<3#|w)--;9T^|{?nlRK?9={WN(ZO|fdbw7K(6r%E*QLFW$R*mguCd<3vY*Ftk z9ZG&rgy+|I<_kUcy{VRXJs*pJ;h4%=49`$K2EJd7d4ltBi^lx&jr(WDT83xTRuBFau!b<>Z zgFd|2>*Hjy53LCACfTKMYay~%d7h8?ak zOYm?|7C#<=qc0iWtdB}yh%9!og!_2T|K)C`Ji9mZC#$P#P9c@dzA9X#d9K~*;*~%; z9u0xoYu@F>udTmVCESlz?jE&jER~Ygn0A2Wpt>Dds7?ey_}(}1&W+ewJ*L}sKhz?( zcrG&N|59KvT(lGQ{zl8_SJ=)HOpJqTuR23jtZ_O(Nd$)jF0A!xZBjfR#%&e6b*pe+ z+Bn7#4LMhy++fpKHKA=~dHI@SfzMa}O{uV)jkP2mbN1NhxT0My!xYFfUtf2d88U#9 zH`=@}Eps&MdLm~{|I2BQ#jNi=izfwgjCQHJsyX2*0KU?7;Z$D(3Vf_N8W9F_BMY+n zVnHy@4L}N%#p*b zQ-W~#QTc6JgJv)jv;hp~{;SJ=kJY*oJJRkBNA$f?>%xyKAu8y`y+9pzH_$0%^~XR_ z@>EL%bi|8398y^Kf^~p$`sX`ss$Dw9j`GlG1bxTt!E^`H777ww6$@8!kIRp2 zoJ}nyUjGkgZvho$yS5G6fGDMaBHi6Fbc=L%jC6NN3(|;4cXxM}4CRp04BZ{l4gWp* z?EU!c_uc>Z{r_5{+zZyMx#zmC>x|<(&f}bfTFxi2%@P;QP-;DK-W}JJp%{fgsUTD1 zTDp!QpJo;2fy!u>A0JkD*~gX0ur*CB!tI#%YFfkVfCMYS36t|)BdcKnkzE2It@GUI zf~&HDItl^P7d}iqOr0}j8otUXQ8yv=>4wu`YSwa11~bN@R;}!bjuyMS&-u)^H-YP$ zEt?EO;6`UO&7p0wTYz;+syVeKclRXT`0l;A3oX||T1XgYagk0r+G-7r2Y-{bYAqk; zyW^+vzbh=(h#tmB98o*|ah+(mYDFr|Qk+}>C$Kg^5OmQ~SZOl;#(qWZG~k@}%g)WW z_BE!OrCwP&6*<_=l{t$Mw8kn%`Q(r+l|Cxtow~aFM)xb^Ch}&`xSoeeS06{v9VeVH zSIk(UspZsOAk=HV^@EPBG^;_mKw;qgLo{AYcExa>Z=i+uVOP4pfH2b4?n9bI(ppoG zVl<}^LMu^|iSYI+p};fc1#{`MM4UoWk6PP@ynN0%QiFR(uas%D$7x4M8agE!HFrf@ zuixooHScfeSC%amlw`_QnFuFuxzYL98UjW52V*#Vw9bcYk;UWw+>e007%mCmQ|HMj z$expW7WH;IDF}Y6OVgS)vAZcBuF)F`BhlB*2S;w6aMI!&F&>ERSwN!(; zc+&IiChT}}xr^^)=4abz(Ppv3?X?Thjs;!m5FU3`W^M}W%+cYamv6Ap0okOggDIvo z|RYgZ_UtG(apO!GW8zD*@;D{fb4v@3Fy4p{$0s5kTD)Tak)SIgrB7B;xL` z+Rwj$cO1lDR;Ele$fT}m?Ev7GJ^|{j@!7_6f5j$!dq*q&2ymm`GBEEFiRBj~kpUV+v(Uc9{8Pb^;pf~I@5QsirE zE-w~uEq4S(vL2nlm|<#lGA#;-k~2cC1ilR?==m=DPdOkj_^;w5u&IefNO-fMghHCFv%FhAios!z_TLjhMA=K)sa;V|C z`sqyIp|Q3}AOXr>hb;qT&luuVk@ETcGS{2boa!;>+p8!WR80j;^_Yf}v0Gq7?iEdMm&L5@R4+rqO+WKMyx#XZx|P zvdz}<>nf{RR|!ebYZFav(8UO9;fh*=p~g)@ZV^qbnPa2Pwpmi+$&t^EA7Zs#lm3H_4P@m&;5p2X}Xb9W$nJ!ugqLgP%6?1T&28tkKYOkQ) zeol>kKV4u`{3{n9j|yVx#Y#{2gzKyISl<^#+ZS$(B{z3B53Z4jrdnn|(3ssb#Vi~np3 zmb|y`QQDWt?m^znc|~_IJTgqSM_*8{2iP@^kcgRy>ofi=BnGK9N{{2kMx}zNvxInM z2=uD6m*0H6h|Gzo#ingKCbsoMiiLKoX(cyEf_Hyg26e{z=duHB^1O=&3kyKmCY}O1 zoDfMH;2^3uB^dxoL|K8PrlSRlkSQ2~*K^i8KUH?<`DKMzIgKT=ocNS+iASmNK%-wX z|1%oF_#KU;)dh|FaF(!Xj@v+oHE`trch2^V)Bw_35L8jg>gAXNj5(Iy{3}p*tG3mg zDt5QU(+0UHo+McH8_a1#BqqFkMN{Pv0QaP_3(!qs*U*mU!Ib!~a8w+PnogN9v9NG< z7uUg_x#i2x%#-1$k=i4up!3Mh<`Qb2ntWlP|F*9%C|?t%-)8jbO|uUHe&oXtf@sjN zm99VCJ$6$wwZ)|dRNl!D95xF9OzNmyTuxewd-SKTD=Ka5#xC!WRKHcOHiYebKz)uC z<2AX2p{b+S>*2LGLp}p`=Gd0nJos2O)BQZkCc=-@qP~YN39BR+W`~IY2Aso!a-&aq zY5fUPT7R+<$m@RPJ8T(h#%}7B9R2TefEM}=YLw6w6c}{f8=FrSAev;k~o+Ex_ zkh|-3Gfrh~5Uh6a#$n-`AQ42JvRBQ9)oex1MZ2j~m7o;@J+A4`vx%U{E9u9z9?6Ne z8Jtd{Z@p%gc=sKu4kOR=U@yjessg%zEQ!Li$E>`kriwFj(9ifC;BG=EsP=Ucx>TGyn@&Rjc>R$Ly)4E~OPBAxzGwJ!8y z`pfn8Tbu6mPsizbSLt;%KW{?u&$YUVCA^4O{36|DG#j1pvJr=jg>Cl>0}R0>S%RMe zdTF&ciYLUac@%sj;bp%T4_EG-yRj|n%}wJc&}(&;TqNgJwmvR(qNJ5=`R466P|mWl z=D|E9#%b;2R zwEt+Mp!b`+2?ra2mp~L+S>WS#F5^NpC_INSUWizYi-*n0FZKQSt1&nO^>=&R3oG*V zM>I*-<`XDeM32O%&nwxXjt&5h@ASDBJvTw&LQgc`3_3ilVKDR{HtvEt!#C0?Hnf0e zMiSVDMRM6}Yu|?kN4g2#pne`H=v|HUR+S9PlUx<@csaQAAmqlmg?#!>}Sd(EwE4> z3cNDQk{l62FHG*!U0xt4T=bdT>fhuE4e4RTV#rXZXTK5F?pp*>ovX2l;UA~Y^=!`l z_Ag{AKBjk`uV;Ntha(GXC04pGWcKEo1B?)Br*~Rr!8R{sZjX;jkAITL_88H=S5c7} zJAgvIpUo$3gSz%!W~g}DcrJ%djD);++lT^iVQ8?pY}cN7oJ?@((FALv?y%5oURA^c zBL$J|qSz_`2#sy_J^{adLc(We+CaXkCQL_wyVXl60aCBDc${#OcB0i8v%OZNBUtKw zQE$=St=BrfYj_Qm;B(*w$S#EKZksx3{^DK54Z0$JULJ5s%!Wfrh=t**e%E6)n{M1Au(xZ}WD!0NZ2B!(n?W z9^ZX|uP1&4jVOmKNy>U!4q(&lp*|I)P31qf`Gof6kgW__97;)*pQiIN+LkQIfN7p} zkljHu9AI*mCxN4F&M$ilhB~a8XA-_Q$rB93jz8Ev^JwT4uhGbdINw=(oggW>i%07_ zvc()o1DpRYG@b=Rc9z-kc%?KTqs4tw+Zzw~!4PO4AKcq2S;3+W&8i3Ht7( zalCaJFYr(mWkaG7=IzTZb3hf&SKCeA+)+2m%d(y}xA?J4+@T<^HVFqxGm23Z(4m_AL?tkMNFL~qr#Whx7m)#nJ))lgG z=F?syssIjDg&sRm%N8?q$DnTcxSASpqF$6cg)J!rp+NUQxeOT9>wqef;)mnJ>j#Mf zzMmG+WCq;UJrY=53R+DydUmXKlop3FyEkqg6AT+m#tZ{hGNl?VEQ}bA06y+-FM~9m z@&*Zv&lhX6u56aLsxP$d)gd5G96JO5_V0euNu$w+Df5*M78r}cnZGLqqCPfuPO05_ z8k-e%eES}EY|ZDJV$1_EscIV#q9`m1R7CXQX2?yW-Da;)H%)1gv|mI7rSqQF@n8+$>z+dBF2Xk?f|H;Sd9)}0)Lkt0O70N*z< z*!L=;v{Es~Q-b#8%GVfkoim*o`wOl)v+H*wT%-gnt_#b-pAtdCsWu8H2OB%DkK6g* z7%FI&vIF=j?V}||6-2)`V|J~#+cAt3PP?KLU>)fic>)W;-GLx|!wA1<&Q9xe;k8z} z5o_LSU-uw^G3DMJ>ZDP+kJVPQK2K2HHA)Wi6?5~4=xPhcD6r=FIoug%0eFHXj6}Qf zEGP8M9T66pjJxh<+TM4+P87y^$Np3*gZkSLJ{=2<(WuBHcb;L@K#@iqVtHQvge3{k zrqkyO&9K~g&rd3MCluu;osaS5qcuGopB;v<+h6iosmMdb8_mr;H$Q^;78tdXjuN$9 zLSf{%=!g_Iierygv=sTpQX9YOX@u>-@{r2k^YH3kH1L}Md92}!J!jiiqA0?FOe>-Y z-^l%@#*gGOuIe%)dks^Td#0;`AgV7X=*ugTZ0@0I)sQluy^!h4lQ&W!7cE;G7Zya3 zbcR#Hv`O>3+qioGmw|}**`h(9K*k$5D>qO9-YK`~-(IB+^Z~m3Ds=e@#Uh$V8h4aR ztyAh;e@kWoXIwk``Ahwy5gDjH#-H{i@6FsfBHU26dC(ny@ZbD(lyY;1tzs~P!x_liqF~|4E=(SBg=A*zbBR!SOkO&zXML(<`GC+r{QzbvN{op+0iv6)vZBo zcTcDhrC+3ew``Ul@^jlY-*qu=UqvvjCJ-d>P^>SL10ovQXia9T807?>l7lFCRMWKJ zQzT5v1xHDGmd@@QNX9|}n|Z#|t_JJKGKxlYz9A5>d)+xBTh4VuHgHFE)QtKTm#m^o zdnFdWUj^>jsoFj>$`5%pVm7FP=P23bjYu)Cc9L!Cc$k^{L>`(YD5va|qB^6FfCHG%O{iNeXaE0T}p))WP6luOP&uvh1BH zs>Q_#z?@!T%Z|3`1V%`Z{2g`qKD7R2 zd$Dzj$Q`{`hJz#1u7wOCz;Cy(j3}0=XtbjKD%-I6<;A#`8VHGF7UtgFz4f>1iU2!l z8h((Qy_s~gcz`viBPzmQ`LBzZLpW42q^o=}4n6^^< z%(l2929Z9aTr5d!FB}196qY*G%B*#5Rg!^!lr8!fPQ>Om2{>+Fcgyz!c2Rw?K(&;< znbou@vzTFVrFFVSv0G-=;0BKGp3P2=4UL1l7+SAo5K!?lc!Gi)j`}&c3bw4ST+bR} zUC*}m^4eebgfe$ObPOGE%p|MAj2Utw;53j?tqw?CW0<)ZoDWoX}T=^p&!{O13*6UB$|aJ8$K2hnn#Fb z(4_5%RtfRf;ve^mY^eK62ProM)&5YeYq&P-C0EZX;%FF?lue;;(Nirx;4HFoktIz{ zA4<7VPOQcHT1==qyDHDYI74O7e^qbGSS<)e9#Hm}_?Z?iG(l(DU4R zwqatpmqA(%wsr`#=Z$8Wn#X(Y47H42?4cN`mstX#%uJI@VVO^(`oQv9qE!};3r0Vu ztuL6gPP5K&?c|iAr-n87hws$jh`H^dsxAG-vaMII&$||{s(@6EJ7LsT-6j#noq@*u z3*|XCLLjZ&6R!11ia|EMirbVH25qLsP4QD>(g>b$SZ(E9wSLrIWCDgRHzF=|!8u3dt7vLrZ1XhU$(DXD#uX;2;@ z9l>&iM!@mn)=d{NeP<^MQJLYXpG~l2fa+-H7vWY_PNwL(~HCC;pWZtR1cGKH5Z^@xdm%Pg_p<1$LM5q(C9a( ztD1WqLYjVlazUX1yGylR%^@hgRlBQbl=fKcq&l9vM#a4;fR?*8zInqM4wb>19*LCw zKJ`HI}x;2XD8URofc9UXSp2yNxC=GX`%}q5KBN>QRv_sae|nP z7&4bC0*+&g=uBC4EN4Q;C8&|3opUjNrJUk&1URVVM{CWzAq7e;qqGwwJ=Ex$rHXsY z#?5@mW@AMqsw~S5gq4HB&G}+y^hU469NK(ZJz&F>Pcbams)hoqim4@@z&l0o&67?F zbl~*G&9a|eC7aw*I231_=G4kLo4f>1k^HzRzGUJBpvcWq#|}l|pEaK5Z~dGhM~)q! zraZ`GXp6P#AJ$n9scucQs#ah5t|!J@q*WVp*~%?u#5~8vugT>-DhLEb~!!xXzUW zr>9L9tQTbMpdTe7b2TRckdX@t1i zyNj822_%WilhfV26oVX#HE`!r55-02+pk5N_7+Z^w#wb(a0xS4RxdrW8NnK@_O>lb z;`U0xdA7|^cyP1^*vx>nPQI8Xl* zBcxWM42q#YutajWI8Z1Fi7?%F-4n!Qv^f`ZD&k)+w@@PJZEG&xTW8uUXPZwA4CUnFs#(Kesel`&V z8M$OlRFwGNVyTrT=aq)F*=>iFT-UYR3v>vvq(|?SHgSa*H8Y8kUw9kcdCDqOo5ji> z!YZpgZ{8;G7~%jlH_@1B?I&Tc*i!f|R#?=>i_~9S{H!zxTB_1*pJx>h6df;cRfvp(%rGmU(HjhNGyfrp~-K1k+TSNJC%=CEa{!En1i{~1Xv}M+-cizKrN^N)V_xTQi4F? zEaS8JrK)>|GD0E}WSBWVdRO*8I`yn#9>*44M62~>2m#ijr-J&dA9a1Y+ENrrh_J1@ ztx!m-(RP{NOs#@Hjssc5V7B38*eAJX`6kluNy~$fK-g3^hC1Kzdj_Jd2EV76G8y}= zcjEY93$`!9tjH9y!S+LI9&Xalaz!o=>RAjMHltOMv1d5q4C`OmDO3*|_Ol|V!3p1& zPRn5C{VB=9z?*{C%5>_%^oR`1=D>&uXsQ?S<1bo^@#DK9UcfNWPoWmST6v&lYtyBU zZe|oSzKwpWt=CCLNU_tn4zb_1Ug=Akv~#_B;8W+=^x z=-8eSRl7gu`aZR9S-%PvJs~%6o^;&re{vk521ao&zC6!wE3pc!PujPRLbg{?*WYto$J;6N2MhwPgATN65 z9O-lAesLIdbWQDQ)u9H9@&g`mn<>5YbqBqiX7wg%F-ygFo5>%7a6+vF*3uk9Y$KgH9$8(1!XYI=Ig{@+fB#ioWKDD@2d6ADz{X{i==qK)}{taL)9*Yn zLoM&rahx^P+LpkvkG0<30HTN$=+@b;`~GZ(i=wW24f!qrqIG?C8*+#02Z9)?%wSr@ zRzG?HUs7rNodgn#0I^fpNpi@K{O>Jl)+2U^~0*Vjcr&==* zC2gL^23lvOcDZLrN@-?LTVIW2h_X;C)O}sX_3+xi$^)p?Yc}N$o*b%Nk;L#|9G;#2 z7t^#_qS@wcq7eS=w>HmjHU;4n;wzulzPM_7mQmj@pd}w2Xvu#x@^ASZa{o%8pA_gK ztr0ddHV^^j<0n*ynkI z=&d`=T|}>OwmU8BLEz$3V?DoFTbyVUAqr03+uN(8tF^5Jwu>AuR((yH+5;VW$w^4gu#h1OE+HSM{&78q*wgtyy~yf4L))4+b~LD~^S78#*6 zT|8YL>e|938nby-i6PU#KFpkIHTLDh-08Qa5_*Q#_Zt4yvG%S&w?cM;VQ(X5yh~)P zyIw%;J(PKgZ*UmM3vMraWWVPfwYRj#b!PpbMyub z45cf$C};fg*skRP^3q$!2C=4NU0&lXvLqe=$gNIc9IoQx1lM`j%;%otu<%|0*!(jC z&vc&CXdC9QwijB^bt#mvrVE^#s!eOXq2&Nsl%Fv7y$KpWxpB02Q|mX^6v(D+VYmCq zg+PIE#FdZIZ>!}ARBDm5Rm!%ste|MGbaqXtcCVUMT}|u6@osy(OH~KhS9F@rjKzId zIAW`3dt;x@Qy+S@4hGsVXU;3GkambM&SSUSoFd?`im2tBG+k$04#!^G^&jU)=Dlx| zJl=`pY}HiZdI9WNe?;d0ej5DkZb#KG2x4g{RwbC{6de5g{sWzP{|mNUH}!}!`C{H5 z!vZwj_4QfoQ`#DBI5yj^Q_e9D1!PY~ezX}z;)t{dieLl+EwJ?=htLxIBp~lHKxU#% zS@{XH$9iat+a-PjmMT9v~D_Z zZ7A*LRVq|@t~^#@P^g~S-9kBQwf)%QvElCB_z)`pwTKl&yu|JNCpr$dCvmYx^^`@A zN;B8|Y*0Zkg3lSUE-FG}r?|4qY^v9gq+-qpfRrf5Xz9?;q|c44(wn(X)5W;+w(VU^ zKE41Du49W$;<9y*Szq%*tSC)2gClIGy(#JC)Kt<5`O1IR#JIRyz>% zI~TiSTEANyoFADCd*-~(FgFrum8UXG`=)ZkL*uwNY-Mn@oPO;CfCxcOtVJt5Muyrq zHZ~)TroaYOWeW}=XeBm3*009fWf4Psvhk!Hu{#^4rNuf4nQvcS4Rwe!B&w(=V<+$L zQEFeE*6j<%N5_0T00zT!_-#9S7f&JGTf`Fv zusSn?GtKHfCr}!kFIPUU?EqksKW);g$I3}GIAKYBj3}gFuerW_GRz$GNUlJ}HMXTF z3U(!qdDLJyibj>Tr2jdL4Fzx}78jqxO5x4koeWea`@>R|iLlMy7*L7i^A1Ro0PBwdpV;hHPrM6(VA7mp#aB4O4qlL}e-W%%n@saYGvmFW)V2#63oV`Va-FUa zT@#PY?XiEDN&?#X)hP%Q?E+(szug{Z8klgOTQt{dbh7NY_-0NQMq>p#WN1E|qU}9V zbt2?zaM%+`=622k8XEG7^0fGlFC8u|w~bmSNW5se=22Cy>to10FPZQ_wtYoC;~Ez@ zcHPw{TKg}=JV2>x&s2*91T|&`Z9=TrPeqQg9f!GUb}S!CZ%<5#L(CjJba|&#O@L+w zt!@M>%eQB2O=Hyw^gl=T!z&Lb;Wfp*;WvC7?@CA-=hrMZX)Iu^v3mf|k`{lsh0$}Rc{_|D~m;rR%az0a6U%r)|%uL0ME}91^c{`YhgwASycFUM`AK7|2%N(FzZ5or(~ODyALae6-!!0R(Vz{-YRkVY z0qy^)p-FOu@g5l%rOY5xw`(vl;&Mp(q^iOq-fz~OoSa;O!^PH?^IbjTDOr*d-ccO4 z(@qxY0VCt9^e18c_C|&D7I?i@9-^VkH9Qnr4*Rg?Sh%hPnQx-4*8}X@(Sm}b^d!8{exVYBPw zHVcH+CWdM?hR%&UPT1ZXMW8jHZ2ib~LT7{uxZtoTjShglapHWs1|A_0=h5^ek`wym>t@01f^S2KjlA|NfZY7bQS1 zszYbQEuaTIGWd+{SBA(9XTx(_N*5vfMouF9&0>XTk8ZyJp9TpmGGbbpr|9G%EYEK_ zJD8Poo=XtZMc~#Y6^q!Mge(o3v_H-#PR0I1K-p9}c=_7RLBj4SS#L_<)>!^-kS?I| zBndR=^sR;t>4kjr)Fmrf)}GBq?rz-QBAjKf7#jupZij#fA{U!NCS0HgkYCv$W??A? zca6tm!L_Io z`+jRt`GVxf4@gg_-)dqB^jP1`$%uYF`s^iJV?w!|pDiaW1Tq!$7hxv>o*Vmgnp$!o z@i+Rd0A3FN82X#x{ifgD_457JcrX9FDd1B;K(f7QfT4uq8!4zOOad>bd}jxiypKH* zgN7K;nhcu#H%a){MFqlrj&$&cajDqXuD+jmzOree>;hGOg?~zu0h;W;lm)%ffG33} zk@xUH+l%+T9g?kTGS&m0AvIRBMw@xM?TH%)VpqRJJTKn;JEQ-7@d&OY_zje;jtqga zqNhKAuZ@8@uuw+Z{cr4P5Ec#kEbWRI|5!2scCz>A$o`Ia#X_S0N38GreE=iJ<#y7l z`y!j3bZ`JyLc2!?-=cuNVgM>Z`V9h#!tM11{ItJh_`?0qCX0LC3viHvhg%XbeRQC& zzoca1;H%$fd1%oL`E{2e(ST+h{4c*=fkeOct)??XShbXoKK%dF>LN^fHZ=avW-&yH zOow*eso&?s=RZO&u3sN&Y>i2s0B;6)20;J+jnpmrOZ@FWo&tQ)^?&W$<^NAR7cNUy zSqs-ER0w2LPcr>ENEGvjK4E^o9@WzSb_Th;7JWYd)inEmqYn$Lhp)mtN8raji~{(* z3$T;J&%j(AQ=J)_OxMEOZt72ephX6fz?X65DEzBJXq)kWst`Uy`uh?7`&j}Pfr!6W z?ed#ZGcKOz+AlpLa%-}QE!7~Fdt112Q zuovYxQ#bcoa}U?a_b*|+_37DOnr>0XNvJHJS3d5BEer3ag80=2Q~MrwBYZ*i>JFf8 z9|n|P#A(9P6k*ap3<4fV<(Ea`v{(3oJ3xRl@}QHWdL|{Y%bviLO@I@A7)3Y%vz6)o zQ1228SRoA?!apSf038|0U%o>_&FhBc|4rsCkbw0s4PC!Zaf+Mc^$pa+IyT?PC&JtT zRiN~lD}hl<{vI>FE|t(3S+KkNY9X7Ti@~0=sU>#x4YA{<`EASLm}?qO#Hkn}h2tW{ ze&*%v>re>2W0L3=^VEgj?c9+nD?Y)b=cMP>%&X9=(gf}p75ELiJWB3Cfk5HHcZ=;} z9e281&U;BvV%fPSxFj9`6dZq*JMUjy(!mX#)4DwXztsiDOP} zel8GA)q1t|8KoPoQb$wqeUW7uFSDPZAG))RkB{T#P%d$&!sGY!aoU+NEslFj?RD#} zl}QhY6c9)2%$WRjqm09`HEdB&-lt5mJ#{Xd&PFU z!yAsPz0P}7x4jRGW=q`<&Z0|eG_x2y`hh*KK@cT2d~1R!b9fW#6%t_@-M*C7;$`f| zD28Vo-q2^p_iEnl78-o>;<^o-oLF|3J-?Kv7mytdcw7~H!Q2dh6}r}^K2>A+COa$Z z+yITj*ACDr&V2Crkb5hM-^<%+XHt+tHpL-o^R>9RxKfVPYbsWy3j`G0tY){f0#ZzB zt+<|;g9HoJ$J5R`S^8pOJ*3DF7#fQTUMg74w`eOPnZz@I`5KOgC5*JOf&n66^S3;o zEw+LeArE)k_~wBWGVmmb#LW``DZEg%&srT%)3ruu4T_0HGI49HZaAdZv`W8`JQk?>j6;Y)M@!Y!nqwvQGKMy=l#0cr<8JcRk5 z@erf0TYNb^nv6snNoEWn8A{`=5&T_LMIyLL5D6mg5q3>@7v?$u-w31 z<5|yz%w+yDuZ8oU_BUTTj}S^(d?JA_Aww>>DgyL3c1C#JRR$?^PWN~}s_9Sz#0@K{ z?T} zh)JG_vnNoNovq_ z1E{skeHRj|O&bKyJJIG9x##N!Mby60yc?x+u>)6|jj>K>?{fp(zeQqEfDOF}(Y*fJ zw>Kk;#IeX_z6T6@tpK8^h&kRRLSWPbU_XNTaam}92G%|cv!Z_#W!Wiy1!~%k@#*Ky zU*@aU-uItIlO3I)RyL<>l9a#|svo-biirId+1@Ii9SxcwA+FP*~Nr6{W*;q(#N&5pg@+ zVLF0kp9C#a^f>@)LPqImtue{A;lZ;{9-VEQJc7C@VO z+9Xr8)~T=+1)|`73R=afPo)PQtJBl_vyFp#E(%EIyC+|tc<)Gk48sP#@e$USV#iN5 z%r!L}<5+(-C0+r_%EOJ8zf|?rl8zOGp8fIHKhhFCxZxw38VB~lOuab=9;f?c);Fu- z?Q0 z9hu$aCfq%CIf|ccKH5{YzNE2^(ADivsIIbE6sk2*tS)wF^{l?XNa{vwp{OZszhK!~ zD>p|6+t#n~i}bWkeEz)sc#EYbNy4-FrR_UtAIyAv|=k5M9_br4!jek_v4D3G4=I3N*vrKb2S`&|0 zLb92C8u(EF9b;h|5dtOFn&jgmL!`Lcfap*Cd5}cKzF{DrZtU!=2kq54)zlD@(!7tK z=99zdW88KG;W3G-&9juc)fi0$Lqk6$ zWJKO&mn11;e9y%UZnbwJk8-sPo>I8nOfFLd#EfHAS6{kr?QHxoy&Y@y@|rS;w57&+ zc6%^_DN{pbyOuQAL^m%MhA;XFVLFBDQzn301jF^3JF8PXJlN4>PET0w9U=THnFA64 zN~{MlYGq;+hE(X~${aOYdqb7almARL;MvIUmjFAEN5?-8E(jCClo?QjKy&sGDO4#J zR}^GH^}yXzhU*$qjscIGR>VLyW^H^SGYZYR-G2>`N?-4bm$bCBoKmTYw_N`*Gb03c zKk)l@mdxXKfrSh5p^#6`i^JO;GHs!d8Bj{$B)~^If0vHVUTIM z@PkJR@R2eSadPj?_ZyJ*ZW2vQ@<25Q;^`m#}p1$3kF>P-s-{Mw5KBTuT8&ti{e_R5uOLmq_l ziF_<2u^5{Tz-s!Q`*hJDoPjY1;Scxm!x&LbuMI!B`i5r+Z(?8^%h%vBt^G8DgwJau zZ3cYYP8vlIwa)TKHCrf<|CSQJWCB*JvZ~IHI!UWV%Tl$uZ@R=aQo3uCF8M}{I6QAE z!__acIECy~HKXOe8M5W+gNxNzaKjjYE64zceYWcLg$5GsL|4t!nmgEH7^BO^&(n+Q-<7x;$>ntGUc!A0V9{PT#dqB^Al(NvsX(1|2@2o_2_h zi5_}XJ^MjjJ)adBcR7@RVSc_%!4aicZau>HV7VKZ*S3tzmW}^~P)-VP$h0|Q9a@A* z9h`q)d4Lt@6#RAgqiD&9Yqq*nW_ev}((V8EtoQp9_!k$HKamGE!1y@(s*7!jq&F{v zRShiXercrV&~i?JOzV`!30f4OVaT6t!n$?JqzidekVok}f@^AOnmx$R!NXHflUT?H z>Ue=`r>?)ub-7ho3NrKCdrHB7bIcMfLadS+gz^0ObBQRBlxmQ%b(6bQlm&kN)0a2w z2@ojGr_BQ8LQ_C6#_B}GN2TPY_4S7ft8Qw@bn;QnItE5@=x7`Iqu}s+V1}O{_0KfZ z9P2=MJg?>4_e+HRuYH|%4jhBc;`~m?unS~4OAP71$h>cG!?Cbo4eSD&h}=8BDZP4i z%W7Kh#~(7^ej$Y6B#L^`sFpo&|)f;<@(NBWuopG#>zl=n2A^6icwZFV0UDrotlV2O=F?!WJWP-zE@-^NMgm{bu#0958hI=fLzBUzuv~1*0|2P+NE01W) z--iv1DG)=JN$;xbg_eFY$al*mJ5lCWN!Tsec@A`qHJ+C;IliIaP`YrJGu#SDEq5wt zD)~Ym?BuWk;t%^$C7LIFCcO}PmhDn*q%azki=L@g;_cZPl(o5AoFNv-vp?ffVn zVeZG52$p{*UM;t+KAfS{1^A@72?<+uLW6sK!n|17ckYJ-uc;Ty8yXV2!sfLmf+&(! zAl2q?Hn&S#ovv_rK9pfpeX$!c>fq-KArYfwNW68glvYa;&C~DxfMoZ7Sz1lD(UXFs>=pbP4rp1hI< zf3w1Z!v`wFBu@c#`lG2d9)tmK*+;JEcTDoHIIM8T#!gU`g7R8z*66Ae6B8dA8a+YY zo}4yNk3WlGi(mLU&G9=RsMj{6PFgWeTpM57!HeW&iiwjI($6f*mBJ#IKx6u4Yb4$H zx)Kri?WBRB04V~s?*u_m`_RMz796X_jCb~lA^h6?=p5JD^2^3iQa^1e z<;Vkxq$8Im6UOJi;<_~17lj%Z%Q|RfVmeE9{_;eipOP%=7{q_6WPm-|IHxkcmI{bnrMlp-T3>}Zt25oHOwDRzf zP98{g)}Tw>%7v;!)T@R=FXhHZNAoOeuZF&PKdkQV{IGLze+kIZO|s4AjRH^VJd4fv zMO=7_2-Fw`@n@}6@+`l_7Fd>(SyYd4yduFR{6}g63W}(k1pnSWVNv>w4LE5T{F2rWRhnXoiYKRVto)Susu;aA^a0-JJGr( zpKa#yM4A=Agg8oDT2i_`!zQIAJNP}RAy5S}ixP$Dnp``p?;wzm0243^ts+jfcEA5Q z(7HI0)M+3cI!8cbgGx*KDUQ}7#w5J;ks2eEAGcw&)|Cv;CbaWnFGJwhxB|co9tM9T z!`hMWm5SHxTP6-OHa15Vs(28StzWA?5rQCg&~xq7xdni}Y6u2@hcf?;X@Cph^S{$9 zu0*gE=9g#3Z<(8!%H46%rD_EXnTjeF(SoPu=tFcmpf6sG`qjpwt(HIE`IRFAoZAWBFM zi{O>S(}<6EJo`$vTkBC)d7Z0^=`SA*(CPjaa7DOcSCJ}|dV zppXAr3Z4hFUl~df_ioWk`3{i-em$*9Iw1 z?E$Zk1D4I~1;GVr6=Q-pR-gjt=N|ZQR`#E)H3ALY57(8C2ZT!JRgLFUUVv z>7Ac|4xl9UhEK?aigx0Z!CXtyoSn68*?_t*i0k)iG`|&SB?xLJUBo8Y4M(w*ly(#? zh53355-I|2DMw}iOFBkQ*)n=s?U7-24++6lx^G&a=%;ty=wFX!UP>Qc^a=KWzSt*I z5yE$)fG+y`Hq!at%yO^Rg)0f&Vlef%hF+Tzj)4{hIp61M=kDrCN7HvI@0Dsj(n#ZU z$4{2pbcRe?^X_i}iD#Nw>ZP|dUN)8)t@`A%YdO9vO@eeWZ0amkxZBLQ~K%7p-bQ&wv zRj~wN-_onC^bvcsUIxAd-RB(S&XXGK;2Gp>=b7mJe$noIEAi^ypyA_|pNzn`*0c?z zxHD_A{b8?-wn+aE6?HK>zMj1NG>S%fA|IK&)9K_KiptFWHP>oT8EWkM|1zk+h~07# zse4q0Mwq#lNTN~S)gDD!JOXnkZ>itA`yN%_OyRSFvz4ppA*OI~g8-Tj2j+ytp#7Jk z$Oh&E7l1bKfM%j}gkR{BXe0>&O3oDZpj%kf>Igan>aOv8^4HvkdidOiy?FhO6nM?d z%tF+HFaydM?mfDQzZlBER+1MDezbxssSxIO-@PPOHA?>O^7@uT%QM`c4Zfki zYCez-wfvIHBQ~7f36{9c-dh|1fAaGvg%RztYkvwvOIiaw|wGQPFVcRr$8cqmQBH`*lNq*dxaO-nswz zKk(5mfS~z?4NqhgRXV9#f<=f(RjxR!g1c62m;i2z62 z@c5vsn?&IAR~+NfE#3!qbHQcgFqZ+JHwO?>d==Z2v$;!M1Ni$9Nfugb?eXeW17^FI zZ*zw8$i#@BrYo?4XEvoD|S8UsheuRgel#uq4l@LDLM2mmL1B$?@b{5ful zkv$3?3P}oAJb2Qu`;e^d*}qIZAFvz{iliO64CwRispF4$8jShZq6J)I)e^^fO;QpI zJnIxOnGGZQQ2FOw_!JyP)+6nQC!!LxFfReN=mNSHV8V0+=uf2aZ#OSsg>)PYc*&YY zD=RA^zL=O8KsL89uQD^TEA&m`=(GVTPWIX>N<7K)%CARr11 z-60`e64E6df*{@9Aqr9ol0yt2EiE-PBi-E$Auur1(4GH#e4qTi@As`W%QfP1Io@-w zbDgvIKKsP}EQ6MX?HLK$1L5JlXv~d%I-R`e@PLQ?Ox;3Xg8U5%cT8sr42AAJH$p_ee$&ScDkaQ1Q(NF}1C}zlyl%goxPfM2z!80A$v)<1K5^vi}%z-}=?JVDU zpDpPE=na5p!Fs<7OFJQA_K$XbA5K`XL7-HuH_T$4wUq``7kpkJ=)!zO} zH>X~{OlA0iL@*BJmF(lE$-IM{V~uLU7SSrYujL*d9;zF{mCL-AF&9iq-gbQZeR_G( zePeR=drBP&Aj27l%;Lp54p6;PDKQ+=^nG&{#3;m1YZfs)L(r*C$`UVkE>1k#>EnQ& z@(vKE9~_;`fs$?wCg0h2YuS~I5mLs}Au5}YO)M$Y%Q%%wF%|~yI`R|~1)nF+TF@Xy zHl@zZo|&V7=(nH#DBjdTKqX)V@EhJ+M=KVaNsQ^7%Oqv_IdY&&A_rK%a-pPaZb$Sx z1-`C#Jj}T9WOzq>Q%yDbu-Ex(1A1-+Je#4ft5h$)Bj>vrvjtq%(N#fOs5|2XSan(D z{nCYyz%UVI2R+?TYzp0};(zv={q^AfenW9H0D=vGSf~2egs5*XZ|4;kixwHqO9GZM z*CRb_z7~{=3T~@Di$iRD|M|m5*vDY7JZ-SjCT=4)Y7yz@R1;(YvndNz(qH! zr;30oauBx z6e?C{+0?>BsjGonvi6ls{Lpadf1f}qy7xA=8pe{eNiK~=f~L3cPOMgpN%ubPclI+T z$qy~2mlh$O!h0|0zK(*yxJ$6?yOaQBN$ML_D5c($pkVl<)4rP^< zUsizrKtn^LqKod`?EU`as`t~=)8C=-ATbP}YksCyFg@;l6=tfgVem5ffxQEBpI+nV z=?uK5yoCYzaVKR}w*q4tq{x@h2VKk$eHcZ@Z)%#L5%W;~F!}}@rV&CeypN&ZKMOu@ zixJ-C6y3E^Nn*Nbz(thm@Tdu+M2q7t9>fJnYR*Pg%Q3L4@2N$I7hb5rQB1J%d#`!k zqenwD;h0ksFM`#tRwWt>9w$x6o~D}hgOMz0QltY2+*{QtqMh!yj}Vr3PyHyQ%ULEI zp-~t(7!AN-~O{j z|7Z7d0}~MtIS0f*oU99s9c!u9Dk49^z5(2s8FO0O60lQI=hkGOY_?t*yZirz^1bV74^?BxhdMEJTi}`vg6zvuj>XqbSnI zn0^^rUB0RGV%5rHXsy^7VZM;kIL`M`w>8Qi8dbmA@cwsF_4+KP1c>Od-3zvwK7KFu z7uB7w2pBIk$b_!5Y3aGzCplzH<_l7i|DjVmpt^avPIGh>X!y0FqdsC(oj8}b%s}!> zy0h4~M}Yv~D3S1;l{|l|o*|xikV>Sp6`o}YX0%xCS(Js{c=^QDyeKPji?r|1NHy?c zN7wO@qoh52Duw?H?uD$TW?$QyQTSwv@Ic75jU>(&s}CCsPPmSDk4Wy=^#0smM2BkH zqLb|pMW;08#{raZHgVa~H>Z}j*62EswSMS!E83-7c*>X=yU8G67xf^&*b<0(T4|%)9y4Kp7Gin=S z;h1~w)70r^mkDIc37>o>(#h<*C~=C2aNP-c%p2uFj$NZ(4^~n{_3vW9xTyXke6A<# z8P}iRUN@5)evusaR4t`=3aw90?04i?_Ne{)@}h999wked! zy1PP!pjr0IZP?%0`ky!8w~qS=eZHy5Ng2S?UBzE!Lntej1Q?tNJfT;$u$dF_`jIWHsbR#Gh^eoangyaNFL&7JGyWIav|J|zb>2dSEuEE9n!~-d zdgA0V&j;`Nkl!G|PO%$d%ci7=`^(#Yco_-tD^EM?S35zbG$%A`k8O%OUM4sSfoEEk_$PGu)~>IN zr{i&Mr^;VYXho>C5IzBJrsp)wgGK+Bt8>Hu!pzHHlr=4sA8S$$^!##)v zi$1g7)cu|OCO?0Pb}qhByc+HGO*$bZtF04Y>GHpsf&ctgSQe;*WK$Jr@Y7dT%v?Xe zwzOmfe2?WsDW2v+w~IC59`smI7O_ciIK%MJOF~mqbv+#^!sX@ABt+JO<}S$Fc8cF6 zQPrITW=*7UfnU_E1(P{8!Uyu=-x^ruHsVXf;_m#BUH8L>n)f3?>z!e3ZO*1E>`Z9ZE$ElK? zcZGcUuXINm0EAs_bHz0p1f6}L-vRQN)uuDT%Iw{T&j-VNm9tFQhO2smBk?EgaD2?n zVlofX)=KkKJ^R8uXI4a-ZNQC+0UQGXA8TGs)#jY&nk6I1I~;YE^h-)6jr&K8TFc$X z!6W^r3~3HWr(G}jJ4qq2F+@k4T5K^wdEnKAz763az8VICaVG@FQc9!~Thh!04_&R+ z!Ki2JQD;qbzd#Z+*?Gk?Db2{NL4A=*E_R!~=EN>K?9FTGt&}_;zf;l3>PYn!>UR#l zyF&f?I?oxAcwoop8&1>px!IgVRbAYjlg%H_^YR%d<`?+bmPvV0-TlHp&kGl?-UOtl z^hsH5BART|>hpQy^EWE7(RfmrremntNX}J4UZ(tPXk3TvTt*!oU6Kg_1e(th4%i1& zNqJV=ObzC2sgaIOX*9$A3S0}=vR@x=>In;IJ?&OnmiZtv>?esb*MR#JDKqvNvH-qy~<@+E|(gZ<`fBc3}%H+jh z2!}bBRboa!bqi+q>R}CtGb|aub({Q!n{GkEv00R1YX^27mPoZQ%!DTh%c%JVNl)oV zZ(LCFxlM(8K>wkAHB>_q6qqv2KN7kBL(i_lm1n;zc z{m_Z56Vhk>awSR0KQF?1Jf>zx_Xh>d9HftDt^LxNFjY@raoJV(}lh;@9Ms3Ol8C@`G6;I5lgf_ve@b&i!M?3j9a)Rx7dcHRDtAI?$dUypoZMNDn38^pH&(=o3^ za!;Y_%b)rkl9yiAy_Jvw&4^v0I_e~Z2x1yxpd&N|KPH2AJ=o*_y6(<>jl?^SlNn@~ zzuC9XNLbwb<$T~EwcS?jAtyP!D{YzdWX5D6OEi#U_3F@m&QQ|g`zvU9B_pMdAAtl$ zn0{A1+o{0vere&%#t;FIm*;SeR*uu>#qkw}N~olaFhi~d*ciYwgGZAzjE}w-Pyi05 zTP2XRPiB+OynE-bqXv+bgj;^M7wp9d6JYp97JuoQtky3Zpx8~Olry7tCBYuj5r zjdm4WK6%g6Z^C{Y1m1n=_>sEXfeqhJdM&FV;uNFgPDwnq$5$Vb?nxo?>jY1MCLs9OKmID?`%%PTV8=XL)%fjAJGw9RRzvj{rN8B?*e@}-xCFBzS=qgi3dND_M zZJNrrQ&ke@!Z@u1XJf#m30215IJqDi#wR{5kodeAuO`sGato3h;m{-+F~YW6dr}hf z{MD5omtv1s$SO_LdzulBTIb8QXKMX;IwdYo9N`|#4CL&a2Fr$OvOSeV14>+m#S)f4 z3{dZXJ@dH=^5ojbHkgdC2~jbfQIA|n%CYh;Ycy5NHei|%hBu-35`<3Y7GYIgNL6Ut zFXIx@Ho8)28$9po)WVY1Y*tW>aFwgyhqMBH>6Kl~gm!BG;#_zF>*cc&Ea{(8zB*N8vH(GfM^l&G9A7)1w+qW<1FA(^Mx-yhRbY0zm>KGg`haE%Dpl*<9Ei4}2YltOsgk}DkG`fK%QS=}6sCEwc+{KNs#S(=bn%t-L%{jw zs+K*r&Ew(wr!&qGP_Xi~mrT-zlObstWB(A@Q&_88qB~FG)0S0>$wTm(hcWLyK8Jk% z#&T8oIl8RYAAjFQ5TV`8g7Sl)z@W7+iF^}peWJkh9*&5PM5kDe5#c0jMkLO0)TUq3 zI$v3%{(OB7U!U{xBR9qS@*+tuw`_+$_4N9cH$|SC)%AHhBnaEcCs2%6On{J$+4Dd4 zM-2^EHeg_RkqNLLqSMoluB%_dZY1SVyTaLi2_>?l(N3PwwPIpwo{nJr6*A!akLb*< za2@^$yNeB;K_eCk5n_Huf0dt((6n#9fbXG`e*lG5xRPD z$MRPO&A$0`{XDb%nzL`@#JW)0e0hEwMYWkIy!`Ja(W7ci)fpqR%O!9K~Y)^;ZZ5Bo@q^y&KUVCdXLfD_|@DjS1o-mE0Vj z-4L^pb>r?Jy2>-?={n=-S=Nsdx^`thof}&y3e=Z3Qt0#R6X9xrLe67Y6A;#N#rjaL z*~7RRT7kXlD~kOiB)$B3qJwXZ|E_1-%Lsv?FNVgvk&GW0YKYGw*Knx!arKT}&gIn8 zY>^bw`$BR^0qy~^)H4PYajIlVGfH3LgkGbNws~VZyBD~*4ezs zjBaSGhA4n??c7?UaC2(5EZ9_Wy$C=9F`-u9H@c!w%D}$Jcl(c2X-Q3Y8L;W$@XW`m z3Lf5eL`ttRH|?YOD+>hh^7BiEZv$>qh9p`4Qlb6TfKqS-)Z;6$>69lu)k_L(iw3B) z>AiNdO43Vj2LHKMx~5zVHIvDk57E zQZ@A^U+5E}z+JPRjPtXn;ST}N2OiB5HCONj=S27#OWexL+eaMt2hVx!fpuYz;?S$Q(v=9JkGtGAcRM+dPR$zSR7fWhUe+u^C5Te zR^w}hc1C`Vi4Y#nsfxHd2X{%@$Q_(gn(Axy+gj33C^Gf-9+{;n`BfiFU3+laDTC^~ zaXdfpBALv*)%dTyybMCmB6-dIpIuk3vGbNJDIi&Hd7W-5A)Q+*Iv@nda@(BCsrrbI z@A#dhOM?eI&4u(T7?xL}N|>+tAGg28KI#2L={UmHc*Gy#A&^y@Z0dwxN$Jl!Hm~~b zR!cNK5}prd(6q~GS={`}v6{q=@|A01DAr8f7aM&oBQ@8PD` zS{+U_FcsR{4jC{6<9;8oE{Or+Npwo(_HSM`@x346V{cF^y9~g~u8gr=)f^H63wcbK z7G*u7W@f>Av%=1kI5lPf*umb1tv zhRxvxiMg1{CpYEHx8y_Q$)btOs26i<-Sayd7M&VG8H%)8e*VnUS6 zzT5cYPI!la#(A}9O=I>K{T`>Zs0$m?HorCIO#v<#Ea8~St_7K5$lc}kDRin;6CQ#tOub%uqkVuJFi=d)c%W+5}Mc{!I>zk9g4#9Bw*0BW>BeOb^q zf8G(gzJgT?I_zPGm>_SxA?ses^78B7J(3BWjj@z`Quc!0`zhjiZ?~|&0tg>) zTmV_(qgDB4+5PNt8-B}14>0kMDKEyfF0a5!yj>h{;w@IsQqplcxaV5f+=Vf7jI+B< z%nQ!*x4SoCvGL&L*JfCc_y!P@G1k3H4y#*d2}tGvMM)Eo?VA@6WGTidgAONB}*y$YyIqVm9&>TFU$-? zA={X?Cvq+{&mkR0H26mjDdJdVbAHJU-UaktdkmA6HO0@JtccmUV!(`;CRF{x)BKUu zjB#V~R>qRhKN4ys{d>RkabX1l4=Xgxny3TnyZy7!k+i(>cI)`9~VLgJ@{|#$W{8lLFS9{UEsD!@O@Wl8+%B>9_ zfV)>oQO6T^tJB4A2mq*m5??!db~oSxt(x{Lx>vYH9?(bwF?qeWm$KxyOB8-NJtprP z|J`v_mfgy1?vLEpNqPL0_7*E7hK*~&0;g(tq;2P-I z=ouOB<%C1H;Yzcwuxzo%sY6>=B~xd7#`25b@oVNzjCT~~31pjRlQ#KXzi@C#o@DdT z^YpZXwAoDUwS)BtYx9lfhy;sx0w?>ZZ4Rnf7r5Xo?S<|5aZ zO5$&~|E9(J(P9E;#FHQQ?jO8ZpvjCS-XR4O7m)HA%F%m=4ji8AViGj$%G)~^D8>}o zxX+D{uS>d6NISndA*>-dS#5aEUUB%MChWWT9fK7gokzcVCzF}M$QXw%h&0WF-=1Zj> zlPdUVnLAQan?wn5`SpwUf0yTvZ=$a>&H)*2xi74JXWFU;N@(cS@Y#96ywF{o1ru_1 z9EIOOO!{arkaCS7J)5|7r-T2L-&z28W~tRaOet|>E4`p6hU>dghv{&`KF9dSl%p+%8R=M6!Xfk z`cv;|4nD6=V%qI~;oiEH*1BRJqQ`ab4MaAA(r03ZYd}HwFSB5q}`>~BHH@v9*uvHiSl2zkLMk~$3-hZ_SVJ3j>|eqZ1J9erVmVsrQDu?cwq>d>sVsAO@udJ2`+-)i+mp!B8vV<;U9Z8CvT>+oDK zR?LuC3G1<+r#;qZ8c>JBtqXiz=rphk+~e207qcYc$H}lf3L5IS;btczahHv5dF7!4 zw9=cw&Wt2d(vm$a{CpEspcLlU=5!}*$HF*^V}-oJ?R3uxq=3&NCHM1+^j96seY^RR zpk!0Qj%T(1?aPypAx#HkWt5L`j85 zXDL9vkQIz7i`Yp`O>qc-5Gzr*#-UW%K9pEX%UK{ zW*`4jQ9cwiGN#*`_S*GBi{YiEIQZ;B!!kJfYj(3wU%PhtrWwl&C9(Oeuvx-!Exp^=VQHokE~i$ zamv)3nO${p%kp@*Y?&EfW5^WH#f(0;VfaGIADyEx6?AsI4gS%W?C&3L;C-oB(4Uk1 zIg>#7Bs~tS^r56Y+0T=?vZ6w_4@dCe?X=%Hs<2)GAJ8u6^3MB&8~C~2^}RYJuCN%Q zva+?!Zu%HJ2uwm))S;l+w~x+w6jSTT;^O${W?R~8kaKGlCTpBktE-t2-|T(fWhD0_ zJEz`O^HQ&K`F-FLE^xlf%t0?+!rB%MCMMvYH+8u?L z*`F!l&hk&^jDzk(06%O{6qB5PnKzH)zJUfb95P0*rh}NTGT#PHD@SPif5 z;h2_AODPH(v)V?S+NJBiiiu8>f4{!{_=(!Ygqre54f4$s0YqWq_VA8Ti+ImP zVj>oO4d_VVw4lx|_cD(7m4665q<(QvezliNX}<3y!(LtYTdkW zXLnEb$>38y>`?vbxrx9SF0*NfLlf1baekC+=eRLCNL(X04BwmLAV zpaqkw%}tx=H=q8m-O*#x-{SpoJvm8xd22yE02n3w!9rH|r%?G*dDuJPk=)*R|GD+f z;(dDd8EC3NX867mUl&}g{3olyq*-#&S~hW7xR%ZGc~DF+$nS}w@V-kyzd$AH$p;MV zRsV9)%(an^@b~3U_6)B*J~A;g&${gbQ`-xr(x5Egqq&}{ecXIN zWV#Q;k;}cl*EC?LKaV+^)HHla*RM@uLOWyp@_0UyO Sfju@hR&lzL+{V0hctHXv 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

+ + + +

); }); @@ -170,3 +186,15 @@ export const HostDetailsFlyout = () => { ); }; + +const useHostLogsUrl = (hostId: string): { url: string; appId: string; appPath: string } => { + const { services } = useKibana(); + return useMemo(() => { + const appPath = `/stream?logFilter=(expression:'host.id:${hostId}',kind:kuery)`; + return { + url: `${services.application.getUrlForApp('logs')}${appPath}`, + appId: 'logs', + appPath, + }; + }, [hostId, services.application]); +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx index f6dfae99c1b11..c3ff41268e3db 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx @@ -6,40 +6,26 @@ import React from 'react'; import * as reactTestingLibrary from '@testing-library/react'; -import { Provider } from 'react-redux'; -import { I18nProvider } from '@kbn/i18n/react'; -import { EuiThemeProvider } from '../../../../../../../legacy/common/eui_styled_components'; -import { appStoreFactory } from '../../store'; -import { RouteCapture } from '../route_capture'; -import { createMemoryHistory, MemoryHistory } from 'history'; -import { Router } from 'react-router-dom'; +import { fireEvent } from '@testing-library/react'; import { AppAction } from '../../types'; import { HostList } from './index'; -import { mockHostResultList } from '../../store/hosts/mock_host_result_list'; +import { + mockHostDetailsApiResult, + mockHostResultList, +} from '../../store/hosts/mock_host_result_list'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../mocks'; +import { HostInfo } from '../../../../../common/types'; describe('when on the hosts page', () => { - let render: () => reactTestingLibrary.RenderResult; - let history: MemoryHistory; - let store: ReturnType; + let render: () => ReturnType; + let history: AppContextTestRender['history']; + let store: AppContextTestRender['store']; + let coreStart: AppContextTestRender['coreStart']; beforeEach(async () => { - history = createMemoryHistory(); - store = appStoreFactory(); - render = () => { - return reactTestingLibrary.render( - - - - - - - - - - - - ); - }; + const mockedContext = createAppRootMockRenderer(); + ({ history, store, coreStart } = mockedContext); + render = () => mockedContext.render(); }); it('should show a table', async () => { @@ -56,7 +42,7 @@ describe('when on the hosts page', () => { expect(e).not.toBeNull(); }); }); - describe('when data loads', () => { + describe('when list data loads', () => { beforeEach(() => { reactTestingLibrary.act(() => { const action: AppAction = { @@ -76,6 +62,16 @@ describe('when on the hosts page', () => { describe('when the user clicks the hostname in the table', () => { let renderResult: reactTestingLibrary.RenderResult; beforeEach(async () => { + const hostDetailsApiResponse = mockHostDetailsApiResult(); + + coreStart.http.get.mockReturnValue(Promise.resolve(hostDetailsApiResponse)); + reactTestingLibrary.act(() => { + store.dispatch({ + type: 'serverReturnedHostDetails', + payload: hostDetailsApiResponse, + }); + }); + renderResult = render(); const detailsLink = await renderResult.findByTestId('hostnameCellLink'); if (detailsLink) { @@ -93,19 +89,71 @@ describe('when on the hosts page', () => { }); describe('when there is a selected host in the url', () => { + let hostDetails: HostInfo; beforeEach(() => { + const { + host_status, + metadata: { host, ...details }, + } = mockHostDetailsApiResult(); + hostDetails = { + host_status, + metadata: { + ...details, + host: { + ...host, + id: '1', + }, + }, + }; + + coreStart.http.get.mockReturnValue(Promise.resolve(hostDetails)); + coreStart.application.getUrlForApp.mockReturnValue('/app/logs'); + reactTestingLibrary.act(() => { history.push({ ...history.location, search: '?selected_host=1', }); }); + reactTestingLibrary.act(() => { + store.dispatch({ + type: 'serverReturnedHostDetails', + payload: hostDetails, + }); + }); }); + afterEach(() => { + jest.clearAllMocks(); + }); + it('should show the flyout', () => { const renderResult = render(); return renderResult.findByTestId('hostDetailsFlyout').then(flyout => { expect(flyout).not.toBeNull(); }); }); + it('should include the link to logs', async () => { + const renderResult = render(); + const linkToLogs = await renderResult.findByTestId('hostDetailsLinkToLogs'); + expect(linkToLogs).not.toBeNull(); + expect(linkToLogs.textContent).toEqual('Endpoint Logs'); + expect(linkToLogs.getAttribute('href')).toEqual( + "/app/logs/stream?logFilter=(expression:'host.id:1',kind:kuery)" + ); + }); + describe('when link to logs is clicked', () => { + beforeEach(async () => { + const renderResult = render(); + const linkToLogs = await renderResult.findByTestId('hostDetailsLinkToLogs'); + reactTestingLibrary.act(() => { + fireEvent.click(linkToLogs); + }); + }); + + it('should navigate to logs without full page refresh', async () => { + // FIXME: this is not working :( + expect(coreStart.application.navigateToApp.mock.calls).toHaveLength(1); + }); + }); }); }); From 0dd89e388d3a0d87e7ea07be74b706db234c1c26 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 9 Apr 2020 09:56:11 -0600 Subject: [PATCH 012/121] [Maps] create NOT EXISTS filter for tooltip property with no value (#62849) * [Maps] create NOT EXISTS filter for tooltip property with no value * review feedback --- .../tooltips/es_tooltip_property.test.ts | 105 ++++++++++++++++++ .../layers/tooltips/es_tooltip_property.ts | 19 +++- .../layers/tooltips/join_tooltip_property.ts | 4 +- .../layers/tooltips/tooltip_property.ts | 6 +- 4 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.test.ts diff --git a/x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.test.ts b/x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.test.ts new file mode 100644 index 0000000000000..2cc9e1513719b --- /dev/null +++ b/x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.test.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IFieldType, IndexPattern } from '../../../../../../src/plugins/data/public'; +import { ESTooltipProperty } from './es_tooltip_property'; +import { TooltipProperty } from './tooltip_property'; +import { AbstractField } from '../fields/field'; +import { FIELD_ORIGIN } from '../../../common/constants'; + +class MockField extends AbstractField {} + +const indexPatternField = { + name: 'machine.os', + type: 'string', + esTypes: ['text'], + count: 0, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: false, +} as IFieldType; + +const featurePropertyField = new MockField({ + fieldName: 'machine.os', + origin: FIELD_ORIGIN.SOURCE, +}); + +const indexPattern = { + id: 'indexPatternId', + fields: { + getByName: (name: string): IFieldType | null => { + return name === 'machine.os' ? indexPatternField : null; + }, + }, + title: 'my index pattern', +} as IndexPattern; + +describe('getESFilters', () => { + test('Should return empty array when field does not exist in index pattern', async () => { + const notFoundFeaturePropertyField = new MockField({ + fieldName: 'field name that is not in index pattern', + origin: FIELD_ORIGIN.SOURCE, + }); + const esTooltipProperty = new ESTooltipProperty( + new TooltipProperty( + notFoundFeaturePropertyField.getName(), + await notFoundFeaturePropertyField.getLabel(), + 'my value' + ), + indexPattern, + notFoundFeaturePropertyField + ); + expect(await esTooltipProperty.getESFilters()).toEqual([]); + }); + + test('Should return phrase filter when field value is provided', async () => { + const esTooltipProperty = new ESTooltipProperty( + new TooltipProperty( + featurePropertyField.getName(), + await featurePropertyField.getLabel(), + 'my value' + ), + indexPattern, + featurePropertyField + ); + expect(await esTooltipProperty.getESFilters()).toEqual([ + { + meta: { + index: 'indexPatternId', + }, + query: { + match_phrase: { + ['machine.os']: 'my value', + }, + }, + }, + ]); + }); + + test('Should return NOT exists filter for null values', async () => { + const esTooltipProperty = new ESTooltipProperty( + new TooltipProperty( + featurePropertyField.getName(), + await featurePropertyField.getLabel(), + undefined + ), + indexPattern, + featurePropertyField + ); + expect(await esTooltipProperty.getESFilters()).toEqual([ + { + meta: { + index: 'indexPatternId', + negate: true, + }, + exists: { + field: 'machine.os', + }, + }, + ]); + }); +}); diff --git a/x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.ts b/x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.ts index 5c35009881920..d2fdcfaab476c 100644 --- a/x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.ts +++ b/x-pack/plugins/maps/public/layers/tooltips/es_tooltip_property.ts @@ -7,8 +7,12 @@ import _ from 'lodash'; import { ITooltipProperty } from './tooltip_property'; import { IField } from '../fields/field'; -import { esFilters, IFieldType, IndexPattern } from '../../../../../../src/plugins/data/public'; -import { PhraseFilter } from '../../../../../../src/plugins/data/public'; +import { + esFilters, + Filter, + IFieldType, + IndexPattern, +} from '../../../../../../src/plugins/data/public'; export class ESTooltipProperty implements ITooltipProperty { private readonly _tooltipProperty: ITooltipProperty; @@ -64,12 +68,19 @@ export class ESTooltipProperty implements ITooltipProperty { ); } - async getESFilters(): Promise { + async getESFilters(): Promise { const indexPatternField = this._getIndexPatternField(); if (!indexPatternField) { return []; } - return [esFilters.buildPhraseFilter(indexPatternField, this.getRawValue(), this._indexPattern)]; + const value = this.getRawValue(); + if (value == null) { + const existsFilter = esFilters.buildExistsFilter(indexPatternField, this._indexPattern); + existsFilter.meta.negate = true; + return [existsFilter]; + } else { + return [esFilters.buildPhraseFilter(indexPatternField, value, this._indexPattern)]; + } } } diff --git a/x-pack/plugins/maps/public/layers/tooltips/join_tooltip_property.ts b/x-pack/plugins/maps/public/layers/tooltips/join_tooltip_property.ts index 4af236f6e9e36..cc95c12ef630f 100644 --- a/x-pack/plugins/maps/public/layers/tooltips/join_tooltip_property.ts +++ b/x-pack/plugins/maps/public/layers/tooltips/join_tooltip_property.ts @@ -6,7 +6,7 @@ import { ITooltipProperty } from './tooltip_property'; import { IJoin } from '../joins/join'; -import { PhraseFilter } from '../../../../../../src/plugins/data/public'; +import { Filter } from '../../../../../../src/plugins/data/public'; export class JoinTooltipProperty implements ITooltipProperty { private readonly _tooltipProperty: ITooltipProperty; @@ -37,7 +37,7 @@ export class JoinTooltipProperty implements ITooltipProperty { return this._tooltipProperty.getHtmlDisplayValue(); } - async getESFilters(): Promise { + async getESFilters(): Promise { const esFilters = []; if (this._tooltipProperty.isFilterable()) { esFilters.push(...(await this._tooltipProperty.getESFilters())); diff --git a/x-pack/plugins/maps/public/layers/tooltips/tooltip_property.ts b/x-pack/plugins/maps/public/layers/tooltips/tooltip_property.ts index 7d680dfe9cae0..8da2ed795943b 100644 --- a/x-pack/plugins/maps/public/layers/tooltips/tooltip_property.ts +++ b/x-pack/plugins/maps/public/layers/tooltips/tooltip_property.ts @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import { PhraseFilter } from '../../../../../../src/plugins/data/public'; +import { Filter } from '../../../../../../src/plugins/data/public'; import { TooltipFeature } from '../../../../../plugins/maps/common/descriptor_types'; export interface ITooltipProperty { @@ -14,7 +14,7 @@ export interface ITooltipProperty { getHtmlDisplayValue(): string; getRawValue(): string | undefined; isFilterable(): boolean; - getESFilters(): Promise; + getESFilters(): Promise; } export interface LoadFeatureProps { @@ -70,7 +70,7 @@ export class TooltipProperty implements ITooltipProperty { return false; } - async getESFilters(): Promise { + async getESFilters(): Promise { return []; } } From dfea62187f0e1984a50c9cff0c367f31b8728083 Mon Sep 17 00:00:00 2001 From: Maryia Lapata Date: Thu, 9 Apr 2020 18:56:36 +0300 Subject: [PATCH 013/121] [NP] Inline buildPointSeriesData and buildHierarchicalData dependencies (#61575) * Move buildHierarchicalData to vislib * Move shortened version of buildPointSeriesData to Discover * Move buildPointSeriesData to vis_type_vislib * Convert unit tests to jest * Remove ui/agg_response * Convert point_series files to TS * Update TS in unit tests * Convert buildHierarchicalData to TS * Convert buildPointSeriesData to TS in Discover * Clean TS in Discover * Update TS for buildHierarchicalData * Update buildHierarchicalData unit tests * Clean up TS in point_series * Add unit tests fro response_handler.js * Simplify point_series for Discover * Return array for data * Add check for empty row * Simplify point_series for Discover * Return all points * Specify TS * Refactoring * Simplifying * improve types * Update _get_point.test.ts Co-authored-by: Elastic Machine Co-authored-by: Joe Reuter --- .../kibana/public/discover/kibana_services.ts | 2 - .../np_ready/angular/directives/histogram.tsx | 14 +- .../np_ready/angular/helpers/index.ts} | 0 .../np_ready/angular/helpers/point_series.ts | 111 +++++++ .../np_ready/angular/response_handler.js | 3 +- .../core_plugins/kibana/public/kibana.js | 1 - .../vis_type_vislib/public/legacy_imports.ts | 5 - .../vislib/__tests__/response_handlers.js | 137 --------- .../build_hierarchical_data.test.ts} | 108 ++++--- .../hierarchical/build_hierarchical_data.ts} | 50 +++- .../public/vislib/helpers/index.ts} | 13 +- .../helpers/point_series/_add_to_siri.test.ts | 84 ++++++ .../helpers/point_series/_add_to_siri.ts | 60 ++++ .../point_series/_fake_x_aspect.test.ts} | 15 +- .../helpers/point_series/_fake_x_aspect.ts} | 5 +- .../point_series/_get_aspects.test.ts} | 53 ++-- .../helpers/point_series/_get_aspects.ts} | 20 +- .../helpers/point_series/_get_point.test.ts | 104 +++++++ .../helpers/point_series/_get_point.ts} | 53 +++- .../helpers/point_series/_get_series.test.ts | 281 +++++++++++++++++ .../helpers/point_series/_get_series.ts | 88 ++++++ .../point_series/_init_x_axis.test.ts} | 91 +++--- .../helpers/point_series/_init_x_axis.ts} | 20 +- .../point_series/_init_y_axis.test.ts} | 19 +- .../helpers/point_series/_init_y_axis.ts} | 13 +- .../point_series/_ordered_date_axis.test.ts} | 20 +- .../point_series/_ordered_date_axis.ts} | 10 +- .../vislib/helpers/point_series/index.ts} | 10 +- .../point_series/point_series.test.ts} | 81 ++--- .../helpers/point_series/point_series.ts | 118 ++++++++ .../public/vislib/response_handler.js | 4 +- .../public/vislib/response_handler.test.ts | 130 ++++++++ .../vis_type_vislib/public/vislib/types.ts} | 36 ++- .../point_series/__tests__/_add_to_siri.js | 82 ----- .../point_series/__tests__/_get_point.js | 97 ------ .../point_series/__tests__/_get_series.js | 283 ------------------ .../agg_response/point_series/_get_series.js | 100 ------- .../agg_response/point_series/point_series.js | 42 --- .../dashboard_mode/public/dashboard_viewer.js | 1 - .../translations/translations/ja-JP.json | 2 +- .../translations/translations/zh-CN.json | 2 +- 41 files changed, 1328 insertions(+), 1040 deletions(-) rename src/legacy/{ui/public/agg_response/point_series/index.js => core_plugins/kibana/public/discover/np_ready/angular/helpers/index.ts} (100%) create mode 100644 src/legacy/core_plugins/kibana/public/discover/np_ready/angular/helpers/point_series.ts delete mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/response_handlers.js rename src/legacy/{ui/public/agg_response/hierarchical/build_hierarchical_data.test.js => core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.test.ts} (80%) rename src/legacy/{ui/public/agg_response/hierarchical/build_hierarchical_data.js => core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.ts} (63%) rename src/legacy/{ui/public/agg_response/point_series/__tests__/point_series.js => core_plugins/vis_type_vislib/public/vislib/helpers/index.ts} (71%) create mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts create mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts rename src/legacy/{ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.test.ts} (74%) rename src/legacy/{ui/public/agg_response/point_series/_fake_x_aspect.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.ts} (88%) rename src/legacy/{ui/public/agg_response/point_series/__tests__/_get_aspects.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts} (53%) rename src/legacy/{ui/public/agg_response/point_series/_get_aspects.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts} (72%) create mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts rename src/legacy/{ui/public/agg_response/point_series/_get_point.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts} (69%) create mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.test.ts create mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.ts rename src/legacy/{ui/public/agg_response/point_series/__tests__/_init_x_axis.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts} (51%) rename src/legacy/{ui/public/agg_response/point_series/_init_x_axis.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts} (73%) rename src/legacy/{ui/public/agg_response/point_series/__tests__/_init_y_axis.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.test.ts} (81%) rename src/legacy/{ui/public/agg_response/point_series/_init_y_axis.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.ts} (82%) rename src/legacy/{ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts} (76%) rename src/legacy/{ui/public/agg_response/point_series/_ordered_date_axis.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.ts} (72%) rename src/legacy/{ui/public/agg_response/index.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/index.ts} (69%) rename src/legacy/{ui/public/agg_response/point_series/__tests__/_main.js => core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts} (62%) create mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts create mode 100644 src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.test.ts rename src/legacy/{ui/public/agg_response/point_series/_add_to_siri.js => core_plugins/vis_type_vislib/public/vislib/types.ts} (67%) delete mode 100644 src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js delete mode 100644 src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js delete mode 100644 src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js delete mode 100644 src/legacy/ui/public/agg_response/point_series/_get_series.js delete mode 100644 src/legacy/ui/public/agg_response/point_series/point_series.js diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts index 98679a8f24d16..0a81ca0222b0a 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -76,5 +76,3 @@ export { EsQuerySortValue, SortDirection, } from '../../../../../plugins/data/public'; -// @ts-ignore -export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series'; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx index f788347ac016c..8c55622e4c604 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/directives/histogram.tsx @@ -46,9 +46,10 @@ import { IUiSettingsClient } from 'kibana/public'; import { EuiChartThemeType } from '@elastic/eui/dist/eui_charts_theme'; import { Subscription } from 'rxjs'; import { getServices } from '../../../kibana_services'; +import { Chart as IChart } from '../helpers/point_series'; export interface DiscoverHistogramProps { - chartData: any; + chartData: IChart; timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; } @@ -163,7 +164,7 @@ export class DiscoverHistogram extends Component { - const xAxisFormat = this.props.chartData.xAxisFormat.params.pattern; + const xAxisFormat = this.props.chartData.xAxisFormat.params!.pattern; return moment(val).format(xAxisFormat); }; @@ -208,18 +209,19 @@ export class DiscoverHistogram extends Component domainStart ? domainStart : data[0].x; + const domainMin = data[0]?.x > domainStart ? domainStart : data[0]?.x; const domainMax = domainEnd - xInterval > lastXValue ? domainEnd - xInterval : lastXValue; const xDomain = { diff --git a/src/legacy/ui/public/agg_response/point_series/index.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/helpers/index.ts similarity index 100% rename from src/legacy/ui/public/agg_response/point_series/index.js rename to src/legacy/core_plugins/kibana/public/discover/np_ready/angular/helpers/index.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/helpers/point_series.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/helpers/point_series.ts new file mode 100644 index 0000000000000..02dd024b09812 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/helpers/point_series.ts @@ -0,0 +1,111 @@ +/* + * 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 { uniq } from 'lodash'; +import { Duration, Moment } from 'moment'; +import { Unit } from '@elastic/datemath'; + +import { SerializedFieldFormat } from '../../../../../../../../plugins/expressions/common/types'; + +export interface Column { + id: string; + name: string; +} + +export interface Row { + [key: string]: number | 'NaN'; +} + +export interface Table { + columns: Column[]; + rows: Row[]; +} + +interface HistogramParams { + date: true; + interval: Duration; + intervalESValue: number; + intervalESUnit: Unit; + format: string; + bounds: { + min: Moment; + max: Moment; + }; +} +export interface Dimension { + accessor: 0 | 1; + format: SerializedFieldFormat<{ pattern: string }>; +} + +export interface Dimensions { + x: Dimension & { params: HistogramParams }; + y: Dimension; +} + +interface Ordered { + date: true; + interval: Duration; + intervalESUnit: string; + intervalESValue: number; + min: Moment; + max: Moment; +} +export interface Chart { + values: Array<{ + x: number; + y: number; + }>; + xAxisOrderedValues: number[]; + xAxisFormat: Dimension['format']; + xAxisLabel: Column['name']; + yAxisLabel?: Column['name']; + ordered: Ordered; +} + +export const buildPointSeriesData = (table: Table, dimensions: Dimensions) => { + const { x, y } = dimensions; + const xAccessor = table.columns[x.accessor].id; + const yAccessor = table.columns[y.accessor].id; + const chart = {} as Chart; + + chart.xAxisOrderedValues = uniq(table.rows.map(r => r[xAccessor] as number)); + chart.xAxisFormat = x.format; + chart.xAxisLabel = table.columns[x.accessor].name; + + const { intervalESUnit, intervalESValue, interval, bounds } = x.params; + chart.ordered = { + date: true, + interval, + intervalESUnit, + intervalESValue, + min: bounds.min, + max: bounds.max, + }; + + chart.yAxisLabel = table.columns[y.accessor].name; + + chart.values = table.rows + .filter(row => row && row[yAccessor] !== 'NaN') + .map(row => ({ + x: row[xAccessor] as number, + y: row[yAccessor] as number, + })); + + return chart; +}; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js index 0c19c10841535..04ccb67ec7e25 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js @@ -17,7 +17,8 @@ * under the License. */ -import { buildPointSeriesData, getServices } from '../../kibana_services'; +import { getServices } from '../../kibana_services'; +import { buildPointSeriesData } from './helpers'; function tableResponseHandler(table, dimensions) { const converted = { tables: [] }; diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index bceb3fa7eef8a..0a026a5e0c310 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -46,7 +46,6 @@ import './discover/legacy'; import './visualize/legacy'; import './management'; import './dev_tools'; -import 'ui/agg_response'; import { showAppRedirectNotification } from '../../../../plugins/kibana_legacy/public'; import 'leaflet'; import { localApplicationService } from './local_application_service'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts index da16a38deba9f..c04ffa506eb04 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/legacy_imports.ts @@ -19,8 +19,3 @@ import { search } from '../../../../plugins/data/public'; export const { tabifyAggResponse, tabifyGetColumns } = search; - -// @ts-ignore -export { buildHierarchicalData } from 'ui/agg_response/hierarchical/build_hierarchical_data'; -// @ts-ignore -export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/response_handlers.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/response_handlers.js deleted file mode 100644 index 3574fb232883d..0000000000000 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/response_handlers.js +++ /dev/null @@ -1,137 +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 sinon from 'sinon'; -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; - -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { aggResponseIndex } from 'ui/agg_response'; - -import { vislibSeriesResponseHandler } from '../response_handler'; - -/** - * TODO: Fix these tests if still needed - * - * All these tests were not being run in master or prodiced false positive results - * Fixing them would require changes to the response handler logic. - */ - -describe.skip('Basic Response Handler', function() { - beforeEach(ngMock.module('kibana')); - - it('returns empty object if conversion failed', () => { - const data = vislibSeriesResponseHandler({}); - expect(data).to.not.be.an('undefined'); - expect(data).to.equal({}); - }); - - it('returns empty object if no data was found', () => { - const data = vislibSeriesResponseHandler({ - columns: [{ id: '1', title: '1', aggConfig: {} }], - rows: [], - }); - expect(data).to.not.be.an('undefined'); - expect(data.rows).to.equal([]); - }); -}); - -describe.skip('renderbot#buildChartData', function() { - describe('for hierarchical vis', function() { - it('defers to hierarchical aggResponse converter', function() { - const football = {}; - const stub = sinon.stub(aggResponseIndex, 'hierarchical').returns(football); - expect(vislibSeriesResponseHandler(football)).to.be(football); - expect(stub).to.have.property('callCount', 1); - expect(stub.firstCall.args[1]).to.be(football); - }); - }); - - describe('for point plot', function() { - it('calls tabify to simplify the data into a table', function() { - const football = { tables: [], hits: { total: 1 } }; - const stub = sinon.stub(aggResponseIndex, 'tabify').returns(football); - expect(vislibSeriesResponseHandler(football)).to.eql({ rows: [], hits: 1 }); - expect(stub).to.have.property('callCount', 1); - expect(stub.firstCall.args[1]).to.be(football); - }); - - it('returns a single chart if the tabify response contains only a single table', function() { - const chart = { hits: 1, rows: [], columns: [] }; - const esResp = { hits: { total: 1 } }; - const tabbed = { tables: [{}] }; - - sinon.stub(aggResponseIndex, 'tabify').returns(tabbed); - expect(vislibSeriesResponseHandler(esResp)).to.eql(chart); - }); - - it('converts table groups into rows/columns wrappers for charts', function() { - const converter = sinon.stub().returns('chart'); - const esResp = { hits: { total: 1 } }; - const tables = [{}, {}, {}, {}]; - - sinon.stub(aggResponseIndex, 'tabify').returns({ - tables: [ - { - aggConfig: { params: { row: true } }, - tables: [ - { - aggConfig: { params: { row: false } }, - tables: [tables[0]], - }, - { - aggConfig: { params: { row: false } }, - tables: [tables[1]], - }, - ], - }, - { - aggConfig: { params: { row: true } }, - tables: [ - { - aggConfig: { params: { row: false } }, - tables: [tables[2]], - }, - { - aggConfig: { params: { row: false } }, - tables: [tables[3]], - }, - ], - }, - ], - }); - - const chartData = vislibSeriesResponseHandler(esResp); - - // verify tables were converted - expect(converter).to.have.property('callCount', 4); - expect(converter.args[0][1]).to.be(tables[0]); - expect(converter.args[1][1]).to.be(tables[1]); - expect(converter.args[2][1]).to.be(tables[2]); - expect(converter.args[3][1]).to.be(tables[3]); - - expect(chartData).to.have.property('rows'); - expect(chartData.rows).to.have.length(2); - chartData.rows.forEach(function(row) { - expect(row).to.have.property('columns'); - expect(row.columns).to.eql(['chart', 'chart']); - }); - }); - }); -}); diff --git a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.test.ts similarity index 80% rename from src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.test.ts index 21a937bf1fb66..475555f3a15f3 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.test.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.test.ts @@ -17,24 +17,26 @@ * under the License. */ -import { buildHierarchicalData } from './build_hierarchical_data'; +import { buildHierarchicalData, Dimensions, Dimension } from './build_hierarchical_data'; +import { Table, TableParent } from '../../types'; -function tableVisResponseHandler(table, dimensions) { - const converted = { +function tableVisResponseHandler(table: Table, dimensions: Dimensions) { + const converted: { + tables: Array; + } = { tables: [], }; const split = dimensions.splitColumn || dimensions.splitRow; if (split) { - converted.direction = dimensions.splitRow ? 'row' : 'column'; const splitColumnIndex = split[0].accessor; const splitColumn = table.columns[splitColumnIndex]; - const splitMap = {}; + const splitMap: { [key: string]: number } = {}; let splitIndex = 0; table.rows.forEach((row, rowIndex) => { - const splitValue = row[splitColumn.id]; + const splitValue = row[splitColumn.id] as string; if (!splitMap.hasOwnProperty(splitValue)) { splitMap[splitValue] = splitIndex++; @@ -46,8 +48,8 @@ function tableVisResponseHandler(table, dimensions) { column: splitColumnIndex, row: rowIndex, table, - tables: [], - }; + tables: [] as Table[], + } as any; tableGroup.tables.push({ $parent: tableGroup, @@ -59,34 +61,30 @@ function tableVisResponseHandler(table, dimensions) { } const tableIndex = splitMap[splitValue]; - converted.tables[tableIndex].tables[0].rows.push(row); + (converted.tables[tableIndex] as TableParent).tables![0].rows.push(row); }); } else { converted.tables.push({ columns: table.columns, rows: table.rows, - }); + } as Table); } return converted; } -jest.mock('ui/new_platform'); -jest.mock('ui/chrome', () => ({ - getUiSettingsClient: jest.fn().mockReturnValue({ - get: jest.fn().mockReturnValue('KQL'), - }), -})); -jest.mock('ui/visualize/loader/pipeline_helpers/utilities', () => ({ - getFormat: jest.fn(() => ({ - convert: jest.fn(v => v), +jest.mock('../../../services', () => ({ + getFormatService: jest.fn(() => ({ + deserialize: () => ({ + convert: jest.fn(v => JSON.stringify(v)), + }), })), })); describe('buildHierarchicalData convertTable', () => { describe('metric only', () => { - let dimensions; - let table; + let dimensions: Dimensions; + let table: Table; beforeEach(() => { const tabifyResponse = { @@ -94,11 +92,11 @@ describe('buildHierarchicalData convertTable', () => { rows: [{ 'col-0-agg_1': 412032 }], }; dimensions = { - metric: { accessor: 0 }, + metric: { accessor: 0 } as Dimension, }; const tableGroup = tableVisResponseHandler(tabifyResponse, dimensions); - table = tableGroup.tables[0]; + table = tableGroup.tables[0] as Table; }); it('should set the slices with one child to a consistent label', () => { @@ -118,8 +116,8 @@ describe('buildHierarchicalData convertTable', () => { }); describe('threeTermBuckets', () => { - let dimensions; - let tables; + let dimensions: Dimensions; + let tables: TableParent[]; beforeEach(async () => { const tabifyResponse = { @@ -231,60 +229,60 @@ describe('buildHierarchicalData convertTable', () => { ], }; dimensions = { - splitRow: [{ accessor: 0 }], - metric: { accessor: 5 }, - buckets: [{ accessor: 2 }, { accessor: 4 }], + splitRow: [{ accessor: 0 } as Dimension], + metric: { accessor: 5 } as Dimension, + buckets: [{ accessor: 2 }, { accessor: 4 }] as Dimension[], }; const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); - tables = tableGroup.tables; + tables = tableGroup.tables as TableParent[]; }); it('should set the correct hits attribute for each of the results', () => { tables.forEach(t => { - const results = buildHierarchicalData(t.tables[0], dimensions); + const results = buildHierarchicalData(t.tables![0], dimensions); expect(results).toHaveProperty('hits'); expect(results.hits).toBe(4); }); }); it('should set the correct names for each of the results', () => { - const results0 = buildHierarchicalData(tables[0].tables[0], dimensions); + const results0 = buildHierarchicalData(tables[0].tables![0], dimensions); expect(results0).toHaveProperty('names'); expect(results0.names).toHaveLength(5); - const results1 = buildHierarchicalData(tables[1].tables[0], dimensions); + const results1 = buildHierarchicalData(tables[1].tables![0], dimensions); expect(results1).toHaveProperty('names'); expect(results1.names).toHaveLength(5); - const results2 = buildHierarchicalData(tables[2].tables[0], dimensions); + const results2 = buildHierarchicalData(tables[2].tables![0], dimensions); expect(results2).toHaveProperty('names'); expect(results2.names).toHaveLength(4); }); it('should set the parent of the first item in the split', () => { - const results0 = buildHierarchicalData(tables[0].tables[0], dimensions); + const results0 = buildHierarchicalData(tables[0].tables![0], dimensions); expect(results0).toHaveProperty('slices'); expect(results0.slices).toHaveProperty('children'); expect(results0.slices.children).toHaveLength(2); - expect(results0.slices.children[0].rawData.table.$parent).toHaveProperty('key', 'png'); + expect(results0.slices.children[0].rawData!.table.$parent).toHaveProperty('key', 'png'); - const results1 = buildHierarchicalData(tables[1].tables[0], dimensions); + const results1 = buildHierarchicalData(tables[1].tables![0], dimensions); expect(results1).toHaveProperty('slices'); expect(results1.slices).toHaveProperty('children'); expect(results1.slices.children).toHaveLength(2); - expect(results1.slices.children[0].rawData.table.$parent).toHaveProperty('key', 'css'); + expect(results1.slices.children[0].rawData!.table.$parent).toHaveProperty('key', 'css'); - const results2 = buildHierarchicalData(tables[2].tables[0], dimensions); + const results2 = buildHierarchicalData(tables[2].tables![0], dimensions); expect(results2).toHaveProperty('slices'); expect(results2.slices).toHaveProperty('children'); expect(results2.slices.children).toHaveLength(2); - expect(results2.slices.children[0].rawData.table.$parent).toHaveProperty('key', 'html'); + expect(results2.slices.children[0].rawData!.table.$parent).toHaveProperty('key', 'html'); }); }); describe('oneHistogramBucket', () => { - let dimensions; - let table; + let dimensions: Dimensions; + let table: Table; beforeEach(async () => { const tabifyResponse = { @@ -302,11 +300,11 @@ describe('buildHierarchicalData convertTable', () => { ], }; dimensions = { - metric: { accessor: 1 }, - buckets: [{ accessor: 0, params: { field: 'bytes', interval: 8192 } }], + metric: { accessor: 1 } as Dimension, + buckets: [{ accessor: 0 } as Dimension], }; const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); - table = tableGroup.tables[0]; + table = tableGroup.tables[0] as Table; }); it('should set the hits attribute for the results', () => { @@ -320,8 +318,8 @@ describe('buildHierarchicalData convertTable', () => { }); describe('oneRangeBucket', () => { - let dimensions; - let table; + let dimensions: Dimensions; + let table: Table; beforeEach(async () => { const tabifyResponse = { @@ -335,11 +333,11 @@ describe('buildHierarchicalData convertTable', () => { ], }; dimensions = { - metric: { accessor: 1 }, - buckets: [{ accessor: 0, format: { id: 'range', params: { id: 'agg_2' } } }], + metric: { accessor: 1 } as Dimension, + buckets: [{ accessor: 0, format: { id: 'range', params: { id: 'agg_2' } } } as Dimension], }; const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); - table = tableGroup.tables[0]; + table = tableGroup.tables[0] as Table; }); it('should set the hits attribute for the results', () => { @@ -348,13 +346,13 @@ describe('buildHierarchicalData convertTable', () => { expect(results).toHaveProperty('slices'); expect(results.slices).toHaveProperty('children'); expect(results).toHaveProperty('names'); - // expect(results.names).toHaveLength(2); + expect(results.names).toHaveLength(2); }); }); describe('oneFilterBucket', () => { - let dimensions; - let table; + let dimensions: Dimensions; + let table: Table; beforeEach(async () => { const tabifyResponse = { @@ -368,15 +366,15 @@ describe('buildHierarchicalData convertTable', () => { ], }; dimensions = { - metric: { accessor: 1 }, + metric: { accessor: 1 } as Dimension, buckets: [ { accessor: 0, }, - ], + ] as Dimension[], }; const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions); - table = tableGroup.tables[0]; + table = tableGroup.tables[0] as Table; }); it('should set the hits attribute for the results', () => { diff --git a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.ts similarity index 63% rename from src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.ts index dcc27e956b3f8..2c6d62ed084b5 100644 --- a/src/legacy/ui/public/agg_response/hierarchical/build_hierarchical_data.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/hierarchical/build_hierarchical_data.ts @@ -18,11 +18,41 @@ */ import { toArray } from 'lodash'; -import { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +import { SerializedFieldFormat } from '../../../../../../../plugins/expressions/common/types'; +import { getFormatService } from '../../../services'; +import { Table } from '../../types'; -export const buildHierarchicalData = (table, { metric, buckets = [] }) => { - let slices; - const names = {}; +export interface Dimension { + accessor: number; + format: { + id?: string; + params?: SerializedFieldFormat; + }; +} + +export interface Dimensions { + metric: Dimension; + buckets?: Dimension[]; + splitRow?: Dimension[]; + splitColumn?: Dimension[]; +} + +interface Slice { + name: string; + size: number; + parent?: Slice; + children?: []; + rawData?: { + table: Table; + row: number; + column: number; + value: string | number | object; + }; +} + +export const buildHierarchicalData = (table: Table, { metric, buckets = [] }: Dimensions) => { + let slices: Slice[]; + const names: { [key: string]: string } = {}; const metricColumn = table.columns[metric.accessor]; const metricFieldFormatter = metric.format; @@ -30,25 +60,25 @@ export const buildHierarchicalData = (table, { metric, buckets = [] }) => { slices = [ { name: metricColumn.name, - size: table.rows[0][metricColumn.id], + size: table.rows[0][metricColumn.id] as number, }, ]; names[metricColumn.name] = metricColumn.name; } else { slices = []; table.rows.forEach((row, rowIndex) => { - let parent; + let parent: Slice; let dataLevel = slices; buckets.forEach(bucket => { const bucketColumn = table.columns[bucket.accessor]; const bucketValueColumn = table.columns[bucket.accessor + 1]; - const bucketFormatter = getFormat(bucket.format); + const bucketFormatter = getFormatService().deserialize(bucket.format); const name = bucketFormatter.convert(row[bucketColumn.id]); - const size = row[bucketValueColumn.id]; + const size = row[bucketValueColumn.id] as number; names[name] = name; - let slice = dataLevel.find(slice => slice.name === name); + let slice = dataLevel.find(dataLevelSlice => dataLevelSlice.name === name); if (!slice) { slice = { name, @@ -66,7 +96,7 @@ export const buildHierarchicalData = (table, { metric, buckets = [] }) => { } parent = slice; - dataLevel = slice.children; + dataLevel = slice.children as []; }); }); } diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/point_series.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/index.ts similarity index 71% rename from src/legacy/ui/public/agg_response/point_series/__tests__/point_series.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/index.ts index 9c3e1c8180eb5..90924e79f6027 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/point_series.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/index.ts @@ -17,14 +17,5 @@ * under the License. */ -describe('Point Series Agg Response', function() { - require('./_main'); - require('./_add_to_siri'); - require('./_fake_x_aspect'); - require('./_get_aspects'); - require('./_get_point'); - require('./_get_series'); - require('./_init_x_axis'); - require('./_init_y_axis'); - require('./_ordered_date_axis'); -}); +export { buildPointSeriesData } from './point_series'; +export { buildHierarchicalData } from './hierarchical/build_hierarchical_data'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts new file mode 100644 index 0000000000000..e4fdd6bb71c00 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.test.ts @@ -0,0 +1,84 @@ +/* + * 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 { addToSiri, Serie } from './_add_to_siri'; +import { Point } from './_get_point'; +import { Dimension } from './point_series'; + +describe('addToSiri', function() { + it('creates a new series the first time it sees an id', function() { + const series = new Map(); + const point = {} as Point; + const id = 'id'; + addToSiri(series, point, id, id, { id }); + + const expectedSerie = series.get(id) as Serie; + expect(series.has(id)).toBe(true); + expect(expectedSerie).toEqual(expect.any(Object)); + expect(expectedSerie.label).toBe(id); + expect(expectedSerie.values).toHaveLength(1); + expect(expectedSerie.values[0]).toBe(point); + }); + + it('adds points to existing series if id has been seen', function() { + const series = new Map(); + const id = 'id'; + + const point = {} as Point; + addToSiri(series, point, id, id, { id }); + + const point2 = {} as Point; + addToSiri(series, point2, id, id, { id }); + + expect(series.has(id)).toBe(true); + expect(series.get(id)).toEqual(expect.any(Object)); + expect(series.get(id).label).toBe(id); + expect(series.get(id).values).toHaveLength(2); + expect(series.get(id).values[0]).toBe(point); + expect(series.get(id).values[1]).toBe(point2); + }); + + it('allows overriding the series label', function() { + const series = new Map(); + const id = 'id'; + const label = 'label'; + const point = {} as Point; + addToSiri(series, point, id, label, { id }); + + expect(series.has(id)).toBe(true); + expect(series.get(id)).toEqual(expect.any(Object)); + expect(series.get(id).label).toBe(label); + expect(series.get(id).values).toHaveLength(1); + expect(series.get(id).values[0]).toBe(point); + }); + + it('correctly sets id and rawId', function() { + const series = new Map(); + const id = 'id-id2'; + + const point = {} as Point; + addToSiri(series, point, id, undefined, {} as Dimension['format']); + + expect(series.has(id)).toBe(true); + expect(series.get(id)).toEqual(expect.any(Object)); + expect(series.get(id).label).toBe(id); + expect(series.get(id).rawId).toBe(id); + expect(series.get(id).id).toBe('id2'); + }); +}); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.ts new file mode 100644 index 0000000000000..5e5185d6c31ab --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_add_to_siri.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 { Point } from './_get_point'; +import { Dimension } from './point_series'; + +export interface Serie { + id: string; + rawId: string; + label: string; + count: number; + values: Point[]; + format: Dimension['format']; + zLabel?: string; + zFormat?: Dimension['format']; +} + +export function addToSiri( + series: Map, + point: Point, + id: string, + yLabel: string | undefined | null, + yFormat: Dimension['format'], + zFormat?: Dimension['format'], + zLabel?: string +) { + id = id == null ? '' : id + ''; + + if (series.has(id)) { + (series.get(id) as Serie).values.push(point); + return; + } + + series.set(id, { + id: id.split('-').pop() as string, + rawId: id, + label: yLabel == null ? id : yLabel, + count: 0, + values: [point], + format: yFormat, + zLabel, + zFormat, + }); +} diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.test.ts similarity index 74% rename from src/legacy/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.test.ts index 6c246d7f50897..43d4c3d7ca7c4 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_fake_x_aspect.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.test.ts @@ -16,20 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - -import expect from '@kbn/expect'; -import { makeFakeXAspect } from '../_fake_x_aspect'; +import { makeFakeXAspect } from './_fake_x_aspect'; describe('makeFakeXAspect', function() { it('creates an object that looks like an aspect', function() { const aspect = makeFakeXAspect(); - expect(aspect) - .to.have.property('accessor', -1) - .and.have.property('title', 'All docs') - .and.have.property('format') - .and.have.property('params'); + expect(aspect).toHaveProperty('accessor', -1); + expect(aspect).toHaveProperty('title', 'All docs'); + expect(aspect).toHaveProperty('format'); + expect(aspect).toHaveProperty('params'); - expect(aspect.params).to.have.property('defaultValue', '_all'); + expect(aspect.params).toHaveProperty('defaultValue', '_all'); }); }); diff --git a/src/legacy/ui/public/agg_response/point_series/_fake_x_aspect.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.ts similarity index 88% rename from src/legacy/ui/public/agg_response/point_series/_fake_x_aspect.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.ts index 254a42baeddb0..1bffa4cceb5b0 100644 --- a/src/legacy/ui/public/agg_response/point_series/_fake_x_aspect.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_fake_x_aspect.ts @@ -18,16 +18,17 @@ */ import { i18n } from '@kbn/i18n'; +import { Aspect } from './point_series'; export function makeFakeXAspect() { return { accessor: -1, - title: i18n.translate('common.ui.aggResponse.allDocsTitle', { + title: i18n.translate('visTypeVislib.aggResponse.allDocsTitle', { defaultMessage: 'All docs', }), params: { defaultValue: '_all', }, format: {}, - }; + } as Aspect; } diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_aspects.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts similarity index 53% rename from src/legacy/ui/public/agg_response/point_series/__tests__/_get_aspects.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts index fab5c2e290e7e..450b283abbed2 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_aspects.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.test.ts @@ -17,37 +17,37 @@ * under the License. */ -import expect from '@kbn/expect'; -import { getAspects } from '../_get_aspects'; +import { getAspects } from './_get_aspects'; +import { Dimension, Dimensions, Aspect } from './point_series'; +import { Table, Row } from '../../types'; describe('getAspects', function() { - let table; - let dimensions; + let table: Table; + let dimensions: Dimensions; - function validate(aspect, i) { - expect(aspect) - .to.be.an('object') - .and.have.property('accessor', i); + function validate(aspect: Aspect, i: string) { + expect(aspect).toEqual(expect.any(Object)); + expect(aspect).toHaveProperty('accessor', i); } - function init(group, x, y) { + function init(group: number, x: number | null, y: number) { table = { columns: [ - { id: '0', title: 'date' }, // date - { id: '1', title: 'date utc_time' }, // date - { id: '2', title: 'ext' }, // extension - { id: '3', title: 'geo.src' }, // extension - { id: '4', title: 'count' }, // count - { id: '5', title: 'avg bytes' }, // avg + { id: '0', name: 'date' }, // date + { id: '1', name: 'date utc_time' }, // date + { id: '2', name: 'ext' }, // extension + { id: '3', name: 'geo.src' }, // extension + { id: '4', name: 'count' }, // count + { id: '5', name: 'avg bytes' }, // avg ], - rows: [], - }; + rows: [] as Row[], + } as Table; dimensions = { - x: { accessor: x }, - y: { accessor: y }, - series: { accessor: group }, - }; + x: { accessor: x } as Dimension, + y: [{ accessor: y } as Dimension], + series: [{ accessor: group } as Dimension], + } as Dimensions; } it('produces an aspect object for each of the aspect types found in the columns', function() { @@ -55,8 +55,8 @@ describe('getAspects', function() { const aspects = getAspects(table, dimensions); validate(aspects.x[0], '0'); - validate(aspects.series[0], '1'); - validate(aspects.y[0], '2'); + validate(aspects.series![0], '1'); + validate(aspects.y![0], '2'); }); it('creates a fake x aspect if the column does not exist', function() { @@ -64,9 +64,8 @@ describe('getAspects', function() { const aspects = getAspects(table, dimensions); - expect(aspects.x[0]) - .to.be.an('object') - .and.have.property('accessor', -1) - .and.have.property('title'); + expect(aspects.x[0]).toEqual(expect.any(Object)); + expect(aspects.x[0]).toHaveProperty('accessor', -1); + expect(aspects.x[0]).toHaveProperty('title'); }); }); diff --git a/src/legacy/ui/public/agg_response/point_series/_get_aspects.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts similarity index 72% rename from src/legacy/ui/public/agg_response/point_series/_get_aspects.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts index fe74d8566c0e7..29134409ddd5f 100644 --- a/src/legacy/ui/public/agg_response/point_series/_get_aspects.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_aspects.ts @@ -18,20 +18,22 @@ */ import { makeFakeXAspect } from './_fake_x_aspect'; +import { Dimensions, Aspects } from './point_series'; +import { Table } from '../../types'; /** * Identify and group the columns based on the aspect of the pointSeries * they represent. * - * @param {array} columns - the list of columns * @return {object} - an object with a key for each aspect (see map). The values - * may be undefined, a single aspect, or an array of aspects. + * may be undefined or an array of aspects. */ -export function getAspects(table, dimensions) { - const aspects = {}; - Object.keys(dimensions).forEach(name => { - const dimension = Array.isArray(dimensions[name]) ? dimensions[name] : [dimensions[name]]; - dimension.forEach(d => { +export function getAspects(table: Table, dimensions: Dimensions) { + const aspects: Partial = {}; + (Object.keys(dimensions) as Array).forEach(name => { + const dimension = dimensions[name]; + const dimensionList = Array.isArray(dimension) ? dimension : [dimension]; + dimensionList.forEach(d => { if (!d) { return; } @@ -42,7 +44,7 @@ export function getAspects(table, dimensions) { if (!aspects[name]) { aspects[name] = []; } - aspects[name].push({ + aspects[name]!.push({ accessor: column.id, column: d.accessor, title: column.name, @@ -56,5 +58,5 @@ export function getAspects(table, dimensions) { aspects.x = [makeFakeXAspect()]; } - return aspects; + return aspects as Aspects; } diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts new file mode 100644 index 0000000000000..0c79c5b263cea --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.test.ts @@ -0,0 +1,104 @@ +/* + * 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 { IFieldFormatsRegistry } from '../../../../../../../plugins/data/common'; +import { getPoint } from './_get_point'; +import { setFormatService } from '../../../services'; +import { Aspect } from './point_series'; +import { Table, Row, Column } from '../../types'; + +describe('getPoint', function() { + let deserialize: IFieldFormatsRegistry['deserialize']; + + beforeAll(() => { + deserialize = jest.fn(() => ({ + convert: jest.fn(v => v), + })) as any; + + setFormatService({ + deserialize, + } as any); + }); + + const table = { + columns: [{ id: '0' }, { id: '1' }, { id: '3' }] as Column[], + rows: [ + { '0': 1, '1': 2, '2': 3 }, + { '0': 4, '1': 'NaN', '2': 6 }, + ], + } as Table; + + describe('Without series aspect', function() { + let seriesAspect: undefined; + let xAspect: Aspect; + let yAspect: Aspect; + + beforeEach(function() { + xAspect = { accessor: '0' } as Aspect; + yAspect = { accessor: '1', title: 'Y' } as Aspect; + }); + + it('properly unwraps values', function() { + const row = table.rows[0]; + const zAspect = { accessor: '2' } as Aspect; + const point = getPoint(table, xAspect, seriesAspect, row, 0, yAspect, zAspect); + + expect(point).toHaveProperty('x', 1); + expect(point).toHaveProperty('y', 2); + expect(point).toHaveProperty('z', 3); + expect(point).toHaveProperty('series', yAspect.title); + }); + + it('ignores points with a y value of NaN', function() { + const row = table.rows[1]; + const point = getPoint(table, xAspect, seriesAspect, row, 1, yAspect); + expect(point).toBe(void 0); + }); + }); + + describe('With series aspect', function() { + let row: Row; + let xAspect: Aspect; + let yAspect: Aspect; + + beforeEach(function() { + row = table.rows[0]; + xAspect = { accessor: '0' } as Aspect; + yAspect = { accessor: '2' } as Aspect; + }); + + it('properly unwraps values', function() { + const seriesAspect = [{ accessor: '1' } as Aspect]; + const point = getPoint(table, xAspect, seriesAspect, row, 0, yAspect); + + expect(point).toHaveProperty('x', 1); + expect(point).toHaveProperty('series', '2'); + expect(point).toHaveProperty('y', 3); + }); + + it('should call deserialize', function() { + const seriesAspect = [ + { accessor: '1', format: { id: 'number', params: { pattern: '$' } } } as Aspect, + ]; + getPoint(table, xAspect, seriesAspect, row, 0, yAspect); + + expect(deserialize).toHaveBeenCalledWith(seriesAspect[0].format); + }); + }); +}); diff --git a/src/legacy/ui/public/agg_response/point_series/_get_point.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts similarity index 69% rename from src/legacy/ui/public/agg_response/point_series/_get_point.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts index 11e639f3f54a8..3fc13eb0c04b5 100644 --- a/src/legacy/ui/public/agg_response/point_series/_get_point.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_point.ts @@ -17,19 +17,55 @@ * under the License. */ -import { getFormat } from '../../visualize/loader/pipeline_helpers/utilities'; +import { getFormatService } from '../../../services'; +import { Aspect } from './point_series'; +import { Table, Row } from '../../types'; -export function getPoint(table, x, series, yScale, row, rowIndex, y, z) { +type RowValue = number | string | object | 'NaN'; +interface Raw { + table: Table; + column: number | undefined; + row: number | undefined; + value?: RowValue; +} +export interface Point { + x: RowValue | '_all'; + y: RowValue; + z?: RowValue; + extraMetrics: []; + seriesRaw?: Raw; + xRaw: Raw; + yRaw: Raw; + zRaw?: Raw; + tableRaw?: { + table: Table; + column: number; + row: number; + value: number; + title: string; + }; + parent: Aspect | null; + series?: string; + seriesId?: string; +} +export function getPoint( + table: Table, + x: Aspect, + series: Aspect[] | undefined, + row: Row, + rowIndex: number, + y: Aspect, + z?: Aspect +): Point | undefined { const xRow = x.accessor === -1 ? '_all' : row[x.accessor]; const yRow = row[y.accessor]; const zRow = z && row[z.accessor]; - const point = { + const point: Point = { x: xRow, y: yRow, z: zRow, extraMetrics: [], - yScale: yScale, seriesRaw: series && { table, column: series[0].column, @@ -71,10 +107,9 @@ export function getPoint(table, x, series, yScale, row, rowIndex, y, z) { } if (series) { - const seriesArray = series.length ? series : [series]; - point.series = seriesArray + point.series = series .map(s => { - const fieldFormatter = getFormat(s.format); + const fieldFormatter = getFormatService().deserialize(s.format); return fieldFormatter.convert(row[s.accessor]); }) .join(' - '); @@ -84,9 +119,5 @@ export function getPoint(table, x, series, yScale, row, rowIndex, y, z) { point.series = y.title; } - if (yScale) { - point.y *= yScale; - } - return point; } diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.test.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.test.ts new file mode 100644 index 0000000000000..6b94b9de8e15f --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.test.ts @@ -0,0 +1,281 @@ +/* + * 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 { getSeries } from './_get_series'; +import { setFormatService } from '../../../services'; +import { Chart, Aspect } from './point_series'; +import { Table, Column } from '../../types'; +import { Serie } from './_add_to_siri'; +import { Point } from './_get_point'; + +describe('getSeries', function() { + beforeAll(() => { + setFormatService({ + deserialize: () => ({ + convert: jest.fn(v => v), + }), + } as any); + }); + + it('produces a single series with points for each row', function() { + const table = { + columns: [{ id: '0' }, { id: '1' }, { id: '3' }] as Column[], + rows: [ + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + ], + } as Table; + + const chart = { + aspects: { + x: [{ accessor: '0' }], + y: [{ accessor: '1', title: 'y' }], + z: [{ accessor: '2' }], + }, + } as Chart; + + const series = getSeries(table, chart); + + expect(series).toEqual(expect.any(Array)); + expect(series).toHaveLength(1); + + const siri = series[0]; + + expect(siri).toEqual(expect.any(Object)); + expect(siri).toHaveProperty('label', chart.aspects.y[0].title); + expect(siri).toHaveProperty('values'); + + expect(siri.values).toEqual(expect.any(Array)); + expect(siri.values).toHaveLength(5); + + siri.values.forEach(point => { + expect(point).toHaveProperty('x', 1); + expect(point).toHaveProperty('y', 2); + expect(point).toHaveProperty('z', 3); + }); + }); + + it('adds the seriesId to each point', function() { + const table = { + columns: [{ id: '0' }, { id: '1' }, { id: '3' }] as Column[], + rows: [ + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + ], + } as Table; + + const chart = { + aspects: { + x: [{ accessor: '0' }], + y: [ + { accessor: '1', title: '0' }, + { accessor: '2', title: '1' }, + ], + }, + } as Chart; + + const series = getSeries(table, chart); + + series[0].values.forEach(point => { + expect(point).toHaveProperty('seriesId', '1'); + }); + + series[1].values.forEach(point => { + expect(point).toHaveProperty('seriesId', '2'); + }); + }); + + it('produces multiple series if there are multiple y aspects', function() { + const table = { + columns: [{ id: '0' }, { id: '1' }, { id: '3' }] as Column[], + rows: [ + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + ], + } as Table; + + const chart = { + aspects: { + x: [{ accessor: '0' }], + y: [ + { accessor: '1', title: '0' }, + { accessor: '2', title: '1' }, + ], + }, + } as Chart; + + const series = getSeries(table, chart); + + expect(series).toEqual(expect.any(Array)); + expect(series).toHaveLength(2); + + series.forEach(function(siri: Serie, i: number) { + expect(siri).toEqual(expect.any(Object)); + expect(siri).toHaveProperty('label', '' + i); + expect(siri).toHaveProperty('values'); + + expect(siri.values).toEqual(expect.any(Array)); + expect(siri.values).toHaveLength(5); + + siri.values.forEach(function(point: Point) { + expect(point).toHaveProperty('x', 1); + expect(point).toHaveProperty('y', i + 2); + }); + }); + }); + + it('produces multiple series if there is a series aspect', function() { + const table = { + columns: [{ id: '0' }, { id: '1' }, { id: '3' }] as Column[], + rows: [ + { '0': 0, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 0, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 0, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + ], + } as Table; + + const chart = { + aspects: { + x: [{ accessor: -1 } as Aspect], + series: [{ accessor: '0' }], + y: [{ accessor: '1', title: '0' }], + }, + } as Chart; + + const series = getSeries(table, chart); + + expect(series).toEqual(expect.any(Array)); + expect(series).toHaveLength(2); + + series.forEach(function(siri: Serie, i: number) { + expect(siri).toEqual(expect.any(Object)); + expect(siri).toHaveProperty('label', '' + i); + expect(siri).toHaveProperty('values'); + + expect(siri.values).toEqual(expect.any(Array)); + expect(siri.values).toHaveLength(3); + + siri.values.forEach(function(point: Point) { + expect(point).toHaveProperty('y', 2); + }); + }); + }); + + it('produces multiple series if there is a series aspect and multiple y aspects', function() { + const table = { + columns: [{ id: '0' }, { id: '1' }, { id: '3' }] as Column[], + rows: [ + { '0': 0, '1': 3, '2': 4 }, + { '0': 1, '1': 3, '2': 4 }, + { '0': 0, '1': 3, '2': 4 }, + { '0': 1, '1': 3, '2': 4 }, + { '0': 0, '1': 3, '2': 4 }, + { '0': 1, '1': 3, '2': 4 }, + ], + } as Table; + + const chart = { + aspects: { + x: [{ accessor: -1 } as Aspect], + series: [{ accessor: '0' }], + y: [ + { accessor: '1', title: '0' }, + { accessor: '2', title: '1' }, + ], + }, + } as Chart; + + const series = getSeries(table, chart); + + expect(series).toEqual(expect.any(Array)); + expect(series).toHaveLength(4); // two series * two metrics + + checkSiri(series[0], '0: 0', 3); + checkSiri(series[1], '0: 1', 4); + checkSiri(series[2], '1: 0', 3); + checkSiri(series[3], '1: 1', 4); + + function checkSiri(siri: Serie, label: string, y: number) { + expect(siri).toEqual(expect.any(Object)); + expect(siri).toHaveProperty('label', label); + expect(siri).toHaveProperty('values'); + + expect(siri.values).toEqual(expect.any(Array)); + expect(siri.values).toHaveLength(3); + + siri.values.forEach(function(point: Point) { + expect(point).toHaveProperty('y', y); + }); + } + }); + + it('produces a series list in the same order as its corresponding metric column', function() { + const table = { + columns: [{ id: '0' }, { id: '1' }, { id: '3' }] as Column[], + rows: [ + { '0': 0, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 0, '1': 2, '2': 3 }, + { '0': 1, '1': 2, '2': 3 }, + { '0': 0, '1': 2, '2': 3 }, + ], + } as Table; + + const chart = { + aspects: { + x: [{ accessor: -1 } as Aspect], + series: [{ accessor: '0' }], + y: [ + { accessor: '1', title: '0' }, + { accessor: '2', title: '1' }, + ], + }, + } as Chart; + + const series = getSeries(table, chart); + expect(series[0]).toHaveProperty('label', '0: 0'); + expect(series[1]).toHaveProperty('label', '0: 1'); + expect(series[2]).toHaveProperty('label', '1: 0'); + expect(series[3]).toHaveProperty('label', '1: 1'); + + // switch the order of the y columns + chart.aspects.y = chart.aspects.y.reverse(); + chart.aspects.y.forEach(function(y: any, i) { + y.i = i; + }); + + const series2 = getSeries(table, chart); + expect(series2[0]).toHaveProperty('label', '0: 1'); + expect(series2[1]).toHaveProperty('label', '0: 0'); + expect(series2[2]).toHaveProperty('label', '1: 1'); + expect(series2[3]).toHaveProperty('label', '1: 0'); + }); +}); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.ts new file mode 100644 index 0000000000000..edde5b69af022 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_get_series.ts @@ -0,0 +1,88 @@ +/* + * 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 { partial } from 'lodash'; +import { getPoint } from './_get_point'; +import { addToSiri, Serie } from './_add_to_siri'; +import { Chart } from './point_series'; +import { Table } from '../../types'; + +export function getSeries(table: Table, chart: Chart) { + const aspects = chart.aspects; + const xAspect = aspects.x[0]; + const yAspect = aspects.y[0]; + const zAspect = aspects.z && aspects.z[0]; + const multiY = Array.isArray(aspects.y) && aspects.y.length > 1; + + const partGetPoint = partial(getPoint, table, xAspect, aspects.series); + + const seriesMap = new Map(); + + table.rows.forEach((row, rowIndex) => { + if (!multiY) { + const point = partGetPoint(row, rowIndex, yAspect, zAspect); + if (point) { + const id = `${point.series}-${yAspect.accessor}`; + point.seriesId = id; + addToSiri( + seriesMap, + point, + id, + point.series, + yAspect.format, + zAspect && zAspect.format, + zAspect && zAspect.title + ); + } + return; + } + + aspects.y.forEach(function(y) { + const point = partGetPoint(row, rowIndex, y, zAspect); + if (!point) { + return; + } + + // use the point's y-axis as it's series by default, + // but augment that with series aspect if it's actually + // available + let seriesId = y.accessor; + let seriesLabel = y.title; + + if (aspects.series) { + const prefix = point.series ? point.series + ': ' : ''; + seriesId = prefix + seriesId; + seriesLabel = prefix + seriesLabel; + } + + point.seriesId = seriesId; + addToSiri( + seriesMap, + point, + seriesId as string, + seriesLabel, + y.format, + zAspect && zAspect.format, + zAspect && zAspect.title + ); + }); + }); + + return [...seriesMap.values()]; +} diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_x_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts similarity index 51% rename from src/legacy/ui/public/agg_response/point_series/__tests__/_init_x_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts index a8512edee658b..d3049d7675408 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_x_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.test.ts @@ -17,14 +17,22 @@ * under the License. */ -import expect from '@kbn/expect'; import moment from 'moment'; -import { initXAxis } from '../_init_x_axis'; -import { makeFakeXAspect } from '../_fake_x_aspect'; +import { initXAxis } from './_init_x_axis'; +import { makeFakeXAspect } from './_fake_x_aspect'; +import { + Aspects, + Chart, + DateHistogramOrdered, + DateHistogramParams, + HistogramOrdered, + HistogramParams, +} from './point_series'; +import { Table, Column } from '../../types'; describe('initXAxis', function() { - let chart; - let table; + let chart: Chart; + let table: Table; beforeEach(function() { chart = { @@ -32,50 +40,48 @@ describe('initXAxis', function() { x: [ { ...makeFakeXAspect(), - accessor: 0, + accessor: '0', title: 'label', }, ], - }, - }; + } as Aspects, + } as Chart; table = { - columns: [{ id: '0' }], + columns: [{ id: '0' } as Column], rows: [{ '0': 'hello' }, { '0': 'world' }, { '0': 'foo' }, { '0': 'bar' }, { '0': 'baz' }], }; }); it('sets the xAxisFormatter if the agg is not ordered', function() { initXAxis(chart, table); - expect(chart) - .to.have.property('xAxisLabel', 'label') - .and.have.property('xAxisFormat', chart.aspects.x[0].format); + expect(chart).toHaveProperty('xAxisLabel', 'label'); + expect(chart).toHaveProperty('xAxisFormat', chart.aspects.x[0].format); }); it('makes the chart ordered if the agg is ordered', function() { - chart.aspects.x[0].params.interval = 10; + (chart.aspects.x[0].params as HistogramParams).interval = 10; initXAxis(chart, table); - expect(chart) - .to.have.property('xAxisLabel', 'label') - .and.have.property('xAxisFormat', chart.aspects.x[0].format) - .and.have.property('ordered'); + expect(chart).toHaveProperty('xAxisLabel', 'label'); + expect(chart).toHaveProperty('xAxisFormat', chart.aspects.x[0].format); + expect(chart).toHaveProperty('ordered'); }); describe('xAxisOrderedValues', function() { it('sets the xAxisOrderedValues property', function() { initXAxis(chart, table); - expect(chart).to.have.property('xAxisOrderedValues'); + expect(chart).toHaveProperty('xAxisOrderedValues'); }); it('returns a list of values, preserving the table order', function() { initXAxis(chart, table); - expect(chart.xAxisOrderedValues).to.eql(['hello', 'world', 'foo', 'bar', 'baz']); + expect(chart.xAxisOrderedValues).toEqual(['hello', 'world', 'foo', 'bar', 'baz']); }); it('only returns unique values', function() { table = { - columns: [{ id: '0' }], + columns: [{ id: '0' } as Column], rows: [ { '0': 'hello' }, { '0': 'world' }, @@ -88,45 +94,46 @@ describe('initXAxis', function() { ], }; initXAxis(chart, table); - expect(chart.xAxisOrderedValues).to.eql(['hello', 'world', 'foo', 'bar', 'baz']); + expect(chart.xAxisOrderedValues).toEqual(['hello', 'world', 'foo', 'bar', 'baz']); }); it('returns the defaultValue if using fake x aspect', function() { chart = { aspects: { x: [makeFakeXAspect()], - }, - }; + } as Aspects, + } as Chart; initXAxis(chart, table); - expect(chart.xAxisOrderedValues).to.eql(['_all']); + expect(chart.xAxisOrderedValues).toEqual(['_all']); }); }); it('reads the date interval param from the x agg', function() { - chart.aspects.x[0].params.interval = 'P1D'; - chart.aspects.x[0].params.intervalESValue = 1; - chart.aspects.x[0].params.intervalESUnit = 'd'; - chart.aspects.x[0].params.date = true; + const dateHistogramParams = chart.aspects.x[0].params as DateHistogramParams; + dateHistogramParams.interval = 'P1D'; + dateHistogramParams.intervalESValue = 1; + dateHistogramParams.intervalESUnit = 'd'; + dateHistogramParams.date = true; initXAxis(chart, table); - expect(chart) - .to.have.property('xAxisLabel', 'label') - .and.have.property('xAxisFormat', chart.aspects.x[0].format) - .and.have.property('ordered'); + expect(chart).toHaveProperty('xAxisLabel', 'label'); + expect(chart).toHaveProperty('xAxisFormat', chart.aspects.x[0].format); + expect(chart).toHaveProperty('ordered'); - expect(moment.isDuration(chart.ordered.interval)).to.be(true); - expect(chart.ordered.interval.toISOString()).to.eql('P1D'); - expect(chart.ordered.intervalESValue).to.be(1); - expect(chart.ordered.intervalESUnit).to.be('d'); + expect(chart.ordered).toEqual(expect.any(Object)); + const { intervalESUnit, intervalESValue, interval } = chart.ordered as DateHistogramOrdered; + expect(moment.isDuration(interval)).toBe(true); + expect(interval.toISOString()).toEqual('P1D'); + expect(intervalESValue).toBe(1); + expect(intervalESUnit).toBe('d'); }); it('reads the numeric interval param from the x agg', function() { - chart.aspects.x[0].params.interval = 0.5; + (chart.aspects.x[0].params as HistogramParams).interval = 0.5; initXAxis(chart, table); - expect(chart) - .to.have.property('xAxisLabel', 'label') - .and.have.property('xAxisFormat', chart.aspects.x[0].format) - .and.have.property('ordered'); + expect(chart).toHaveProperty('xAxisLabel', 'label'); + expect(chart).toHaveProperty('xAxisFormat', chart.aspects.x[0].format); + expect(chart).toHaveProperty('ordered'); - expect(chart.ordered.interval).to.eql(0.5); + expect((chart.ordered as HistogramOrdered).interval).toEqual(0.5); }); }); diff --git a/src/legacy/ui/public/agg_response/point_series/_init_x_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts similarity index 73% rename from src/legacy/ui/public/agg_response/point_series/_init_x_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts index 4a81486783b08..9d16c4857be00 100644 --- a/src/legacy/ui/public/agg_response/point_series/_init_x_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_x_axis.ts @@ -19,27 +19,31 @@ import { uniq } from 'lodash'; import moment from 'moment'; +import { Chart } from './point_series'; +import { Table } from '../../types'; -export function initXAxis(chart, table) { +export function initXAxis(chart: Chart, table: Table) { const { format, title, params, accessor } = chart.aspects.x[0]; chart.xAxisOrderedValues = - accessor === -1 ? [params.defaultValue] : uniq(table.rows.map(r => r[accessor])); + accessor === -1 && 'defaultValue' in params + ? [params.defaultValue] + : uniq(table.rows.map(r => r[accessor])); chart.xAxisFormat = format; chart.xAxisLabel = title; - const { interval, date } = params; - if (interval) { - if (date) { + if ('interval' in params) { + const { interval } = params; + if ('date' in params) { const { intervalESUnit, intervalESValue } = params; chart.ordered = { interval: moment.duration(interval), - intervalESUnit: intervalESUnit, - intervalESValue: intervalESValue, + intervalESUnit, + intervalESValue, }; } else { chart.ordered = { - interval, + interval: params.interval, }; } } diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_y_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.test.ts similarity index 81% rename from src/legacy/ui/public/agg_response/point_series/__tests__/_init_y_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.test.ts index 78cd5334e6c86..df84d69c9f849 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_init_y_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.test.ts @@ -18,8 +18,8 @@ */ import _ from 'lodash'; -import expect from '@kbn/expect'; -import { initYAxis } from '../_init_y_axis'; +import { initYAxis } from './_init_y_axis'; +import { Chart } from './point_series'; describe('initYAxis', function() { const baseChart = { @@ -34,7 +34,7 @@ describe('initYAxis', function() { }, ], }, - }; + } as Chart; describe('with a single y aspect', function() { const singleYBaseChart = _.cloneDeep(baseChart); @@ -43,13 +43,13 @@ describe('initYAxis', function() { it('sets the yAxisFormatter the the field formats convert fn', function() { const chart = _.cloneDeep(singleYBaseChart); initYAxis(chart); - expect(chart).to.have.property('yAxisFormat'); + expect(chart).toHaveProperty('yAxisFormat'); }); it('sets the yAxisLabel', function() { const chart = _.cloneDeep(singleYBaseChart); initYAxis(chart); - expect(chart).to.have.property('yAxisLabel', 'y1'); + expect(chart).toHaveProperty('yAxisLabel', 'y1'); }); }); @@ -58,16 +58,15 @@ describe('initYAxis', function() { const chart = _.cloneDeep(baseChart); initYAxis(chart); - expect(chart).to.have.property('yAxisFormat'); - expect(chart.yAxisFormat) - .to.be(chart.aspects.y[0].format) - .and.not.be(chart.aspects.y[1].format); + expect(chart).toHaveProperty('yAxisFormat'); + expect(chart.yAxisFormat).toBe(chart.aspects.y[0].format); + expect(chart.yAxisFormat).not.toBe(chart.aspects.y[1].format); }); it('does not set the yAxisLabel, it does not make sense to put multiple labels on the same axis', function() { const chart = _.cloneDeep(baseChart); initYAxis(chart); - expect(chart).to.have.property('yAxisLabel', ''); + expect(chart).toHaveProperty('yAxisLabel', ''); }); }); }); diff --git a/src/legacy/ui/public/agg_response/point_series/_init_y_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.ts similarity index 82% rename from src/legacy/ui/public/agg_response/point_series/_init_y_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.ts index 42f5e79a63172..43ba0557949ac 100644 --- a/src/legacy/ui/public/agg_response/point_series/_init_y_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_init_y_axis.ts @@ -17,7 +17,9 @@ * under the License. */ -export function initYAxis(chart) { +import { Chart } from './point_series'; + +export function initYAxis(chart: Chart) { const y = chart.aspects.y; if (Array.isArray(y)) { @@ -28,12 +30,7 @@ export function initYAxis(chart) { const z = chart.aspects.series; if (z) { - if (Array.isArray(z)) { - chart.zAxisFormat = z[0].format; - chart.zAxisLabel = ''; - } else { - chart.zAxisFormat = z.format; - chart.zAxisLabel = z.title; - } + chart.zAxisFormat = z[0].format; + chart.zAxisLabel = ''; } } diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts similarity index 76% rename from src/legacy/ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts index 2e08be16278d5..25e466f21c3e7 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_ordered_date_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.test.ts @@ -19,8 +19,8 @@ import moment from 'moment'; import _ from 'lodash'; -import expect from '@kbn/expect'; -import { orderedDateAxis } from '../_ordered_date_axis'; +import { orderedDateAxis } from './_ordered_date_axis'; +import { DateHistogramParams, OrderedChart } from './point_series'; describe('orderedDateAxis', function() { const baseArgs = { @@ -46,7 +46,7 @@ describe('orderedDateAxis', function() { }, ], }, - }, + } as OrderedChart, }; describe('ordered object', function() { @@ -54,24 +54,24 @@ describe('orderedDateAxis', function() { const args = _.cloneDeep(baseArgs); orderedDateAxis(args.chart); - expect(args.chart).to.have.property('ordered'); + expect(args.chart).toHaveProperty('ordered'); - expect(args.chart.ordered).to.have.property('date', true); + expect(args.chart.ordered).toHaveProperty('date', true); }); it('sets the min/max when the buckets are bounded', function() { const args = _.cloneDeep(baseArgs); orderedDateAxis(args.chart); - expect(args.chart.ordered).to.have.property('min'); - expect(args.chart.ordered).to.have.property('max'); + expect(args.chart.ordered).toHaveProperty('min'); + expect(args.chart.ordered).toHaveProperty('max'); }); it('does not set the min/max when the buckets are unbounded', function() { const args = _.cloneDeep(baseArgs); - args.chart.aspects.x[0].params.bounds = null; + (args.chart.aspects.x[0].params as DateHistogramParams).bounds = undefined; orderedDateAxis(args.chart); - expect(args.chart.ordered).to.not.have.property('min'); - expect(args.chart.ordered).to.not.have.property('max'); + expect(args.chart.ordered).not.toHaveProperty('min'); + expect(args.chart.ordered).not.toHaveProperty('max'); }); }); }); diff --git a/src/legacy/ui/public/agg_response/point_series/_ordered_date_axis.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.ts similarity index 72% rename from src/legacy/ui/public/agg_response/point_series/_ordered_date_axis.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.ts index a1dd50dc6c71b..193b10a563563 100644 --- a/src/legacy/ui/public/agg_response/point_series/_ordered_date_axis.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/_ordered_date_axis.ts @@ -17,17 +17,17 @@ * under the License. */ -// import moment from 'moment'; +import { OrderedChart } from './point_series'; -export function orderedDateAxis(chart) { +export function orderedDateAxis(chart: OrderedChart) { const x = chart.aspects.x[0]; - const { bounds } = x.params; + const bounds = 'bounds' in x.params ? x.params.bounds : undefined; chart.ordered.date = true; if (bounds) { - chart.ordered.min = isNaN(bounds.min) ? Date.parse(bounds.min) : bounds.min; - chart.ordered.max = isNaN(bounds.max) ? Date.parse(bounds.max) : bounds.max; + chart.ordered.min = typeof bounds.min === 'string' ? Date.parse(bounds.min) : bounds.min; + chart.ordered.max = typeof bounds.max === 'string' ? Date.parse(bounds.max) : bounds.max; } else { chart.ordered.endzones = false; } diff --git a/src/legacy/ui/public/agg_response/index.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/index.ts similarity index 69% rename from src/legacy/ui/public/agg_response/index.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/index.ts index 982c1c25a8101..9bfba4de966be 100644 --- a/src/legacy/ui/public/agg_response/index.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/index.ts @@ -17,12 +17,4 @@ * under the License. */ -import { buildHierarchicalData } from './hierarchical/build_hierarchical_data'; -import { buildPointSeriesData } from './point_series/point_series'; -import { search } from '../../../../plugins/data/public'; - -export const aggResponseIndex = { - hierarchical: buildHierarchicalData, - pointSeries: buildPointSeriesData, - tabify: search.tabifyAggResponse, -}; +export { buildPointSeriesData } from './point_series'; diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_main.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts similarity index 62% rename from src/legacy/ui/public/agg_response/point_series/__tests__/_main.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts index a4c23cb537488..3725bf06660e2 100644 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_main.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.test.ts @@ -18,17 +18,25 @@ */ import _ from 'lodash'; -import expect from '@kbn/expect'; -import { buildPointSeriesData } from '../point_series'; +import { buildPointSeriesData, Dimensions } from './point_series'; +import { Table, Column } from '../../types'; +import { setFormatService } from '../../../services'; +import { Serie } from './_add_to_siri'; describe('pointSeriesChartDataFromTable', function() { - this.slow(1000); + beforeAll(() => { + setFormatService({ + deserialize: () => ({ + convert: jest.fn(v => v), + }), + } as any); + }); it('handles a table with just a count', function() { const table = { - columns: [{ id: '0' }], + columns: [{ id: '0' } as Column], rows: [{ '0': 100 }], - }; + } as Table; const chartData = buildPointSeriesData(table, { y: [ { @@ -36,16 +44,15 @@ describe('pointSeriesChartDataFromTable', function() { params: {}, }, ], - }); + } as Dimensions); - expect(chartData).to.be.an('object'); - expect(chartData.series).to.be.an('array'); - expect(chartData.series).to.have.length(1); + expect(chartData).toEqual(expect.any(Object)); + expect(chartData.series).toEqual(expect.any(Array)); + expect(chartData.series).toHaveLength(1); const series = chartData.series[0]; - expect(series.values).to.have.length(1); - expect(series.values[0]) - .to.have.property('x', '_all') - .and.have.property('y', 100); + expect(series.values).toHaveLength(1); + expect(series.values[0]).toHaveProperty('x', '_all'); + expect(series.values[0]).toHaveProperty('y', 100); }); it('handles a table with x and y column', function() { @@ -59,21 +66,21 @@ describe('pointSeriesChartDataFromTable', function() { { '0': 2, '1': 200 }, { '0': 3, '1': 200 }, ], - }; + } as Table; const dimensions = { - x: [{ accessor: 0, params: {} }], + x: { accessor: 0, params: {} }, y: [{ accessor: 1, params: {} }], - }; + } as Dimensions; const chartData = buildPointSeriesData(table, dimensions); - expect(chartData).to.be.an('object'); - expect(chartData.series).to.be.an('array'); - expect(chartData.series).to.have.length(1); + expect(chartData).toEqual(expect.any(Object)); + expect(chartData.series).toEqual(expect.any(Array)); + expect(chartData.series).toHaveLength(1); const series = chartData.series[0]; - expect(series).to.have.property('label', 'Count'); - expect(series.values).to.have.length(3); + expect(series).toHaveProperty('label', 'Count'); + expect(series.values).toHaveLength(3); }); it('handles a table with an x and two y aspects', function() { @@ -84,23 +91,23 @@ describe('pointSeriesChartDataFromTable', function() { { '0': 2, '1': 200, '2': 300 }, { '0': 3, '1': 200, '2': 300 }, ], - }; + } as Table; const dimensions = { - x: [{ accessor: 0, params: {} }], + x: { accessor: 0, params: {} }, y: [ { accessor: 1, params: {} }, { accessor: 2, params: {} }, ], - }; + } as Dimensions; const chartData = buildPointSeriesData(table, dimensions); - expect(chartData).to.be.an('object'); - expect(chartData.series).to.be.an('array'); - expect(chartData.series).to.have.length(2); - chartData.series.forEach(function(siri, i) { - expect(siri).to.have.property('label', `Count-${i}`); - expect(siri.values).to.have.length(3); + expect(chartData).toEqual(expect.any(Object)); + expect(chartData.series).toEqual(expect.any(Array)); + expect(chartData.series).toHaveLength(2); + chartData.series.forEach(function(siri: Serie, i: number) { + expect(siri).toHaveProperty('label', `Count-${i}`); + expect(siri.values).toHaveLength(3); }); }); @@ -121,21 +128,21 @@ describe('pointSeriesChartDataFromTable', function() { }; const dimensions = { - x: [{ accessor: 0, params: {} }], + x: { accessor: 0, params: {} }, series: [{ accessor: 1, params: {} }], y: [ { accessor: 2, params: {} }, { accessor: 3, params: {} }, ], - }; + } as Dimensions; const chartData = buildPointSeriesData(table, dimensions); - expect(chartData).to.be.an('object'); - expect(chartData.series).to.be.an('array'); + expect(chartData).toEqual(expect.any(Object)); + expect(chartData.series).toEqual(expect.any(Array)); // one series for each extension, and then one for each metric inside - expect(chartData.series).to.have.length(4); - chartData.series.forEach(function(siri) { - expect(siri.values).to.have.length(2); + expect(chartData.series).toHaveLength(4); + chartData.series.forEach(function(siri: Serie) { + expect(siri.values).toHaveLength(2); }); }); }); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts new file mode 100644 index 0000000000000..a1681e0d71bd3 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/helpers/point_series/point_series.ts @@ -0,0 +1,118 @@ +/* + * 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 { Duration } from 'moment'; +import { getSeries } from './_get_series'; +import { getAspects } from './_get_aspects'; +import { initYAxis } from './_init_y_axis'; +import { initXAxis } from './_init_x_axis'; +import { orderedDateAxis } from './_ordered_date_axis'; +import { Serie } from './_add_to_siri'; +import { Column, Table } from '../../types'; + +export interface DateHistogramParams { + date: boolean; + interval: string; + intervalESValue: number; + intervalESUnit: string; + format: string; + bounds?: { + min: string | number; + max: string | number; + }; +} +export interface HistogramParams { + interval: number; +} +export interface FakeParams { + defaultValue: string; +} +export interface Dimension { + accessor: number; + format: { + id?: string; + params?: { pattern?: string; [key: string]: any }; + }; + params: DateHistogramParams | HistogramParams | FakeParams | {}; +} + +export interface Dimensions { + x: Dimension | null; + y: Dimension[]; + z?: Dimension[]; + series?: Dimension | Dimension[]; +} +export interface Aspect { + accessor: Column['id']; + column?: Dimension['accessor']; + title: Column['name']; + format: Dimension['format']; + params: Dimension['params']; +} +export type Aspects = { x: Aspect[]; y: Aspect[] } & { [key in keyof Dimensions]?: Aspect[] }; + +export interface DateHistogramOrdered { + interval: Duration; + intervalESUnit: DateHistogramParams['intervalESUnit']; + intervalESValue: DateHistogramParams['intervalESValue']; +} +export interface HistogramOrdered { + interval: HistogramParams['interval']; +} + +type Ordered = (DateHistogramOrdered | HistogramOrdered) & { + date?: boolean; + min?: number; + max?: number; + endzones?: boolean; +}; + +export interface Chart { + aspects: Aspects; + series: Serie[]; + xAxisOrderedValues?: Array; + xAxisFormat?: Dimension['format']; + xAxisLabel?: Column['name']; + yAxisFormat?: Dimension['format']; + yAxisLabel?: Column['name']; + zAxisFormat?: Dimension['format']; + zAxisLabel?: Column['name']; + ordered?: Ordered; +} + +export type OrderedChart = Chart & { ordered: Ordered }; + +export const buildPointSeriesData = (table: Table, dimensions: Dimensions) => { + const chart = { + aspects: getAspects(table, dimensions), + } as Chart; + + initXAxis(chart, table); + initYAxis(chart); + + if ('date' in chart.aspects.x[0].params) { + // initXAxis will turn `chart` into an `OrderedChart if it is a date axis` + orderedDateAxis(chart as OrderedChart); + } + + chart.series = getSeries(table, chart); + + delete chart.aspects; + return chart; +}; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js index 9ba86c5181a4c..b5f80303b1d74 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.js @@ -17,8 +17,8 @@ * under the License. */ -import { buildHierarchicalData, buildPointSeriesData } from '../legacy_imports'; import { getFormatService } from '../services'; +import { buildHierarchicalData, buildPointSeriesData } from './helpers'; function tableResponseHandler(table, dimensions) { const converted = { tables: [] }; @@ -72,7 +72,7 @@ function tableResponseHandler(table, dimensions) { function convertTableGroup(tableGroup, convertTable) { const tables = tableGroup.tables; - if (!tables.length) return; + if (!tables || !tables.length) return; const firstChild = tables[0]; if (firstChild.columns) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.test.ts b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.test.ts new file mode 100644 index 0000000000000..4a8bebc493235 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/response_handler.test.ts @@ -0,0 +1,130 @@ +/* + * 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 { setFormatService } from '../services'; + +jest.mock('./helpers', () => ({ + buildHierarchicalData: jest.fn(() => ({})), + buildPointSeriesData: jest.fn(() => ({})), +})); + +// @ts-ignore +import { vislibSeriesResponseHandler, vislibSlicesResponseHandler } from './response_handler'; +import { buildHierarchicalData, buildPointSeriesData } from './helpers'; +import { Table } from './types'; + +describe('response_handler', () => { + describe('vislibSlicesResponseHandler', () => { + test('should not call buildHierarchicalData when no columns', () => { + vislibSlicesResponseHandler({ rows: [] }, {}); + expect(buildHierarchicalData).not.toHaveBeenCalled(); + }); + + test('should call buildHierarchicalData', () => { + const response = { + rows: [{ 'col-0-1': 1 }], + columns: [{ id: 'col-0-1', name: 'Count' }], + }; + const dimensions = { metric: { accessor: 0 } }; + vislibSlicesResponseHandler(response, dimensions); + + expect(buildHierarchicalData).toHaveBeenCalledWith( + { columns: [...response.columns], rows: [...response.rows] }, + dimensions + ); + }); + }); + + describe('vislibSeriesResponseHandler', () => { + let resp: Table; + let expected: any; + + beforeAll(() => { + setFormatService({ + deserialize: () => ({ + convert: jest.fn(v => v), + }), + } as any); + }); + + beforeAll(() => { + resp = { + rows: [ + { 'col-0-3': 158599872, 'col-1-1': 1 }, + { 'col-0-3': 158599893, 'col-1-1': 2 }, + { 'col-0-3': 158599908, 'col-1-1': 1 }, + ], + columns: [ + { id: 'col-0-3', name: 'timestamp per 30 seconds' }, + { id: 'col-1-1', name: 'Count' }, + ], + } as Table; + + const colId = resp.columns[0].id; + expected = [ + { label: `${resp.rows[0][colId]}: ${resp.columns[0].name}` }, + { label: `${resp.rows[1][colId]}: ${resp.columns[0].name}` }, + { label: `${resp.rows[2][colId]}: ${resp.columns[0].name}` }, + ]; + }); + + test('should not call buildPointSeriesData when no columns', () => { + vislibSeriesResponseHandler({ rows: [] }, {}); + expect(buildPointSeriesData).not.toHaveBeenCalled(); + }); + + test('should call buildPointSeriesData', () => { + const response = { + rows: [{ 'col-0-1': 1 }], + columns: [{ id: 'col-0-1', name: 'Count' }], + }; + const dimensions = { x: null, y: { accessor: 0 } }; + vislibSeriesResponseHandler(response, dimensions); + + expect(buildPointSeriesData).toHaveBeenCalledWith( + { columns: [...response.columns], rows: [...response.rows] }, + dimensions + ); + }); + + test('should split columns', () => { + const dimensions = { + x: null, + y: [{ accessor: 1 }], + splitColumn: [{ accessor: 0 }], + }; + + const convertedResp = vislibSlicesResponseHandler(resp, dimensions); + expect(convertedResp.columns).toHaveLength(resp.rows.length); + expect(convertedResp.columns).toEqual(expected); + }); + + test('should split rows', () => { + const dimensions = { + x: null, + y: [{ accessor: 1 }], + splitRow: [{ accessor: 0 }], + }; + + const convertedResp = vislibSlicesResponseHandler(resp, dimensions); + expect(convertedResp.rows).toHaveLength(resp.rows.length); + expect(convertedResp.rows).toEqual(expected); + }); + }); +}); diff --git a/src/legacy/ui/public/agg_response/point_series/_add_to_siri.js b/src/legacy/core_plugins/vis_type_vislib/public/vislib/types.ts similarity index 67% rename from src/legacy/ui/public/agg_response/point_series/_add_to_siri.js rename to src/legacy/core_plugins/vis_type_vislib/public/vislib/types.ts index 9a0fcbc7b267c..ad59603663b84 100644 --- a/src/legacy/ui/public/agg_response/point_series/_add_to_siri.js +++ b/src/legacy/core_plugins/vis_type_vislib/public/vislib/types.ts @@ -17,22 +17,26 @@ * under the License. */ -export function addToSiri(series, point, id, yLabel, yFormat, zFormat, zLabel) { - id = id == null ? '' : id + ''; +export interface Column { + // -1 value can be in a fake X aspect + id: string | -1; + name: string; +} - if (series.has(id)) { - series.get(id).values.push(point); - return; - } +export interface Row { + [key: string]: number | string | object; +} - series.set(id, { - id: id.split('-').pop(), - rawId: id, - label: yLabel == null ? id : yLabel, - count: 0, - values: [point], - format: yFormat, - zLabel, - zFormat, - }); +export interface TableParent { + table: Table; + tables?: Table[]; + column: number; + row: number; + key: number; + name: string; +} +export interface Table { + columns: Column[]; + rows: Row[]; + $parent?: TableParent; } diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js deleted file mode 100644 index 43a10ebbfb12e..0000000000000 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_add_to_siri.js +++ /dev/null @@ -1,82 +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 expect from '@kbn/expect'; -import { addToSiri } from '../_add_to_siri'; - -describe('addToSiri', function() { - it('creates a new series the first time it sees an id', function() { - const series = new Map(); - const point = {}; - const id = 'id'; - addToSiri(series, point, id, id, { id: id }); - - expect(series.has(id)).to.be(true); - expect(series.get(id)).to.be.an('object'); - expect(series.get(id).label).to.be(id); - expect(series.get(id).values).to.have.length(1); - expect(series.get(id).values[0]).to.be(point); - }); - - it('adds points to existing series if id has been seen', function() { - const series = new Map(); - const id = 'id'; - - const point = {}; - addToSiri(series, point, id, id, { id: id }); - - const point2 = {}; - addToSiri(series, point2, id, id, { id: id }); - - expect(series.has(id)).to.be(true); - expect(series.get(id)).to.be.an('object'); - expect(series.get(id).label).to.be(id); - expect(series.get(id).values).to.have.length(2); - expect(series.get(id).values[0]).to.be(point); - expect(series.get(id).values[1]).to.be(point2); - }); - - it('allows overriding the series label', function() { - const series = new Map(); - const id = 'id'; - const label = 'label'; - const point = {}; - addToSiri(series, point, id, label, { id: id }); - - expect(series.has(id)).to.be(true); - expect(series.get(id)).to.be.an('object'); - expect(series.get(id).label).to.be(label); - expect(series.get(id).values).to.have.length(1); - expect(series.get(id).values[0]).to.be(point); - }); - - it('correctly sets id and rawId', function() { - const series = new Map(); - const id = 'id-id2'; - - const point = {}; - addToSiri(series, point, id); - - expect(series.has(id)).to.be(true); - expect(series.get(id)).to.be.an('object'); - expect(series.get(id).label).to.be(id); - expect(series.get(id).rawId).to.be(id); - expect(series.get(id).id).to.be('id2'); - }); -}); diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js deleted file mode 100644 index 0eb2c608d6d6c..0000000000000 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_point.js +++ /dev/null @@ -1,97 +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 expect from '@kbn/expect'; -import { getPoint } from '../_get_point'; - -describe('getPoint', function() { - const table = { - columns: [{ id: '0' }, { id: '1' }, { id: '3' }], - rows: [ - { '0': 1, '1': 2, '2': 3 }, - { '0': 4, '1': 'NaN', '2': 6 }, - ], - }; - - describe('Without series aspect', function() { - let seriesAspect; - let xAspect; - let yAspect; - let yScale; - - beforeEach(function() { - seriesAspect = null; - xAspect = { accessor: 0 }; - yAspect = { accessor: 1, title: 'Y' }; - yScale = 5; - }); - - it('properly unwraps and scales values', function() { - const row = table.rows[0]; - const zAspect = { accessor: 2 }; - const point = getPoint(table, xAspect, seriesAspect, yScale, row, 0, yAspect, zAspect); - - expect(point) - .to.have.property('x', 1) - .and.have.property('y', 10) - .and.have.property('z', 3) - .and.have.property('series', yAspect.title); - }); - - it('ignores points with a y value of NaN', function() { - const row = table.rows[1]; - const point = getPoint(table, xAspect, seriesAspect, yScale, row, 1, yAspect); - expect(point).to.be(void 0); - }); - }); - - describe('With series aspect', function() { - let row; - let xAspect; - let yAspect; - let yScale; - - beforeEach(function() { - row = table.rows[0]; - xAspect = { accessor: 0 }; - yAspect = { accessor: 2 }; - yScale = null; - }); - - it('properly unwraps and scales values', function() { - const seriesAspect = [{ accessor: 1 }]; - const point = getPoint(table, xAspect, seriesAspect, yScale, row, 0, yAspect); - - expect(point) - .to.have.property('x', 1) - .and.have.property('series', '2') - .and.have.property('y', 3); - }); - - it('properly formats series values', function() { - const seriesAspect = [{ accessor: 1, format: { id: 'number', params: { pattern: '$' } } }]; - const point = getPoint(table, xAspect, seriesAspect, yScale, row, 0, yAspect); - - expect(point) - .to.have.property('x', 1) - .and.have.property('series', '$2') - .and.have.property('y', 3); - }); - }); -}); diff --git a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js b/src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js deleted file mode 100644 index 1727994976383..0000000000000 --- a/src/legacy/ui/public/agg_response/point_series/__tests__/_get_series.js +++ /dev/null @@ -1,283 +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 _ from 'lodash'; -import expect from '@kbn/expect'; -import { getSeries } from '../_get_series'; - -describe('getSeries', function() { - it('produces a single series with points for each row', function() { - const table = { - columns: [{ id: '0' }, { id: '1' }, { id: '3' }], - rows: [ - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - ], - }; - - const chart = { - aspects: { - x: [{ accessor: 0 }], - y: [{ accessor: 1, title: 'y' }], - z: { accessor: 2 }, - }, - }; - - const series = getSeries(table, chart); - - expect(series) - .to.be.an('array') - .and.to.have.length(1); - - const siri = series[0]; - expect(siri) - .to.be.an('object') - .and.have.property('label', chart.aspects.y.title) - .and.have.property('values'); - - expect(siri.values) - .to.be.an('array') - .and.have.length(5); - - siri.values.forEach(function(point) { - expect(point) - .to.have.property('x', 1) - .and.property('y', 2) - .and.property('z', 3); - }); - }); - - it('adds the seriesId to each point', function() { - const table = { - columns: [{ id: '0' }, { id: '1' }, { id: '3' }], - rows: [ - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - ], - }; - - const chart = { - aspects: { - x: [{ accessor: 0 }], - y: [ - { accessor: 1, title: '0' }, - { accessor: 2, title: '1' }, - ], - }, - }; - - const series = getSeries(table, chart); - - series[0].values.forEach(function(point) { - expect(point).to.have.property('seriesId', 1); - }); - - series[1].values.forEach(function(point) { - expect(point).to.have.property('seriesId', 2); - }); - }); - - it('produces multiple series if there are multiple y aspects', function() { - const table = { - columns: [{ id: '0' }, { id: '1' }, { id: '3' }], - rows: [ - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - ], - }; - - const chart = { - aspects: { - x: [{ accessor: 0 }], - y: [ - { accessor: 1, title: '0' }, - { accessor: 2, title: '1' }, - ], - }, - }; - - const series = getSeries(table, chart); - - expect(series) - .to.be.an('array') - .and.to.have.length(2); - - series.forEach(function(siri, i) { - expect(siri) - .to.be.an('object') - .and.have.property('label', '' + i) - .and.have.property('values'); - - expect(siri.values) - .to.be.an('array') - .and.have.length(5); - - siri.values.forEach(function(point) { - expect(point) - .to.have.property('x', 1) - .and.property('y', i + 2); - }); - }); - }); - - it('produces multiple series if there is a series aspect', function() { - const table = { - columns: [{ id: '0' }, { id: '1' }, { id: '3' }], - rows: [ - { '0': 0, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 0, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 0, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - ], - }; - - const chart = { - aspects: { - x: [{ accessor: -1 }], - series: [{ accessor: 0, fieldFormatter: _.identity }], - y: [{ accessor: 1, title: '0' }], - }, - }; - - const series = getSeries(table, chart); - - expect(series) - .to.be.an('array') - .and.to.have.length(2); - - series.forEach(function(siri, i) { - expect(siri) - .to.be.an('object') - .and.have.property('label', '' + i) - .and.have.property('values'); - - expect(siri.values) - .to.be.an('array') - .and.have.length(3); - - siri.values.forEach(function(point) { - expect(point).to.have.property('y', 2); - }); - }); - }); - - it('produces multiple series if there is a series aspect and multiple y aspects', function() { - const table = { - columns: [{ id: '0' }, { id: '1' }, { id: '3' }], - rows: [ - { '0': 0, '1': 3, '2': 4 }, - { '0': 1, '1': 3, '2': 4 }, - { '0': 0, '1': 3, '2': 4 }, - { '0': 1, '1': 3, '2': 4 }, - { '0': 0, '1': 3, '2': 4 }, - { '0': 1, '1': 3, '2': 4 }, - ], - }; - - const chart = { - aspects: { - x: [{ accessor: -1 }], - series: [{ accessor: 0, fieldFormatter: _.identity }], - y: [ - { accessor: 1, title: '0' }, - { accessor: 2, title: '1' }, - ], - }, - }; - - const series = getSeries(table, chart); - - expect(series) - .to.be.an('array') - .and.to.have.length(4); // two series * two metrics - - checkSiri(series[0], '0: 0', 3); - checkSiri(series[1], '0: 1', 4); - checkSiri(series[2], '1: 0', 3); - checkSiri(series[3], '1: 1', 4); - - function checkSiri(siri, label, y) { - expect(siri) - .to.be.an('object') - .and.have.property('label', label) - .and.have.property('values'); - - expect(siri.values) - .to.be.an('array') - .and.have.length(3); - - siri.values.forEach(function(point) { - expect(point).to.have.property('y', y); - }); - } - }); - - it('produces a series list in the same order as its corresponding metric column', function() { - const table = { - columns: [{ id: '0' }, { id: '1' }, { id: '3' }], - rows: [ - { '0': 0, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 0, '1': 2, '2': 3 }, - { '0': 1, '1': 2, '2': 3 }, - { '0': 0, '1': 2, '2': 3 }, - ], - }; - - const chart = { - aspects: { - x: [{ accessor: -1 }], - series: [{ accessor: 0, fieldFormatter: _.identity }], - y: [ - { accessor: 1, title: '0' }, - { accessor: 2, title: '1' }, - ], - }, - }; - - const series = getSeries(table, chart); - expect(series[0]).to.have.property('label', '0: 0'); - expect(series[1]).to.have.property('label', '0: 1'); - expect(series[2]).to.have.property('label', '1: 0'); - expect(series[3]).to.have.property('label', '1: 1'); - - // switch the order of the y columns - chart.aspects.y = chart.aspects.y.reverse(); - chart.aspects.y.forEach(function(y, i) { - y.i = i; - }); - - const series2 = getSeries(table, chart); - expect(series2[0]).to.have.property('label', '0: 1'); - expect(series2[1]).to.have.property('label', '0: 0'); - expect(series2[2]).to.have.property('label', '1: 1'); - expect(series2[3]).to.have.property('label', '1: 0'); - }); -}); diff --git a/src/legacy/ui/public/agg_response/point_series/_get_series.js b/src/legacy/ui/public/agg_response/point_series/_get_series.js deleted file mode 100644 index 73c1735191abc..0000000000000 --- a/src/legacy/ui/public/agg_response/point_series/_get_series.js +++ /dev/null @@ -1,100 +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 _ from 'lodash'; -import { getPoint } from './_get_point'; -import { addToSiri } from './_add_to_siri'; - -export function getSeries(table, chart) { - const aspects = chart.aspects; - const xAspect = aspects.x[0]; - const yAspect = aspects.y[0]; - const zAspect = aspects.z && aspects.z.length ? aspects.z[0] : aspects.z; - const multiY = Array.isArray(aspects.y) && aspects.y.length > 1; - const yScale = chart.yScale; - - const partGetPoint = _.partial(getPoint, table, xAspect, aspects.series, yScale); - - let series = _(table.rows) - .transform(function(series, row, rowIndex) { - if (!multiY) { - const point = partGetPoint(row, rowIndex, yAspect, zAspect); - if (point) { - const id = `${point.series}-${yAspect.accessor}`; - point.seriesId = id; - addToSiri( - series, - point, - id, - point.series, - yAspect.format, - zAspect && zAspect.format, - zAspect && zAspect.title - ); - } - return; - } - - aspects.y.forEach(function(y) { - const point = partGetPoint(row, rowIndex, y, zAspect); - if (!point) return; - - // use the point's y-axis as it's series by default, - // but augment that with series aspect if it's actually - // available - let seriesId = y.accessor; - let seriesLabel = y.title; - - if (aspects.series) { - const prefix = point.series ? point.series + ': ' : ''; - seriesId = prefix + seriesId; - seriesLabel = prefix + seriesLabel; - } - - point.seriesId = seriesId; - addToSiri( - series, - point, - seriesId, - seriesLabel, - y.format, - zAspect && zAspect.format, - zAspect && zAspect.title - ); - }); - }, new Map()) - .thru(series => [...series.values()]) - .value(); - - if (multiY) { - series = _.sortBy(series, function(siri) { - const firstVal = siri.values[0]; - let y; - - if (firstVal) { - y = _.find(aspects.y, function(y) { - return y.accessor === firstVal.accessor; - }); - } - - return y ? y.i : series.length; - }); - } - return series; -} diff --git a/src/legacy/ui/public/agg_response/point_series/point_series.js b/src/legacy/ui/public/agg_response/point_series/point_series.js deleted file mode 100644 index 8489f7bc2ca45..0000000000000 --- a/src/legacy/ui/public/agg_response/point_series/point_series.js +++ /dev/null @@ -1,42 +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 { getSeries } from './_get_series'; -import { getAspects } from './_get_aspects'; -import { initYAxis } from './_init_y_axis'; -import { initXAxis } from './_init_x_axis'; -import { orderedDateAxis } from './_ordered_date_axis'; - -export const buildPointSeriesData = (table, dimensions) => { - const chart = { - aspects: getAspects(table, dimensions), - }; - - initXAxis(chart, table); - initYAxis(chart); - - if (chart.aspects.x[0].params.date) { - orderedDateAxis(chart); - } - - chart.series = getSeries(table, chart); - - delete chart.aspects; - return chart; -}; diff --git a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js index 905c88a6d18a0..532c49803e7b0 100644 --- a/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js +++ b/x-pack/legacy/plugins/dashboard_mode/public/dashboard_viewer.js @@ -27,7 +27,6 @@ import 'uiExports/search'; import 'uiExports/shareContextMenuExtensions'; import _ from 'lodash'; import 'ui/autoload/all'; -import 'ui/agg_response'; import 'leaflet'; import { npStart } from 'ui/new_platform'; import { localApplicationService } from 'plugins/kibana/local_application_service'; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index d357e40c02934..705a4577cbd07 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -130,7 +130,6 @@ "charts.colormaps.greysText": "グレー", "charts.colormaps.redsText": "赤", "charts.colormaps.yellowToRedText": "黄色から赤", - "common.ui.aggResponse.allDocsTitle": "すべてのドキュメント", "common.ui.errorAutoCreateIndex.breadcrumbs.errorText": "エラー", "common.ui.errorAutoCreateIndex.errorDescription": "Elasticsearch クラスターの {autoCreateIndexActionConfig} 設定が原因で、Kibana が保存されたオブジェクトを格納するインデックスを自動的に作成できないようです。Kibana は、保存されたオブジェクトインデックスが適切なマッピング/スキーマを使用し Kibana から Elasticsearch へのポーリングの回数を減らすための最適な手段であるため、この Elasticsearch の機能を使用します。", "common.ui.errorAutoCreateIndex.errorDisclaimer": "申し訳ございませんが、この問題が解決されるまで Kibana で何も保存することができません。", @@ -3809,6 +3808,7 @@ "visTypeVega.visualization.renderErrorTitle": "Vega エラー", "visTypeVega.visualization.unableToFindDefaultIndexErrorMessage": "デフォルトのインデックスが見つかりません", "visTypeVega.visualization.unableToRenderWithoutDataWarningMessage": "データなしにはレンダリングできません", + "visTypeVislib.aggResponse.allDocsTitle": "すべてのドキュメント", "visTypeVislib.area.areaDescription": "折れ線グラフの下の数量を強調します。", "visTypeVislib.area.areaTitle": "エリア", "visTypeVislib.area.countText": "カウント", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 839c89f3b1cae..50b807a4934ed 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -130,7 +130,6 @@ "charts.colormaps.greysText": "灰色", "charts.colormaps.redsText": "红色", "charts.colormaps.yellowToRedText": "黄到红", - "common.ui.aggResponse.allDocsTitle": "所有文档", "common.ui.errorAutoCreateIndex.breadcrumbs.errorText": "错误", "common.ui.errorAutoCreateIndex.errorDescription": "似乎 Elasticsearch 集群的 {autoCreateIndexActionConfig} 设置使 Kibana 无法自动创建用于存储已保存对象的索引。Kibana 将使用此 Elasticsearch 功能,因为这是确保已保存对象索引使用正确映射/架构的最好方式,而且其允许 Kibana 较少地轮询 Elasticsearch。", "common.ui.errorAutoCreateIndex.errorDisclaimer": "但是,只有解决了此问题后,您才能在 Kibana 保存内容。", @@ -3810,6 +3809,7 @@ "visTypeVega.visualization.renderErrorTitle": "Vega 错误", "visTypeVega.visualization.unableToFindDefaultIndexErrorMessage": "找不到默认索引", "visTypeVega.visualization.unableToRenderWithoutDataWarningMessage": "没有数据时无法渲染", + "visTypeVislib.aggResponse.allDocsTitle": "所有文档", "visTypeVislib.area.areaDescription": "突出折线图下方的数量", "visTypeVislib.area.areaTitle": "面积图", "visTypeVislib.area.countText": "计数", From b73fe279d6609162530619b4582f7f1da35a88c6 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Thu, 9 Apr 2020 09:44:33 -0700 Subject: [PATCH 014/121] [EPM] Update UI copy to use `integration` (#63077) * Update epm copy to say Integrations * Update copy in create data source flow * Update copy in data sources table * Fix missed copies * Remove unused translation keys (they were renamed & strings were changed) --- .../ingest_manager/layouts/default.tsx | 4 ++-- .../components/layout.tsx | 2 +- .../components/navigation.tsx | 2 +- .../create_datasource_page/index.tsx | 2 +- .../step_select_package.tsx | 8 ++++---- .../datasources/datasources_table.tsx | 2 +- .../epm/components/package_list_grid.tsx | 2 +- .../sections/epm/screens/detail/header.tsx | 8 +++++++- .../sections/epm/screens/home/header.tsx | 4 ++-- .../sections/epm/screens/home/index.tsx | 18 +++++++++--------- .../translations/translations/ja-JP.json | 5 ----- .../translations/translations/zh-CN.json | 5 ----- 12 files changed, 29 insertions(+), 33 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index 8ec2d2ec03b35..26f2c85a291a3 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -55,8 +55,8 @@ export const DefaultLayout: React.FunctionComponent = ({ section, childre disabled={!epm?.enabled} > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx index 8bb7b2553c1b1..dd242f366e8c0 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx @@ -88,7 +88,7 @@ export const CreateDatasourcePageLayout: React.FunctionComponent<{ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx index 099a7a83caa10..7dae981e65c30 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx @@ -27,7 +27,7 @@ export const CreateDatasourceStepsNavigation: React.FunctionComponent<{ from === 'config' ? { title: i18n.translate('xpack.ingestManager.createDatasource.stepSelectPackageLabel', { - defaultMessage: 'Select package', + defaultMessage: 'Select integration', }), isSelected: currentStep === 'selectPackage', isComplete: diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx index 7815ab9cd1d6e..461bb750ca6f5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx @@ -221,7 +221,7 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { {from === 'config' ? ( ) : ( } error={packagesError} @@ -114,7 +114,7 @@ export const StepSelectPackage: React.FunctionComponent<{

@@ -149,7 +149,7 @@ export const StepSelectPackage: React.FunctionComponent<{ placeholder: i18n.translate( 'xpack.ingestManager.createDatasource.stepSelectPackage.filterPackagesInputPlaceholder', { - defaultMessage: 'Search for packages', + defaultMessage: 'Search for integrations', } ), }} @@ -179,7 +179,7 @@ export const StepSelectPackage: React.FunctionComponent<{ title={ } error={selectedPkgError} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/datasources/datasources_table.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/datasources/datasources_table.tsx index 87155afdc21be..1eee9f6b0c346 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/datasources/datasources_table.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/details_page/components/datasources/datasources_table.tsx @@ -138,7 +138,7 @@ export const DatasourcesTable: React.FunctionComponent = ({ name: i18n.translate( 'xpack.ingestManager.configDetails.datasourcesTable.packageNameColumnTitle', { - defaultMessage: 'Package', + defaultMessage: 'Integration', } ), render(packageTitle: string, datasource: InMemoryDatasource) { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx index 2ca49298decf9..818b365d5be12 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx @@ -62,7 +62,7 @@ export function PackageListGrid({ query={searchTerm} box={{ placeholder: i18n.translate('xpack.ingestManager.epmList.searchPackagesPlaceholder', { - defaultMessage: 'Search for a package', + defaultMessage: 'Search for integrations', }), incremental: true, }} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx index a7204dd722603..d83910f29f1a7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/header.tsx @@ -5,6 +5,7 @@ */ import React, { Fragment } from 'react'; import styled from 'styled-components'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, EuiFlexItem, EuiPage, EuiTitle, IconType, EuiButton } from '@elastic/eui'; import { PackageInfo } from '../../../../types'; @@ -41,7 +42,12 @@ export function Header(props: HeaderProps) { return ( - + {iconType ? ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx index 4230775c04e00..4d6c02eeef8b4 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx @@ -17,7 +17,7 @@ export const HeroCopy = memo(() => {

@@ -27,7 +27,7 @@ export const HeroCopy = memo(() => {

diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx index 5f215b7788259..bf785147502b5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/index.tsx @@ -35,16 +35,16 @@ export function EPMHomePage() { ([ { id: 'all_packages', - name: i18n.translate('xpack.ingestManager.epmList.allPackagesTabText', { - defaultMessage: 'All packages', + name: i18n.translate('xpack.ingestManager.epmList.allTabText', { + defaultMessage: 'All integrations', }), href: ALL_PACKAGES_URI, isSelected: tabId !== 'installed', }, { id: 'installed_packages', - name: i18n.translate('xpack.ingestManager.epmList.installedPackagesTabText', { - defaultMessage: 'Installed packages', + name: i18n.translate('xpack.ingestManager.epmList.installedTabText', { + defaultMessage: 'Installed integrations', }), href: INSTALLED_PACKAGES_URI, isSelected: tabId === 'installed', @@ -72,14 +72,14 @@ function InstalledPackages() { ? allPackages.response.filter(pkg => pkg.status === 'installed') : []; - const title = i18n.translate('xpack.ingestManager.epmList.installedPackagesTitle', { - defaultMessage: 'Installed packages', + const title = i18n.translate('xpack.ingestManager.epmList.installedTitle', { + defaultMessage: 'Installed integrations', }); const categories = [ { id: '', - title: i18n.translate('xpack.ingestManager.epmList.allPackagesFilterLinkText', { + title: i18n.translate('xpack.ingestManager.epmList.allFilterLinkText', { defaultMessage: 'All', }), count: packages.length, @@ -120,8 +120,8 @@ function AvailablePackages() { const packages = categoryPackagesRes && categoryPackagesRes.response ? categoryPackagesRes.response : []; - const title = i18n.translate('xpack.ingestManager.epmList.allPackagesTitle', { - defaultMessage: 'All packages', + const title = i18n.translate('xpack.ingestManager.epmList.allTitle', { + defaultMessage: 'All integrations', }); const categories = [ diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 705a4577cbd07..687834a683c4d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8389,7 +8389,6 @@ "xpack.ingestManager.appNavigation.configurationsLinkText": "構成", "xpack.ingestManager.appNavigation.fleetLinkText": "フリート", "xpack.ingestManager.appNavigation.overviewLinkText": "概要", - "xpack.ingestManager.appNavigation.packagesLinkText": "パッケージ", "xpack.ingestManager.appTitle": "Ingest Manager", "xpack.ingestManager.configDetails.addDatasourceButtonText": "データソースを作成", "xpack.ingestManager.configDetails.configDetailsTitle": "構成「{id}」", @@ -8515,10 +8514,6 @@ "xpack.ingestManager.epm.pageSubtitle": "人気のアプリやサービスのパッケージを参照する", "xpack.ingestManager.epm.pageTitle": "Elastic Package Manager", "xpack.ingestManager.epmList.allPackagesFilterLinkText": "すべて", - "xpack.ingestManager.epmList.allPackagesTabText": "すべてのパッケージ", - "xpack.ingestManager.epmList.allPackagesTitle": "すべてのパッケージ", - "xpack.ingestManager.epmList.installedPackagesTabText": "パッケージをインストールしました", - "xpack.ingestManager.epmList.installedPackagesTitle": "パッケージをインストールしました", "xpack.ingestManager.epmList.noPackagesFoundPlaceholder": "パッケージが見つかりません", "xpack.ingestManager.epmList.searchPackagesPlaceholder": "パッケージを検索", "xpack.ingestManager.epmList.updatesAvailableFilterLinkText": "更新が可能です", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 50b807a4934ed..58905787da8d5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8392,7 +8392,6 @@ "xpack.ingestManager.appNavigation.configurationsLinkText": "配置", "xpack.ingestManager.appNavigation.fleetLinkText": "Fleet", "xpack.ingestManager.appNavigation.overviewLinkText": "概览", - "xpack.ingestManager.appNavigation.packagesLinkText": "软件包", "xpack.ingestManager.appTitle": "Ingest Manager", "xpack.ingestManager.configDetails.addDatasourceButtonText": "创建数据源", "xpack.ingestManager.configDetails.configDetailsTitle": "配置“{id}”", @@ -8518,10 +8517,6 @@ "xpack.ingestManager.epm.pageSubtitle": "浏览热门应用和服务的软件。", "xpack.ingestManager.epm.pageTitle": "Elastic Package Manager", "xpack.ingestManager.epmList.allPackagesFilterLinkText": "全部", - "xpack.ingestManager.epmList.allPackagesTabText": "所有软件包", - "xpack.ingestManager.epmList.allPackagesTitle": "所有软件包", - "xpack.ingestManager.epmList.installedPackagesTabText": "已安装软件包", - "xpack.ingestManager.epmList.installedPackagesTitle": "已安装软件包", "xpack.ingestManager.epmList.noPackagesFoundPlaceholder": "未找到任何软件包", "xpack.ingestManager.epmList.searchPackagesPlaceholder": "搜索软件包", "xpack.ingestManager.epmList.updatesAvailableFilterLinkText": "有可用更新", From 59c044ff00d88d63c7bf30685a6f1371c7164f8c Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Thu, 9 Apr 2020 12:42:30 -0500 Subject: [PATCH 015/121] [DOCS] Removed references to right (#62508) --- docs/apm/spans.asciidoc | 2 +- docs/apm/transactions.asciidoc | 1 + docs/canvas/canvas-share-workpad.asciidoc | 4 ++-- docs/canvas/canvas-tutorial.asciidoc | 6 +++--- docs/canvas/canvas-workpad.asciidoc | 2 +- .../alerting/alert-management.asciidoc | 14 ++++++------- .../alerting/connector-management.asciidoc | 8 ++++---- docs/management/index-patterns.asciidoc | 1 - docs/management/managing-fields.asciidoc | 2 +- .../create_and_manage_rollups.asciidoc | 4 ++-- docs/maps/geojson-upload.asciidoc | 3 +-- .../indexing-geojson-data-tutorial.asciidoc | 4 ++-- docs/maps/maps-getting-started.asciidoc | 5 ++--- docs/maps/search.asciidoc | 2 +- docs/user/alerting/defining-alerts.asciidoc | 20 +++++++++---------- docs/user/dashboard.asciidoc | 2 +- docs/user/discover.asciidoc | 2 +- docs/user/graph/getting-started.asciidoc | 4 ++-- docs/user/monitoring/beats-details.asciidoc | 4 ++-- docs/visualize/lens.asciidoc | 12 +++++------ 20 files changed, 50 insertions(+), 52 deletions(-) diff --git a/docs/apm/spans.asciidoc b/docs/apm/spans.asciidoc index b09de576f2d4a..ef21e1c5333e0 100644 --- a/docs/apm/spans.asciidoc +++ b/docs/apm/spans.asciidoc @@ -34,4 +34,4 @@ which indicates the next transaction in the trace. These transactions can be expanded and viewed in detail by clicking on them. After exploring these traces, -you can return to the full trace by clicking *View full trace* in the upper right hand corner of the page. +you can return to the full trace by clicking *View full trace*. diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index 5c92afa55109d..1eb037009efff 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -105,6 +105,7 @@ image::apm/images/apm-transaction-duration-dist.png[Example view of transactions This graph shows a typical distribution, and indicates most of our requests were served quickly - awesome! It's the requests on the right, the ones taking longer than average, that we probably want to focus on. + When you select one of these buckets, you're presented with up to ten trace samples. Each sample has a span timeline waterfall that shows what a typical request in that bucket was doing. diff --git a/docs/canvas/canvas-share-workpad.asciidoc b/docs/canvas/canvas-share-workpad.asciidoc index ee29926914ad6..5cae3fcc7b531 100644 --- a/docs/canvas/canvas-share-workpad.asciidoc +++ b/docs/canvas/canvas-share-workpad.asciidoc @@ -76,7 +76,7 @@ After you've added the workpad to your website, you can change the autoplay and To change the autoplay settings: -. In the lower right corner of the shareable workpad, click the settings icon. +. Click the settings icon. . Click *Auto Play*, then change the settings. + @@ -85,7 +85,7 @@ image::images/canvas_share_autoplay_480.gif[Autoplay settings] To change the toolbar settings: -. In the lower right corner, click the settings icon. +. Click the settings icon. . Click *Toolbar*, then change the settings. + diff --git a/docs/canvas/canvas-tutorial.asciidoc b/docs/canvas/canvas-tutorial.asciidoc index b6d684bdf5dde..a38ab4a69598e 100644 --- a/docs/canvas/canvas-tutorial.asciidoc +++ b/docs/canvas/canvas-tutorial.asciidoc @@ -18,7 +18,7 @@ Your first step to working with Canvas is to create a workpad. . Click *Create workpad*. -. To add a *Name* for your workpad, use the editor on the right. For example, `My Canvas Workpad`. +. To add a *Name* for your workpad, use the editor. For example, `My Canvas Workpad`. [float] === Customize your workpad with images @@ -29,7 +29,7 @@ To customize your workpad to look the way you want, add your own images. + The default Elastic logo image appears on your page. -. To replace the Elastic logo with your own image, select the image, then use the editor on the right. +. To replace the Elastic logo with your own image, select the image, then use the editor. . To move the image, click and drag it to your preferred location. @@ -73,7 +73,7 @@ You'll notice that the error is gone, but the number could use some formatting. . To format the number, use the Canvas expression language. -.. In the lower right corner, click *Expression editor*. +.. Click *Expression editor*. + You're now looking at the raw data syntax that Canvas uses to display the element. diff --git a/docs/canvas/canvas-workpad.asciidoc b/docs/canvas/canvas-workpad.asciidoc index c5c163441439c..42eedf55c404d 100644 --- a/docs/canvas/canvas-workpad.asciidoc +++ b/docs/canvas/canvas-workpad.asciidoc @@ -124,7 +124,7 @@ Organize your ideas onto separate pages by adding more pages. . Click *Page 1*, then click *+*. -. On the *Page* editor panel on the right, select the page transition from the *Transition* dropdown. +. On the *Page* editor panel, select the page transition from the *Transition* dropdown. + [role="screenshot"] image::images/canvas-add-pages.gif[Add pages] diff --git a/docs/management/alerting/alert-management.asciidoc b/docs/management/alerting/alert-management.asciidoc index caf260937b7be..73cf40c4d7c40 100644 --- a/docs/management/alerting/alert-management.asciidoc +++ b/docs/management/alerting/alert-management.asciidoc @@ -18,9 +18,9 @@ For more information on alerting concepts and the types of alerts and actions av [float] ==== Finding alerts -The *Alerts* tab lists all alerts in the current space, including summary information about their execution frequency, tags, and type. +The *Alerts* tab lists all alerts in the current space, including summary information about their execution frequency, tags, and type. -The *search bar* can be used to quickly find alerts by name or tag. +The *search bar* can be used to quickly find alerts by name or tag. [role="screenshot"] image::images/alerts-filter-by-search.png[Filtering the alerts list using the search bar] @@ -30,7 +30,7 @@ The *type* dropdown lets you filter to a subset of alert types. [role="screenshot"] image::images/alerts-filter-by-type.png[Filtering the alerts list by types of alert] -The *Action type* dropdown lets you filter by the type of action used in the alert. +The *Action type* dropdown lets you filter by the type of action used in the alert. [role="screenshot"] image::images/alerts-filter-by-action-type.png[Filtering the alert list by type of action] @@ -39,16 +39,16 @@ image::images/alerts-filter-by-action-type.png[Filtering the alert list by type [[create-edit-alerts]] ==== Creating and editing alerts -Many alerts must be created within the context of a {kib} app like <>, <>, or <>, but others are generic. Generic alert types can be created in the *Alerts* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting an alert type and configuring it's properties. Refer to <> for details on what types of alerts are available and how to configure them. +Many alerts must be created within the context of a {kib} app like <>, <>, or <>, but others are generic. Generic alert types can be created in the *Alerts* management UI by clicking the *Create* button. This will launch a flyout that guides you through selecting an alert type and configuring it's properties. Refer to <> for details on what types of alerts are available and how to configure them. -After an alert is created, you can re-open the flyout and change an alerts properties by clicking the *Edit* button shown on each row of the alert listing. +After an alert is created, you can re-open the flyout and change an alerts properties by clicking the *Edit* button shown on each row of the alert listing. [float] [[controlling-alerts]] ==== Controlling alerts -The alert listing allows you to quickly mute/unmute, disable/enable, and delete individual alerts by clicking the action button at the right of each row. +The alert listing allows you to quickly mute/unmute, disable/enable, and delete individual alerts by clicking the action button. [role="screenshot"] image:management/alerting/images/individual-mute-disable.png[The actions button allows an individual alert to be muted, disabled, or deleted] @@ -56,4 +56,4 @@ image:management/alerting/images/individual-mute-disable.png[The actions button These operations can also be performed in bulk by multi-selecting alerts and clicking the *Manage alerts* button: [role="screenshot"] -image:management/alerting/images/bulk-mute-disable.png[The Manage alerts button lets you mute/unmute, enable/disable, and delete in bulk] \ No newline at end of file +image:management/alerting/images/bulk-mute-disable.png[The Manage alerts button lets you mute/unmute, enable/disable, and delete in bulk] diff --git a/docs/management/alerting/connector-management.asciidoc b/docs/management/alerting/connector-management.asciidoc index 1002a372f9460..46e106e6e9648 100644 --- a/docs/management/alerting/connector-management.asciidoc +++ b/docs/management/alerting/connector-management.asciidoc @@ -15,7 +15,7 @@ image::images/connector-listing.png[Example connector listing in the Alerts and [float] ==== Connector list -The *Connectors* tab lists all connectors in the current space. The *search bar* can be used to find specific connectors by name and/or type. +The *Connectors* tab lists all connectors in the current space. The *search bar* can be used to find specific connectors by name and/or type. [role="screenshot"] image::images/connector-filter-by-search.png[Filtering the connector list using the search bar] @@ -26,12 +26,12 @@ The *type* dropdown also lets you filter to a subset of action types. [role="screenshot"] image::images/connector-filter-by-type.png[Filtering the connector list by types of actions] -The *Actions* column indicates the number of actions that reference the connector. This count helps you confirm a connector is unused before you delete it, and tells you how many actions will be affected when a connector is modified. +The *Actions* column indicates the number of actions that reference the connector. This count helps you confirm a connector is unused before you delete it, and tells you how many actions will be affected when a connector is modified. [role="screenshot"] image::images/connector-action-count.png[Filtering the connector list by types of actions] -You can delete individual connectors using the trash icon on the right of each row. Connectors can also be deleted in bulk by multi-selecting them and clicking the *Delete* button to the left of the search box. +You can delete individual connectors using the trash icon. Connectors can also be deleted in bulk by multi-selecting them and clicking the *Delete* button to the left of the search box. [role="screenshot"] image::images/connector-delete.png[Deleting connectors individually or in bulk] @@ -44,4 +44,4 @@ When this happens the action will fail to execute, and appear as errors in the { ==== Creating a new connector -New connectors can be created by clicking the *Create connector* button, which will guide you to select the type of connector and configure it's properties. Refer to <> for the types of connectors available and how to configure them. Once you create a connector it will be made available to you anytime you set up an action in the current space. \ No newline at end of file +New connectors can be created by clicking the *Create connector* button, which will guide you to select the type of connector and configure it's properties. Refer to <> for the types of connectors available and how to configure them. Once you create a connector it will be made available to you anytime you set up an action in the current space. diff --git a/docs/management/index-patterns.asciidoc b/docs/management/index-patterns.asciidoc index 45f8bd13a5c54..bb16faab7fe5a 100644 --- a/docs/management/index-patterns.asciidoc +++ b/docs/management/index-patterns.asciidoc @@ -38,7 +38,6 @@ image:management/index-patterns/images/rollup-index-pattern.png["Menu with rollu Just start typing in the *Index pattern* field, and {kib} looks for the names of {es} indices that match your input. Make sure that the name of the index pattern is unique. -To include system indices in your search, toggle the switch in the upper right. [role="screenshot"] image:management/index-patterns/images/create-index-pattern.png["Create index pattern"] diff --git a/docs/management/managing-fields.asciidoc b/docs/management/managing-fields.asciidoc index 1a1bcec10ab50..9682d918aabe4 100644 --- a/docs/management/managing-fields.asciidoc +++ b/docs/management/managing-fields.asciidoc @@ -25,7 +25,7 @@ the *Index patterns* overview. [role="screenshot"] image::management/index-patterns/images/new-index-pattern.png["Index files and data types"] -Use the icons in the upper right to perform the following actions: +Use the icons to perform the following actions: * [[set-default-pattern]]*Set the default index pattern.* {kib} uses a badge to make users aware of which index pattern is the default. The first pattern diff --git a/docs/management/rollups/create_and_manage_rollups.asciidoc b/docs/management/rollups/create_and_manage_rollups.asciidoc index 6a56970687fd6..da2e190847fdb 100644 --- a/docs/management/rollups/create_and_manage_rollups.asciidoc +++ b/docs/management/rollups/create_and_manage_rollups.asciidoc @@ -42,8 +42,8 @@ image::images/management_create_rollup_job.png[][Wizard that walks you through c === Start, stop, and delete rollup jobs Once you’ve saved a rollup job, you’ll see it the *Rollup Jobs* overview page, -where you can drill down for further investigation. The *Manage* menu in -the lower right enables you to start, stop, and delete the rollup job. +where you can drill down for further investigation. The *Manage* menu enables +you to start, stop, and delete the rollup job. You must first stop a rollup job before deleting it. [role="screenshot"] diff --git a/docs/maps/geojson-upload.asciidoc b/docs/maps/geojson-upload.asciidoc index ad20264f56138..7e2cdddfd30ef 100644 --- a/docs/maps/geojson-upload.asciidoc +++ b/docs/maps/geojson-upload.asciidoc @@ -37,7 +37,6 @@ the Elasticsearch responses are shown on the *Layer add panel* and the indexed d appears on the map. The geospatial data on the map should be identical to the locally-previewed data, but now it's indexed data from Elasticsearch. -. To continue adding data to the map, click *Add layer* in the lower -right-hand corner. +. To continue adding data to the map, click *Add layer*. . In *Layer settings*, adjust any settings or <> as needed. . Click *Save & close*. diff --git a/docs/maps/indexing-geojson-data-tutorial.asciidoc b/docs/maps/indexing-geojson-data-tutorial.asciidoc index a94e5757d5dfa..bf846a2b80e03 100644 --- a/docs/maps/indexing-geojson-data-tutorial.asciidoc +++ b/docs/maps/indexing-geojson-data-tutorial.asciidoc @@ -55,14 +55,14 @@ auto-populate *Index type* with either {ref}/geo-point.html[geo_point] or {ref}/geo-shape.html[geo_shape] and *Index name* with ``. -. Click *Import file* in the lower right. +. Click *Import file*. + You'll see activity as the GeoJSON Upload utility creates a new index and index pattern for the data set. When the process is complete, you should receive messages that the creation of the new index and index pattern were successful. -. Click *Add layer* in the bottom right. +. Click *Add layer*. . In *Layer settings*, adjust settings and <> as needed. . Click *Save & close*. diff --git a/docs/maps/maps-getting-started.asciidoc b/docs/maps/maps-getting-started.asciidoc index b13eeebe56fd8..6495b8a057cf6 100644 --- a/docs/maps/maps-getting-started.asciidoc +++ b/docs/maps/maps-getting-started.asciidoc @@ -80,7 +80,7 @@ To symbolize countries by web traffic, you'll need to augment the world country To do this, you'll create a <> to link the vector source *World Countries* to the {es} index `kibana_sample_data_logs` on the shared key iso2 = geo.src. -. Click plus image:maps/images/gs_plus_icon.png[] to the right of *Term Joins* label. +. Click plus image:maps/images/gs_plus_icon.png[] next to the *Term Joins* label. . Click *Join --select--* . Set *Left field* to *ISO 3166-1 alpha-2 code*. . Set *Right source* to *kibana_sample_data_logs*. @@ -238,7 +238,7 @@ The *machine.os.keyword: osx* filter appears in the dashboard query bar. + . Click the *x* to remove the *machine.os.keyword: osx* filter. . In the map, click in the United States vector. -. Click plus image:maps/images/gs_plus_icon.png[] to the right of *iso2* row in the tooltip. +. Click plus image:maps/images/gs_plus_icon.png[] next to the *iso2* row in the tooltip. + Both the visualizations and the map are filtered to only show documents where *geo.src* is *US*. The *geo.src: US* filter appears in the dashboard query bar. @@ -247,4 +247,3 @@ Your dashboard should look like this: + [role="screenshot"] image::maps/images/gs_dashboard_with_terms_filter.png[] - diff --git a/docs/maps/search.asciidoc b/docs/maps/search.asciidoc index 8a93352798d2c..a461ab6fbb3a6 100644 --- a/docs/maps/search.asciidoc +++ b/docs/maps/search.asciidoc @@ -4,7 +4,7 @@ **Elastic Maps** embeds the search bar for real-time search. Only layers requesting data from {es} are filtered when you submit a search request. -Layers narrowed by the search context contain the filter icon image:maps/images/filter_icon.png[] to the right of layer name in the legend. +Layers narrowed by the search context contain the filter icon image:maps/images/filter_icon.png[] next to the layer name in the legend. You can create a layer that requests data from {es} from the following: diff --git a/docs/user/alerting/defining-alerts.asciidoc b/docs/user/alerting/defining-alerts.asciidoc index 89c4c88708d58..f05afac34e595 100644 --- a/docs/user/alerting/defining-alerts.asciidoc +++ b/docs/user/alerting/defining-alerts.asciidoc @@ -2,7 +2,7 @@ [[defining-alerts]] == Defining alerts -{kib} alerts can be created in a variety of apps including <>, <>, <>, <> and from <> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail. +{kib} alerts can be created in a variety of apps including <>, <>, <>, <> and from <> UI. While alerting details may differ from app to app, they share a common interface for defining and configuring alerts that this section describes in more detail. [float] === Alert flyout @@ -25,20 +25,20 @@ All alert share the following four properties in common: image::images/alert-flyout-general-details.png[All alerts have name, tags, check every, and re-notify every properties in common] Name:: The name of the alert. While this name does not have to be unique, the name can be referenced in actions and also appears in the searchable alert listing in the management UI. A distinctive name can help identify and find an alert. -Tags:: A list of tag names that can be applied to an alert. Tags can help you organize and find alerts, because tags appear in the alert listing in the management UI which is searchable by tag. +Tags:: A list of tag names that can be applied to an alert. Tags can help you organize and find alerts, because tags appear in the alert listing in the management UI which is searchable by tag. Check every:: This value determines how frequently the alert conditions below are checked. Note that the timing of background alert checks are not guaranteed, particularly for intervals of less than 10 seconds. See <> for more information. -Re-notify every:: This value limits how often actions are repeated when an alert instance remains active across alert checks. See <> for more information. +Re-notify every:: This value limits how often actions are repeated when an alert instance remains active across alert checks. See <> for more information. [float] [[defining-alerts-type-conditions]] === Alert type and conditions -Depending upon the {kib} app and context, you may be prompted to choose the type of alert you wish to create. Some apps will pre-select the type of alert for you. +Depending upon the {kib} app and context, you may be prompted to choose the type of alert you wish to create. Some apps will pre-select the type of alert for you. [role="screenshot"] image::images/alert-flyout-alert-type-selection.png[Choosing the type of alert to create] -Each alert type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold alert the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field. +Each alert type provides its own way of defining the conditions to detect, but an expression formed by a series of clauses is a common pattern. Each clause has a UI control that allows you to define the clause. For example, in an index threshold alert the `WHEN` clause allows you to select an aggregation operation to apply to a numeric field. [role="screenshot"] image::images/alert-flyout-alert-conditions.png[UI for defining alert conditions on an index threshold alert] @@ -52,19 +52,19 @@ To add an action to an alert, you first select the type of action: [role="screenshot"] image::images/alert-flyout-action-type-selection.png[UI for selecting an action type] -Each action must specify a <> instance. If no connectors exist for that action type, click "Add new" to create one. +Each action must specify a <> instance. If no connectors exist for that action type, click "Add new" to create one. -Each action type exposes different properties. For example an email action allows you to set the recipients, the subject, and a message body in markdown format. See <> for details on the types of actions provided by {kib} and their properties. +Each action type exposes different properties. For example an email action allows you to set the recipients, the subject, and a message body in markdown format. See <> for details on the types of actions provided by {kib} and their properties. [role="screenshot"] image::images/alert-flyout-action-details.png[UI for defining an email action] -Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. Available variables differ by alert type, and a list can be accessed using the "add variable" button at the right of the text box. +Using the https://mustache.github.io/[Mustache] template syntax `{{variable name}}`, you can pass alert values at the time a condition is detected to an action. Available variables differ by alert type, and a list can be accessed using the "add variable" button. [role="screenshot"] image::images/alert-flyout-action-variables.png[Passing alert values to an action] -You can attach more than one action. Clicking the "Add action" button will prompt you to select another alert type and repeat the above steps again. +You can attach more than one action. Clicking the "Add action" button will prompt you to select another alert type and repeat the above steps again. [role="screenshot"] image::images/alert-flyout-add-action.png[You can add multiple actions on an alert] @@ -77,4 +77,4 @@ Actions are not required on alerts. In some cases you may want to run an alert w [float] === Managing alerts -To modify an alert after it was created, including muting or disabling it, use the <>. \ No newline at end of file +To modify an alert after it was created, including muting or disabling it, use the <>. diff --git a/docs/user/dashboard.asciidoc b/docs/user/dashboard.asciidoc index a17e46c5b3542..ab529a533d5e3 100644 --- a/docs/user/dashboard.asciidoc +++ b/docs/user/dashboard.asciidoc @@ -90,7 +90,7 @@ In *Edit* mode, you can move, resize, customize, and delete panels to suit your * To move a panel, click and hold the panel header and drag to the new location. [[resizing-containers]] -* To resize a panel, click the resize control on the lower right and drag +* To resize a panel, click the resize control and drag to the new dimensions. * To toggle the use of margins and panel titles, use the *Options* menu. diff --git a/docs/user/discover.asciidoc b/docs/user/discover.asciidoc index 4222ba40debb7..2547b38a22616 100644 --- a/docs/user/discover.asciidoc +++ b/docs/user/discover.asciidoc @@ -33,7 +33,7 @@ which has a pre-built index pattern. By default, *Discover* shows data for the last 15 minutes. If you have a time-based index, and no data displays, -you might need to increase the time range. Using the <> in the upper right, +you might need to increase the time range. Using the <>, you can specify a common or recently-used time range, a relative time from now, or an absolute time range. diff --git a/docs/user/graph/getting-started.asciidoc b/docs/user/graph/getting-started.asciidoc index 1749678ace9e3..a155017f1bb22 100644 --- a/docs/user/graph/getting-started.asciidoc +++ b/docs/user/graph/getting-started.asciidoc @@ -38,7 +38,7 @@ image::user/graph/images/graph-url-connections.png["URL connections"] [role="screenshot"] image::user/graph/images/graph-link-summary.png["Link summary"] -. Use the control bar on the right to explore +. Use the control bar to explore additional connections: + * To display additional vertices that connect to your graph, click the expand icon @@ -70,7 +70,7 @@ select *Edit settings*. To change the color and label of selected vertices, click the style icon image:user/graph/images/graph-style-button.png[Style] -in the control bar on the right. +in the control bar. [float] diff --git a/docs/user/monitoring/beats-details.asciidoc b/docs/user/monitoring/beats-details.asciidoc index 0b2be4dd9e3d9..f4ecb2a74d91e 100644 --- a/docs/user/monitoring/beats-details.asciidoc +++ b/docs/user/monitoring/beats-details.asciidoc @@ -14,8 +14,8 @@ image::user/monitoring/images/monitoring-beats.jpg["Monitoring Beats",link="imag To view an overview of the Beats data in the cluster, click *Overview*. The overview page has a section for activity in the last day, which is a real-time sample of data. The summary bar and charts follow the typical paradigm -of data in the Monitoring UI, which is bound to the span of the time filter in -the top right corner of the page. This overview page can therefore show +of data in the Monitoring UI, which is bound to the span of the time filter. +This overview page can therefore show up-to-date or historical information. To view a listing of the individual Beat instances in the cluster, click *Beats*. diff --git a/docs/visualize/lens.asciidoc b/docs/visualize/lens.asciidoc index 35570ea7ca1dc..b181763c0d0d0 100644 --- a/docs/visualize/lens.asciidoc +++ b/docs/visualize/lens.asciidoc @@ -38,7 +38,7 @@ you'll see two places highlighted in green: * The visualization builder pane -* The *X-axis* or *Y-axis* fields in the right column +* The *X-axis* or *Y-axis* fields You can incorporate many fields into your visualization, and Lens uses heuristics to decide how to apply each one to the visualization. @@ -89,8 +89,8 @@ You can switch between suggestions without losing your previous state: [role="screenshot"] image::images/lens_suggestions.gif[] -If you want to switch to a chart type that is not suggested, click the chart type in the -top right, then select a chart type. When there is an exclamation point (!) +If you want to switch to a chart type that is not suggested, click the chart type, +then select a chart type. When there is an exclamation point (!) next to a chart type, Lens is unable to transfer your current data, but still allows you to make the change. @@ -106,7 +106,7 @@ If there is a match, Lens displays the new data. All fields that do not match th . Change the data field options, such as the aggregation or label. -.. Click *Drop a field here* or the field name in the right column. +.. Click *Drop a field here* or the field name in the column. .. Change the options that appear depending on the type of field. @@ -168,7 +168,7 @@ image::images/lens_tutorial_2.png[Lens tutorial] Customize your visualization to look exactly how you want. -. In the right column, click *Average of taxful_total_price*. +. Click *Average of taxful_total_price*. .. Change the *Label* to `Sales`, or a name that you prefer for the data. @@ -180,7 +180,7 @@ six available categories. . Look at the suggestions. None of them show an area chart, but for sales data, a stacked area chart might make sense. To switch the chart type: -.. Click *Stacked bar chart* in the right column. +.. Click *Stacked bar chart* in the column. .. Click *Stacked area*. + From bc3f38288337220fba91c32de3ed5a14e9c219cc Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 9 Apr 2020 10:47:42 -0700 Subject: [PATCH 016/121] skip flaky suite (#62927) --- x-pack/test/functional/apps/canvas/custom_elements.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/canvas/custom_elements.ts b/x-pack/test/functional/apps/canvas/custom_elements.ts index 6c34556840960..de3976509be1f 100644 --- a/x-pack/test/functional/apps/canvas/custom_elements.ts +++ b/x-pack/test/functional/apps/canvas/custom_elements.ts @@ -19,7 +19,8 @@ export default function canvasCustomElementTest({ const PageObjects = getPageObjects(['canvas', 'common']); const find = getService('find'); - describe('custom elements', function() { + // FLAKY: https://github.com/elastic/kibana/issues/62927 + describe.skip('custom elements', function() { this.tags('skipFirefox'); before(async () => { From 2574d0f8055981e4a44416dcfea2a9b9b64c5d9b Mon Sep 17 00:00:00 2001 From: Joel Griffith Date: Thu, 9 Apr 2020 11:01:25 -0700 Subject: [PATCH 017/121] Adds a new config flag to encode with BOM for our CSVs (#63006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adds a new config flag to encode with BOM for our CSVs * Push out bom-chars to it's own constant * Getting those snapshots back into shape 💪 Co-authored-by: Elastic Machine --- .../__snapshots__/index.test.js.snap | 4 ++ .../plugins/reporting/common/constants.ts | 1 + x-pack/legacy/plugins/reporting/config.ts | 1 + .../csv/server/execute_job.test.js | 45 +++++++++++++++++++ .../export_types/csv/server/execute_job.ts | 6 ++- .../plugins/reporting/server/config/index.ts | 1 + 6 files changed, 56 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap b/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap index 757677f1d4f82..3ae3079da136b 100644 --- a/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap +++ b/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap @@ -66,6 +66,7 @@ Object { "duration": "30s", "size": 500, }, + "useByteOrderMarkEncoding": false, }, "enabled": true, "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", @@ -162,6 +163,7 @@ Object { "duration": "30s", "size": 500, }, + "useByteOrderMarkEncoding": false, }, "enabled": true, "index": ".reporting", @@ -257,6 +259,7 @@ Object { "duration": "30s", "size": 500, }, + "useByteOrderMarkEncoding": false, }, "enabled": true, "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", @@ -353,6 +356,7 @@ Object { "duration": "30s", "size": 500, }, + "useByteOrderMarkEncoding": false, }, "enabled": true, "index": ".reporting", diff --git a/x-pack/legacy/plugins/reporting/common/constants.ts b/x-pack/legacy/plugins/reporting/common/constants.ts index 8f7a06ba9f8e9..e3d6a4274e7df 100644 --- a/x-pack/legacy/plugins/reporting/common/constants.ts +++ b/x-pack/legacy/plugins/reporting/common/constants.ts @@ -19,6 +19,7 @@ export const API_GENERATE_IMMEDIATE = `${API_BASE_URL_V1}/generate/immediate/csv export const CONTENT_TYPE_CSV = 'text/csv'; export const CSV_REPORTING_ACTION = 'downloadCsvReport'; +export const CSV_BOM_CHARS = '\ufeff'; export const WHITELISTED_JOB_CONTENT_TYPES = [ 'application/json', diff --git a/x-pack/legacy/plugins/reporting/config.ts b/x-pack/legacy/plugins/reporting/config.ts index 211fa70301bbf..5eceb84c83e43 100644 --- a/x-pack/legacy/plugins/reporting/config.ts +++ b/x-pack/legacy/plugins/reporting/config.ts @@ -135,6 +135,7 @@ export async function config(Joi: any) { .default(), }).default(), csv: Joi.object({ + useByteOrderMarkEncoding: Joi.boolean().default(false), checkForFormulas: Joi.boolean().default(true), enablePanelActionDownload: Joi.boolean().default(true), maxSizeBytes: Joi.number() diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js index 93dbe598b367c..4870e1e35cdaf 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js @@ -13,6 +13,7 @@ import { createMockReportingCore } from '../../../test_helpers'; import { LevelLogger } from '../../../server/lib/level_logger'; import { setFieldFormats } from '../../../server/services'; import { executeJobFactory } from './execute_job'; +import { CSV_BOM_CHARS } from '../../../common/constants'; const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms)); @@ -374,6 +375,50 @@ describe('CSV Execute Job', function() { }); }); + describe('Byte order mark encoding', () => { + it('encodes CSVs with BOM', async () => { + configGetStub.withArgs('csv', 'useByteOrderMarkEncoding').returns(true); + callAsCurrentUserStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: 'one', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + + expect(content).toEqual(`${CSV_BOM_CHARS}one,two\none,bar\n`); + }); + + it('encodes CSVs without BOM', async () => { + configGetStub.withArgs('csv', 'useByteOrderMarkEncoding').returns(false); + callAsCurrentUserStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: 'one', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); + const jobParams = { + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }; + const { content } = await executeJob('job123', jobParams, cancellationToken); + + expect(content).toEqual('one,two\none,bar\n'); + }); + }); + describe('Elasticsearch call errors', function() { it('should reject Promise if search call errors out', async function() { callAsCurrentUserStub.rejects(new Error()); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index 3a282eb0b2974..376a398da274f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import Hapi from 'hapi'; import { IUiSettingsClient, KibanaRequest } from '../../../../../../../src/core/server'; -import { CSV_JOB_TYPE } from '../../../common/constants'; +import { CSV_JOB_TYPE, CSV_BOM_CHARS } from '../../../common/constants'; import { ReportingCore } from '../../../server/core'; import { cryptoFactory } from '../../../server/lib'; import { getFieldFormats } from '../../../server/services'; @@ -121,6 +121,8 @@ export const executeJobFactory: ExecuteJobFactory Date: Thu, 9 Apr 2020 21:26:13 +0300 Subject: [PATCH 018/121] [SIEM][CASE] Test configuration API and hooks (#62803) * Test API * Test useConnectors * Test useConfigure * Fixes --- .../case/configure/__mocks__/api.ts | 31 ++ .../containers/case/configure/api.test.ts | 115 +++++++ .../public/containers/case/configure/mock.ts | 99 ++++++ .../case/configure/use_configure.test.tsx | 299 ++++++++++++++++++ .../case/configure/use_configure.tsx | 2 +- .../case/configure/use_connectors.test.tsx | 95 ++++++ 6 files changed, 640 insertions(+), 1 deletion(-) create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/configure/__mocks__/api.ts create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/configure/api.test.ts create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/configure/mock.ts create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/configure/use_connectors.test.tsx diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/__mocks__/api.ts b/x-pack/legacy/plugins/siem/public/containers/case/configure/__mocks__/api.ts new file mode 100644 index 0000000000000..03f7d241e5dff --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/__mocks__/api.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 { + CasesConfigurePatch, + CasesConfigureRequest, + Connector, +} from '../../../../../../../../plugins/case/common/api'; + +import { ApiProps } from '../../types'; +import { CaseConfigure } from '../types'; +import { connectorsMock, caseConfigurationCamelCaseResponseMock } from '../mock'; + +export const fetchConnectors = async ({ signal }: ApiProps): Promise => + Promise.resolve(connectorsMock); + +export const getCaseConfigure = async ({ signal }: ApiProps): Promise => + Promise.resolve(caseConfigurationCamelCaseResponseMock); + +export const postCaseConfigure = async ( + caseConfiguration: CasesConfigureRequest, + signal: AbortSignal +): Promise => Promise.resolve(caseConfigurationCamelCaseResponseMock); + +export const patchCaseConfigure = async ( + caseConfiguration: CasesConfigurePatch, + signal: AbortSignal +): Promise => Promise.resolve(caseConfigurationCamelCaseResponseMock); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/api.test.ts b/x-pack/legacy/plugins/siem/public/containers/case/configure/api.test.ts new file mode 100644 index 0000000000000..ef0e51fb1c24d --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/api.test.ts @@ -0,0 +1,115 @@ +/* + * 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 { KibanaServices } from '../../../lib/kibana'; +import { fetchConnectors, getCaseConfigure, postCaseConfigure, patchCaseConfigure } from './api'; +import { + connectorsMock, + caseConfigurationMock, + caseConfigurationResposeMock, + caseConfigurationCamelCaseResponseMock, +} from './mock'; + +const abortCtrl = new AbortController(); +const mockKibanaServices = KibanaServices.get as jest.Mock; +jest.mock('../../../lib/kibana'); + +const fetchMock = jest.fn(); +mockKibanaServices.mockReturnValue({ http: { fetch: fetchMock } }); + +describe('Case Configuration API', () => { + describe('fetch connectors', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(connectorsMock); + }); + + test('check url, method, signal', async () => { + await fetchConnectors({ signal: abortCtrl.signal }); + expect(fetchMock).toHaveBeenCalledWith('/api/cases/configure/connectors/_find', { + method: 'GET', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await fetchConnectors({ signal: abortCtrl.signal }); + expect(resp).toEqual(connectorsMock); + }); + }); + + describe('fetch configuration', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(caseConfigurationResposeMock); + }); + + test('check url, method, signal', async () => { + await getCaseConfigure({ signal: abortCtrl.signal }); + expect(fetchMock).toHaveBeenCalledWith('/api/cases/configure', { + method: 'GET', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getCaseConfigure({ signal: abortCtrl.signal }); + expect(resp).toEqual(caseConfigurationCamelCaseResponseMock); + }); + + test('return null on empty response', async () => { + fetchMock.mockResolvedValue({}); + const resp = await getCaseConfigure({ signal: abortCtrl.signal }); + expect(resp).toBe(null); + }); + }); + + describe('create configuration', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(caseConfigurationResposeMock); + }); + + test('check url, body, method, signal', async () => { + await postCaseConfigure(caseConfigurationMock, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith('/api/cases/configure', { + body: + '{"connector_id":"123","connector_name":"My Connector","closure_type":"close-by-user"}', + method: 'POST', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await postCaseConfigure(caseConfigurationMock, abortCtrl.signal); + expect(resp).toEqual(caseConfigurationCamelCaseResponseMock); + }); + }); + + describe('update configuration', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(caseConfigurationResposeMock); + }); + + test('check url, body, method, signal', async () => { + await patchCaseConfigure({ connector_id: '456', version: 'WzHJ12' }, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith('/api/cases/configure', { + body: '{"connector_id":"456","version":"WzHJ12"}', + method: 'PATCH', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await patchCaseConfigure( + { connector_id: '456', version: 'WzHJ12' }, + abortCtrl.signal + ); + expect(resp).toEqual(caseConfigurationCamelCaseResponseMock); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/mock.ts b/x-pack/legacy/plugins/siem/public/containers/case/configure/mock.ts new file mode 100644 index 0000000000000..d2491b39fdf56 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/mock.ts @@ -0,0 +1,99 @@ +/* + * 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 { + Connector, + CasesConfigureResponse, + CasesConfigureRequest, +} from '../../../../../../../plugins/case/common/api'; +import { CaseConfigure } from './types'; + +export const connectorsMock: Connector[] = [ + { + id: '123', + actionTypeId: '.servicenow', + name: 'My Connector', + config: { + apiUrl: 'https://instance1.service-now.com', + casesConfiguration: { + mapping: [ + { + source: 'title', + target: 'short_description', + actionType: 'overwrite', + }, + { + source: 'description', + target: 'description', + actionType: 'append', + }, + { + source: 'comments', + target: 'comments', + actionType: 'append', + }, + ], + }, + }, + isPreconfigured: true, + }, + { + id: '456', + actionTypeId: '.servicenow', + name: 'My Connector 2', + config: { + apiUrl: 'https://instance2.service-now.com', + casesConfiguration: { + mapping: [ + { + source: 'title', + target: 'short_description', + actionType: 'overwrite', + }, + { + source: 'description', + target: 'description', + actionType: 'overwrite', + }, + { + source: 'comments', + target: 'comments', + actionType: 'append', + }, + ], + }, + }, + isPreconfigured: true, + }, +]; + +export const caseConfigurationResposeMock: CasesConfigureResponse = { + created_at: '2020-04-06T13:03:18.657Z', + created_by: { username: 'elastic', full_name: 'Elastic', email: 'elastic@elastic.co' }, + connector_id: '123', + connector_name: 'My Connector', + closure_type: 'close-by-user', + updated_at: '2020-04-06T14:03:18.657Z', + updated_by: { username: 'elastic', full_name: 'Elastic', email: 'elastic@elastic.co' }, + version: 'WzHJ12', +}; + +export const caseConfigurationMock: CasesConfigureRequest = { + connector_id: '123', + connector_name: 'My Connector', + closure_type: 'close-by-user', +}; + +export const caseConfigurationCamelCaseResponseMock: CaseConfigure = { + createdAt: '2020-04-06T13:03:18.657Z', + createdBy: { username: 'elastic', fullName: 'Elastic', email: 'elastic@elastic.co' }, + connectorId: '123', + connectorName: 'My Connector', + closureType: 'close-by-user', + updatedAt: '2020-04-06T14:03:18.657Z', + updatedBy: { username: 'elastic', fullName: 'Elastic', email: 'elastic@elastic.co' }, + version: 'WzHJ12', +}; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.test.tsx new file mode 100644 index 0000000000000..3ee16e19eaf9f --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.test.tsx @@ -0,0 +1,299 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import { useCaseConfigure, ReturnUseCaseConfigure, PersistCaseConfigure } from './use_configure'; +import { caseConfigurationCamelCaseResponseMock } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +const configuration: PersistCaseConfigure = { + connectorId: '456', + connectorName: 'My Connector 2', + closureType: 'close-by-pushing', +}; + +describe('useConfigure', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + const args = { + setConnector: jest.fn(), + setClosureType: jest.fn(), + setCurrentConfiguration: jest.fn(), + }; + + test('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + loading: true, + persistLoading: false, + refetchCaseConfigure: result.current.refetchCaseConfigure, + persistCaseConfigure: result.current.persistCaseConfigure, + }); + }); + }); + + test('fetch case configuration', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + loading: false, + persistLoading: false, + refetchCaseConfigure: result.current.refetchCaseConfigure, + persistCaseConfigure: result.current.persistCaseConfigure, + }); + }); + }); + + test('fetch case configuration - setConnector', async () => { + await act(async () => { + const { waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(args.setConnector).toHaveBeenCalledWith('123', 'My Connector'); + }); + }); + + test('fetch case configuration - setClosureType', async () => { + await act(async () => { + const { waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(args.setClosureType).toHaveBeenCalledWith('close-by-user'); + }); + }); + + test('fetch case configuration - setCurrentConfiguration', async () => { + await act(async () => { + const { waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(args.setCurrentConfiguration).toHaveBeenCalledWith({ + connectorId: '123', + closureType: 'close-by-user', + }); + }); + }); + + test('fetch case configuration - only setConnector', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure({ setConnector: jest.fn() }) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + loading: false, + persistLoading: false, + refetchCaseConfigure: result.current.refetchCaseConfigure, + persistCaseConfigure: result.current.persistCaseConfigure, + }); + }); + }); + + test('refetch case configuration', async () => { + const spyOnGetCaseConfigure = jest.spyOn(api, 'getCaseConfigure'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.refetchCaseConfigure(); + expect(spyOnGetCaseConfigure).toHaveBeenCalledTimes(2); + }); + }); + + test('set isLoading to true when fetching case configuration', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.refetchCaseConfigure(); + + expect(result.current.loading).toBe(true); + }); + }); + + test('persist case configuration', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + result.current.persistCaseConfigure(configuration); + + expect(result.current).toEqual({ + loading: false, + persistLoading: true, + refetchCaseConfigure: result.current.refetchCaseConfigure, + persistCaseConfigure: result.current.persistCaseConfigure, + }); + }); + }); + + test('save case configuration - postCaseConfigure', async () => { + // When there is no version, a configuration is created. Otherwise is updated. + const spyOnGetCaseConfigure = jest.spyOn(api, 'getCaseConfigure'); + spyOnGetCaseConfigure.mockImplementation(() => + Promise.resolve({ + ...caseConfigurationCamelCaseResponseMock, + version: '', + }) + ); + + const spyOnPostCaseConfigure = jest.spyOn(api, 'postCaseConfigure'); + spyOnPostCaseConfigure.mockImplementation(() => + Promise.resolve({ + ...caseConfigurationCamelCaseResponseMock, + ...configuration, + }) + ); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + result.current.persistCaseConfigure(configuration); + + await waitForNextUpdate(); + + expect(args.setConnector).toHaveBeenNthCalledWith(2, '456'); + expect(args.setClosureType).toHaveBeenNthCalledWith(2, 'close-by-pushing'); + expect(args.setCurrentConfiguration).toHaveBeenNthCalledWith(2, { + connectorId: '456', + closureType: 'close-by-pushing', + }); + }); + }); + + test('save case configuration - patchCaseConfigure', async () => { + const spyOnPatchCaseConfigure = jest.spyOn(api, 'patchCaseConfigure'); + spyOnPatchCaseConfigure.mockImplementation(() => + Promise.resolve({ + ...caseConfigurationCamelCaseResponseMock, + ...configuration, + }) + ); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + result.current.persistCaseConfigure(configuration); + + await waitForNextUpdate(); + + expect(args.setConnector).toHaveBeenNthCalledWith(2, '456'); + expect(args.setClosureType).toHaveBeenNthCalledWith(2, 'close-by-pushing'); + expect(args.setCurrentConfiguration).toHaveBeenNthCalledWith(2, { + connectorId: '456', + closureType: 'close-by-pushing', + }); + }); + }); + + test('save case configuration - only setConnector', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure({ setConnector: jest.fn() }) + ); + + await waitForNextUpdate(); + await waitForNextUpdate(); + + result.current.persistCaseConfigure(configuration); + + await waitForNextUpdate(); + + expect(result.current).toEqual({ + loading: false, + persistLoading: false, + refetchCaseConfigure: result.current.refetchCaseConfigure, + persistCaseConfigure: result.current.persistCaseConfigure, + }); + }); + }); + + test('unhappy path - fetch case configuration', async () => { + const spyOnGetCaseConfigure = jest.spyOn(api, 'getCaseConfigure'); + spyOnGetCaseConfigure.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + loading: false, + persistLoading: false, + refetchCaseConfigure: result.current.refetchCaseConfigure, + persistCaseConfigure: result.current.persistCaseConfigure, + }); + }); + }); + + test('unhappy path - persist case configuration', async () => { + const spyOnPostCaseConfigure = jest.spyOn(api, 'postCaseConfigure'); + spyOnPostCaseConfigure.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useCaseConfigure(args) + ); + + await waitForNextUpdate(); + await waitForNextUpdate(); + + result.current.persistCaseConfigure(configuration); + + await waitForNextUpdate(); + + expect(result.current).toEqual({ + loading: false, + persistLoading: false, + refetchCaseConfigure: result.current.refetchCaseConfigure, + persistCaseConfigure: result.current.persistCaseConfigure, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx index 19d80bba1e0f8..7f57149d4e56d 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx @@ -12,7 +12,7 @@ import * as i18n from './translations'; import { ClosureType } from './types'; import { CurrentConfiguration } from '../../../pages/case/components/configure_cases/reducer'; -interface PersistCaseConfigure { +export interface PersistCaseConfigure { connectorId: string; connectorName: string; closureType: ClosureType; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_connectors.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_connectors.test.tsx new file mode 100644 index 0000000000000..0d6b6acfd9065 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_connectors.test.tsx @@ -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 { renderHook, act } from '@testing-library/react-hooks'; +import { useConnectors, ReturnConnectors } from './use_connectors'; +import { connectorsMock } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useConnectors', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + test('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useConnectors() + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + loading: true, + connectors: [], + refetchConnectors: result.current.refetchConnectors, + }); + }); + }); + + test('fetch connectors', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useConnectors() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + loading: false, + connectors: connectorsMock, + refetchConnectors: result.current.refetchConnectors, + }); + }); + }); + + test('refetch connectors', async () => { + const spyOnfetchConnectors = jest.spyOn(api, 'fetchConnectors'); + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useConnectors() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.refetchConnectors(); + expect(spyOnfetchConnectors).toHaveBeenCalledTimes(2); + }); + }); + + test('set isLoading to true when refetching connectors', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useConnectors() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.refetchConnectors(); + + expect(result.current.loading).toBe(true); + }); + }); + + test('unhappy path', async () => { + const spyOnfetchConnectors = jest.spyOn(api, 'fetchConnectors'); + spyOnfetchConnectors.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook(() => + useConnectors() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + loading: false, + connectors: [], + refetchConnectors: result.current.refetchConnectors, + }); + }); + }); +}); From 9fd63a7daad6f3f13585d2d6397402654c278914 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Thu, 9 Apr 2020 11:31:19 -0700 Subject: [PATCH 019/121] [DOCS] Adds docs for Painless Lab (#62997) * [DOCS] Adds docs for Painless Lab * [DOCS] Incorporated review comments --- .../painlesslab/images/painless-lab.png | Bin 0 -> 220876 bytes docs/dev-tools/painlesslab/index.asciidoc | 17 +++++++++++ docs/user/dev-tools.asciidoc | 28 ++++++++++++++---- 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 docs/dev-tools/painlesslab/images/painless-lab.png create mode 100644 docs/dev-tools/painlesslab/index.asciidoc diff --git a/docs/dev-tools/painlesslab/images/painless-lab.png b/docs/dev-tools/painlesslab/images/painless-lab.png new file mode 100644 index 0000000000000000000000000000000000000000..f65257852792e03eae3d2e111da11d81f6df630f GIT binary patch literal 220876 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%0DJ;r1F_I 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

}xIV{+K-l~dNlQoghqoZX| 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, +process {ref}/docs-reindex.html[reindexed data], define complex +<>, +and work with data in other contexts. + +To get started, go to *Dev Tools > Painless Lab*. + +image::dev-tools/painlesslab/images/painless-lab.png[Painless Lab] diff --git a/docs/user/dev-tools.asciidoc b/docs/user/dev-tools.asciidoc index 77a781fd069e4..0ee7fbc741e00 100644 --- a/docs/user/dev-tools.asciidoc +++ b/docs/user/dev-tools.asciidoc @@ -4,13 +4,29 @@ [partintro] -- -The *Dev Tools* page contains development tools that you can use to interact -with your data in Kibana. +*Dev Tools* contains tools that you can use to interact +with your data. -* <> -* <> -* <> +[cols="2"] +|=== +a| <> + +| Interact with the REST API of Elasticsearch, including sending requests +and viewing API documentation. + +a| <> + +| Inspect and analyze your search queries. + +a| <> + +| Build and debug grok patterns before you use them in your data processing pipelines. + +a| <> + +| beta:[] Test and debug Painless scripts in real-time. +|=== -- @@ -19,3 +35,5 @@ include::{kib-repo-dir}/dev-tools/console/console.asciidoc[] include::{kib-repo-dir}/dev-tools/searchprofiler/index.asciidoc[] include::{kib-repo-dir}/dev-tools/grokdebugger/index.asciidoc[] + +include::{kib-repo-dir}/dev-tools/painlesslab/index.asciidoc[] From 087df824523d007409c68e7d3ba32d824cce07ee Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 9 Apr 2020 11:48:56 -0700 Subject: [PATCH 020/121] [TSVB] Add Positive Rate to Aggregations (#59843) * [TSVB] Add Rate to Aggregations * Fixing i18n labels * Changing from rate to growth_rate; adding message to aggregation form; * Change units to scale; change free text to combobox * Fixing placeholder * Fixing i18n label * Changing from Growth Rate to Positive Rate Co-authored-by: Elastic Machine --- .../public/components/aggs/agg_select.js | 6 + .../public/components/aggs/positive_rate.js | 191 ++++++++++++++++++ .../public/components/lib/agg_to_component.js | 2 + .../vis_type_timeseries/common/agg_lookup.js | 3 + .../common/calculate_label.js | 6 + .../request_processors/series/index.js | 2 + .../series/positive_rate.js | 68 +++++++ .../series/positive_rate.test.js | 95 +++++++++ .../request_processors/table/index.js | 2 + .../request_processors/table/positive_rate.js | 35 ++++ 10 files changed, 410 insertions(+) create mode 100644 src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/positive_rate.js create mode 100644 src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js create mode 100644 src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js create mode 100644 src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_select.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_select.js index f93dee14d0eed..8607ff184dfaa 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_select.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/agg_select.js @@ -49,6 +49,12 @@ const metricAggs = [ }), value: 'filter_ratio', }, + { + label: i18n.translate('visTypeTimeseries.aggSelect.metricsAggs.positiveRateLabel', { + defaultMessage: 'Positive Rate', + }), + value: 'positive_rate', + }, { label: i18n.translate('visTypeTimeseries.aggSelect.metricsAggs.maxLabel', { defaultMessage: 'Max', diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/positive_rate.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/positive_rate.js new file mode 100644 index 0000000000000..39558fa3a9224 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/aggs/positive_rate.js @@ -0,0 +1,191 @@ +/* + * 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 PropTypes from 'prop-types'; +import React from 'react'; +import { AggSelect } from './agg_select'; +import { FieldSelect } from './field_select'; +import { AggRow } from './agg_row'; +import { createChangeHandler } from '../lib/create_change_handler'; +import { createSelectHandler } from '../lib/create_select_handler'; +import { + htmlIdGenerator, + EuiFlexGroup, + EuiFlexItem, + EuiFormLabel, + EuiFormRow, + EuiSpacer, + EuiText, + EuiLink, + EuiComboBox, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { KBN_FIELD_TYPES } from '../../../../../../plugins/data/public'; + +const UNIT_OPTIONS = [ + { + label: i18n.translate('visTypeTimeseries.units.auto', { defaultMessage: 'auto' }), + value: '', + }, + { + label: i18n.translate('visTypeTimeseries.units.perMillisecond', { + defaultMessage: 'per millisecond', + }), + value: '1ms', + }, + { + label: i18n.translate('visTypeTimeseries.units.perSecond', { defaultMessage: 'per second' }), + value: '1s', + }, + { + label: i18n.translate('visTypeTimeseries.units.perMinute', { defaultMessage: 'per minute' }), + value: '1m', + }, + { + label: i18n.translate('visTypeTimeseries.units.perHour', { defaultMessage: 'per hour' }), + value: '1h', + }, + { + label: i18n.translate('visTypeTimeseries.units.perDay', { defaultMessage: 'per day' }), + value: '1d', + }, +]; + +export const PositiveRateAgg = props => { + const defaults = { unit: '' }; + const model = { ...defaults, ...props.model }; + + const handleChange = createChangeHandler(props.onChange, model); + const handleSelectChange = createSelectHandler(handleChange); + + const htmlId = htmlIdGenerator(); + const indexPattern = + (props.series.override_index_pattern && props.series.series_index_pattern) || + props.panel.index_pattern; + + const selectedUnitOptions = UNIT_OPTIONS.filter(o => o.value === model.unit); + + return ( + + + + + + + + + + + + } + fullWidth + > + + + + + + } + fullWidth + > + + + + + + +

+ + + + ), + }} + /> +

+ + + ); +}; + +PositiveRateAgg.propTypes = { + disableDelete: PropTypes.bool, + fields: PropTypes.object, + model: PropTypes.object, + onAdd: PropTypes.func, + onChange: PropTypes.func, + onDelete: PropTypes.func, + panel: PropTypes.object, + series: PropTypes.object, + siblings: PropTypes.array, +}; diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/agg_to_component.js b/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/agg_to_component.js index ca40d60f20848..a53192afafdcc 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/agg_to_component.js +++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/lib/agg_to_component.js @@ -33,6 +33,7 @@ import { PercentileRankAgg } from '../aggs/percentile_rank'; import { Static } from '../aggs/static'; import { MathAgg } from '../aggs/math'; import { TopHitAgg } from '../aggs/top_hit'; +import { PositiveRateAgg } from '../aggs/positive_rate'; export const aggToComponent = { count: StandardAgg, @@ -65,4 +66,5 @@ export const aggToComponent = { static: Static, math: MathAgg, top_hit: TopHitAgg, + positive_rate: PositiveRateAgg, }; diff --git a/src/plugins/vis_type_timeseries/common/agg_lookup.js b/src/plugins/vis_type_timeseries/common/agg_lookup.js index 4dfdc83dcfabb..432da03e3d45d 100644 --- a/src/plugins/vis_type_timeseries/common/agg_lookup.js +++ b/src/plugins/vis_type_timeseries/common/agg_lookup.js @@ -97,6 +97,9 @@ export const lookup = { defaultMessage: 'Static Value', }), top_hit: i18n.translate('visTypeTimeseries.aggLookup.topHitLabel', { defaultMessage: 'Top Hit' }), + positive_rate: i18n.translate('visTypeTimeseries.aggLookup.positiveRateLabel', { + defaultMessage: 'Positive Rate', + }), }; const pipeline = [ diff --git a/src/plugins/vis_type_timeseries/common/calculate_label.js b/src/plugins/vis_type_timeseries/common/calculate_label.js index 756d6e57a83e8..71aa0aed7dc11 100644 --- a/src/plugins/vis_type_timeseries/common/calculate_label.js +++ b/src/plugins/vis_type_timeseries/common/calculate_label.js @@ -70,6 +70,12 @@ export function calculateLabel(metric, metrics) { defaultMessage: 'Filter Ratio', }); } + if (metric.type === 'positive_rate') { + return i18n.translate('visTypeTimeseries.calculateLabel.positiveRateLabel', { + defaultMessage: 'Positive Rate of {field}', + values: { field: metric.field }, + }); + } if (metric.type === 'static') { return i18n.translate('visTypeTimeseries.calculateLabel.staticValueLabel', { defaultMessage: 'Static Value of {metricValue}', diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/index.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/index.js index 4b0b8f33716a2..c727a3131f5df 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/index.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/index.js @@ -26,6 +26,7 @@ import { dateHistogram } from './date_histogram'; import { metricBuckets } from './metric_buckets'; import { siblingBuckets } from './sibling_buckets'; import { ratios as filterRatios } from './filter_ratios'; +import { positiveRate } from './positive_rate'; import { normalizeQuery } from './normalize_query'; export const processors = [ @@ -38,5 +39,6 @@ export const processors = [ metricBuckets, siblingBuckets, filterRatios, + positiveRate, normalizeQuery, ]; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js new file mode 100644 index 0000000000000..1ff548cc19e02 --- /dev/null +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js @@ -0,0 +1,68 @@ +/* + * 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 { getBucketSize } from '../../helpers/get_bucket_size'; +import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; +import { bucketTransform } from '../../helpers/bucket_transform'; +import { set } from 'lodash'; + +export const filter = metric => metric.type === 'positive_rate'; + +export const createPositiveRate = (doc, intervalString, aggRoot) => metric => { + const maxFn = bucketTransform.max; + const derivativeFn = bucketTransform.derivative; + const positiveOnlyFn = bucketTransform.positive_only; + + const maxMetric = { id: `${metric.id}-positive-rate-max`, type: 'max', field: metric.field }; + const derivativeMetric = { + id: `${metric.id}-positive-rate-derivative`, + type: 'derivative', + field: `${metric.id}-positive-rate-max`, + unit: metric.unit, + }; + const positiveOnlyMetric = { + id: metric.id, + type: 'positive_only', + field: `${metric.id}-positive-rate-derivative`, + }; + + const fakeSeriesMetrics = [maxMetric, derivativeMetric, positiveOnlyMetric]; + + const maxBucket = maxFn(maxMetric, fakeSeriesMetrics, intervalString); + const derivativeBucket = derivativeFn(derivativeMetric, fakeSeriesMetrics, intervalString); + const positiveOnlyBucket = positiveOnlyFn(positiveOnlyMetric, fakeSeriesMetrics, intervalString); + + set(doc, `${aggRoot}.timeseries.aggs.${metric.id}-positive-rate-max`, maxBucket); + set(doc, `${aggRoot}.timeseries.aggs.${metric.id}-positive-rate-derivative`, derivativeBucket); + set(doc, `${aggRoot}.timeseries.aggs.${metric.id}`, positiveOnlyBucket); +}; + +export function positiveRate(req, panel, series, esQueryConfig, indexPatternObject, capabilities) { + return next => doc => { + const { interval } = getIntervalAndTimefield(panel, series, indexPatternObject); + const { intervalString } = getBucketSize(req, interval, capabilities); + if (series.metrics.some(filter)) { + series.metrics + .filter(filter) + .forEach(createPositiveRate(doc, intervalString, `aggs.${series.id}.aggs`)); + return next(doc); + } + return next(doc); + }; +} diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js new file mode 100644 index 0000000000000..946884c05c722 --- /dev/null +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.test.js @@ -0,0 +1,95 @@ +/* + * 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 { positiveRate } from './positive_rate'; +describe('positiveRate(req, panel, series)', () => { + let panel; + let series; + let req; + beforeEach(() => { + panel = { + time_field: 'timestamp', + }; + series = { + id: 'test', + split_mode: 'terms', + terms_size: 10, + terms_field: 'host', + metrics: [ + { + id: 'metric-1', + type: 'positive_rate', + field: 'system.network.out.bytes', + unit: '1s', + }, + ], + }; + req = { + payload: { + timerange: { + min: '2017-01-01T00:00:00Z', + max: '2017-01-01T01:00:00Z', + }, + }, + }; + }); + + test('calls next when finished', () => { + const next = jest.fn(); + positiveRate(req, panel, series)(next)({}); + expect(next.mock.calls.length).toEqual(1); + }); + + test('returns positive rate aggs', () => { + const next = doc => doc; + const doc = positiveRate(req, panel, series)(next)({}); + expect(doc).toEqual({ + aggs: { + test: { + aggs: { + timeseries: { + aggs: { + 'metric-1-positive-rate-max': { + max: { field: 'system.network.out.bytes' }, + }, + 'metric-1-positive-rate-derivative': { + derivative: { + buckets_path: 'metric-1-positive-rate-max', + gap_policy: 'skip', + unit: '1s', + }, + }, + 'metric-1': { + bucket_script: { + buckets_path: { value: 'metric-1-positive-rate-derivative[normalized_value]' }, + script: { + source: 'params.value > 0.0 ? params.value : 0.0', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, + }, + }, + }, + }, + }, + }); + }); +}); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/index.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/index.js index a62533ae7a37c..5864d2538005d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/index.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/index.js @@ -26,6 +26,7 @@ import { metricBuckets } from './metric_buckets'; import { siblingBuckets } from './sibling_buckets'; import { ratios as filterRatios } from './filter_ratios'; import { normalizeQuery } from './normalize_query'; +import { positiveRate } from './positive_rate'; export const processors = [ query, @@ -36,5 +37,6 @@ export const processors = [ metricBuckets, siblingBuckets, filterRatios, + positiveRate, normalizeQuery, ]; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js new file mode 100644 index 0000000000000..da4b834822d70 --- /dev/null +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js @@ -0,0 +1,35 @@ +/* + * 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 { getBucketSize } from '../../helpers/get_bucket_size'; +import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; +import { calculateAggRoot } from './calculate_agg_root'; +import { createPositiveRate, filter } from '../series/positive_rate'; + +export function positiveRate(req, panel, esQueryConfig, indexPatternObject) { + return next => doc => { + const { interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); + const { intervalString } = getBucketSize(req, interval); + panel.series.forEach(column => { + const aggRoot = calculateAggRoot(doc, column); + column.metrics.filter(filter).forEach(createPositiveRate(doc, intervalString, aggRoot)); + }); + return next(doc); + }; +} From b8738b0eebf7a7ad708b5f498dcc51f6a7fb2c87 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Thu, 9 Apr 2020 15:05:09 -0400 Subject: [PATCH 021/121] Ensure that discover data exists for home/_navigation test so that the test suite can run in isolation (#62516) --- test/functional/apps/home/_navigation.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/functional/apps/home/_navigation.ts b/test/functional/apps/home/_navigation.ts index efc0dad394464..2c927e9a2f4c7 100644 --- a/test/functional/apps/home/_navigation.ts +++ b/test/functional/apps/home/_navigation.ts @@ -52,6 +52,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { describe('Kibana browser back navigation should work', function describeIndexTests() { before(async () => { + await esArchiver.loadIfNeeded('discover'); await esArchiver.loadIfNeeded('logstash_functional'); if (browser.isInternetExplorer) { await kibanaServer.uiSettings.replace({ 'state:storeInSessionStorage': false }); From e61680571acce5b6bb8be8d9f6e574864c49f290 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Thu, 9 Apr 2020 15:05:21 -0400 Subject: [PATCH 022/121] Ensure alerting action exists in connectors test setup (#62511) --- .../apps/triggers_actions_ui/connectors.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts index c2013ba3502e2..b5bcd33c3b9ab 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts @@ -13,12 +13,20 @@ function generateUniqueKey() { } export default ({ getPageObjects, getService }: FtrProviderContext) => { + const alerting = getService('alerting'); const testSubjects = getService('testSubjects'); const pageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']); const find = getService('find'); describe('Connectors', function() { before(async () => { + await alerting.actions.createAction({ + name: `server-log-${Date.now()}`, + actionTypeId: '.server-log', + config: {}, + secrets: {}, + }); + await pageObjects.common.navigateToApp('triggersActions'); await testSubjects.click('connectorsTab'); }); From 783e3c17a9ed32d6a5aff39a83bdfa38aa152bf1 Mon Sep 17 00:00:00 2001 From: Tim Schnell Date: Thu, 9 Apr 2020 14:32:24 -0500 Subject: [PATCH 023/121] ignore some things for code coverage (#62701) Co-authored-by: Elastic Machine --- x-pack/legacy/plugins/canvas/scripts/jest.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/canvas/scripts/jest.js b/x-pack/legacy/plugins/canvas/scripts/jest.js index cce1b8d355846..133f775c7192f 100644 --- a/x-pack/legacy/plugins/canvas/scripts/jest.js +++ b/x-pack/legacy/plugins/canvas/scripts/jest.js @@ -36,6 +36,14 @@ run( `!${path}/**/__tests__/**/*`, '--collectCoverageFrom', // Ignore coverage on example files `!${path}/**/__examples__/**/*`, + '--collectCoverageFrom', // Ignore flot files + `!${path}/**/flot-charts/**`, + '--collectCoverageFrom', // Ignore coverage files + `!${path}/**/coverage/**`, + '--collectCoverageFrom', // Ignore scripts + `!${path}/**/scripts/**`, + '--collectCoverageFrom', // Ignore mock files + `!${path}/**/mocks/**`, '--collectCoverageFrom', // Include JS files `${path}/**/*.js`, '--collectCoverageFrom', // Include TS/X files @@ -76,7 +84,7 @@ run( --all Runs all tests and snapshots. Slower. --storybook Runs Storybook Snapshot tests only. --update Updates Storybook Snapshot tests. - --path Runs any tests at a given path. + --path Runs any tests at a given path. --coverage Collect coverage statistics. `, }, From 834306458ac5178cbe26a0f962c764a0451568e2 Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Thu, 9 Apr 2020 13:52:02 -0600 Subject: [PATCH 024/121] Fixes a needed import that was coming from APM but now isolates things better for optimization import builds ## Summary Adds a single line to work with ts config optimizers. What is happening is that this is relying on an import from here: ``` x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx ``` when really it should be isolated and imported within this file. Testing is just to go to siem and run these commands: ```ts cd /projects/kibana node x-pack/legacy/plugins/siem/scripts/optimize_tsconfig.js node scripts/type_check.js --project x-pack/tsconfig.json ``` Ensure you don't see any errors. --- .../public/application/components/health_check.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx index 5156a6146f3a1..9c51139993b3f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx @@ -10,6 +10,7 @@ import { HealthCheck } from './health_check'; import { act } from 'react-dom/test-utils'; import { httpServiceMock } from '../../../../../../src/core/public/mocks'; +import '@testing-library/jest-dom/extend-expect'; const docLinks = { ELASTIC_WEBSITE_URL: 'elastic.co/', DOC_LINK_VERSION: 'current' }; From bc8c4a754db653762fe50a7bfc9bee7f9006e20c Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Thu, 9 Apr 2020 15:43:07 -0600 Subject: [PATCH 025/121] [File upload] Change 'file_upload' id and refs to 'fileUpload' (#63000) --- x-pack/plugins/file_upload/kibana.json | 3 +-- x-pack/plugins/maps/public/plugin.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/file_upload/kibana.json b/x-pack/plugins/file_upload/kibana.json index 3fda32fb6ebe5..7676a01d0b0f9 100644 --- a/x-pack/plugins/file_upload/kibana.json +++ b/x-pack/plugins/file_upload/kibana.json @@ -1,8 +1,7 @@ { - "id": "file_upload", + "id": "fileUpload", "version": "8.0.0", "kibanaVersion": "kibana", - "configPath": ["xpack", "file_upload"], "server": true, "ui": true, "requiredPlugins": ["data", "usageCollection"] diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 9437c2512ded4..14487b615e759 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -43,9 +43,9 @@ export const bindSetupCoreAndPlugins = (core: CoreSetup, plugins: any) => { }; export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { - const { file_upload, data, inspector } = plugins; + const { fileUpload, data, inspector } = plugins; setInspector(inspector); - setFileUpload(file_upload); + setFileUpload(fileUpload); setIndexPatternSelect(data.ui.IndexPatternSelect); setTimeFilter(data.query.timefilter.timefilter); setIndexPatternService(data.indexPatterns); From 93b34632c08884e7850114f1fe21adfb47471c22 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Thu, 9 Apr 2020 23:53:47 +0200 Subject: [PATCH 026/121] [TSVB] Fix wrongly display stacked as percentage charts (#62654) Update to elastic-charts 18.2.2 with the valid 0% rendering --- package.json | 2 +- packages/kbn-ui-shared-deps/package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index bd0fec3a5c116..ea930d07e7b43 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "@babel/core": "^7.9.0", "@babel/register": "^7.9.0", "@elastic/apm-rum": "^4.6.0", - "@elastic/charts": "^18.1.1", + "@elastic/charts": "18.2.2", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.8.0", "@elastic/eui": "21.0.1", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index e2823f23d0431..7c5d6a62a11ca 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -9,7 +9,7 @@ "kbn:watch": "node scripts/build --watch" }, "dependencies": { - "@elastic/charts": "^18.1.1", + "@elastic/charts": "18.2.2", "@elastic/eui": "21.0.1", "@kbn/i18n": "1.0.0", "abortcontroller-polyfill": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index 3f04b2d26a013..20e33fdefc996 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1197,10 +1197,10 @@ dependencies: "@elastic/apm-rum-core" "^4.7.0" -"@elastic/charts@^18.1.1": - version "18.2.0" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-18.2.0.tgz#e141151b4d7ecc71c9f6f235f8ce141665c67195" - integrity sha512-OWsARaHI/4Ict/GkeKIO3a+e2c86esGw3FtSGRLPFVgzpwBXdjvjYyraGntKOIVs/NAGNVWYj5XoRRb5C6cMlQ== +"@elastic/charts@18.2.2": + version "18.2.2" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-18.2.2.tgz#f59d6ee597d553d193314d8598561c65da787e8d" + integrity sha512-ss8AqLj9wHa2C+9ULUKbXw8ZCQmEjLuaVU5AkqE2j3hOVtAN75HO2p7nMIsxcSldfmqy+4jSptybJLNAfizegQ== dependencies: classnames "^2.2.6" d3-array "^1.2.4" From 982c0da78e67694e0c2e05e8e2e7431ab9bda880 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Thu, 9 Apr 2020 16:51:22 -0700 Subject: [PATCH 027/121] Move ILM out of legacy (#61915) * Rename IndexMgmtSetup to IndexManagementPluginSetup. * Remove unused fetch index template route and related tests. * Remove unnecessary custom styles. --- .github/CODEOWNERS | 2 +- x-pack/.i18nrc.json | 2 +- x-pack/index.js | 2 - .../np_ready/extend_index_management.ts | 4 +- .../public/np_ready/plugin.ts | 4 +- .../server/np_ready/plugin.ts | 4 +- .../index_lifecycle_management/index.ts | 62 -------- .../index_lifecycle_management/plugin.ts | 54 ------- .../public/legacy.ts | 109 ------------- .../_index_lifecycle_management.scss | 17 -- .../public/np_ready/application/index.scss | 3 - .../public/np_ready/application/index.tsx | 63 -------- .../np_ready/application/services/api.js | 81 ---------- .../public/np_ready/plugin.tsx | 58 ------- .../call_with_request_factory.ts | 19 --- .../lib/call_with_request_factory/index.ts | 7 - .../check_license/__tests__/check_license.js | 145 ------------------ .../server/lib/check_license/check_license.ts | 66 -------- .../__tests__/wrap_custom_error.js | 21 --- .../error_wrappers/__tests__/wrap_es_error.js | 38 ----- .../__tests__/wrap_unknown_error.js | 19 --- .../server/lib/error_wrappers/index.ts | 9 -- .../lib/error_wrappers/wrap_custom_error.ts | 18 --- .../lib/error_wrappers/wrap_es_error.ts | 29 ---- .../lib/error_wrappers/wrap_unknown_error.ts | 17 -- .../server/lib/is_es_error/index.ts | 7 - .../__tests__/license_pre_routing_factory.js | 69 --------- .../license_pre_routing_factory.ts | 29 ---- .../lib/register_license_checker/index.ts | 7 - .../register_license_checker.ts | 23 --- .../server/routes/api/index/index.ts | 7 - .../api/index/register_add_policy_route.ts | 58 ------- .../routes/api/index/register_remove_route.ts | 51 ------ .../routes/api/index/register_retry_route.ts | 51 ------ .../server/routes/api/nodes/constants.ts | 15 -- .../server/routes/api/nodes/index.ts | 7 - .../api/nodes/register_details_route.ts | 61 -------- .../routes/api/nodes/register_list_route.ts | 63 -------- .../server/routes/api/policies/index.ts | 7 - .../api/policies/register_create_route.ts | 52 ------- .../api/policies/register_delete_route.ts | 46 ------ .../api/policies/register_fetch_route.ts | 84 ---------- .../server/routes/api/templates/index.ts | 7 - .../templates/register_add_policy_route.ts | 67 -------- .../api/templates/register_get_route.ts | 48 ------ .../index_lifecycle_management/shim.ts | 17 -- .../legacy/plugins/index_management/index.ts | 1 + x-pack/legacy/plugins/rollup/public/plugin.ts | 4 +- x-pack/legacy/plugins/rollup/server/plugin.ts | 4 +- .../extend_index_management.test.js.snap | 0 .../__snapshots__/policy_table.test.js.snap | 0 .../__jest__/components/edit_policy.test.js | 20 ++- .../__jest__/components/policy_table.test.js | 16 +- .../__jest__/extend_index_management.test.js | 17 +- .../common/constants/index.ts | 6 + .../index_lifecycle_management/kibana.json | 16 ++ .../public}/application/app.tsx | 2 +- .../public}/application/constants/index.ts | 0 .../application/constants/ui_metric.ts | 0 .../public/application/index.tsx | 27 ++++ .../sections/components/active_badge.js | 0 .../application/sections/components/index.js | 0 .../sections/components/learn_more_link.js | 0 .../sections/components/optional_label.js | 0 .../components/phase_error_message.js | 0 .../cold_phase/cold_phase.container.js | 0 .../components/cold_phase/cold_phase.js | 0 .../components/cold_phase/index.js | 0 .../delete_phase/delete_phase.container.js | 0 .../components/delete_phase/delete_phase.js | 0 .../components/delete_phase/index.js | 0 .../hot_phase/hot_phase.container.js | 0 .../components/hot_phase/hot_phase.js | 0 .../edit_policy/components/hot_phase/index.js | 0 .../edit_policy/components/min_age_input.js | 0 .../components/node_allocation/index.js | 0 .../node_allocation.container.js | 0 .../node_allocation/node_allocation.js | 0 .../components/node_attrs_details/index.js | 0 .../node_attrs_details.container.js | 0 .../node_attrs_details/node_attrs_details.js | 0 .../components/policy_json_flyout.js | 0 .../components/set_priority_input.js | 0 .../components/warm_phase/index.js | 0 .../warm_phase/warm_phase.container.js | 0 .../components/warm_phase/warm_phase.js | 0 .../edit_policy/edit_policy.container.js | 0 .../sections/edit_policy/edit_policy.js | 0 .../sections/edit_policy/form_errors.js | 0 .../sections/edit_policy/index.d.ts | 0 .../application/sections/edit_policy/index.js | 0 .../no_match/components/no_match/index.js | 0 .../no_match/components/no_match/no_match.js | 0 .../policy_table/components/no_match/index.js | 0 .../add_policy_to_template_confirm_modal.js | 0 .../components/policy_table/confirm_delete.js | 0 .../components/policy_table/index.js | 0 .../policy_table/policy_table.container.js | 0 .../components/policy_table/policy_table.js | 8 +- .../sections/policy_table/index.d.ts | 0 .../sections/policy_table/index.js | 0 .../public/application/services/api.js | 72 +++++++++ .../application/services/api_errors.js | 0 .../application/services/documentation.ts | 0 .../application/services/filter_items.js | 0 .../application/services/find_errors.js | 0 .../services/flatten_panel_tree.js | 0 .../public}/application/services/http.ts | 14 +- .../public}/application/services/index.js | 0 .../application/services/navigation.ts | 12 +- .../application/services/notification.ts | 0 .../application/services/sort_table.js | 0 .../application/services/ui_metric.test.js | 0 .../public}/application/services/ui_metric.ts | 11 +- .../application/store/actions/general.js | 0 .../application/store/actions/index.js | 0 .../application/store/actions/lifecycle.js | 0 .../application/store/actions/nodes.js | 0 .../application/store/actions/policies.js | 0 .../application/store/defaults/cold_phase.js | 0 .../store/defaults/delete_phase.js | 0 .../application/store/defaults/hot_phase.js | 0 .../application/store/defaults/index.d.ts | 0 .../application/store/defaults/index.js | 0 .../application/store/defaults/warm_phase.js | 0 .../public}/application/store/index.d.ts | 0 .../public}/application/store/index.js | 0 .../application/store/reducers/general.js | 0 .../application/store/reducers/index.js | 0 .../application/store/reducers/nodes.js | 0 .../application/store/reducers/policies.js | 0 .../application/store/selectors/general.js | 0 .../application/store/selectors/index.js | 0 .../application/store/selectors/lifecycle.js | 0 .../application/store/selectors/nodes.js | 0 .../application/store/selectors/policies.js | 0 .../public}/application/store/store.js | 0 .../components/add_lifecycle_confirm_modal.js | 6 +- .../components/index_lifecycle_summary.js | 0 .../remove_lifecycle_confirm_modal.js | 4 +- .../extend_index_management/index.d.ts | 0 .../public}/extend_index_management/index.js | 50 +----- .../public}/index.ts | 8 +- .../public/plugin.tsx | 69 +++++++++ .../public/types.ts | 21 +++ .../server/config.ts | 18 +++ .../server/index.ts | 19 +++ .../server/lib}/is_es_error.ts | 0 .../server/plugin.ts | 86 +++++++++++ .../server/routes/api/index/index.ts} | 9 +- .../api/index/register_add_policy_route.ts | 66 ++++++++ .../routes/api/index/register_remove_route.ts | 54 +++++++ .../routes/api/index/register_retry_route.ts | 54 +++++++ .../server/routes/api/nodes/index.ts} | 7 +- .../api/nodes/register_details_route.ts | 64 ++++++++ .../routes/api/nodes/register_list_route.ts | 69 +++++++++ .../server/routes/api/policies/index.ts} | 9 +- .../api/policies/register_create_route.ts | 145 ++++++++++++++++++ .../api/policies/register_delete_route.ts | 50 ++++++ .../api/policies/register_fetch_route.ts | 90 +++++++++++ .../server/routes/api/templates/index.ts} | 9 +- .../templates/register_add_policy_route.ts | 81 ++++++++++ .../api/templates/register_fetch_route.ts | 51 +++--- .../server/routes/index.ts | 19 +++ .../server/services/add_base_path.ts} | 4 +- .../server/services}/index.ts | 3 +- .../server/services/license.ts | 82 ++++++++++ .../server/types.ts | 27 ++++ .../index_actions_context_menu.js | 15 +- .../plugins/index_management/public/index.ts | 4 +- .../plugins/index_management/public/plugin.ts | 4 +- .../plugins/index_management/server/index.ts | 2 +- .../plugins/index_management/server/plugin.ts | 6 +- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - .../templates.helpers.js | 3 - .../index_lifecycle_management/templates.js | 19 +-- 177 files changed, 1264 insertions(+), 1828 deletions(-) delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/plugin.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/public/legacy.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/_index_lifecycle_management.scss delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.scss delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.tsx delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/api.js delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/plugin.tsx delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/check_license.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/is_es_error/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/constants.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/index.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.ts delete mode 100644 x-pack/legacy/plugins/index_lifecycle_management/shim.ts rename x-pack/{legacy => }/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap (100%) rename x-pack/{legacy => }/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap (100%) rename x-pack/{legacy => }/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js (96%) rename x-pack/{legacy => }/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js (91%) rename x-pack/{legacy => }/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js (93%) rename x-pack/{legacy => }/plugins/index_lifecycle_management/common/constants/index.ts (72%) create mode 100644 x-pack/plugins/index_lifecycle_management/kibana.json rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/app.tsx (94%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/constants/index.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/constants/ui_metric.ts (100%) create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/index.tsx rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/components/active_badge.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/components/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/components/learn_more_link.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/components/optional_label.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/components/phase_error_message.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/cold_phase/cold_phase.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/cold_phase/cold_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/cold_phase/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/delete_phase/delete_phase.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/delete_phase/delete_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/delete_phase/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/hot_phase/hot_phase.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/hot_phase/hot_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/hot_phase/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/min_age_input.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/node_allocation/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/node_allocation/node_allocation.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/node_allocation/node_allocation.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/node_attrs_details/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/policy_json_flyout.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/set_priority_input.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/warm_phase/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/warm_phase/warm_phase.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/components/warm_phase/warm_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/edit_policy.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/edit_policy.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/form_errors.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/index.d.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/edit_policy/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/no_match/components/no_match/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/no_match/components/no_match/no_match.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/no_match/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/policy_table/add_policy_to_template_confirm_modal.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/policy_table/confirm_delete.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/policy_table/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/policy_table/policy_table.container.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/components/policy_table/policy_table.js (98%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/index.d.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/sections/policy_table/index.js (100%) create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/api.js rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/api_errors.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/documentation.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/filter_items.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/find_errors.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/flatten_panel_tree.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/http.ts (50%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/navigation.ts (59%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/notification.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/sort_table.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/ui_metric.test.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/services/ui_metric.ts (85%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/actions/general.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/actions/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/actions/lifecycle.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/actions/nodes.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/actions/policies.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/defaults/cold_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/defaults/delete_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/defaults/hot_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/defaults/index.d.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/defaults/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/defaults/warm_phase.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/index.d.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/reducers/general.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/reducers/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/reducers/nodes.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/reducers/policies.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/selectors/general.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/selectors/index.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/selectors/lifecycle.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/selectors/nodes.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/selectors/policies.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/application/store/store.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/extend_index_management/components/add_lifecycle_confirm_modal.js (97%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/extend_index_management/components/index_lifecycle_summary.js (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/extend_index_management/components/remove_lifecycle_confirm_modal.js (96%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/extend_index_management/index.d.ts (100%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/extend_index_management/index.js (80%) rename x-pack/{legacy/plugins/index_lifecycle_management/public/np_ready => plugins/index_lifecycle_management/public}/index.ts (58%) create mode 100644 x-pack/plugins/index_lifecycle_management/public/plugin.tsx create mode 100644 x-pack/plugins/index_lifecycle_management/public/types.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/config.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/index.ts rename x-pack/{legacy/plugins/index_lifecycle_management/server/lib/is_es_error => plugins/index_lifecycle_management/server/lib}/is_es_error.ts (100%) create mode 100644 x-pack/plugins/index_lifecycle_management/server/plugin.ts rename x-pack/{legacy/plugins/index_lifecycle_management/server/routes/api/index/register_index_routes.ts => plugins/index_lifecycle_management/server/routes/api/index/index.ts} (65%) create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts rename x-pack/{legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.ts => plugins/index_lifecycle_management/server/routes/api/nodes/index.ts} (65%) create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts rename x-pack/{legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.ts => plugins/index_lifecycle_management/server/routes/api/policies/index.ts} (64%) create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts rename x-pack/{legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.ts => plugins/index_lifecycle_management/server/routes/api/templates/index.ts} (64%) create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts rename x-pack/{legacy => }/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts (63%) create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/index.ts rename x-pack/{legacy/plugins/index_lifecycle_management/server/lib/check_license/index.ts => plugins/index_lifecycle_management/server/services/add_base_path.ts} (64%) rename x-pack/{legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory => plugins/index_lifecycle_management/server/services}/index.ts (74%) create mode 100644 x-pack/plugins/index_lifecycle_management/server/services/license.ts create mode 100644 x-pack/plugins/index_lifecycle_management/server/types.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e707250ff3261..267f3dde0b66f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -180,7 +180,7 @@ /src/plugins/console/ @elastic/es-ui /src/plugins/es_ui_shared/ @elastic/es-ui /x-pack/legacy/plugins/cross_cluster_replication/ @elastic/es-ui -/x-pack/legacy/plugins/index_lifecycle_management/ @elastic/es-ui +/x-pack/plugins/index_lifecycle_management/ @elastic/es-ui /x-pack/legacy/plugins/index_management/ @elastic/es-ui /x-pack/legacy/plugins/license_management/ @elastic/es-ui /x-pack/legacy/plugins/rollup/ @elastic/es-ui diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index ae8d61769b14c..bbbcc062786b0 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -18,7 +18,7 @@ "xpack.graph": ["legacy/plugins/graph", "plugins/graph"], "xpack.grokDebugger": "plugins/grokdebugger", "xpack.idxMgmt": "plugins/index_management", - "xpack.indexLifecycleMgmt": "legacy/plugins/index_lifecycle_management", + "xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management", "xpack.infra": "plugins/infra", "xpack.ingestManager": "plugins/ingest_manager", "xpack.lens": "legacy/plugins/lens", diff --git a/x-pack/index.js b/x-pack/index.js index 6fab13d726fa6..3126dc17a7107 100644 --- a/x-pack/index.js +++ b/x-pack/index.js @@ -16,7 +16,6 @@ import { beats } from './legacy/plugins/beats_management'; import { apm } from './legacy/plugins/apm'; import { maps } from './legacy/plugins/maps'; import { indexManagement } from './legacy/plugins/index_management'; -import { indexLifecycleManagement } from './legacy/plugins/index_lifecycle_management'; import { spaces } from './legacy/plugins/spaces'; import { canvas } from './legacy/plugins/canvas'; import { infra } from './legacy/plugins/infra'; @@ -50,7 +49,6 @@ module.exports = function(kibana) { maps(kibana), canvas(kibana), indexManagement(kibana), - indexLifecycleManagement(kibana), infra(kibana), taskManager(kibana), rollup(kibana), diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/extend_index_management.ts b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/extend_index_management.ts index 01c6250383fb8..4ffe0db4e3c4e 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/extend_index_management.ts +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/extend_index_management.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; -import { IndexMgmtSetup } from '../../../../../plugins/index_management/public'; +import { IndexManagementPluginSetup } from '../../../../../plugins/index_management/public'; const propertyPath = 'isFollowerIndex'; @@ -21,7 +21,7 @@ const followerBadgeExtension = { filterExpression: 'isFollowerIndex:true', }; -export const extendIndexManagement = (indexManagement?: IndexMgmtSetup) => { +export const extendIndexManagement = (indexManagement?: IndexManagementPluginSetup) => { if (indexManagement) { indexManagement.extensionsService.addBadge(followerBadgeExtension); } diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/plugin.ts b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/plugin.ts index f7651cbb210a7..46259c698b282 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/plugin.ts +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/plugin.ts @@ -11,7 +11,7 @@ import { DocLinksStart, } from 'src/core/public'; -import { IndexMgmtSetup } from '../../../../../plugins/index_management/public'; +import { IndexManagementPluginSetup } from '../../../../../plugins/index_management/public'; // @ts-ignore; import { setHttpClient } from './app/services/api'; @@ -21,7 +21,7 @@ import { setNotifications } from './app/services/notifications'; import { extendIndexManagement } from './extend_index_management'; interface PluginDependencies { - indexManagement: IndexMgmtSetup; + indexManagement: IndexManagementPluginSetup; __LEGACY: { chrome: any; MANAGEMENT_BREADCRUMB: ChromeBreadcrumb; diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/plugin.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/plugin.ts index 1012c07af3d2a..829de10ad0177 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/plugin.ts +++ b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/plugin.ts @@ -6,7 +6,7 @@ import { Plugin, PluginInitializerContext, CoreSetup } from 'src/core/server'; -import { IndexMgmtSetup } from '../../../../../plugins/index_management/server'; +import { IndexManagementPluginSetup } from '../../../../../plugins/index_management/server'; // @ts-ignore import { registerLicenseChecker } from './lib/register_license_checker'; @@ -15,7 +15,7 @@ import { registerRoutes } from './routes/register_routes'; import { ccrDataEnricher } from './cross_cluster_replication_data'; interface PluginDependencies { - indexManagement: IndexMgmtSetup; + indexManagement: IndexManagementPluginSetup; __LEGACY: { server: any; ccrUIEnabled: boolean; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/index.ts deleted file mode 100644 index 9b14b7143bf44..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Legacy } from 'kibana'; -import { resolve } from 'path'; -import { PLUGIN } from './common/constants'; -import { Plugin as IndexLifecycleManagementPlugin } from './plugin'; -import { createShim } from './shim'; - -export function indexLifecycleManagement(kibana: any) { - return new kibana.Plugin({ - id: PLUGIN.ID, - configPrefix: 'xpack.ilm', - publicDir: resolve(__dirname, 'public'), - require: ['kibana', 'elasticsearch', 'xpack_main', 'index_management'], - uiExports: { - styleSheetPaths: resolve(__dirname, 'public/np_ready/application/index.scss'), - managementSections: ['plugins/index_lifecycle_management/legacy'], - injectDefaultVars(server: Legacy.Server) { - const config = server.config(); - return { - ilmUiEnabled: config.get('xpack.ilm.ui.enabled'), - }; - }, - }, - config: (Joi: any) => { - return Joi.object({ - // display menu item - ui: Joi.object({ - enabled: Joi.boolean().default(true), - }).default(), - - // enable plugin - enabled: Joi.boolean().default(true), - - filteredNodeAttributes: Joi.array() - .items(Joi.string()) - .default([]), - }).default(); - }, - isEnabled(config: any) { - return ( - config.get('xpack.ilm.enabled') && - config.has('xpack.index_management.enabled') && - config.get('xpack.index_management.enabled') - ); - }, - init(server: Legacy.Server) { - const core = server.newPlatform.setup.core; - const plugins = {}; - const __LEGACY = createShim(server); - - const indexLifecycleManagementPlugin = new IndexLifecycleManagementPlugin(); - - // Set up plugin. - indexLifecycleManagementPlugin.setup(core, plugins, __LEGACY); - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/plugin.ts b/x-pack/legacy/plugins/index_lifecycle_management/plugin.ts deleted file mode 100644 index 38d1bea45ce07..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/plugin.ts +++ /dev/null @@ -1,54 +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 { CoreSetup } from 'kibana/server'; -import { LegacySetup } from './shim'; -import { registerLicenseChecker } from './server/lib/register_license_checker'; -import { registerIndexRoutes } from './server/routes/api/index'; -import { registerNodesRoutes } from './server/routes/api/nodes'; -import { registerPoliciesRoutes } from './server/routes/api/policies'; -import { registerTemplatesRoutes } from './server/routes/api/templates'; - -const indexLifecycleDataEnricher = async (indicesList: any, callWithRequest: any) => { - if (!indicesList || !indicesList.length) { - return; - } - const params = { - path: '/*/_ilm/explain', - method: 'GET', - }; - const { indices: ilmIndicesData } = await callWithRequest('transport.request', params); - return indicesList.map((index: any): any => { - return { - ...index, - ilm: { ...(ilmIndicesData[index.name] || {}) }, - }; - }); -}; - -export class Plugin { - public setup(core: CoreSetup, plugins: any, __LEGACY: LegacySetup): void { - const { server } = __LEGACY; - - registerLicenseChecker(server); - - // Register routes. - registerIndexRoutes(server); - registerNodesRoutes(server); - registerPoliciesRoutes(server); - registerTemplatesRoutes(server); - - const serverPlugins = server.newPlatform.setup.plugins as any; - - if ( - server.config().get('xpack.ilm.ui.enabled') && - serverPlugins.indexManagement && - serverPlugins.indexManagement.indexDataEnricher - ) { - serverPlugins.indexManagement.indexDataEnricher.add(indexLifecycleDataEnricher); - } - } -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/legacy.ts b/x-pack/legacy/plugins/index_lifecycle_management/public/legacy.ts deleted file mode 100644 index 006e5f6098f2b..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/legacy.ts +++ /dev/null @@ -1,109 +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 { App } from 'src/core/public'; - -/* Legacy Imports */ -import { npSetup, npStart } from 'ui/new_platform'; -import chrome from 'ui/chrome'; -import routes from 'ui/routes'; -import { management } from 'ui/management'; -import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public'; - -import { PLUGIN, BASE_PATH } from '../common/constants'; -import { createPlugin } from './np_ready'; -import { addAllExtensions } from './np_ready/extend_index_management'; - -if (chrome.getInjected('ilmUiEnabled')) { - // We have to initialize this outside of the NP lifecycle, otherwise these extensions won't - // be available in Index Management unless the user visits ILM first. - if ((npSetup.plugins as any).indexManagement) { - addAllExtensions((npSetup.plugins as any).indexManagement.extensionsService); - } - - // This method handles the cleanup needed when route is scope is destroyed. It also prevents Angular - // from destroying scope when route changes and both old route and new route are this same route. - const manageAngularLifecycle = ($scope: any, $route: any, unmount: () => void) => { - const lastRoute = $route.current; - const deregister = $scope.$on('$locationChangeSuccess', () => { - const currentRoute = $route.current; - // if templates are the same we are on the same route - if (lastRoute.$$route.template === currentRoute.$$route.template) { - // this prevents angular from destroying scope - $route.current = lastRoute; - } - }); - $scope.$on('$destroy', () => { - if (deregister) { - deregister(); - } - unmount(); - }); - }; - - // Once this app no longer depends upon Angular's routing (e.g. for the "redirect" service), we can - // use the Management plugin's API to register this app within the Elasticsearch section. - const esSection = management.getSection('elasticsearch'); - esSection.register('index_lifecycle_policies', { - visible: true, - display: PLUGIN.TITLE, - order: 2, - url: `#${BASE_PATH}policies`, - }); - - const REACT_ROOT_ID = 'indexLifecycleManagementReactRoot'; - - const template = ` -
- - `; - - routes.when(`${BASE_PATH}:view?/:action?/:id?`, { - template, - controllerAs: 'indexLifecycleManagement', - controller: class IndexLifecycleManagementController { - constructor($scope: any, $route: any, kbnUrl: any, $rootScope: any) { - $scope.$$postDigest(() => { - const element = document.getElementById(REACT_ROOT_ID)!; - const { core } = npSetup; - - const coreDependencies = { - ...core, - application: { - ...core.application, - async register(app: App) { - const unmountApp = await app.mount({ ...npStart } as any, { - element, - appBasePath: '', - onAppLeave: () => undefined, - // TODO: adapt to use Core's ScopedHistory - history: {} as any, - }); - manageAngularLifecycle($scope, $route, unmountApp as any); - }, - }, - }; - - // The Plugin interface won't allow us to pass __LEGACY as a third argument, so we'll just - // sneak it inside of the plugins argument for now. - const pluginDependencies = { - __LEGACY: { - redirect: (path: string) => { - $scope.$evalAsync(() => { - kbnUrl.redirect(path); - }); - }, - createUiStatsReporter, - }, - }; - - const plugin = createPlugin({} as any); - plugin.setup(coreDependencies, pluginDependencies); - }); - } - } as any, - } as any); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/_index_lifecycle_management.scss b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/_index_lifecycle_management.scss deleted file mode 100644 index 96c6d1a938c61..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/_index_lifecycle_management.scss +++ /dev/null @@ -1,17 +0,0 @@ -.policyTable__horizontalScrollContainer { - overflow-x: auto; - max-width: 100%; -} - -.policyTable__horizontalScroll { - min-width: 800px; - width: 100%; -} - -.policyTable__link { - font-weight: 400; -} - -.ilmEditPolicyPageContent { - max-width: 1200px !important; -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.scss b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.scss deleted file mode 100644 index 53e90e2aae35b..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; -@import 'index_lifecycle_management'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.tsx b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.tsx deleted file mode 100644 index b87a633d65c9c..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/index.tsx +++ /dev/null @@ -1,63 +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 { render, unmountComponentAtNode } from 'react-dom'; -import { Provider } from 'react-redux'; -import { DocLinksStart, ToastsSetup, HttpSetup, FatalErrorsSetup } from 'src/core/public'; - -import { App } from './app'; -import { indexLifecycleManagementStore } from './store'; -import { init as initHttp } from './services/http'; -import { init as initNavigation } from './services/navigation'; -import { init as initDocumentation } from './services/documentation'; -import { init as initUiMetric } from './services/ui_metric'; -import { init as initNotification } from './services/notification'; - -export interface LegacySetup { - redirect: any; - createUiStatsReporter: any; -} - -interface AppDependencies { - legacy: LegacySetup; - I18nContext: any; - http: HttpSetup; - toasts: ToastsSetup; - fatalErrors: FatalErrorsSetup; - docLinks: DocLinksStart; - element: HTMLElement; -} - -export const renderApp = (appDependencies: AppDependencies) => { - const { - legacy: { redirect, createUiStatsReporter }, - I18nContext, - http, - toasts, - fatalErrors, - docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, - element, - } = appDependencies; - - // Initialize services - initHttp(http); - initNavigation(redirect); - initDocumentation(`${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`); - initUiMetric(createUiStatsReporter); - initNotification(toasts, fatalErrors); - - render( - - - - - , - element - ); - - return () => unmountComponentAtNode(element); -}; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/api.js b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/api.js deleted file mode 100644 index f13bbcb6162b8..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/api.js +++ /dev/null @@ -1,81 +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 { - UIM_POLICY_DELETE, - UIM_POLICY_ATTACH_INDEX, - UIM_POLICY_ATTACH_INDEX_TEMPLATE, - UIM_POLICY_DETACH_INDEX, - UIM_INDEX_RETRY_STEP, -} from '../constants'; - -import { trackUiMetric } from './ui_metric'; -import { sendGet, sendPost, sendDelete } from './http'; - -// The extend_index_management module that we support an injected httpClient here. - -export async function loadNodes(httpClient) { - return await sendGet(`nodes/list`, httpClient); -} - -export async function loadNodeDetails(selectedNodeAttrs, httpClient) { - return await sendGet(`nodes/${selectedNodeAttrs}/details`, httpClient); -} - -export async function loadIndexTemplates(httpClient) { - return await sendGet(`templates`, httpClient); -} - -export async function loadIndexTemplate(templateName, httpClient) { - if (!templateName) { - return {}; - } - return await sendGet(`templates/${templateName}`, httpClient); -} - -export async function loadPolicies(withIndices, httpClient) { - const query = withIndices ? '?withIndices=true' : ''; - return await sendGet('policies', query, httpClient); -} - -export async function savePolicy(policy, httpClient) { - return await sendPost(`policies`, policy, httpClient); -} - -export async function deletePolicy(policyName, httpClient) { - const response = await sendDelete(`policies/${encodeURIComponent(policyName)}`, httpClient); - // Only track successful actions. - trackUiMetric('count', UIM_POLICY_DELETE); - return response; -} - -export const retryLifecycleForIndex = async (indexNames, httpClient) => { - const response = await sendPost(`index/retry`, { indexNames }, httpClient); - // Only track successful actions. - trackUiMetric('count', UIM_INDEX_RETRY_STEP); - return response; -}; - -export const removeLifecycleForIndex = async (indexNames, httpClient) => { - const response = await sendPost(`index/remove`, { indexNames }, httpClient); - // Only track successful actions. - trackUiMetric('count', UIM_POLICY_DETACH_INDEX); - return response; -}; - -export const addLifecyclePolicyToIndex = async (body, httpClient) => { - const response = await sendPost(`index/add`, body, httpClient); - // Only track successful actions. - trackUiMetric('count', UIM_POLICY_ATTACH_INDEX); - return response; -}; - -export const addLifecyclePolicyToTemplate = async (body, httpClient) => { - const response = await sendPost(`template`, body, httpClient); - // Only track successful actions. - trackUiMetric('count', UIM_POLICY_ATTACH_INDEX_TEMPLATE); - return response; -}; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/plugin.tsx b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/plugin.tsx deleted file mode 100644 index e2897f09fa892..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/plugin.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; -import { PLUGIN } from '../../common/constants'; -import { LegacySetup } from './application'; - -interface PluginsSetup { - __LEGACY: LegacySetup; -} - -export class IndexLifecycleManagementPlugin implements Plugin { - setup(core: CoreSetup, plugins: PluginsSetup) { - // Extract individual core dependencies. - const { - application, - notifications: { toasts }, - fatalErrors, - http, - } = core; - - // The Plugin interface won't allow us to pass __LEGACY as a third argument, so we'll just - // sneak it inside of the plugins parameter for now. - const { __LEGACY } = plugins; - - application.register({ - id: PLUGIN.ID, - title: PLUGIN.TITLE, - async mount(config, mountPoint) { - const { - core: { - docLinks, - i18n: { Context: I18nContext }, - }, - } = config; - - const { element } = mountPoint; - const { renderApp } = await import('./application'); - - // Inject all dependencies into our app. - return renderApp({ - legacy: { ...__LEGACY }, - I18nContext, - http, - toasts, - fatalErrors, - docLinks, - element, - }); - }, - }); - } - start(core: CoreStart, plugins: any) {} - stop() {} -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.ts deleted file mode 100644 index 1b28dc4fde4f7..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { once } from 'lodash'; -import { Legacy } from 'kibana'; - -const callWithRequest = once((server: Legacy.Server): any => { - const cluster = server.plugins.elasticsearch.getCluster('data'); - return cluster.callWithRequest; -}); - -export const callWithRequestFactory = (server: Legacy.Server, request: any) => { - return (...args: any[]) => { - return callWithRequest(server)(request, ...args); - }; -}; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/index.ts deleted file mode 100644 index 787814d87dff9..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/call_with_request_factory/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 { callWithRequestFactory } from './call_with_request_factory'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js deleted file mode 100644 index 933fda01c055d..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js +++ /dev/null @@ -1,145 +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 { set } from 'lodash'; -import { checkLicense } from '../check_license'; - -describe('check_license', function() { - let mockLicenseInfo; - beforeEach(() => (mockLicenseInfo = {})); - - describe('license information is undefined', () => { - beforeEach(() => (mockLicenseInfo = undefined)); - - it('should set isAvailable to false', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false); - }); - - it('should set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined); - }); - }); - - describe('license information is not available', () => { - beforeEach(() => (mockLicenseInfo.isAvailable = () => false)); - - it('should set isAvailable to false', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false); - }); - - it('should set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined); - }); - }); - - describe('license information is available', () => { - beforeEach(() => { - mockLicenseInfo.isAvailable = () => true; - set(mockLicenseInfo, 'license.getType', () => 'basic'); - }); - - describe('& license is > basic', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => true)); - - describe('& license is active', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true)); - - it('should set isAvailable to true', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to true', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(true); - }); - - it('should not set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.be(undefined); - }); - }); - - describe('& license is expired', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false)); - - it('should set isAvailable to false', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to false', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false); - }); - - it('should set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined); - }); - }); - }); - - describe('& license is basic', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => true)); - - describe('& license is active', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true)); - - it('should set isAvailable to true', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set enableLinks to true', () => { - expect(checkLicense(mockLicenseInfo).enableLinks).to.be(true); - }); - - it('should not set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.be(undefined); - }); - }); - - describe('& license is expired', () => { - beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false)); - - it('should set isAvailable to false', () => { - expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false); - }); - - it('should set showLinks to true', () => { - expect(checkLicense(mockLicenseInfo).showLinks).to.be(true); - }); - - it('should set a message', () => { - expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined); - }); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/check_license.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/check_license.ts deleted file mode 100644 index b35ab14964d55..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/check_license.ts +++ /dev/null @@ -1,66 +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 { i18n } from '@kbn/i18n'; - -export function checkLicense(xpackLicenseInfo: any): any { - const pluginName = 'Index Lifecycle Policies'; - - // If, for some reason, we cannot get the license information - // from Elasticsearch, assume worst case and disable - if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) { - return { - isAvailable: false, - showLinks: true, - enableLinks: false, - message: i18n.translate('xpack.indexLifecycleMgmt.checkLicense.errorUnavailableMessage', { - defaultMessage: - 'You cannot use {pluginName} because license information is not available at this time.', - values: { pluginName }, - }), - }; - } - - const VALID_LICENSE_MODES = ['basic', 'standard', 'gold', 'platinum', 'enterprise', 'trial']; - - const isLicenseModeValid = xpackLicenseInfo.license.isOneOf(VALID_LICENSE_MODES); - const isLicenseActive = xpackLicenseInfo.license.isActive(); - const licenseType = xpackLicenseInfo.license.getType(); - - // License is not valid - if (!isLicenseModeValid) { - return { - isAvailable: false, - showLinks: false, - message: i18n.translate('xpack.indexLifecycleMgmt.checkLicense.errorUnsupportedMessage', { - defaultMessage: - 'Your {licenseType} license does not support {pluginName}. Please upgrade your license.', - values: { licenseType, pluginName }, - }), - }; - } - - // License is valid but not active - if (!isLicenseActive) { - return { - isAvailable: false, - showLinks: true, - enableLinks: false, - message: i18n.translate('xpack.indexLifecycleMgmt.checkLicense.errorExpiredMessage', { - defaultMessage: - 'You cannot use {pluginName} because your {licenseType} license has expired.', - values: { pluginName, licenseType }, - }), - }; - } - - // License is valid and active - return { - isAvailable: true, - showLinks: true, - enableLinks: true, - }; -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js deleted file mode 100644 index f9c102be7a1ff..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ /dev/null @@ -1,21 +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 { wrapCustomError } from '../wrap_custom_error'; - -describe('wrap_custom_error', () => { - describe('#wrapCustomError', () => { - it('should return a Boom object', () => { - const originalError = new Error('I am an error'); - const statusCode = 404; - const wrappedError = wrapCustomError(originalError, statusCode); - - expect(wrappedError.isBoom).to.be(true); - expect(wrappedError.output.statusCode).to.equal(statusCode); - }); - }); -}); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js deleted file mode 100644 index fe2b6cce652f1..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ /dev/null @@ -1,38 +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 { wrapEsError } from '../wrap_es_error'; - -describe('wrap_es_error', () => { - describe('#wrapEsError', () => { - let originalError; - beforeEach(() => { - originalError = new Error('I am an error'); - originalError.statusCode = 404; - }); - - it('should return a Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.isBoom).to.be(true); - }); - - it('should return the correct Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.output.statusCode).to.be(originalError.statusCode); - expect(wrappedError.output.payload.message).to.be(originalError.message); - }); - - it('should return the correct Boom object with custom message', () => { - const wrappedError = wrapEsError(originalError, { 404: 'No encontrado!' }); - - expect(wrappedError.output.statusCode).to.be(originalError.statusCode); - expect(wrappedError.output.payload.message).to.be('No encontrado!'); - }); - }); -}); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js deleted file mode 100644 index 85e0b2b3033ad..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { wrapUnknownError } from '../wrap_unknown_error'; - -describe('wrap_unknown_error', () => { - describe('#wrapUnknownError', () => { - it('should return a Boom object', () => { - const originalError = new Error('I am an error'); - const wrappedError = wrapUnknownError(originalError); - - expect(wrappedError.isBoom).to.be(true); - }); - }); -}); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/index.ts deleted file mode 100644 index f275f15637091..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/index.ts +++ /dev/null @@ -1,9 +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 { wrapCustomError } from './wrap_custom_error'; -export { wrapEsError } from './wrap_es_error'; -export { wrapUnknownError } from './wrap_unknown_error'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.ts deleted file mode 100644 index c5780e7c83fb5..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; - -/** - * Wraps a custom error into a Boom error response and returns it - * - * @param err Object error - * @param statusCode Error status code - * @return Object Boom error response - */ -export function wrapCustomError(err: any, statusCode: any): any { - return Boom.boomify(err, { statusCode }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.ts deleted file mode 100644 index 6980a5afa5eac..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.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 Boom from 'boom'; - -/** - * Wraps an error thrown by the ES JS client into a Boom error response and returns it - * - * @param err Object Error thrown by ES JS client - * @param statusCodeToMessageMap Object Optional map of HTTP status codes => error messages - * @return Object Boom error response - */ -export function wrapEsError(err: any, statusCodeToMessageMap: any = {}): any { - const statusCode = err.statusCode; - - // If no custom message if specified for the error's status code, just - // wrap the error as a Boom error response and return it - if (!statusCodeToMessageMap[statusCode]) { - return Boom.boomify(err, { statusCode }); - } - - // Otherwise, use the custom message to create a Boom error response and - // return it - const message = statusCodeToMessageMap[statusCode]; - return new Boom(message, { statusCode }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.ts deleted file mode 100644 index ede1baec286f3..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.ts +++ /dev/null @@ -1,17 +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 Boom from 'boom'; - -/** - * Wraps an unknown error into a Boom error response and returns it - * - * @param err Object Unknown error - * @return Object Boom error response - */ -export function wrapUnknownError(err: any): any { - return Boom.boomify(err); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/is_es_error/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/is_es_error/index.ts deleted file mode 100644 index a9a3c61472d8c..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/is_es_error/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 { isEsError } from './is_es_error'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js deleted file mode 100644 index 4d3b33f8b3af3..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ /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 expect from '@kbn/expect'; -import { licensePreRoutingFactory } from '../license_pre_routing_factory'; - -describe('license_pre_routing_factory', () => { - describe('#reportingFeaturePreRoutingFactory', () => { - let mockServer; - let mockLicenseCheckResults; - - beforeEach(() => { - mockServer = { - plugins: { - xpack_main: { - info: { - feature: () => ({ - getLicenseCheckResults: () => mockLicenseCheckResults, - }), - }, - }, - }, - }; - }); - - it('only instantiates one instance per server', () => { - const firstInstance = licensePreRoutingFactory(mockServer); - const secondInstance = licensePreRoutingFactory(mockServer); - - expect(firstInstance).to.be(secondInstance); - }); - - describe('isAvailable is false', () => { - beforeEach(() => { - mockLicenseCheckResults = { - isAvailable: false, - }; - }); - - it('replies with 403', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - expect(() => licensePreRouting(stubRequest)).to.throwException(response => { - expect(response).to.be.an(Error); - expect(response.isBoom).to.be(true); - expect(response.output.statusCode).to.be(403); - }); - }); - }); - - describe('isAvailable is true', () => { - beforeEach(() => { - mockLicenseCheckResults = { - isAvailable: true, - }; - }); - - it('replies with nothing', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - const response = licensePreRouting(stubRequest); - expect(response).to.be(null); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts deleted file mode 100644 index e348125967c14..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.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 { once } from 'lodash'; -import { Legacy } from 'kibana'; - -import { PLUGIN } from '../../../common/constants'; -import { wrapCustomError } from '../error_wrappers'; - -export const licensePreRoutingFactory = once((server: Legacy.Server) => { - const xpackMainPlugin = server.plugins.xpack_main; - - // License checking and enable/disable logic - function licensePreRouting() { - const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); - if (!licenseCheckResults.isAvailable) { - const error = new Error(licenseCheckResults.message); - const statusCode = 403; - throw wrapCustomError(error, statusCode); - } - - return null; - } - - return licensePreRouting; -}); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/index.ts deleted file mode 100644 index 7b0f97c38d129..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/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 { registerLicenseChecker } from './register_license_checker'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.ts deleted file mode 100644 index 8e3b89fa20e33..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.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 { Legacy } from 'kibana'; -// @ts-ignore -import { mirrorPluginStatus } from '../../../../../server/lib/mirror_plugin_status'; -import { PLUGIN } from '../../../common/constants'; -import { checkLicense } from '../check_license'; - -export function registerLicenseChecker(server: Legacy.Server) { - const xpackMainPlugin = server.plugins.xpack_main as any; - const ilmPlugin = (server.plugins as any).index_lifecycle_management; - - mirrorPluginStatus(xpackMainPlugin, ilmPlugin); - xpackMainPlugin.status.once('green', () => { - // Register a function that is called whenever the xpack info changes, - // to re-compute the license check results for this plugin - xpackMainPlugin.info.feature(PLUGIN.ID).registerLicenseCheckResultsGenerator(checkLicense); - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/index.ts deleted file mode 100644 index 82fb2e3b2a372..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/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 { registerIndexRoutes } from './register_index_routes'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts deleted file mode 100644 index c3e235220931c..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -async function addLifecyclePolicy( - callWithRequest: any, - indexName: string, - policyName: string, - alias: string -) { - const body = { - lifecycle: { - name: policyName, - rollover_alias: alias, - }, - }; - - const params = { - method: 'PUT', - path: `/${encodeURIComponent(indexName)}/_settings`, - body, - }; - - return callWithRequest('transport.request', params); -} - -export function registerAddPolicyRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/index/add', - method: 'POST', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - const { indexName, policyName, alias } = request.payload as any; - try { - const response = await addLifecyclePolicy(callWithRequest, indexName, policyName, alias); - return response; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts deleted file mode 100644 index ed3b5a97a3b42..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts +++ /dev/null @@ -1,51 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -async function removeLifecycle(callWithRequest: any, indexNames: string[]) { - const responses = []; - for (let i = 0; i < indexNames.length; i++) { - const indexName = indexNames[i]; - const params = { - method: 'POST', - path: `/${encodeURIComponent(indexName)}/_ilm/remove`, - ignore: [404], - }; - - responses.push(callWithRequest('transport.request', params)); - } - return Promise.all(responses); -} - -export function registerRemoveRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/index/remove', - method: 'POST', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - - try { - const response = await removeLifecycle(callWithRequest, request.payload.indexNames); - return response; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts deleted file mode 100644 index 89278edbecea2..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts +++ /dev/null @@ -1,51 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -async function retryLifecycle(callWithRequest: any, indexNames: string[]) { - const responses = []; - for (let i = 0; i < indexNames.length; i++) { - const indexName = indexNames[i]; - const params = { - method: 'POST', - path: `/${encodeURIComponent(indexName)}/_ilm/retry`, - ignore: [404], - }; - - responses.push(callWithRequest('transport.request', params)); - } - return Promise.all(responses); -} - -export function registerRetryRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/index/retry', - method: 'POST', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - - try { - const response = await retryLifecycle(callWithRequest, request.payload.indexNames); - return response; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/constants.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/constants.ts deleted file mode 100644 index 4392dacac8fa4..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/constants.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. - */ - -export const NODE_ATTRS_KEYS_TO_IGNORE: string[] = [ - 'ml.enabled', - 'ml.machine_memory', - 'ml.max_open_jobs', - // Used by ML to identify nodes that have transform enabled: - // https://github.com/elastic/elasticsearch/pull/52712/files#diff-225cc2c1291b4c60a8c3412a619094e1R147 - 'transform.node', - 'xpack.installed', -]; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/index.ts deleted file mode 100644 index ef0ac271ae60e..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/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 { registerNodesRoutes } from './register_nodes_routes'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts deleted file mode 100644 index c2c3f8bf07028..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts +++ /dev/null @@ -1,61 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function findMatchingNodes(stats: any, nodeAttrs: string): any { - return Object.entries(stats.nodes).reduce((accum: any[], [nodeId, nodeStats]: [any, any]) => { - const attributes = nodeStats.attributes || {}; - for (const [key, value] of Object.entries(attributes)) { - if (`${key}:${value}` === nodeAttrs) { - accum.push({ - nodeId, - stats: nodeStats, - }); - break; - } - } - return accum; - }, []); -} - -async function fetchNodeStats(callWithRequest: any): Promise { - const params = { - format: 'json', - }; - - return await callWithRequest('nodes.stats', params); -} - -export function registerDetailsRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/nodes/{nodeAttrs}/details', - method: 'GET', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - - try { - const stats = await fetchNodeStats(callWithRequest); - const response = findMatchingNodes(stats, request.params.nodeAttrs); - return response; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts deleted file mode 100644 index edbe4289ed83c..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts +++ /dev/null @@ -1,63 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; -import { NODE_ATTRS_KEYS_TO_IGNORE } from './constants'; - -function convertStatsIntoList(stats: any, attributesToBeFiltered: string[]): any { - return Object.entries(stats.nodes).reduce((accum: any, [nodeId, nodeStats]: [any, any]) => { - const attributes = nodeStats.attributes || {}; - for (const [key, value] of Object.entries(attributes)) { - if (!attributesToBeFiltered.includes(key)) { - const attributeString = `${key}:${value}`; - accum[attributeString] = accum[attributeString] || []; - accum[attributeString].push(nodeId); - } - } - return accum; - }, {}); -} - -async function fetchNodeStats(callWithRequest: any): Promise { - const params = { - format: 'json', - }; - - return await callWithRequest('nodes.stats', params); -} - -export function registerListRoute(server: any) { - const config = server.config(); - const filteredNodeAttributes = config.get('xpack.ilm.filteredNodeAttributes'); - const attributesToBeFiltered = [...NODE_ATTRS_KEYS_TO_IGNORE, ...filteredNodeAttributes]; - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/nodes/list', - method: 'GET', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - - try { - const stats = await fetchNodeStats(callWithRequest); - const response = convertStatsIntoList(stats, attributesToBeFiltered); - return response; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/index.ts deleted file mode 100644 index 7c6103a3389ab..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/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 { registerPoliciesRoutes } from './register_policies_routes'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts deleted file mode 100644 index f6bc96dd498a4..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -async function createPolicy(callWithRequest: any, policy: any): Promise { - const body = { - policy: { - phases: policy.phases, - }, - }; - const params = { - method: 'PUT', - path: `/_ilm/policy/${encodeURIComponent(policy.name)}`, - ignore: [404], - body, - }; - - return await callWithRequest('transport.request', params); -} - -export function registerCreateRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/policies', - method: 'POST', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - - try { - const response = await createPolicy(callWithRequest, request.payload); - return response; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts deleted file mode 100644 index c84f2efd92d8f..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -async function deletePolicies(policyNames: string, callWithRequest: any): Promise { - const params = { - method: 'DELETE', - path: `/_ilm/policy/${encodeURIComponent(policyNames)}`, - // we allow 404 since they may have no policies - ignore: [404], - }; - - return await callWithRequest('transport.request', params); -} - -export function registerDeleteRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/policies/{policyNames}', - method: 'DELETE', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - const { policyNames } = request.params; - try { - await deletePolicies(policyNames, callWithRequest); - return {}; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts deleted file mode 100644 index c65f849a47d87..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts +++ /dev/null @@ -1,84 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function formatPolicies(policiesMap: any): any { - if (policiesMap.status === 404) { - return []; - } - - return Object.keys(policiesMap).reduce((accum: any[], lifecycleName: string) => { - const policyEntry = policiesMap[lifecycleName]; - accum.push({ - ...policyEntry, - name: lifecycleName, - }); - return accum; - }, []); -} - -async function fetchPolicies(callWithRequest: any): Promise { - const params = { - method: 'GET', - path: '/_ilm/policy', - // we allow 404 since they may have no policies - ignore: [404], - }; - - return await callWithRequest('transport.request', params); -} -async function addLinkedIndices(policiesMap: any, callWithRequest: any) { - if (policiesMap.status === 404) { - return policiesMap; - } - const params = { - method: 'GET', - path: '/*/_ilm/explain', - // we allow 404 since they may have no policies - ignore: [404], - }; - - const policyExplanation: any = await callWithRequest('transport.request', params); - Object.entries(policyExplanation.indices).forEach(([indexName, { policy }]: [string, any]) => { - if (policy && policiesMap[policy]) { - policiesMap[policy].linkedIndices = policiesMap[policy].linkedIndices || []; - policiesMap[policy].linkedIndices.push(indexName); - } - }); -} - -export function registerFetchRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/policies', - method: 'GET', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - const { withIndices } = request.query; - try { - const policiesMap = await fetchPolicies(callWithRequest); - if (withIndices) { - await addLinkedIndices(policiesMap, callWithRequest); - } - return formatPolicies(policiesMap); - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/index.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/index.ts deleted file mode 100644 index dc9a0acaaf09b..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/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 { registerTemplatesRoutes } from './register_templates_routes'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts deleted file mode 100644 index 57e5a91f60f5b..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts +++ /dev/null @@ -1,67 +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 { merge } from 'lodash'; - -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -async function getIndexTemplate(callWithRequest: any, templateName: string): Promise { - const response = await callWithRequest('indices.getTemplate', { name: templateName }); - return response[templateName]; -} - -async function updateIndexTemplate(callWithRequest: any, indexTemplatePatch: any): Promise { - // Fetch existing template - const template = await getIndexTemplate(callWithRequest, indexTemplatePatch.templateName); - merge(template, { - settings: { - index: { - lifecycle: { - name: indexTemplatePatch.policyName, - rollover_alias: indexTemplatePatch.aliasName, - }, - }, - }, - }); - - const params = { - method: 'PUT', - path: `/_template/${encodeURIComponent(indexTemplatePatch.templateName)}`, - ignore: [404], - body: template, - }; - - return await callWithRequest('transport.request', params); -} - -export function registerAddPolicyRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/template', - method: 'POST', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - - try { - const response = await updateIndexTemplate(callWithRequest, request.payload); - return response; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.ts b/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.ts deleted file mode 100644 index 3edaea6e15818..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.ts +++ /dev/null @@ -1,48 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -async function fetchTemplate(callWithRequest: any, templateName: string): Promise { - const params = { - method: 'GET', - path: `/_template/${encodeURIComponent(templateName)}`, - // we allow 404 incase the user shutdown security in-between the check and now - ignore: [404], - }; - - return await callWithRequest('transport.request', params); -} - -export function registerGetRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/templates/{templateName}', - method: 'GET', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); - const templateName = request.params.templateName; - - try { - const template = await fetchTemplate(callWithRequest, templateName); - return template[templateName]; - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); - } - - return wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/shim.ts b/x-pack/legacy/plugins/index_lifecycle_management/shim.ts deleted file mode 100644 index 18b3d9ef28b6a..0000000000000 --- a/x-pack/legacy/plugins/index_lifecycle_management/shim.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Legacy } from 'kibana'; - -export interface LegacySetup { - server: Legacy.Server; -} - -export function createShim(server: Legacy.Server): LegacySetup { - return { - server, - }; -} diff --git a/x-pack/legacy/plugins/index_management/index.ts b/x-pack/legacy/plugins/index_management/index.ts index 9eba98a526d2b..afca15203b970 100644 --- a/x-pack/legacy/plugins/index_management/index.ts +++ b/x-pack/legacy/plugins/index_management/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +// TODO: Remove this once CCR is migrated to the plugins directory. export function indexManagement(kibana: any) { return new kibana.Plugin({ id: 'index_management', diff --git a/x-pack/legacy/plugins/rollup/public/plugin.ts b/x-pack/legacy/plugins/rollup/public/plugin.ts index 5782e88c3448b..17ec8a5a4aedf 100644 --- a/x-pack/legacy/plugins/rollup/public/plugin.ts +++ b/x-pack/legacy/plugins/rollup/public/plugin.ts @@ -24,7 +24,7 @@ import { // @ts-ignore import { CRUD_APP_BASE_PATH } from './crud_app/constants'; import { ManagementSetup } from '../../../../../src/plugins/management/public'; -import { IndexMgmtSetup } from '../../../../plugins/index_management/public'; +import { IndexManagementPluginSetup } from '../../../../plugins/index_management/public'; import { IndexPatternManagementSetup } from '../../../../../src/plugins/index_pattern_management/public'; import { search } from '../../../../../src/plugins/data/public'; // @ts-ignore @@ -35,7 +35,7 @@ import { renderApp } from './application'; export interface RollupPluginSetupDependencies { home?: HomePublicPluginSetup; management: ManagementSetup; - indexManagement?: IndexMgmtSetup; + indexManagement?: IndexManagementPluginSetup; indexPatternManagement: IndexPatternManagementSetup; } diff --git a/x-pack/legacy/plugins/rollup/server/plugin.ts b/x-pack/legacy/plugins/rollup/server/plugin.ts index 090cb8a47377a..5f29ad160e052 100644 --- a/x-pack/legacy/plugins/rollup/server/plugin.ts +++ b/x-pack/legacy/plugins/rollup/server/plugin.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { VisTypeTimeseriesSetup } from 'src/plugins/vis_type_timeseries/server'; -import { IndexMgmtSetup } from '../../../../plugins/index_management/server'; +import { IndexManagementPluginSetup } from '../../../../plugins/index_management/server'; import { registerLicenseChecker } from '../../../server/lib/register_license_checker'; import { PLUGIN } from '../common'; import { ServerShim, RouteDependencies } from './types'; @@ -44,7 +44,7 @@ export class RollupsServerPlugin implements Plugin { __LEGACY: ServerShim; usageCollection?: UsageCollectionSetup; metrics?: VisTypeTimeseriesSetup; - indexManagement?: IndexMgmtSetup; + indexManagement?: IndexManagementPluginSetup; } ) { const elasticsearch = await elasticsearchService.adminClient; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap rename to x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.js.snap diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap b/x-pack/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap rename to x-pack/plugins/index_lifecycle_management/__jest__/components/__snapshots__/policy_table.test.js.snap diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js similarity index 96% rename from x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js rename to x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js index 9d143c4d3fc8e..bf4de823f1833 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.js @@ -13,13 +13,13 @@ import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import sinon from 'sinon'; import { findTestSubject } from '@elastic/eui/lib/test'; -import { mountWithIntl } from '../../../../../test_utils/enzyme_helpers'; -import { fetchedPolicies, fetchedNodes } from '../../public/np_ready/application/store/actions'; -import { indexLifecycleManagementStore } from '../../public/np_ready/application/store'; -import { EditPolicy } from '../../public/np_ready/application/sections/edit_policy'; -import { init as initHttp } from '../../public/np_ready/application/services/http'; -import { init as initUiMetric } from '../../public/np_ready/application/services/ui_metric'; -import { init as initNotification } from '../../public/np_ready/application/services/notification'; +import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; +import { fetchedPolicies, fetchedNodes } from '../../public/application/store/actions'; +import { indexLifecycleManagementStore } from '../../public/application/store'; +import { EditPolicy } from '../../public/application/sections/edit_policy'; +import { init as initHttp } from '../../public/application/services/http'; +import { init as initUiMetric } from '../../public/application/services/ui_metric'; +import { init as initNotification } from '../../public/application/services/notification'; import { positiveNumbersAboveZeroErrorMessage, positiveNumberRequiredMessage, @@ -33,16 +33,14 @@ import { policyNameMustBeDifferentErrorMessage, policyNameAlreadyUsedErrorMessage, maximumDocumentsRequiredMessage, -} from '../../public/np_ready/application/store/selectors/lifecycle'; +} from '../../public/application/store/selectors/lifecycle'; initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path); -initUiMetric(() => () => {}); +initUiMetric({ reportUiStats: () => {} }); initNotification({ addDanger: () => {}, }); -jest.mock('ui/new_platform'); - let server; let store; const policy = { diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js b/x-pack/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js similarity index 91% rename from x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js rename to x-pack/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js index a3a9c5e59bfa4..78c5c181eea62 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js @@ -12,17 +12,15 @@ import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import sinon from 'sinon'; import { findTestSubject, takeMountedSnapshot } from '@elastic/eui/lib/test'; -import { mountWithIntl } from '../../../../../test_utils/enzyme_helpers'; -import { fetchedPolicies } from '../../public/np_ready/application/store/actions'; -import { indexLifecycleManagementStore } from '../../public/np_ready/application/store'; -import { PolicyTable } from '../../public/np_ready/application/sections/policy_table'; -import { init as initHttp } from '../../public/np_ready/application/services/http'; -import { init as initUiMetric } from '../../public/np_ready/application/services/ui_metric'; +import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; +import { fetchedPolicies } from '../../public/application/store/actions'; +import { indexLifecycleManagementStore } from '../../public/application/store'; +import { PolicyTable } from '../../public/application/sections/policy_table'; +import { init as initHttp } from '../../public/application/services/http'; +import { init as initUiMetric } from '../../public/application/services/ui_metric'; initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path); -initUiMetric(() => () => {}); - -jest.mock('ui/new_platform'); +initUiMetric({ reportUiStats: () => {} }); let server = null; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js similarity index 93% rename from x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js rename to x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js index d2619778617c3..900de27ca36ab 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js +++ b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js @@ -8,7 +8,7 @@ import moment from 'moment-timezone'; import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; +import { mountWithIntl } from '../../../test_utils/enzyme_helpers'; import { retryLifecycleActionExtension, removeLifecyclePolicyActionExtension, @@ -16,21 +16,18 @@ import { ilmBannerExtension, ilmFilterExtension, ilmSummaryExtension, -} from '../public/np_ready/extend_index_management'; -import { init as initHttp } from '../public/np_ready/application/services/http'; -import { init as initUiMetric } from '../public/np_ready/application/services/ui_metric'; +} from '../public/extend_index_management'; +import { init as initHttp } from '../public/application/services/http'; +import { init as initUiMetric } from '../public/application/services/ui_metric'; // We need to init the http with a mock for any tests that depend upon the http service. // For example, add_lifecycle_confirm_modal makes an API request in its componentDidMount // lifecycle method. If we don't mock this, CI will fail with "Call retries were exceeded". initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path); -initUiMetric(() => () => {}); +initUiMetric({ reportUiStats: () => {} }); -jest.mock('ui/new_platform'); -jest.mock('../../../../plugins/index_management/public', async () => { - const { indexManagementMock } = await import( - '../../../../plugins/index_management/public/mocks.ts' - ); +jest.mock('../../../plugins/index_management/public', async () => { + const { indexManagementMock } = await import('../../../plugins/index_management/public/mocks.ts'); return indexManagementMock.createSetup(); }); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/common/constants/index.ts b/x-pack/plugins/index_lifecycle_management/common/constants/index.ts similarity index 72% rename from x-pack/legacy/plugins/index_lifecycle_management/common/constants/index.ts rename to x-pack/plugins/index_lifecycle_management/common/constants/index.ts index 9193efb561a0f..700039985eaf5 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/common/constants/index.ts +++ b/x-pack/plugins/index_lifecycle_management/common/constants/index.ts @@ -5,12 +5,18 @@ */ import { i18n } from '@kbn/i18n'; +import { LicenseType } from '../../../licensing/common/types'; + +const basicLicense: LicenseType = 'basic'; export const PLUGIN = { ID: 'index_lifecycle_management', + minimumLicenseType: basicLicense, TITLE: i18n.translate('xpack.indexLifecycleMgmt.appTitle', { defaultMessage: 'Index Lifecycle Policies', }), }; export const BASE_PATH = '/management/elasticsearch/index_lifecycle_management/'; + +export const API_BASE_PATH = '/api/index_lifecycle_management'; diff --git a/x-pack/plugins/index_lifecycle_management/kibana.json b/x-pack/plugins/index_lifecycle_management/kibana.json new file mode 100644 index 0000000000000..6385646b95789 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/kibana.json @@ -0,0 +1,16 @@ +{ + "id": "indexLifecycleManagement", + "version": "kibana", + "server": true, + "ui": true, + "requiredPlugins": [ + "home", + "licensing", + "management" + ], + "optionalPlugins": [ + "usageCollection", + "indexManagement" + ], + "configPath": ["xpack", "ilm"] +} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/app.tsx b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx similarity index 94% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/app.tsx rename to x-pack/plugins/index_lifecycle_management/public/application/app.tsx index 6738d7caa4444..993dced20bbe6 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/app.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/app.tsx @@ -8,7 +8,7 @@ import React, { useEffect } from 'react'; import { HashRouter, Switch, Route, Redirect } from 'react-router-dom'; import { METRIC_TYPE } from '@kbn/analytics'; -import { BASE_PATH } from '../../../common/constants'; +import { BASE_PATH } from '../../common/constants'; import { UIM_APP_LOAD } from './constants'; import { EditPolicy } from './sections/edit_policy'; import { PolicyTable } from './sections/policy_table'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/constants/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/constants/index.ts rename to x-pack/plugins/index_lifecycle_management/public/application/constants/index.ts diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/constants/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/constants/ui_metric.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/constants/ui_metric.ts rename to x-pack/plugins/index_lifecycle_management/public/application/constants/ui_metric.ts diff --git a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx new file mode 100644 index 0000000000000..a7d88d31e58fc --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { Provider } from 'react-redux'; +import { I18nStart } from 'kibana/public'; +import { UnmountCallback } from 'src/core/public'; + +import { App } from './app'; +import { indexLifecycleManagementStore } from './store'; + +export const renderApp = (element: Element, I18nContext: I18nStart['Context']): UnmountCallback => { + render( + + + + + , + element + ); + + return () => unmountComponentAtNode(element); +}; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/active_badge.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/active_badge.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/active_badge.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/components/active_badge.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/components/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/learn_more_link.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/learn_more_link.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/components/learn_more_link.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/optional_label.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/optional_label.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/optional_label.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/components/optional_label.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/phase_error_message.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/components/phase_error_message.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/components/phase_error_message.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/components/phase_error_message.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/cold_phase/cold_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/cold_phase/cold_phase.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/cold_phase/cold_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/cold_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/cold_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/cold_phase/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/cold_phase/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/delete_phase/delete_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/delete_phase/delete_phase.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/delete_phase/delete_phase.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/delete_phase/delete_phase.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/delete_phase/delete_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/delete_phase/delete_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/delete_phase/delete_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/delete_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/delete_phase/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/delete_phase/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/delete_phase/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/hot_phase/hot_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/hot_phase/hot_phase.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/hot_phase/hot_phase.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/hot_phase/hot_phase.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/hot_phase/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/hot_phase/hot_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/hot_phase/hot_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/hot_phase/hot_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/hot_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/hot_phase/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/hot_phase/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/hot_phase/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/min_age_input.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/min_age_input.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/min_age_input.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_allocation/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_allocation/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_allocation/node_allocation.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_allocation/node_allocation.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_allocation/node_allocation.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_allocation/node_allocation.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_allocation/node_allocation.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_attrs_details/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_attrs_details/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/node_attrs_details/node_attrs_details.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/policy_json_flyout.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/policy_json_flyout.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/policy_json_flyout.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/set_priority_input.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/set_priority_input.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/warm_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/warm_phase/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/warm_phase/warm_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/warm_phase/warm_phase.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/components/warm_phase/warm_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/warm_phase/warm_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/edit_policy.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/edit_policy.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/edit_policy.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/form_errors.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_errors.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/form_errors.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_errors.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/index.d.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/index.d.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/index.d.ts diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/edit_policy/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/no_match/components/no_match/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/no_match/components/no_match/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/no_match/components/no_match/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/no_match/components/no_match/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/no_match/components/no_match/no_match.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/no_match/components/no_match/no_match.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/no_match/components/no_match/no_match.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/no_match/components/no_match/no_match.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/no_match/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/no_match/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/no_match/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/no_match/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/add_policy_to_template_confirm_modal.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/add_policy_to_template_confirm_modal.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/add_policy_to_template_confirm_modal.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/add_policy_to_template_confirm_modal.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/confirm_delete.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/confirm_delete.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/confirm_delete.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/confirm_delete.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/index.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.container.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.container.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.container.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.container.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.js similarity index 98% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js rename to x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.js index 903161fe094fc..d406d86bc6ce7 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/policy_table/policy_table.js @@ -37,8 +37,8 @@ import { import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; -import { getIndexListUri } from '../../../../../../../../../../plugins/index_management/public'; -import { BASE_PATH } from '../../../../../../../common/constants'; +import { getIndexListUri } from '../../../../../../../index_management/public'; +import { BASE_PATH } from '../../../../../../common/constants'; import { UIM_EDIT_CLICK } from '../../../../constants'; import { getPolicyPath } from '../../../../services/navigation'; import { flattenPanelTree } from '../../../../services/flatten_panel_tree'; @@ -52,6 +52,7 @@ const COLUMNS = { label: i18n.translate('xpack.indexLifecycleMgmt.policyTable.headers.nameHeader', { defaultMessage: 'Name', }), + width: 200, }, linkedIndices: { label: i18n.translate('xpack.indexLifecycleMgmt.policyTable.headers.linkedIndicesHeader', { @@ -179,7 +180,6 @@ export class PolicyTable extends Component { return ( /* eslint-disable-next-line @elastic/eui/href-or-on-click */ trackUiMetric('click', UIM_EDIT_CLICK)} @@ -415,7 +415,7 @@ export class PolicyTable extends Component { tableContent = ; } else if (totalNumberOfPolicies > 0) { tableContent = ( - + { + const response = await sendPost(`index/retry`, { indexNames }); + // Only track successful actions. + trackUiMetric('count', UIM_INDEX_RETRY_STEP); + return response; +}; + +export const removeLifecycleForIndex = async indexNames => { + const response = await sendPost(`index/remove`, { indexNames }); + // Only track successful actions. + trackUiMetric('count', UIM_POLICY_DETACH_INDEX); + return response; +}; + +export const addLifecyclePolicyToIndex = async body => { + const response = await sendPost(`index/add`, body); + // Only track successful actions. + trackUiMetric('count', UIM_POLICY_ATTACH_INDEX); + return response; +}; + +export const addLifecyclePolicyToTemplate = async body => { + const response = await sendPost(`template`, body); + // Only track successful actions. + trackUiMetric('count', UIM_POLICY_ATTACH_INDEX_TEMPLATE); + return response; +}; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/api_errors.js b/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/api_errors.js rename to x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/documentation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/documentation.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/documentation.ts rename to x-pack/plugins/index_lifecycle_management/public/application/services/documentation.ts diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/filter_items.js b/x-pack/plugins/index_lifecycle_management/public/application/services/filter_items.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/filter_items.js rename to x-pack/plugins/index_lifecycle_management/public/application/services/filter_items.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/find_errors.js b/x-pack/plugins/index_lifecycle_management/public/application/services/find_errors.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/find_errors.js rename to x-pack/plugins/index_lifecycle_management/public/application/services/find_errors.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/flatten_panel_tree.js b/x-pack/plugins/index_lifecycle_management/public/application/services/flatten_panel_tree.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/flatten_panel_tree.js rename to x-pack/plugins/index_lifecycle_management/public/application/services/flatten_panel_tree.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/http.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts similarity index 50% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/http.ts rename to x-pack/plugins/index_lifecycle_management/public/application/services/http.ts index bbda1ebd2e0e5..47e96ea28bb8c 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/http.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/http.ts @@ -20,16 +20,14 @@ function getFullPath(path: string): string { return apiPrefix; } -// The extend_index_management module requires that we support an injected httpClient here. - -export function sendPost(path: string, payload: any, httpClient = _httpClient): any { - return httpClient.post(getFullPath(path), { body: JSON.stringify(payload) }); +export function sendPost(path: string, payload: any): any { + return _httpClient.post(getFullPath(path), { body: JSON.stringify(payload) }); } -export function sendGet(path: string, query: any, httpClient = _httpClient): any { - return httpClient.get(getFullPath(path), { query }); +export function sendGet(path: string, query: any): any { + return _httpClient.get(getFullPath(path), { query }); } -export function sendDelete(path: string, httpClient = _httpClient): any { - return httpClient.delete(getFullPath(path)); +export function sendDelete(path: string): any { + return _httpClient.delete(getFullPath(path)); } diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/index.js b/x-pack/plugins/index_lifecycle_management/public/application/services/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/services/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/navigation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/navigation.ts similarity index 59% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/navigation.ts rename to x-pack/plugins/index_lifecycle_management/public/application/services/navigation.ts index 943f9a49d0ab6..2d518ebb3015e 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/navigation.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/navigation.ts @@ -4,18 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { BASE_PATH } from '../../../../common/constants'; - -// This depends upon Angular, which is why we use this provider pattern to access it within -// our React app. -let _redirect: any; - -export function init(redirect: any) { - _redirect = redirect; -} +import { BASE_PATH } from '../../../common/constants'; export const goToPolicyList = () => { - _redirect(`${BASE_PATH}policies`); + window.location.hash = `${BASE_PATH}policies`; }; export const getPolicyPath = (policyName: string): string => { diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/notification.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/notification.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/notification.ts rename to x-pack/plugins/index_lifecycle_management/public/application/services/notification.ts diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/sort_table.js b/x-pack/plugins/index_lifecycle_management/public/application/services/sort_table.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/sort_table.js rename to x-pack/plugins/index_lifecycle_management/public/application/services/sort_table.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/ui_metric.test.js b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/ui_metric.test.js rename to x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts similarity index 85% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/ui_metric.ts rename to x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts index d9f2c26048317..ca6c0b44d5804 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/services/ui_metric.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts @@ -6,7 +6,8 @@ import { get } from 'lodash'; -import { createUiStatsReporter } from '../../../../../../../../src/legacy/core_plugins/ui_metric/public'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; +import { UiStatsMetricType } from '@kbn/analytics'; import { UIM_APP_NAME, @@ -22,12 +23,10 @@ import { import { defaultColdPhase, defaultWarmPhase, defaultHotPhase } from '../store/defaults'; -export let trackUiMetric: ReturnType; +export let trackUiMetric: (metricType: UiStatsMetricType, eventName: string) => void; -export function init(getReporter: typeof createUiStatsReporter): void { - if (getReporter) { - trackUiMetric = getReporter(UIM_APP_NAME); - } +export function init(usageCollection: UsageCollectionSetup): void { + trackUiMetric = usageCollection.reportUiStats.bind(usageCollection, UIM_APP_NAME); } export function getUiMetricsForPhases(phases: any): any { diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/general.js b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/general.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/general.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/actions/general.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/index.js b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/actions/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/lifecycle.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/lifecycle.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/actions/lifecycle.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/nodes.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/actions/nodes.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/policies.js b/x-pack/plugins/index_lifecycle_management/public/application/store/actions/policies.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/actions/policies.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/actions/policies.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/store/defaults/cold_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/cold_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/defaults/cold_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/store/defaults/delete_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/delete_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/defaults/delete_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/store/defaults/hot_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/hot_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/defaults/hot_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/index.d.ts b/x-pack/plugins/index_lifecycle_management/public/application/store/defaults/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/index.d.ts rename to x-pack/plugins/index_lifecycle_management/public/application/store/defaults/index.d.ts diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/index.js b/x-pack/plugins/index_lifecycle_management/public/application/store/defaults/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/defaults/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/application/store/defaults/warm_phase.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/defaults/warm_phase.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/defaults/warm_phase.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/index.d.ts b/x-pack/plugins/index_lifecycle_management/public/application/store/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/index.d.ts rename to x-pack/plugins/index_lifecycle_management/public/application/store/index.d.ts diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/index.js b/x-pack/plugins/index_lifecycle_management/public/application/store/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/general.js b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/general.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/general.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/reducers/general.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/index.js b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/reducers/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/nodes.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/reducers/nodes.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/policies.js b/x-pack/plugins/index_lifecycle_management/public/application/store/reducers/policies.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/reducers/policies.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/reducers/policies.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/general.js b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/general.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/general.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/selectors/general.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/index.js b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/index.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/index.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/selectors/index.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/lifecycle.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/lifecycle.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/selectors/lifecycle.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/nodes.js b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/nodes.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/selectors/nodes.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/application/store/selectors/policies.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/selectors/policies.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/selectors/policies.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/store.js b/x-pack/plugins/index_lifecycle_management/public/application/store/store.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/store/store.js rename to x-pack/plugins/index_lifecycle_management/public/application/store/store.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/add_lifecycle_confirm_modal.js b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.js similarity index 97% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/add_lifecycle_confirm_modal.js rename to x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.js index 5b8f2d197daf4..143895150172d 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/add_lifecycle_confirm_modal.js +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.js @@ -23,7 +23,7 @@ import { EuiModalHeaderTitle, } from '@elastic/eui'; -import { BASE_PATH } from '../../../../common/constants'; +import { BASE_PATH } from '../../../common/constants'; import { loadPolicies, addLifecyclePolicyToIndex } from '../../application/services/api'; import { showApiError } from '../../application/services/api_errors'; import { toasts } from '../../application/services/notification'; @@ -38,7 +38,7 @@ export class AddLifecyclePolicyConfirmModal extends Component { }; } addPolicy = async () => { - const { indexName, httpClient, closeModal, reloadIndices } = this.props; + const { indexName, closeModal, reloadIndices } = this.props; const { selectedPolicyName, selectedAlias } = this.state; if (!selectedPolicyName) { this.setState({ @@ -55,7 +55,7 @@ export class AddLifecyclePolicyConfirmModal extends Component { policyName: selectedPolicyName, alias: selectedAlias, }; - await addLifecyclePolicyToIndex(body, httpClient); + await addLifecyclePolicyToIndex(body); closeModal(); toasts.addSuccess( i18n.translate( diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/index_lifecycle_summary.js b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.js similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/index_lifecycle_summary.js rename to x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.js diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/remove_lifecycle_confirm_modal.js b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.js similarity index 96% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/remove_lifecycle_confirm_modal.js rename to x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.js index 0ba5ed1720084..4e0d2383c7d79 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/components/remove_lifecycle_confirm_modal.js +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/remove_lifecycle_confirm_modal.js @@ -24,10 +24,10 @@ export class RemoveLifecyclePolicyConfirmModal extends Component { } removePolicy = async () => { - const { indexNames, httpClient, closeModal, reloadIndices } = this.props; + const { indexNames, closeModal, reloadIndices } = this.props; try { - await removeLifecycleForIndex(indexNames, httpClient); + await removeLifecycleForIndex(indexNames); closeModal(); toasts.addSuccess( i18n.translate( diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.d.ts b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.d.ts rename to x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.d.ts diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.js similarity index 80% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js rename to x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.js index 69658d31695bc..40ff04408002f 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.js @@ -9,8 +9,6 @@ import { get, every, any } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiSearchBar } from '@elastic/eui'; -import { init as initUiMetric } from '../application/services/ui_metric'; -import { init as initNotification } from '../application/services/notification'; import { retryLifecycleForIndex } from '../application/services/api'; import { IndexLifecycleSummary } from './components/index_lifecycle_summary'; import { AddLifecyclePolicyConfirmModal } from './components/add_lifecycle_confirm_modal'; @@ -18,21 +16,7 @@ import { RemoveLifecyclePolicyConfirmModal } from './components/remove_lifecycle const stepPath = 'ilm.step'; -export const retryLifecycleActionExtension = ({ - indices, - usageCollection, - toasts, - fatalErrors, -}) => { - // These are hacks that we can remove once the New Platform migration is done. They're needed here - // because API requests and API errors require them. - const getLegacyReporter = appName => (type, name) => { - usageCollection.reportUiStats(appName, type, name); - }; - - initUiMetric(getLegacyReporter); - initNotification(toasts, fatalErrors); - +export const retryLifecycleActionExtension = ({ indices }) => { const allHaveErrors = every(indices, index => { return index.ilm && index.ilm.failed_step; }); @@ -57,19 +41,7 @@ export const retryLifecycleActionExtension = ({ }; }; -export const removeLifecyclePolicyActionExtension = ({ - indices, - reloadIndices, - createUiStatsReporter, - toasts, - fatalErrors, - httpClient, -}) => { - // These are hacks that we can remove once the New Platform migration is done. They're needed here - // because API requests and API errors require them. - initUiMetric(createUiStatsReporter); - initNotification(toasts, fatalErrors); - +export const removeLifecyclePolicyActionExtension = ({ indices, reloadIndices }) => { const allHaveIlm = every(indices, index => { return index.ilm && index.ilm.managed; }); @@ -83,8 +55,6 @@ export const removeLifecyclePolicyActionExtension = ({ ); @@ -97,19 +67,7 @@ export const removeLifecyclePolicyActionExtension = ({ }; }; -export const addLifecyclePolicyActionExtension = ({ - indices, - reloadIndices, - createUiStatsReporter, - toasts, - fatalErrors, - httpClient, -}) => { - // These are hacks that we can remove once the New Platform migration is done. They're needed here - // because API requests and API errors require them. - initUiMetric(createUiStatsReporter); - initNotification(toasts, fatalErrors); - +export const addLifecyclePolicyActionExtension = ({ indices, reloadIndices }) => { if (indices.length !== 1) { return null; } @@ -126,8 +84,6 @@ export const addLifecyclePolicyActionExtension = ({ diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/index.ts b/x-pack/plugins/index_lifecycle_management/public/index.ts similarity index 58% rename from x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/index.ts rename to x-pack/plugins/index_lifecycle_management/public/index.ts index 1af0b697a9283..586763188a54b 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/index.ts @@ -4,7 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PluginInitializerContext } from 'src/core/public'; +import { PluginInitializerContext } from 'kibana/public'; + import { IndexLifecycleManagementPlugin } from './plugin'; -export const createPlugin = (ctx: PluginInitializerContext) => new IndexLifecycleManagementPlugin(); +/** @public */ +export const plugin = (initializerContext: PluginInitializerContext) => { + return new IndexLifecycleManagementPlugin(initializerContext); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/plugin.tsx b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx new file mode 100644 index 0000000000000..ca93646e20fcf --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { CoreSetup, PluginInitializerContext } from 'src/core/public'; + +import { PLUGIN } from '../common/constants'; +import { init as initHttp } from './application/services/http'; +import { init as initDocumentation } from './application/services/documentation'; +import { init as initUiMetric } from './application/services/ui_metric'; +import { init as initNotification } from './application/services/notification'; +import { addAllExtensions } from './extend_index_management'; +import { PluginsDependencies, ClientConfigType } from './types'; + +export class IndexLifecycleManagementPlugin { + constructor(private readonly initializerContext: PluginInitializerContext) {} + + public setup(coreSetup: CoreSetup, plugins: PluginsDependencies) { + const { + ui: { enabled: isIndexLifecycleManagementUiEnabled }, + } = this.initializerContext.config.get(); + + if (isIndexLifecycleManagementUiEnabled) { + const { + http, + notifications: { toasts }, + fatalErrors, + getStartServices, + } = coreSetup; + + const { usageCollection, management, indexManagement } = plugins; + + // Initialize services even if the app isn't mounted, because they're used by index management extensions. + initHttp(http); + initUiMetric(usageCollection); + initNotification(toasts, fatalErrors); + + management.sections.getSection('elasticsearch')!.registerApp({ + id: PLUGIN.ID, + title: PLUGIN.TITLE, + order: 2, + mount: async ({ element }) => { + const [coreStart] = await getStartServices(); + const { + i18n: { Context: I18nContext }, + docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }, + } = coreStart; + + // Initialize additional services. + initDocumentation( + `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/` + ); + + const { renderApp } = await import('./application'); + return renderApp(element, I18nContext); + }, + }); + + if (indexManagement) { + addAllExtensions(indexManagement.extensionsService); + } + } + } + + public start() {} + public stop() {} +} diff --git a/x-pack/plugins/index_lifecycle_management/public/types.ts b/x-pack/plugins/index_lifecycle_management/public/types.ts new file mode 100644 index 0000000000000..f9e0abae56cb4 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/types.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 { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; +import { ManagementSetup } from '../../../../src/plugins/management/public'; +import { IndexManagementPluginSetup } from '../../index_management/public'; + +export interface PluginsDependencies { + usageCollection: UsageCollectionSetup; + management: ManagementSetup; + indexManagement?: IndexManagementPluginSetup; +} + +export interface ClientConfigType { + ui: { + enabled: boolean; + }; +} diff --git a/x-pack/plugins/index_lifecycle_management/server/config.ts b/x-pack/plugins/index_lifecycle_management/server/config.ts new file mode 100644 index 0000000000000..9728e31a8a148 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema, TypeOf } from '@kbn/config-schema'; + +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), + ui: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + }), + // Cloud requires the ability to hide internal node attributes from users. + filteredNodeAttributes: schema.arrayOf(schema.string(), { defaultValue: [] }), +}); + +export type IndexLifecycleManagementConfig = TypeOf; diff --git a/x-pack/plugins/index_lifecycle_management/server/index.ts b/x-pack/plugins/index_lifecycle_management/server/index.ts new file mode 100644 index 0000000000000..8a5f0fe19f9b0 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializerContext, PluginConfigDescriptor } from 'kibana/server'; +import { IndexLifecycleManagementServerPlugin } from './plugin'; +import { configSchema, IndexLifecycleManagementConfig } from './config'; + +export const plugin = (ctx: PluginInitializerContext) => + new IndexLifecycleManagementServerPlugin(ctx); + +export const config: PluginConfigDescriptor = { + schema: configSchema, + exposeToBrowser: { + ui: true, + }, +}; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/is_es_error/is_es_error.ts b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error.ts similarity index 100% rename from x-pack/legacy/plugins/index_lifecycle_management/server/lib/is_es_error/is_es_error.ts rename to x-pack/plugins/index_lifecycle_management/server/lib/is_es_error.ts diff --git a/x-pack/plugins/index_lifecycle_management/server/plugin.ts b/x-pack/plugins/index_lifecycle_management/server/plugin.ts new file mode 100644 index 0000000000000..48c50f9a48ee5 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/plugin.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 { Observable } from 'rxjs'; +import { first } from 'rxjs/operators'; +import { i18n } from '@kbn/i18n'; +import { CoreSetup, Plugin, Logger, PluginInitializerContext, APICaller } from 'src/core/server'; + +import { PLUGIN } from '../common/constants'; +import { Dependencies } from './types'; +import { registerApiRoutes } from './routes'; +import { License } from './services'; +import { IndexLifecycleManagementConfig } from './config'; +import { isEsError } from './lib/is_es_error'; + +const indexLifecycleDataEnricher = async (indicesList: any, callAsCurrentUser: APICaller) => { + if (!indicesList || !indicesList.length) { + return; + } + + const params = { + path: '/*/_ilm/explain', + method: 'GET', + }; + + const { indices: ilmIndicesData } = await callAsCurrentUser('transport.request', params); + + return indicesList.map((index: any): any => { + return { + ...index, + ilm: { ...(ilmIndicesData[index.name] || {}) }, + }; + }); +}; + +export class IndexLifecycleManagementServerPlugin implements Plugin { + private readonly config$: Observable; + private readonly license: License; + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + this.config$ = initializerContext.config.create(); + this.license = new License(); + } + + async setup({ http }: CoreSetup, { licensing, indexManagement }: Dependencies): Promise { + const router = http.createRouter(); + const config = await this.config$.pipe(first()).toPromise(); + + this.license.setup( + { + pluginId: PLUGIN.ID, + minimumLicenseType: PLUGIN.minimumLicenseType, + defaultErrorMessage: i18n.translate('xpack.indexLifecycleMgmt.licenseCheckErrorMessage', { + defaultMessage: 'License check failed', + }), + }, + { + licensing, + logger: this.logger, + } + ); + + registerApiRoutes({ + router, + config, + license: this.license, + lib: { + isEsError, + }, + }); + + if (config.ui.enabled) { + if (indexManagement.indexDataEnricher) { + indexManagement.indexDataEnricher.add(indexLifecycleDataEnricher); + } + } + } + + start() {} + stop() {} +} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_index_routes.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/index.ts similarity index 65% rename from x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_index_routes.ts rename to x-pack/plugins/index_lifecycle_management/server/routes/api/index/index.ts index 74eb1a86a93ba..abe00af74b63a 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/index/register_index_routes.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/index.ts @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import { RouteDependencies } from '../../../types'; import { registerRetryRoute } from './register_retry_route'; import { registerRemoveRoute } from './register_remove_route'; import { registerAddPolicyRoute } from './register_add_policy_route'; -export function registerIndexRoutes(server: any) { - registerRetryRoute(server); - registerRemoveRoute(server); - registerAddPolicyRoute(server); +export function registerIndexRoutes(dependencies: RouteDependencies) { + registerRetryRoute(dependencies); + registerRemoveRoute(dependencies); + registerAddPolicyRoute(dependencies); } diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts new file mode 100644 index 0000000000000..9627f6399eaaf --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_add_policy_route.ts @@ -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 { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +async function addLifecyclePolicy( + callAsCurrentUser: APICaller, + indexName: string, + policyName: string, + alias: string +) { + const params = { + method: 'PUT', + path: `/${encodeURIComponent(indexName)}/_settings`, + body: { + lifecycle: { + name: policyName, + rollover_alias: alias, + }, + }, + }; + + return callAsCurrentUser('transport.request', params); +} + +const bodySchema = schema.object({ + indexName: schema.string(), + policyName: schema.string(), + alias: schema.maybe(schema.string()), +}); + +export function registerAddPolicyRoute({ router, license, lib }: RouteDependencies) { + router.post( + { path: addBasePath('/index/add'), validate: { body: bodySchema } }, + license.guardApiRoute(async (context, request, response) => { + const body = request.body as typeof bodySchema.type; + const { indexName, policyName, alias = '' } = body; + + try { + await addLifecyclePolicy( + context.core.elasticsearch.dataClient.callAsCurrentUser, + indexName, + policyName, + alias + ); + return response.ok(); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts new file mode 100644 index 0000000000000..8ec94a8591785 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_remove_route.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +async function removeLifecycle(callAsCurrentUser: APICaller, indexNames: string[]) { + const responses = []; + for (let i = 0; i < indexNames.length; i++) { + const indexName = indexNames[i]; + const params = { + method: 'POST', + path: `/${encodeURIComponent(indexName)}/_ilm/remove`, + ignore: [404], + }; + + responses.push(callAsCurrentUser('transport.request', params)); + } + return Promise.all(responses); +} + +const bodySchema = schema.object({ + indexNames: schema.arrayOf(schema.string()), +}); + +export function registerRemoveRoute({ router, license, lib }: RouteDependencies) { + router.post( + { path: addBasePath('/index/remove'), validate: { body: bodySchema } }, + license.guardApiRoute(async (context, request, response) => { + const body = request.body as typeof bodySchema.type; + const { indexNames } = body; + + try { + await removeLifecycle(context.core.elasticsearch.dataClient.callAsCurrentUser, indexNames); + return response.ok(); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts new file mode 100644 index 0000000000000..1e2d621cab173 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +async function retryLifecycle(callAsCurrentUser: APICaller, indexNames: string[]) { + const responses = []; + for (let i = 0; i < indexNames.length; i++) { + const indexName = indexNames[i]; + const params = { + method: 'POST', + path: `/${encodeURIComponent(indexName)}/_ilm/retry`, + ignore: [404], + }; + + responses.push(callAsCurrentUser('transport.request', params)); + } + return Promise.all(responses); +} + +const bodySchema = schema.object({ + indexNames: schema.arrayOf(schema.string()), +}); + +export function registerRetryRoute({ router, license, lib }: RouteDependencies) { + router.post( + { path: addBasePath('/index/retry'), validate: { body: bodySchema } }, + license.guardApiRoute(async (context, request, response) => { + const body = request.body as typeof bodySchema.type; + const { indexNames } = body; + + try { + await retryLifecycle(context.core.elasticsearch.dataClient.callAsCurrentUser, indexNames); + return response.ok(); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/index.ts similarity index 65% rename from x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.ts rename to x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/index.ts index 4486d97038657..bde56f0318bbd 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/index.ts @@ -4,10 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +import { RouteDependencies } from '../../../types'; import { registerListRoute } from './register_list_route'; import { registerDetailsRoute } from './register_details_route'; -export function registerNodesRoutes(server: any) { - registerListRoute(server); - registerDetailsRoute(server); +export function registerNodesRoutes(dependencies: RouteDependencies) { + registerListRoute(dependencies); + registerDetailsRoute(dependencies); } diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts new file mode 100644 index 0000000000000..6ff1f147e7ea7 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +function findMatchingNodes(stats: any, nodeAttrs: string): any { + return Object.entries(stats.nodes).reduce((accum: any[], [nodeId, nodeStats]: [any, any]) => { + const attributes = nodeStats.attributes || {}; + for (const [key, value] of Object.entries(attributes)) { + if (`${key}:${value}` === nodeAttrs) { + accum.push({ + nodeId, + stats: nodeStats, + }); + break; + } + } + return accum; + }, []); +} + +async function fetchNodeStats(callAsCurrentUser: APICaller): Promise { + const params = { + format: 'json', + }; + + return await callAsCurrentUser('nodes.stats', params); +} + +const paramsSchema = schema.object({ + nodeAttrs: schema.string(), +}); + +export function registerDetailsRoute({ router, license, lib }: RouteDependencies) { + router.get( + { path: addBasePath('/nodes/{nodeAttrs}/details'), validate: { params: paramsSchema } }, + license.guardApiRoute(async (context, request, response) => { + const params = request.params as typeof paramsSchema.type; + const { nodeAttrs } = params; + + try { + const stats = await fetchNodeStats(context.core.elasticsearch.dataClient.callAsCurrentUser); + const okResponse = { body: findMatchingNodes(stats, nodeAttrs) }; + return response.ok(okResponse); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts new file mode 100644 index 0000000000000..73d85c78d3b11 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +function convertStatsIntoList(stats: any, disallowedNodeAttributes: string[]): any { + return Object.entries(stats.nodes).reduce((accum: any, [nodeId, nodeStats]: [any, any]) => { + const attributes = nodeStats.attributes || {}; + for (const [key, value] of Object.entries(attributes)) { + const isNodeAttributeAllowed = !disallowedNodeAttributes.includes(key); + if (isNodeAttributeAllowed) { + const attributeString = `${key}:${value}`; + accum[attributeString] = accum[attributeString] || []; + accum[attributeString].push(nodeId); + } + } + return accum; + }, {}); +} + +async function fetchNodeStats(callAsCurrentUser: APICaller): Promise { + const params = { + format: 'json', + }; + + return await callAsCurrentUser('nodes.stats', params); +} + +export function registerListRoute({ router, config, license, lib }: RouteDependencies) { + const { filteredNodeAttributes } = config; + + const NODE_ATTRS_KEYS_TO_IGNORE: string[] = [ + 'ml.enabled', + 'ml.machine_memory', + 'ml.max_open_jobs', + // Used by ML to identify nodes that have transform enabled: + // https://github.com/elastic/elasticsearch/pull/52712/files#diff-225cc2c1291b4c60a8c3412a619094e1R147 + 'transform.node', + 'xpack.installed', + ]; + + const disallowedNodeAttributes = [...NODE_ATTRS_KEYS_TO_IGNORE, ...filteredNodeAttributes]; + + router.get( + { path: addBasePath('/nodes/list'), validate: false }, + license.guardApiRoute(async (context, request, response) => { + try { + const stats = await fetchNodeStats(context.core.elasticsearch.dataClient.callAsCurrentUser); + const okResponse = { body: convertStatsIntoList(stats, disallowedNodeAttributes) }; + return response.ok(okResponse); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/index.ts similarity index 64% rename from x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.ts rename to x-pack/plugins/index_lifecycle_management/server/routes/api/policies/index.ts index 279b016da178f..c30dc04c61169 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/index.ts @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import { RouteDependencies } from '../../../types'; import { registerFetchRoute } from './register_fetch_route'; import { registerCreateRoute } from './register_create_route'; import { registerDeleteRoute } from './register_delete_route'; -export function registerPoliciesRoutes(server: any) { - registerFetchRoute(server); - registerCreateRoute(server); - registerDeleteRoute(server); +export function registerPoliciesRoutes(dependencies: RouteDependencies) { + registerFetchRoute(dependencies); + registerCreateRoute(dependencies); + registerDeleteRoute(dependencies); } diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts new file mode 100644 index 0000000000000..a9c6bab58fdd9 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +async function createPolicy(callAsCurrentUser: APICaller, name: string, phases: any): Promise { + const body = { + policy: { + phases, + }, + }; + const params = { + method: 'PUT', + path: `/_ilm/policy/${encodeURIComponent(name)}`, + ignore: [404], + body, + }; + + return await callAsCurrentUser('transport.request', params); +} + +const minAgeSchema = schema.maybe(schema.string()); + +const setPrioritySchema = schema.maybe( + schema.object({ + priority: schema.number(), + }) +); + +const unfollowSchema = schema.maybe(schema.object({})); // Unfollow has no options + +const allocateNodeSchema = schema.maybe(schema.recordOf(schema.string(), schema.string())); +const allocateSchema = schema.maybe( + schema.object({ + number_of_replicas: schema.maybe(schema.number()), + include: allocateNodeSchema, + exclude: allocateNodeSchema, + require: allocateNodeSchema, + }) +); + +const hotPhaseSchema = schema.object({ + min_age: minAgeSchema, + actions: schema.object({ + set_priority: setPrioritySchema, + unfollow: unfollowSchema, + rollover: schema.maybe( + schema.object({ + max_age: schema.maybe(schema.string()), + max_size: schema.maybe(schema.string()), + max_docs: schema.maybe(schema.number()), + }) + ), + }), +}); + +const warmPhaseSchema = schema.maybe( + schema.object({ + min_age: minAgeSchema, + actions: schema.object({ + set_priority: setPrioritySchema, + unfollow: unfollowSchema, + read_only: schema.maybe(schema.object({})), // Readonly has no options + allocate: allocateSchema, + shrink: schema.maybe( + schema.object({ + number_of_shards: schema.number(), + }) + ), + forcemerge: schema.maybe( + schema.object({ + max_num_segments: schema.number(), + }) + ), + }), + }) +); + +const coldPhaseSchema = schema.maybe( + schema.object({ + min_age: minAgeSchema, + actions: schema.object({ + set_priority: setPrioritySchema, + unfollow: unfollowSchema, + allocate: allocateSchema, + freeze: schema.maybe(schema.object({})), // Freeze has no options + }), + }) +); + +const deletePhaseSchema = schema.maybe( + schema.object({ + min_age: minAgeSchema, + actions: schema.object({ + wait_for_snapshot: schema.maybe( + schema.object({ + policy: schema.string(), + }) + ), + delete: schema.maybe(schema.object({})), // Delete has no options + }), + }) +); + +// Per https://www.elastic.co/guide/en/elasticsearch/reference/current/_actions.html +const bodySchema = schema.object({ + name: schema.string(), + phases: schema.object({ + hot: hotPhaseSchema, + warm: warmPhaseSchema, + cold: coldPhaseSchema, + delete: deletePhaseSchema, + }), +}); + +export function registerCreateRoute({ router, license, lib }: RouteDependencies) { + router.post( + { path: addBasePath('/policies'), validate: { body: bodySchema } }, + license.guardApiRoute(async (context, request, response) => { + const body = request.body as typeof bodySchema.type; + const { name, phases } = body; + + try { + await createPolicy(context.core.elasticsearch.dataClient.callAsCurrentUser, name, phases); + return response.ok(); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts new file mode 100644 index 0000000000000..e08297f4d7bc4 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +async function deletePolicies(callAsCurrentUser: APICaller, policyNames: string): Promise { + const params = { + method: 'DELETE', + path: `/_ilm/policy/${encodeURIComponent(policyNames)}`, + // we allow 404 since they may have no policies + ignore: [404], + }; + + return await callAsCurrentUser('transport.request', params); +} + +const paramsSchema = schema.object({ + policyNames: schema.string(), +}); + +export function registerDeleteRoute({ router, license, lib }: RouteDependencies) { + router.delete( + { path: addBasePath('/policies/{policyNames}'), validate: { params: paramsSchema } }, + license.guardApiRoute(async (context, request, response) => { + const params = request.params as typeof paramsSchema.type; + const { policyNames } = params; + + try { + await deletePolicies(context.core.elasticsearch.dataClient.callAsCurrentUser, policyNames); + return response.ok(); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts new file mode 100644 index 0000000000000..294b7c4c65cba --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +function formatPolicies(policiesMap: any): any { + if (policiesMap.status === 404) { + return []; + } + + return Object.keys(policiesMap).reduce((accum: any[], lifecycleName: string) => { + const policyEntry = policiesMap[lifecycleName]; + accum.push({ + ...policyEntry, + name: lifecycleName, + }); + return accum; + }, []); +} + +async function fetchPolicies(callAsCurrentUser: APICaller): Promise { + const params = { + method: 'GET', + path: '/_ilm/policy', + // we allow 404 since they may have no policies + ignore: [404], + }; + + return await callAsCurrentUser('transport.request', params); +} + +async function addLinkedIndices(callAsCurrentUser: APICaller, policiesMap: any) { + if (policiesMap.status === 404) { + return policiesMap; + } + const params = { + method: 'GET', + path: '/*/_ilm/explain', + // we allow 404 since they may have no policies + ignore: [404], + }; + + const policyExplanation: any = await callAsCurrentUser('transport.request', params); + Object.entries(policyExplanation.indices).forEach(([indexName, { policy }]: [string, any]) => { + if (policy && policiesMap[policy]) { + policiesMap[policy].linkedIndices = policiesMap[policy].linkedIndices || []; + policiesMap[policy].linkedIndices.push(indexName); + } + }); +} + +const querySchema = schema.object({ + withIndices: schema.boolean({ defaultValue: false }), +}); + +export function registerFetchRoute({ router, license, lib }: RouteDependencies) { + router.get( + { path: addBasePath('/policies'), validate: { query: querySchema } }, + license.guardApiRoute(async (context, request, response) => { + const query = request.query as typeof querySchema.type; + const { withIndices } = query; + const { callAsCurrentUser } = context.core.elasticsearch.dataClient; + + try { + const policiesMap = await fetchPolicies(callAsCurrentUser); + if (withIndices) { + await addLinkedIndices(callAsCurrentUser, policiesMap); + } + const okResponse = { body: formatPolicies(policiesMap) }; + return response.ok(okResponse); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/index.ts similarity index 64% rename from x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.ts rename to x-pack/plugins/index_lifecycle_management/server/routes/api/templates/index.ts index 424b2d36b1ba2..a2d885c3170b9 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/index.ts @@ -4,12 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +import { RouteDependencies } from '../../../types'; import { registerFetchRoute } from './register_fetch_route'; -import { registerGetRoute } from './register_get_route'; import { registerAddPolicyRoute } from './register_add_policy_route'; -export function registerTemplatesRoutes(server: any) { - registerFetchRoute(server); - registerGetRoute(server); - registerAddPolicyRoute(server); +export function registerTemplatesRoutes(dependencies: RouteDependencies) { + registerFetchRoute(dependencies); + registerAddPolicyRoute(dependencies); } diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts new file mode 100644 index 0000000000000..0da8535f8d4ec --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.ts @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { merge } from 'lodash'; +import { schema } from '@kbn/config-schema'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; + +async function getIndexTemplate(callAsCurrentUser: APICaller, templateName: string): Promise { + const response = await callAsCurrentUser('indices.getTemplate', { name: templateName }); + return response[templateName]; +} + +async function updateIndexTemplate( + callAsCurrentUser: APICaller, + templateName: string, + policyName: string, + aliasName?: string +): Promise { + // Fetch existing template + const template = await getIndexTemplate(callAsCurrentUser, templateName); + merge(template, { + settings: { + index: { + lifecycle: { + name: policyName, + rollover_alias: aliasName, + }, + }, + }, + }); + + const params = { + method: 'PUT', + path: `/_template/${encodeURIComponent(templateName)}`, + ignore: [404], + body: template, + }; + + return await callAsCurrentUser('transport.request', params); +} + +const bodySchema = schema.object({ + templateName: schema.string(), + policyName: schema.string(), + aliasName: schema.maybe(schema.string()), +}); + +export function registerAddPolicyRoute({ router, license, lib }: RouteDependencies) { + router.post( + { path: addBasePath('/template'), validate: { body: bodySchema } }, + license.guardApiRoute(async (context, request, response) => { + const body = request.body as typeof bodySchema.type; + const { templateName, policyName, aliasName } = body; + + try { + await updateIndexTemplate( + context.core.elasticsearch.dataClient.callAsCurrentUser, + templateName, + policyName, + aliasName + ); + return response.ok(); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); + } + // Case: default + return response.internalError({ body: e }); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts similarity index 63% rename from x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts rename to x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts index fd58f471d69bb..a2dc67cb77afe 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { isEsError } from '../../../lib/is_es_error'; -import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; +import { APICaller } from 'src/core/server'; + +import { RouteDependencies } from '../../../types'; +import { addBasePath } from '../../../services'; /** * We don't want to output system template (whose name starts with a ".") which don't @@ -49,7 +49,7 @@ function filterAndFormatTemplates(templates: any): any { return formattedTemplates; } -async function fetchTemplates(callWithRequest: any): Promise { +async function fetchTemplates(callAsCurrentUser: APICaller): Promise { const params = { method: 'GET', path: '/_template', @@ -57,30 +57,29 @@ async function fetchTemplates(callWithRequest: any): Promise { ignore: [404], }; - return await callWithRequest('transport.request', params); + return await callAsCurrentUser('transport.request', params); } -export function registerFetchRoute(server: any) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/index_lifecycle_management/templates', - method: 'GET', - handler: async (request: any) => { - const callWithRequest = callWithRequestFactory(server, request); +export function registerFetchRoute({ router, license, lib }: RouteDependencies) { + router.get( + { path: addBasePath('/templates'), validate: false }, + license.guardApiRoute(async (context, request, response) => { try { - const templates = await fetchTemplates(callWithRequest); - return filterAndFormatTemplates(templates); - } catch (err) { - if (isEsError(err)) { - return wrapEsError(err); + const templates = await fetchTemplates( + context.core.elasticsearch.dataClient.callAsCurrentUser + ); + const okResponse = { body: filterAndFormatTemplates(templates) }; + return response.ok(okResponse); + } catch (e) { + if (lib.isEsError(e)) { + return response.customError({ + statusCode: e.statusCode, + body: e, + }); } - - return wrapUnknownError(err); + // Case: default + return response.internalError({ body: e }); } - }, - config: { - pre: [licensePreRouting], - }, - }); + }) + ); } diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/index.ts b/x-pack/plugins/index_lifecycle_management/server/routes/index.ts new file mode 100644 index 0000000000000..35996721854c6 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { RouteDependencies } from '../types'; + +import { registerIndexRoutes } from './api/index'; +import { registerNodesRoutes } from './api/nodes'; +import { registerPoliciesRoutes } from './api/policies'; +import { registerTemplatesRoutes } from './api/templates'; + +export function registerApiRoutes(dependencies: RouteDependencies) { + registerIndexRoutes(dependencies); + registerNodesRoutes(dependencies); + registerPoliciesRoutes(dependencies); + registerTemplatesRoutes(dependencies); +} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/index.ts b/x-pack/plugins/index_lifecycle_management/server/services/add_base_path.ts similarity index 64% rename from x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/index.ts rename to x-pack/plugins/index_lifecycle_management/server/services/add_base_path.ts index f2c070fd44b6e..3f3dd131df7c7 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/check_license/index.ts +++ b/x-pack/plugins/index_lifecycle_management/server/services/add_base_path.ts @@ -4,4 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export { checkLicense } from './check_license'; +import { API_BASE_PATH } from '../../common/constants'; + +export const addBasePath = (uri: string): string => `${API_BASE_PATH}${uri}`; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/index.ts b/x-pack/plugins/index_lifecycle_management/server/services/index.ts similarity index 74% rename from x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/index.ts rename to x-pack/plugins/index_lifecycle_management/server/services/index.ts index 0743e443955f4..d7b544b290c39 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/index.ts +++ b/x-pack/plugins/index_lifecycle_management/server/services/index.ts @@ -4,4 +4,5 @@ * you may not use this file except in compliance with the Elastic License. */ -export { licensePreRoutingFactory } from './license_pre_routing_factory'; +export { License } from './license'; +export { addBasePath } from './add_base_path'; diff --git a/x-pack/plugins/index_lifecycle_management/server/services/license.ts b/x-pack/plugins/index_lifecycle_management/server/services/license.ts new file mode 100644 index 0000000000000..31d3654c51e3e --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/services/license.ts @@ -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 { Logger } from 'src/core/server'; +import { + KibanaRequest, + KibanaResponseFactory, + RequestHandler, + RequestHandlerContext, +} from 'kibana/server'; + +import { LicensingPluginSetup } from '../../../licensing/server'; +import { LicenseType } from '../../../licensing/common/types'; + +export interface LicenseStatus { + isValid: boolean; + message?: string; +} + +interface SetupSettings { + pluginId: string; + minimumLicenseType: LicenseType; + defaultErrorMessage: string; +} + +export class License { + private licenseStatus: LicenseStatus = { + isValid: false, + message: 'Invalid License', + }; + + setup( + { pluginId, minimumLicenseType, defaultErrorMessage }: SetupSettings, + { licensing, logger }: { licensing: LicensingPluginSetup; logger: Logger } + ) { + licensing.license$.subscribe(license => { + const { state, message } = license.check(pluginId, minimumLicenseType); + const hasRequiredLicense = state === 'valid'; + + if (hasRequiredLicense) { + this.licenseStatus = { isValid: true }; + } else { + this.licenseStatus = { + isValid: false, + message: message || defaultErrorMessage, + }; + if (message) { + logger.info(message); + } + } + }); + } + + guardApiRoute(handler: RequestHandler) { + const license = this; + + return function licenseCheck( + ctx: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory + ) { + const licenseStatus = license.getStatus(); + + if (!licenseStatus.isValid) { + return response.customError({ + body: { + message: licenseStatus.message || '', + }, + statusCode: 403, + }); + } + + return handler(ctx, request, response); + }; + } + + getStatus() { + return this.licenseStatus; + } +} diff --git a/x-pack/plugins/index_lifecycle_management/server/types.ts b/x-pack/plugins/index_lifecycle_management/server/types.ts new file mode 100644 index 0000000000000..7f64c1a47197a --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/types.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IRouter } from 'src/core/server'; + +import { LicensingPluginSetup } from '../../licensing/server'; +import { IndexManagementPluginSetup } from '../../index_management/server'; +import { License } from './services'; +import { IndexLifecycleManagementConfig } from './config'; +import { isEsError } from './lib/is_es_error'; + +export interface Dependencies { + licensing: LicensingPluginSetup; + indexManagement: IndexManagementPluginSetup; +} + +export interface RouteDependencies { + router: IRouter; + config: IndexLifecycleManagementConfig; + license: License; + lib: { + isEsError: typeof isEsError; + }; +} diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js index 8f794ce1ed612..a351d39b123a8 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js @@ -46,11 +46,7 @@ export class IndexActionsContextMenu extends Component { confirmAction = isActionConfirmed => { this.setState({ isActionConfirmed }); }; - panels({ - core: { fatalErrors }, - services: { extensionsService, httpService, notificationService }, - plugins: { usageCollection }, - }) { + panels({ services: { extensionsService } }) { const { closeIndices, openIndices, @@ -218,15 +214,6 @@ export class IndexActionsContextMenu extends Component { const actionExtensionDefinition = actionExtension({ indices, reloadIndices, - // These config options can be removed once the NP migration out of legacy is complete. - // They're needed for now because ILM's extensions make API calls which require these - // dependencies, but they're not available unless the app's "setup" lifecycle stage occurs. - // Within the old platform, "setup" only occurs once the user actually visits the app. - // Once ILM and IM have been moved out of legacy this hack won't be necessary. - usageCollection, - toasts: notificationService.toasts, - fatalErrors, - httpClient: httpService.httpClient, }); if (actionExtensionDefinition) { const { diff --git a/x-pack/plugins/index_management/public/index.ts b/x-pack/plugins/index_management/public/index.ts index 6bb921ef648f3..7a76fff7f3ec6 100644 --- a/x-pack/plugins/index_management/public/index.ts +++ b/x-pack/plugins/index_management/public/index.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ import './index.scss'; -import { IndexMgmtUIPlugin, IndexMgmtSetup } from './plugin'; +import { IndexMgmtUIPlugin, IndexManagementPluginSetup } from './plugin'; /** @public */ export const plugin = () => { return new IndexMgmtUIPlugin(); }; -export { IndexMgmtSetup }; +export { IndexManagementPluginSetup }; export { getIndexListUri } from './application/services/navigation'; diff --git a/x-pack/plugins/index_management/public/plugin.ts b/x-pack/plugins/index_management/public/plugin.ts index 4aa06d286e3c4..f9e2a47170b3d 100644 --- a/x-pack/plugins/index_management/public/plugin.ts +++ b/x-pack/plugins/index_management/public/plugin.ts @@ -20,7 +20,7 @@ import { setUiMetricService } from './application/services/api'; import { IndexMgmtMetricsType } from './types'; import { ExtensionsService, ExtensionsSetup } from './services'; -export interface IndexMgmtSetup { +export interface IndexManagementPluginSetup { extensionsService: ExtensionsSetup; } @@ -40,7 +40,7 @@ export class IndexMgmtUIPlugin { setUiMetricService(this.uiMetricService); } - public setup(coreSetup: CoreSetup, plugins: PluginsDependencies): IndexMgmtSetup { + public setup(coreSetup: CoreSetup, plugins: PluginsDependencies): IndexManagementPluginSetup { const { http, notifications } = coreSetup; const { usageCollection, management } = plugins; diff --git a/x-pack/plugins/index_management/server/index.ts b/x-pack/plugins/index_management/server/index.ts index e4102711708cb..4d9409e4a516c 100644 --- a/x-pack/plugins/index_management/server/index.ts +++ b/x-pack/plugins/index_management/server/index.ts @@ -17,6 +17,6 @@ export const config = { /** @public */ export { Dependencies } from './types'; -export { IndexMgmtSetup } from './plugin'; +export { IndexManagementPluginSetup } from './plugin'; export { Index } from './types'; export { IndexManagementConfig } from './config'; diff --git a/x-pack/plugins/index_management/server/plugin.ts b/x-pack/plugins/index_management/server/plugin.ts index a0a9151cdb71f..e5bd7451b028f 100644 --- a/x-pack/plugins/index_management/server/plugin.ts +++ b/x-pack/plugins/index_management/server/plugin.ts @@ -12,13 +12,13 @@ import { ApiRoutes } from './routes'; import { License, IndexDataEnricher } from './services'; import { isEsError } from './lib/is_es_error'; -export interface IndexMgmtSetup { +export interface IndexManagementPluginSetup { indexDataEnricher: { add: IndexDataEnricher['add']; }; } -export class IndexMgmtServerPlugin implements Plugin { +export class IndexMgmtServerPlugin implements Plugin { private readonly apiRoutes: ApiRoutes; private readonly license: License; private readonly logger: Logger; @@ -31,7 +31,7 @@ export class IndexMgmtServerPlugin implements Plugin { const loadTemplates = () => supertest.get(`${API_BASE_PATH}/templates`); - const getTemplate = name => supertest.get(`${API_BASE_PATH}/templates/${name}`); - const addPolicyToTemplate = (templateName, policyName, aliasName) => supertest .post(`${API_BASE_PATH}/template`) @@ -23,7 +21,6 @@ export const registerHelpers = ({ supertest }) => { return { loadTemplates, - getTemplate, addPolicyToTemplate, }; }; diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js index 374577825cd94..d30c20527471b 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/templates.js @@ -16,7 +16,7 @@ export default function({ getService }) { const { createIndexTemplate, cleanUp: cleanUpEsResources } = initElasticsearchHelpers(es); - const { loadTemplates, getTemplate, addPolicyToTemplate } = registerTemplatesHelpers({ + const { loadTemplates, addPolicyToTemplate } = registerTemplatesHelpers({ supertest, }); @@ -48,18 +48,6 @@ export default function({ getService }) { }); }); - describe('get', () => { - it('should fetch a single template', async () => { - // Create a template with the ES client - const templateName = getRandomString(); - const template = getTemplatePayload(); - await createIndexTemplate(templateName, template); - - const { body } = await getTemplate(templateName).expect(200); - expect(body.index_patterns).to.eql(template.index_patterns); - }); - }); - describe('update', () => { it('should add a policy to a template', async () => { // Create policy @@ -78,12 +66,13 @@ export default function({ getService }) { await addPolicyToTemplate(templateName, policyName, rolloverAlias).expect(200); // Fetch the template and verify that the policy has been attached - const { body } = await getTemplate(templateName); + const { body } = await loadTemplates(); + const fetchedTemplate = body.find(({ name }) => templateName === name); const { settings: { index: { lifecycle }, }, - } = body; + } = fetchedTemplate; expect(lifecycle.name).to.equal(policyName); expect(lifecycle.rollover_alias).to.equal(rolloverAlias); }); From 330956ec1a7ea94cc6665147b870075f683d05b3 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Fri, 10 Apr 2020 02:55:28 +0300 Subject: [PATCH 028/121] Code coverage: fix missing coverage after merging oss & x-pack data (#63178) * update nyc & istanbul-babel deps * update index.js in kbn-pm Co-authored-by: Elastic Machine --- package.json | 4 +- packages/kbn-pm/dist/index.js | 1919 ++++++++++++++++----------------- yarn.lock | 410 ++++--- 3 files changed, 1190 insertions(+), 1143 deletions(-) diff --git a/package.json b/package.json index ea930d07e7b43..ec72d5b660345 100644 --- a/package.json +++ b/package.json @@ -396,7 +396,7 @@ "axe-core": "^3.4.1", "babel-eslint": "^10.0.3", "babel-jest": "^24.9.0", - "babel-plugin-istanbul": "^5.2.0", + "babel-plugin-istanbul": "^6.0.0", "backport": "5.1.3", "chai": "3.5.0", "chance": "1.0.18", @@ -469,7 +469,7 @@ "nock": "12.0.3", "node-sass": "^4.13.1", "normalize-path": "^3.0.0", - "nyc": "^14.1.1", + "nyc": "^15.0.1", "pixelmatch": "^5.1.0", "pkg-up": "^2.0.0", "pngjs": "^3.4.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 7a858deff41d3..399720f310f67 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(704); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(703); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); @@ -105,10 +105,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; }); -/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(577); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(576); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__["copyWorkspacePackages"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(577); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(688); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(687); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2506,9 +2506,9 @@ module.exports = require("path"); __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(585); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(685); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(686); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(584); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(684); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(685); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2551,8 +2551,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(499); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(500); -/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579); -/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(584); +/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578); +/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(583); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -43866,7 +43866,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(514); /* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(515); -/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(577); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(576); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -47386,7 +47386,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(514); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(516); -/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(562); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(561); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -52557,8 +52557,8 @@ const fs = __webpack_require__(545); const writeFileAtomic = __webpack_require__(549); const sortKeys = __webpack_require__(556); const makeDir = __webpack_require__(558); -const pify = __webpack_require__(560); -const detectIndent = __webpack_require__(561); +const pify = __webpack_require__(559); +const detectIndent = __webpack_require__(560); const init = (fn, filePath, data, options) => { if (!filePath) { @@ -54852,81 +54852,6 @@ module.exports = (input, options) => { "use strict"; -const processFn = (fn, options) => function (...args) { - const P = options.promiseModule; - - return new P((resolve, reject) => { - if (options.multiArgs) { - args.push((...result) => { - if (options.errorFirst) { - if (result[0]) { - reject(result); - } else { - result.shift(); - resolve(result); - } - } else { - resolve(result); - } - }); - } else if (options.errorFirst) { - args.push((error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); - } else { - args.push(resolve); - } - - fn.apply(this, args); - }); -}; - -module.exports = (input, options) => { - options = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, options); - - const objType = typeof input; - if (!(input !== null && (objType === 'object' || objType === 'function'))) { - throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); - } - - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return options.include ? options.include.some(match) : !options.exclude.some(match); - }; - - let ret; - if (objType === 'function') { - ret = function (...args) { - return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); - }; - } else { - ret = Object.create(Object.getPrototypeOf(input)); - } - - for (const key in input) { // eslint-disable-line guard-for-in - const property = input[key]; - ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; - } - - return ret; -}; - - -/***/ }), -/* 561 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - // detect either spaces or tabs but not both to properly handle tabs // for indentation and spaces for alignment const INDENT_RE = /^(?:( )+|\t+)/; @@ -55050,7 +54975,7 @@ module.exports = str => { /***/ }), -/* 562 */ +/* 561 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55059,7 +54984,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "yarnWorkspacesInfo", function() { return yarnWorkspacesInfo; }); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(563); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(562); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -55129,7 +55054,7 @@ async function yarnWorkspacesInfo(directory) { } /***/ }), -/* 563 */ +/* 562 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55140,9 +55065,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(564); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(563); /* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(569); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(568); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } @@ -55208,12 +55133,12 @@ function spawnStreaming(command, args, opts, { } /***/ }), -/* 564 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(565); +const chalk = __webpack_require__(564); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -55235,16 +55160,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 565 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(566); -const stdoutColor = __webpack_require__(567).stdout; +const ansiStyles = __webpack_require__(565); +const stdoutColor = __webpack_require__(566).stdout; -const template = __webpack_require__(568); +const template = __webpack_require__(567); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -55470,7 +55395,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 566 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55643,7 +55568,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 567 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55785,7 +55710,7 @@ module.exports = { /***/ }), -/* 568 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55920,7 +55845,7 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 569 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { // Copyright IBM Corp. 2014,2018. All Rights Reserved. @@ -55928,12 +55853,12 @@ module.exports = (chalk, tmp) => { // This file is licensed under the Apache License 2.0. // License text available at https://opensource.org/licenses/Apache-2.0 -module.exports = __webpack_require__(570); -module.exports.cli = __webpack_require__(574); +module.exports = __webpack_require__(569); +module.exports.cli = __webpack_require__(573); /***/ }), -/* 570 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55948,9 +55873,9 @@ var stream = __webpack_require__(27); var util = __webpack_require__(29); var fs = __webpack_require__(23); -var through = __webpack_require__(571); -var duplexer = __webpack_require__(572); -var StringDecoder = __webpack_require__(573).StringDecoder; +var through = __webpack_require__(570); +var duplexer = __webpack_require__(571); +var StringDecoder = __webpack_require__(572).StringDecoder; module.exports = Logger; @@ -56139,7 +56064,7 @@ function lineMerger(host) { /***/ }), -/* 571 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -56253,7 +56178,7 @@ function through (write, end, opts) { /***/ }), -/* 572 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -56346,13 +56271,13 @@ function duplex(writer, reader) { /***/ }), -/* 573 */ +/* 572 */ /***/ (function(module, exports) { module.exports = require("string_decoder"); /***/ }), -/* 574 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56363,11 +56288,11 @@ module.exports = require("string_decoder"); -var minimist = __webpack_require__(575); +var minimist = __webpack_require__(574); var path = __webpack_require__(16); -var Logger = __webpack_require__(570); -var pkg = __webpack_require__(576); +var Logger = __webpack_require__(569); +var pkg = __webpack_require__(575); module.exports = cli; @@ -56421,7 +56346,7 @@ function usage($0, p) { /***/ }), -/* 575 */ +/* 574 */ /***/ (function(module, exports) { module.exports = function (args, opts) { @@ -56663,13 +56588,13 @@ function isNumber (x) { /***/ }), -/* 576 */ +/* 575 */ /***/ (function(module) { module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); /***/ }), -/* 577 */ +/* 576 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56682,7 +56607,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(578); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(577); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(516); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(500); @@ -56777,7 +56702,7 @@ function packagesFromGlobPattern({ } /***/ }), -/* 578 */ +/* 577 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56847,7 +56772,7 @@ function getProjectPaths({ } /***/ }), -/* 579 */ +/* 578 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56855,13 +56780,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; }); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(580); +/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(579); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(581); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(580); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -57087,19 +57012,19 @@ async function getAllChecksums(kbn, log) { } /***/ }), -/* 580 */ +/* 579 */ /***/ (function(module, exports) { module.exports = require("crypto"); /***/ }), -/* 581 */ +/* 580 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(582); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(581); /* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); /* @@ -57143,7 +57068,7 @@ async function readYarnLock(kbn) { } /***/ }), -/* 582 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { module.exports = @@ -58702,7 +58627,7 @@ module.exports = invariant; /* 9 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(580); +module.exports = __webpack_require__(579); /***/ }), /* 10 */, @@ -61026,7 +60951,7 @@ function onceStrict (fn) { /* 63 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(583); +module.exports = __webpack_require__(582); /***/ }), /* 64 */, @@ -67421,13 +67346,13 @@ module.exports = process && support(supportLevel); /******/ ]); /***/ }), -/* 583 */ +/* 582 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 584 */ +/* 583 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -67524,7 +67449,7 @@ class BootstrapCacheFile { } /***/ }), -/* 585 */ +/* 584 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -67532,9 +67457,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(585); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(674); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(673); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); @@ -67633,21 +67558,21 @@ const CleanCommand = { }; /***/ }), -/* 586 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const path = __webpack_require__(16); -const globby = __webpack_require__(587); -const isGlob = __webpack_require__(604); -const slash = __webpack_require__(665); +const globby = __webpack_require__(586); +const isGlob = __webpack_require__(603); +const slash = __webpack_require__(664); const gracefulFs = __webpack_require__(22); -const isPathCwd = __webpack_require__(667); -const isPathInside = __webpack_require__(668); -const rimraf = __webpack_require__(669); -const pMap = __webpack_require__(670); +const isPathCwd = __webpack_require__(666); +const isPathInside = __webpack_require__(667); +const rimraf = __webpack_require__(668); +const pMap = __webpack_require__(669); const rimrafP = promisify(rimraf); @@ -67761,19 +67686,19 @@ module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options /***/ }), -/* 587 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(588); -const merge2 = __webpack_require__(589); -const glob = __webpack_require__(590); -const fastGlob = __webpack_require__(595); -const dirGlob = __webpack_require__(661); -const gitignore = __webpack_require__(663); -const {FilterStream, UniqueStream} = __webpack_require__(666); +const arrayUnion = __webpack_require__(587); +const merge2 = __webpack_require__(588); +const glob = __webpack_require__(589); +const fastGlob = __webpack_require__(594); +const dirGlob = __webpack_require__(660); +const gitignore = __webpack_require__(662); +const {FilterStream, UniqueStream} = __webpack_require__(665); const DEFAULT_FILTER = () => false; @@ -67946,7 +67871,7 @@ module.exports.gitignore = gitignore; /***/ }), -/* 588 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67958,7 +67883,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 589 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68072,7 +67997,7 @@ function pauseStreams (streams, options) { /***/ }), -/* 590 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -68121,13 +68046,13 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(502) var minimatch = __webpack_require__(504) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(591) +var inherits = __webpack_require__(590) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(510) -var globSync = __webpack_require__(593) -var common = __webpack_require__(594) +var globSync = __webpack_require__(592) +var common = __webpack_require__(593) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -68868,7 +68793,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 591 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -68878,12 +68803,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(592); + module.exports = __webpack_require__(591); } /***/ }), -/* 592 */ +/* 591 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -68916,7 +68841,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 593 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync @@ -68926,12 +68851,12 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(502) var minimatch = __webpack_require__(504) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(590).Glob +var Glob = __webpack_require__(589).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(510) -var common = __webpack_require__(594) +var common = __webpack_require__(593) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -69408,7 +69333,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 594 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -69654,17 +69579,17 @@ function childrenIgnored (self, path) { /***/ }), -/* 595 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(596); -const async_1 = __webpack_require__(624); -const stream_1 = __webpack_require__(657); -const sync_1 = __webpack_require__(658); -const settings_1 = __webpack_require__(660); -const utils = __webpack_require__(597); +const taskManager = __webpack_require__(595); +const async_1 = __webpack_require__(623); +const stream_1 = __webpack_require__(656); +const sync_1 = __webpack_require__(657); +const settings_1 = __webpack_require__(659); +const utils = __webpack_require__(596); function FastGlob(source, options) { try { assertPatternsInput(source); @@ -69722,13 +69647,13 @@ module.exports = FastGlob; /***/ }), -/* 596 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -69796,28 +69721,28 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 597 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const array = __webpack_require__(598); +const array = __webpack_require__(597); exports.array = array; -const errno = __webpack_require__(599); +const errno = __webpack_require__(598); exports.errno = errno; -const fs = __webpack_require__(600); +const fs = __webpack_require__(599); exports.fs = fs; -const path = __webpack_require__(601); +const path = __webpack_require__(600); exports.path = path; -const pattern = __webpack_require__(602); +const pattern = __webpack_require__(601); exports.pattern = pattern; -const stream = __webpack_require__(623); +const stream = __webpack_require__(622); exports.stream = stream; /***/ }), -/* 598 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69830,7 +69755,7 @@ exports.flatten = flatten; /***/ }), -/* 599 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69843,7 +69768,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 600 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69868,7 +69793,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 601 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69889,16 +69814,16 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 602 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const globParent = __webpack_require__(603); -const isGlob = __webpack_require__(604); -const micromatch = __webpack_require__(606); +const globParent = __webpack_require__(602); +const isGlob = __webpack_require__(603); +const micromatch = __webpack_require__(605); const GLOBSTAR = '**'; function isStaticPattern(pattern) { return !isDynamicPattern(pattern); @@ -69987,13 +69912,13 @@ exports.matchAny = matchAny; /***/ }), -/* 603 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isGlob = __webpack_require__(604); +var isGlob = __webpack_require__(603); var pathPosixDirname = __webpack_require__(16).posix.dirname; var isWin32 = __webpack_require__(11).platform() === 'win32'; @@ -70028,7 +69953,7 @@ module.exports = function globParent(str) { /***/ }), -/* 604 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -70038,7 +69963,7 @@ module.exports = function globParent(str) { * Released under the MIT License. */ -var isExtglob = __webpack_require__(605); +var isExtglob = __webpack_require__(604); var chars = { '{': '}', '(': ')', '[': ']'}; var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; @@ -70082,7 +70007,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 605 */ +/* 604 */ /***/ (function(module, exports) { /*! @@ -70108,16 +70033,16 @@ module.exports = function isExtglob(str) { /***/ }), -/* 606 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const util = __webpack_require__(29); -const braces = __webpack_require__(607); -const picomatch = __webpack_require__(617); -const utils = __webpack_require__(620); +const braces = __webpack_require__(606); +const picomatch = __webpack_require__(616); +const utils = __webpack_require__(619); const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); /** @@ -70582,16 +70507,16 @@ module.exports = micromatch; /***/ }), -/* 607 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(608); -const compile = __webpack_require__(610); -const expand = __webpack_require__(614); -const parse = __webpack_require__(615); +const stringify = __webpack_require__(607); +const compile = __webpack_require__(609); +const expand = __webpack_require__(613); +const parse = __webpack_require__(614); /** * Expand the given pattern or create a regex-compatible string. @@ -70759,13 +70684,13 @@ module.exports = braces; /***/ }), -/* 608 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(609); +const utils = __webpack_require__(608); module.exports = (ast, options = {}) => { let stringify = (node, parent = {}) => { @@ -70798,7 +70723,7 @@ module.exports = (ast, options = {}) => { /***/ }), -/* 609 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70917,14 +70842,14 @@ exports.flatten = (...args) => { /***/ }), -/* 610 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(611); -const utils = __webpack_require__(609); +const fill = __webpack_require__(610); +const utils = __webpack_require__(608); const compile = (ast, options = {}) => { let walk = (node, parent = {}) => { @@ -70981,7 +70906,7 @@ module.exports = compile; /***/ }), -/* 611 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70995,7 +70920,7 @@ module.exports = compile; const util = __webpack_require__(29); -const toRegexRange = __webpack_require__(612); +const toRegexRange = __webpack_require__(611); const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); @@ -71237,7 +71162,7 @@ module.exports = fill; /***/ }), -/* 612 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71250,7 +71175,7 @@ module.exports = fill; -const isNumber = __webpack_require__(613); +const isNumber = __webpack_require__(612); const toRegexRange = (min, max, options) => { if (isNumber(min) === false) { @@ -71532,7 +71457,7 @@ module.exports = toRegexRange; /***/ }), -/* 613 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71557,15 +71482,15 @@ module.exports = function(num) { /***/ }), -/* 614 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(611); -const stringify = __webpack_require__(608); -const utils = __webpack_require__(609); +const fill = __webpack_require__(610); +const stringify = __webpack_require__(607); +const utils = __webpack_require__(608); const append = (queue = '', stash = '', enclose = false) => { let result = []; @@ -71677,13 +71602,13 @@ module.exports = expand; /***/ }), -/* 615 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(608); +const stringify = __webpack_require__(607); /** * Constants @@ -71705,7 +71630,7 @@ const { CHAR_SINGLE_QUOTE, /* ' */ CHAR_NO_BREAK_SPACE, CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = __webpack_require__(616); +} = __webpack_require__(615); /** * parse @@ -72017,7 +71942,7 @@ module.exports = parse; /***/ }), -/* 616 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72081,26 +72006,26 @@ module.exports = { /***/ }), -/* 617 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(618); +module.exports = __webpack_require__(617); /***/ }), -/* 618 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const scan = __webpack_require__(619); -const parse = __webpack_require__(622); -const utils = __webpack_require__(620); +const scan = __webpack_require__(618); +const parse = __webpack_require__(621); +const utils = __webpack_require__(619); /** * Creates a matcher function from one or more glob patterns. The @@ -72403,7 +72328,7 @@ picomatch.toRegex = (source, options) => { * @return {Object} */ -picomatch.constants = __webpack_require__(621); +picomatch.constants = __webpack_require__(620); /** * Expose "picomatch" @@ -72413,13 +72338,13 @@ module.exports = picomatch; /***/ }), -/* 619 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(620); +const utils = __webpack_require__(619); const { CHAR_ASTERISK, /* * */ @@ -72437,7 +72362,7 @@ const { CHAR_RIGHT_CURLY_BRACE, /* } */ CHAR_RIGHT_PARENTHESES, /* ) */ CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __webpack_require__(621); +} = __webpack_require__(620); const isPathSeparator = code => { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; @@ -72639,7 +72564,7 @@ module.exports = (input, options) => { /***/ }), -/* 620 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72651,7 +72576,7 @@ const { REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL, REGEX_REMOVE_BACKSLASH -} = __webpack_require__(621); +} = __webpack_require__(620); exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); @@ -72689,7 +72614,7 @@ exports.escapeLast = (input, char, lastIdx) => { /***/ }), -/* 621 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72875,14 +72800,14 @@ module.exports = { /***/ }), -/* 622 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(620); -const constants = __webpack_require__(621); +const utils = __webpack_require__(619); +const constants = __webpack_require__(620); /** * Constants @@ -73893,13 +73818,13 @@ module.exports = parse; /***/ }), -/* 623 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const merge2 = __webpack_require__(589); +const merge2 = __webpack_require__(588); function merge(streams) { const mergedStream = merge2(streams); streams.forEach((stream) => { @@ -73911,14 +73836,14 @@ exports.merge = merge; /***/ }), -/* 624 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(625); -const provider_1 = __webpack_require__(652); +const stream_1 = __webpack_require__(624); +const provider_1 = __webpack_require__(651); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -73946,16 +73871,16 @@ exports.default = ProviderAsync; /***/ }), -/* 625 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const fsStat = __webpack_require__(626); -const fsWalk = __webpack_require__(631); -const reader_1 = __webpack_require__(651); +const fsStat = __webpack_require__(625); +const fsWalk = __webpack_require__(630); +const reader_1 = __webpack_require__(650); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -74008,15 +73933,15 @@ exports.default = ReaderStream; /***/ }), -/* 626 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(627); -const sync = __webpack_require__(628); -const settings_1 = __webpack_require__(629); +const async = __webpack_require__(626); +const sync = __webpack_require__(627); +const settings_1 = __webpack_require__(628); exports.Settings = settings_1.default; function stat(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74039,7 +73964,7 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 627 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74077,7 +74002,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 628 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74106,13 +74031,13 @@ exports.read = read; /***/ }), -/* 629 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(630); +const fs = __webpack_require__(629); class Settings { constructor(_options = {}) { this._options = _options; @@ -74129,7 +74054,7 @@ exports.default = Settings; /***/ }), -/* 630 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74152,16 +74077,16 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 631 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(632); -const stream_1 = __webpack_require__(647); -const sync_1 = __webpack_require__(648); -const settings_1 = __webpack_require__(650); +const async_1 = __webpack_require__(631); +const stream_1 = __webpack_require__(646); +const sync_1 = __webpack_require__(647); +const settings_1 = __webpack_require__(649); exports.Settings = settings_1.default; function walk(dir, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74191,13 +74116,13 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 632 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(633); +const async_1 = __webpack_require__(632); class AsyncProvider { constructor(_root, _settings) { this._root = _root; @@ -74228,17 +74153,17 @@ function callSuccessCallback(callback, entries) { /***/ }), -/* 633 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = __webpack_require__(379); -const fsScandir = __webpack_require__(634); -const fastq = __webpack_require__(643); -const common = __webpack_require__(645); -const reader_1 = __webpack_require__(646); +const fsScandir = __webpack_require__(633); +const fastq = __webpack_require__(642); +const common = __webpack_require__(644); +const reader_1 = __webpack_require__(645); class AsyncReader extends reader_1.default { constructor(_root, _settings) { super(_root, _settings); @@ -74328,15 +74253,15 @@ exports.default = AsyncReader; /***/ }), -/* 634 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(635); -const sync = __webpack_require__(640); -const settings_1 = __webpack_require__(641); +const async = __webpack_require__(634); +const sync = __webpack_require__(639); +const settings_1 = __webpack_require__(640); exports.Settings = settings_1.default; function scandir(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -74359,16 +74284,16 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 635 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(626); -const rpl = __webpack_require__(636); -const constants_1 = __webpack_require__(637); -const utils = __webpack_require__(638); +const fsStat = __webpack_require__(625); +const rpl = __webpack_require__(635); +const constants_1 = __webpack_require__(636); +const utils = __webpack_require__(637); function read(dir, settings, callback) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings, callback); @@ -74457,7 +74382,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 636 */ +/* 635 */ /***/ (function(module, exports) { module.exports = runParallel @@ -74511,7 +74436,7 @@ function runParallel (tasks, cb) { /***/ }), -/* 637 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74527,18 +74452,18 @@ exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = MAJOR_VERSION > 10 || (MAJOR_VERSIO /***/ }), -/* 638 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(639); +const fs = __webpack_require__(638); exports.fs = fs; /***/ }), -/* 639 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74563,15 +74488,15 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 640 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(626); -const constants_1 = __webpack_require__(637); -const utils = __webpack_require__(638); +const fsStat = __webpack_require__(625); +const constants_1 = __webpack_require__(636); +const utils = __webpack_require__(637); function read(dir, settings) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings); @@ -74622,15 +74547,15 @@ exports.readdir = readdir; /***/ }), -/* 641 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(626); -const fs = __webpack_require__(642); +const fsStat = __webpack_require__(625); +const fs = __webpack_require__(641); class Settings { constructor(_options = {}) { this._options = _options; @@ -74653,7 +74578,7 @@ exports.default = Settings; /***/ }), -/* 642 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74678,13 +74603,13 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 643 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var reusify = __webpack_require__(644) +var reusify = __webpack_require__(643) function fastqueue (context, worker, concurrency) { if (typeof context === 'function') { @@ -74858,7 +74783,7 @@ module.exports = fastqueue /***/ }), -/* 644 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74898,7 +74823,7 @@ module.exports = reusify /***/ }), -/* 645 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74929,13 +74854,13 @@ exports.joinPathSegments = joinPathSegments; /***/ }), -/* 646 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const common = __webpack_require__(645); +const common = __webpack_require__(644); class Reader { constructor(_root, _settings) { this._root = _root; @@ -74947,14 +74872,14 @@ exports.default = Reader; /***/ }), -/* 647 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const async_1 = __webpack_require__(633); +const async_1 = __webpack_require__(632); class StreamProvider { constructor(_root, _settings) { this._root = _root; @@ -74984,13 +74909,13 @@ exports.default = StreamProvider; /***/ }), -/* 648 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(649); +const sync_1 = __webpack_require__(648); class SyncProvider { constructor(_root, _settings) { this._root = _root; @@ -75005,15 +74930,15 @@ exports.default = SyncProvider; /***/ }), -/* 649 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsScandir = __webpack_require__(634); -const common = __webpack_require__(645); -const reader_1 = __webpack_require__(646); +const fsScandir = __webpack_require__(633); +const common = __webpack_require__(644); +const reader_1 = __webpack_require__(645); class SyncReader extends reader_1.default { constructor() { super(...arguments); @@ -75071,14 +74996,14 @@ exports.default = SyncReader; /***/ }), -/* 650 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsScandir = __webpack_require__(634); +const fsScandir = __webpack_require__(633); class Settings { constructor(_options = {}) { this._options = _options; @@ -75104,15 +75029,15 @@ exports.default = Settings; /***/ }), -/* 651 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(626); -const utils = __webpack_require__(597); +const fsStat = __webpack_require__(625); +const utils = __webpack_require__(596); class Reader { constructor(_settings) { this._settings = _settings; @@ -75144,17 +75069,17 @@ exports.default = Reader; /***/ }), -/* 652 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const deep_1 = __webpack_require__(653); -const entry_1 = __webpack_require__(654); -const error_1 = __webpack_require__(655); -const entry_2 = __webpack_require__(656); +const deep_1 = __webpack_require__(652); +const entry_1 = __webpack_require__(653); +const error_1 = __webpack_require__(654); +const entry_2 = __webpack_require__(655); class Provider { constructor(_settings) { this._settings = _settings; @@ -75199,13 +75124,13 @@ exports.default = Provider; /***/ }), -/* 653 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -75265,13 +75190,13 @@ exports.default = DeepFilter; /***/ }), -/* 654 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -75326,13 +75251,13 @@ exports.default = EntryFilter; /***/ }), -/* 655 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -75348,13 +75273,13 @@ exports.default = ErrorFilter; /***/ }), -/* 656 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(597); +const utils = __webpack_require__(596); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -75381,15 +75306,15 @@ exports.default = EntryTransformer; /***/ }), -/* 657 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const stream_2 = __webpack_require__(625); -const provider_1 = __webpack_require__(652); +const stream_2 = __webpack_require__(624); +const provider_1 = __webpack_require__(651); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -75417,14 +75342,14 @@ exports.default = ProviderStream; /***/ }), -/* 658 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(659); -const provider_1 = __webpack_require__(652); +const sync_1 = __webpack_require__(658); +const provider_1 = __webpack_require__(651); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -75447,15 +75372,15 @@ exports.default = ProviderSync; /***/ }), -/* 659 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(626); -const fsWalk = __webpack_require__(631); -const reader_1 = __webpack_require__(651); +const fsStat = __webpack_require__(625); +const fsWalk = __webpack_require__(630); +const reader_1 = __webpack_require__(650); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -75497,7 +75422,7 @@ exports.default = ReaderSync; /***/ }), -/* 660 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75557,13 +75482,13 @@ exports.default = Settings; /***/ }), -/* 661 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(662); +const pathType = __webpack_require__(661); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -75639,7 +75564,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 662 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75689,7 +75614,7 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 663 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75697,9 +75622,9 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); const {promisify} = __webpack_require__(29); const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(595); -const gitIgnore = __webpack_require__(664); -const slash = __webpack_require__(665); +const fastGlob = __webpack_require__(594); +const gitIgnore = __webpack_require__(663); +const slash = __webpack_require__(664); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -75813,7 +75738,7 @@ module.exports.sync = options => { /***/ }), -/* 664 */ +/* 663 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -76404,7 +76329,7 @@ if ( /***/ }), -/* 665 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76422,7 +76347,7 @@ module.exports = path => { /***/ }), -/* 666 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76475,7 +76400,7 @@ module.exports = { /***/ }), -/* 667 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76497,7 +76422,7 @@ module.exports = path_ => { /***/ }), -/* 668 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76525,7 +76450,7 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 669 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { const assert = __webpack_require__(30) @@ -76533,7 +76458,7 @@ const path = __webpack_require__(16) const fs = __webpack_require__(23) let glob = undefined try { - glob = __webpack_require__(590) + glob = __webpack_require__(589) } catch (_err) { // treat glob as optional. } @@ -76899,12 +76824,12 @@ rimraf.sync = rimrafSync /***/ }), -/* 670 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(671); +const AggregateError = __webpack_require__(670); module.exports = async ( iterable, @@ -76987,13 +76912,13 @@ module.exports = async ( /***/ }), -/* 671 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(672); -const cleanStack = __webpack_require__(673); +const indentString = __webpack_require__(671); +const cleanStack = __webpack_require__(672); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -77041,7 +76966,7 @@ module.exports = AggregateError; /***/ }), -/* 672 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77083,7 +77008,7 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 673 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77130,15 +77055,15 @@ module.exports = (stack, options) => { /***/ }), -/* 674 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(675); -const cliCursor = __webpack_require__(679); -const cliSpinners = __webpack_require__(683); -const logSymbols = __webpack_require__(564); +const chalk = __webpack_require__(674); +const cliCursor = __webpack_require__(678); +const cliSpinners = __webpack_require__(682); +const logSymbols = __webpack_require__(563); class Ora { constructor(options) { @@ -77285,16 +77210,16 @@ module.exports.promise = (action, options) => { /***/ }), -/* 675 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(676); -const stdoutColor = __webpack_require__(677).stdout; +const ansiStyles = __webpack_require__(675); +const stdoutColor = __webpack_require__(676).stdout; -const template = __webpack_require__(678); +const template = __webpack_require__(677); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -77520,7 +77445,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 676 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77693,7 +77618,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 677 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77835,7 +77760,7 @@ module.exports = { /***/ }), -/* 678 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77970,12 +77895,12 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 679 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(680); +const restoreCursor = __webpack_require__(679); let hidden = false; @@ -78016,12 +77941,12 @@ exports.toggle = (force, stream) => { /***/ }), -/* 680 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(681); +const onetime = __webpack_require__(680); const signalExit = __webpack_require__(377); module.exports = onetime(() => { @@ -78032,12 +77957,12 @@ module.exports = onetime(() => { /***/ }), -/* 681 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(682); +const mimicFn = __webpack_require__(681); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -78078,7 +78003,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 682 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78094,22 +78019,22 @@ module.exports = (to, from) => { /***/ }), -/* 683 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(684); +module.exports = __webpack_require__(683); /***/ }), -/* 684 */ +/* 683 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 685 */ +/* 684 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78169,7 +78094,7 @@ const RunCommand = { }; /***/ }), -/* 686 */ +/* 685 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78180,7 +78105,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(499); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(687); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(686); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -78264,7 +78189,7 @@ const WatchCommand = { }; /***/ }), -/* 687 */ +/* 686 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78338,7 +78263,7 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 688 */ +/* 687 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78346,15 +78271,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(689); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(688); /* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(690); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(689); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(514); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(34); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(500); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(697); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(698); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(696); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(697); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -78442,7 +78367,7 @@ function toArray(value) { } /***/ }), -/* 689 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78476,13 +78401,13 @@ module.exports = (str, count, opts) => { /***/ }), -/* 690 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(691); -const stripAnsi = __webpack_require__(695); +const stringWidth = __webpack_require__(690); +const stripAnsi = __webpack_require__(694); const ESCAPES = new Set([ '\u001B', @@ -78676,13 +78601,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 691 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(692); -const isFullwidthCodePoint = __webpack_require__(694); +const stripAnsi = __webpack_require__(691); +const isFullwidthCodePoint = __webpack_require__(693); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -78719,18 +78644,18 @@ module.exports = str => { /***/ }), -/* 692 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(693); +const ansiRegex = __webpack_require__(692); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 693 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78747,7 +78672,7 @@ module.exports = () => { /***/ }), -/* 694 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78800,18 +78725,18 @@ module.exports = x => { /***/ }), -/* 695 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(696); +const ansiRegex = __webpack_require__(695); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 696 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78828,7 +78753,7 @@ module.exports = () => { /***/ }), -/* 697 */ +/* 696 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78981,7 +78906,7 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 698 */ +/* 697 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -78989,12 +78914,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(699); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(698); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(703); +/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(702); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(578); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(577); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -79135,15 +79060,15 @@ class Kibana { } /***/ }), -/* 699 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const minimatch = __webpack_require__(504); -const arrayUnion = __webpack_require__(700); -const arrayDiffer = __webpack_require__(701); -const arrify = __webpack_require__(702); +const arrayUnion = __webpack_require__(699); +const arrayDiffer = __webpack_require__(700); +const arrify = __webpack_require__(701); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -79167,7 +79092,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 700 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79179,7 +79104,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 701 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79194,7 +79119,7 @@ module.exports = arrayDiffer; /***/ }), -/* 702 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79224,7 +79149,7 @@ module.exports = arrify; /***/ }), -/* 703 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79252,15 +79177,15 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 704 */ +/* 703 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(705); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(704); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(923); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(922); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -79285,19 +79210,19 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 705 */ +/* 704 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(705); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(585); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(578); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(577); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(516); @@ -79433,7 +79358,7 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 706 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79441,13 +79366,13 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { const EventEmitter = __webpack_require__(379); const path = __webpack_require__(16); const os = __webpack_require__(11); -const pAll = __webpack_require__(707); -const arrify = __webpack_require__(709); -const globby = __webpack_require__(710); -const isGlob = __webpack_require__(604); -const cpFile = __webpack_require__(908); -const junk = __webpack_require__(920); -const CpyError = __webpack_require__(921); +const pAll = __webpack_require__(706); +const arrify = __webpack_require__(708); +const globby = __webpack_require__(709); +const isGlob = __webpack_require__(603); +const cpFile = __webpack_require__(907); +const junk = __webpack_require__(919); +const CpyError = __webpack_require__(920); const defaultOptions = { ignoreJunk: true @@ -79566,12 +79491,12 @@ module.exports = (source, destination, { /***/ }), -/* 707 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(708); +const pMap = __webpack_require__(707); module.exports = (iterable, options) => pMap(iterable, element => element(), options); // TODO: Remove this for the next major release @@ -79579,7 +79504,7 @@ module.exports.default = module.exports; /***/ }), -/* 708 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79658,7 +79583,7 @@ module.exports.default = pMap; /***/ }), -/* 709 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79688,17 +79613,17 @@ module.exports = arrify; /***/ }), -/* 710 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(711); -const glob = __webpack_require__(713); -const fastGlob = __webpack_require__(718); -const dirGlob = __webpack_require__(901); -const gitignore = __webpack_require__(904); +const arrayUnion = __webpack_require__(710); +const glob = __webpack_require__(712); +const fastGlob = __webpack_require__(717); +const dirGlob = __webpack_require__(900); +const gitignore = __webpack_require__(903); const DEFAULT_FILTER = () => false; @@ -79843,12 +79768,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 711 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(712); +var arrayUniq = __webpack_require__(711); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -79856,7 +79781,7 @@ module.exports = function () { /***/ }), -/* 712 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79925,7 +79850,7 @@ if ('Set' in global) { /***/ }), -/* 713 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -79974,13 +79899,13 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(502) var minimatch = __webpack_require__(504) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(714) +var inherits = __webpack_require__(713) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(510) -var globSync = __webpack_require__(716) -var common = __webpack_require__(717) +var globSync = __webpack_require__(715) +var common = __webpack_require__(716) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -80721,7 +80646,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 714 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -80731,12 +80656,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(715); + module.exports = __webpack_require__(714); } /***/ }), -/* 715 */ +/* 714 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -80769,7 +80694,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 716 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync @@ -80779,12 +80704,12 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(502) var minimatch = __webpack_require__(504) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(713).Glob +var Glob = __webpack_require__(712).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(510) -var common = __webpack_require__(717) +var common = __webpack_require__(716) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -81261,7 +81186,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 717 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -81507,10 +81432,10 @@ function childrenIgnored (self, path) { /***/ }), -/* 718 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(719); +const pkg = __webpack_require__(718); module.exports = pkg.async; module.exports.default = pkg.async; @@ -81523,19 +81448,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 719 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(720); -var taskManager = __webpack_require__(721); -var reader_async_1 = __webpack_require__(872); -var reader_stream_1 = __webpack_require__(896); -var reader_sync_1 = __webpack_require__(897); -var arrayUtils = __webpack_require__(899); -var streamUtils = __webpack_require__(900); +var optionsManager = __webpack_require__(719); +var taskManager = __webpack_require__(720); +var reader_async_1 = __webpack_require__(871); +var reader_stream_1 = __webpack_require__(895); +var reader_sync_1 = __webpack_require__(896); +var arrayUtils = __webpack_require__(898); +var streamUtils = __webpack_require__(899); /** * Synchronous API. */ @@ -81601,7 +81526,7 @@ function isString(source) { /***/ }), -/* 720 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81639,13 +81564,13 @@ exports.prepare = prepare; /***/ }), -/* 721 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(722); +var patternUtils = __webpack_require__(721); /** * Generate tasks based on parent directory of each pattern. */ @@ -81736,16 +81661,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 722 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var globParent = __webpack_require__(723); -var isGlob = __webpack_require__(726); -var micromatch = __webpack_require__(727); +var globParent = __webpack_require__(722); +var isGlob = __webpack_require__(725); +var micromatch = __webpack_require__(726); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -81891,15 +81816,15 @@ exports.matchAny = matchAny; /***/ }), -/* 723 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(16); -var isglob = __webpack_require__(724); -var pathDirname = __webpack_require__(725); +var isglob = __webpack_require__(723); +var pathDirname = __webpack_require__(724); var isWin32 = __webpack_require__(11).platform() === 'win32'; module.exports = function globParent(str) { @@ -81922,7 +81847,7 @@ module.exports = function globParent(str) { /***/ }), -/* 724 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -81932,7 +81857,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(605); +var isExtglob = __webpack_require__(604); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -81953,7 +81878,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 725 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82103,7 +82028,7 @@ module.exports.win32 = win32; /***/ }), -/* 726 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -82113,7 +82038,7 @@ module.exports.win32 = win32; * Released under the MIT License. */ -var isExtglob = __webpack_require__(605); +var isExtglob = __webpack_require__(604); var chars = { '{': '}', '(': ')', '[': ']'}; module.exports = function isGlob(str, options) { @@ -82155,7 +82080,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 727 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82166,18 +82091,18 @@ module.exports = function isGlob(str, options) { */ var util = __webpack_require__(29); -var braces = __webpack_require__(728); -var toRegex = __webpack_require__(830); -var extend = __webpack_require__(838); +var braces = __webpack_require__(727); +var toRegex = __webpack_require__(829); +var extend = __webpack_require__(837); /** * Local dependencies */ -var compilers = __webpack_require__(841); -var parsers = __webpack_require__(868); -var cache = __webpack_require__(869); -var utils = __webpack_require__(870); +var compilers = __webpack_require__(840); +var parsers = __webpack_require__(867); +var cache = __webpack_require__(868); +var utils = __webpack_require__(869); var MAX_LENGTH = 1024 * 64; /** @@ -83039,7 +82964,7 @@ module.exports = micromatch; /***/ }), -/* 728 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83049,18 +82974,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(729); -var unique = __webpack_require__(741); -var extend = __webpack_require__(738); +var toRegex = __webpack_require__(728); +var unique = __webpack_require__(740); +var extend = __webpack_require__(737); /** * Local dependencies */ -var compilers = __webpack_require__(742); -var parsers = __webpack_require__(757); -var Braces = __webpack_require__(767); -var utils = __webpack_require__(743); +var compilers = __webpack_require__(741); +var parsers = __webpack_require__(756); +var Braces = __webpack_require__(766); +var utils = __webpack_require__(742); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -83364,15 +83289,15 @@ module.exports = braces; /***/ }), -/* 729 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(730); -var extend = __webpack_require__(738); -var not = __webpack_require__(740); +var define = __webpack_require__(729); +var extend = __webpack_require__(737); +var not = __webpack_require__(739); var MAX_LENGTH = 1024 * 64; /** @@ -83519,7 +83444,7 @@ module.exports.makeRe = makeRe; /***/ }), -/* 730 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83532,7 +83457,7 @@ module.exports.makeRe = makeRe; -var isDescriptor = __webpack_require__(731); +var isDescriptor = __webpack_require__(730); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -83557,7 +83482,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 731 */ +/* 730 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83570,9 +83495,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(732); -var isAccessor = __webpack_require__(733); -var isData = __webpack_require__(736); +var typeOf = __webpack_require__(731); +var isAccessor = __webpack_require__(732); +var isData = __webpack_require__(735); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -83586,7 +83511,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 732 */ +/* 731 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -83739,7 +83664,7 @@ function isBuffer(val) { /***/ }), -/* 733 */ +/* 732 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83752,7 +83677,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(734); +var typeOf = __webpack_require__(733); // accessor descriptor properties var accessor = { @@ -83815,10 +83740,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 734 */ +/* 733 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -83937,7 +83862,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 735 */ +/* 734 */ /***/ (function(module, exports) { /*! @@ -83964,7 +83889,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 736 */ +/* 735 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83977,7 +83902,7 @@ function isSlowBuffer (obj) { -var typeOf = __webpack_require__(737); +var typeOf = __webpack_require__(736); // data descriptor properties var data = { @@ -84026,10 +83951,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 737 */ +/* 736 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -84148,13 +84073,13 @@ module.exports = function kindOf(val) { /***/ }), -/* 738 */ +/* 737 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(739); +var isObject = __webpack_require__(738); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -84188,7 +84113,7 @@ function hasOwn(obj, key) { /***/ }), -/* 739 */ +/* 738 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84208,13 +84133,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 740 */ +/* 739 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(738); +var extend = __webpack_require__(737); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -84281,7 +84206,7 @@ module.exports = toRegex; /***/ }), -/* 741 */ +/* 740 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84331,13 +84256,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 742 */ +/* 741 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(743); +var utils = __webpack_require__(742); module.exports = function(braces, options) { braces.compiler @@ -84620,25 +84545,25 @@ function hasQueue(node) { /***/ }), -/* 743 */ +/* 742 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(744); +var splitString = __webpack_require__(743); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(738); -utils.flatten = __webpack_require__(750); -utils.isObject = __webpack_require__(748); -utils.fillRange = __webpack_require__(751); -utils.repeat = __webpack_require__(756); -utils.unique = __webpack_require__(741); +utils.extend = __webpack_require__(737); +utils.flatten = __webpack_require__(749); +utils.isObject = __webpack_require__(747); +utils.fillRange = __webpack_require__(750); +utils.repeat = __webpack_require__(755); +utils.unique = __webpack_require__(740); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -84970,7 +84895,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 744 */ +/* 743 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84983,7 +84908,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(745); +var extend = __webpack_require__(744); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -85148,14 +85073,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 745 */ +/* 744 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(746); -var assignSymbols = __webpack_require__(749); +var isExtendable = __webpack_require__(745); +var assignSymbols = __webpack_require__(748); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -85215,7 +85140,7 @@ function isEnum(obj, key) { /***/ }), -/* 746 */ +/* 745 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85228,7 +85153,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -85236,7 +85161,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 747 */ +/* 746 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85249,7 +85174,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(748); +var isObject = __webpack_require__(747); function isObjectObject(o) { return isObject(o) === true @@ -85280,7 +85205,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 748 */ +/* 747 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85299,7 +85224,7 @@ module.exports = function isObject(val) { /***/ }), -/* 749 */ +/* 748 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85346,7 +85271,7 @@ module.exports = function(receiver, objects) { /***/ }), -/* 750 */ +/* 749 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85375,7 +85300,7 @@ function flat(arr, res) { /***/ }), -/* 751 */ +/* 750 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85389,10 +85314,10 @@ function flat(arr, res) { var util = __webpack_require__(29); -var isNumber = __webpack_require__(752); -var extend = __webpack_require__(738); -var repeat = __webpack_require__(754); -var toRegex = __webpack_require__(755); +var isNumber = __webpack_require__(751); +var extend = __webpack_require__(737); +var repeat = __webpack_require__(753); +var toRegex = __webpack_require__(754); /** * Return a range of numbers or letters. @@ -85590,7 +85515,7 @@ module.exports = fillRange; /***/ }), -/* 752 */ +/* 751 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85603,7 +85528,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(753); +var typeOf = __webpack_require__(752); module.exports = function isNumber(num) { var type = typeOf(num); @@ -85619,10 +85544,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 753 */ +/* 752 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -85741,7 +85666,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 754 */ +/* 753 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85818,7 +85743,7 @@ function repeat(str, num) { /***/ }), -/* 755 */ +/* 754 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85831,8 +85756,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(754); -var isNumber = __webpack_require__(752); +var repeat = __webpack_require__(753); +var isNumber = __webpack_require__(751); var cache = {}; function toRegexRange(min, max, options) { @@ -86119,7 +86044,7 @@ module.exports = toRegexRange; /***/ }), -/* 756 */ +/* 755 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86144,14 +86069,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 757 */ +/* 756 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(758); -var utils = __webpack_require__(743); +var Node = __webpack_require__(757); +var utils = __webpack_require__(742); /** * Braces parsers @@ -86511,15 +86436,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 758 */ +/* 757 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(748); -var define = __webpack_require__(759); -var utils = __webpack_require__(766); +var isObject = __webpack_require__(747); +var define = __webpack_require__(758); +var utils = __webpack_require__(765); var ownNames; /** @@ -87010,7 +86935,7 @@ exports = module.exports = Node; /***/ }), -/* 759 */ +/* 758 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87023,7 +86948,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(760); +var isDescriptor = __webpack_require__(759); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -87048,7 +86973,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 760 */ +/* 759 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87061,9 +86986,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(761); -var isAccessor = __webpack_require__(762); -var isData = __webpack_require__(764); +var typeOf = __webpack_require__(760); +var isAccessor = __webpack_require__(761); +var isData = __webpack_require__(763); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -87077,7 +87002,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 761 */ +/* 760 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -87212,7 +87137,7 @@ function isBuffer(val) { /***/ }), -/* 762 */ +/* 761 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87225,7 +87150,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(763); +var typeOf = __webpack_require__(762); // accessor descriptor properties var accessor = { @@ -87288,7 +87213,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 763 */ +/* 762 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -87423,7 +87348,7 @@ function isBuffer(val) { /***/ }), -/* 764 */ +/* 763 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87436,7 +87361,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(765); +var typeOf = __webpack_require__(764); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -87479,7 +87404,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 765 */ +/* 764 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -87614,13 +87539,13 @@ function isBuffer(val) { /***/ }), -/* 766 */ +/* 765 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(753); +var typeOf = __webpack_require__(752); var utils = module.exports; /** @@ -88640,17 +88565,17 @@ function assert(val, message) { /***/ }), -/* 767 */ +/* 766 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(738); -var Snapdragon = __webpack_require__(768); -var compilers = __webpack_require__(742); -var parsers = __webpack_require__(757); -var utils = __webpack_require__(743); +var extend = __webpack_require__(737); +var Snapdragon = __webpack_require__(767); +var compilers = __webpack_require__(741); +var parsers = __webpack_require__(756); +var utils = __webpack_require__(742); /** * Customize Snapdragon parser and renderer @@ -88751,17 +88676,17 @@ module.exports = Braces; /***/ }), -/* 768 */ +/* 767 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(769); -var define = __webpack_require__(730); -var Compiler = __webpack_require__(798); -var Parser = __webpack_require__(827); -var utils = __webpack_require__(807); +var Base = __webpack_require__(768); +var define = __webpack_require__(729); +var Compiler = __webpack_require__(797); +var Parser = __webpack_require__(826); +var utils = __webpack_require__(806); var regexCache = {}; var cache = {}; @@ -88932,20 +88857,20 @@ module.exports.Parser = Parser; /***/ }), -/* 769 */ +/* 768 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var define = __webpack_require__(770); -var CacheBase = __webpack_require__(771); -var Emitter = __webpack_require__(772); -var isObject = __webpack_require__(748); -var merge = __webpack_require__(789); -var pascal = __webpack_require__(792); -var cu = __webpack_require__(793); +var define = __webpack_require__(769); +var CacheBase = __webpack_require__(770); +var Emitter = __webpack_require__(771); +var isObject = __webpack_require__(747); +var merge = __webpack_require__(788); +var pascal = __webpack_require__(791); +var cu = __webpack_require__(792); /** * Optionally define a custom `cache` namespace to use. @@ -89374,7 +89299,7 @@ module.exports.namespace = namespace; /***/ }), -/* 770 */ +/* 769 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89387,7 +89312,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(760); +var isDescriptor = __webpack_require__(759); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -89412,21 +89337,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 771 */ +/* 770 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(748); -var Emitter = __webpack_require__(772); -var visit = __webpack_require__(773); -var toPath = __webpack_require__(776); -var union = __webpack_require__(777); -var del = __webpack_require__(781); -var get = __webpack_require__(779); -var has = __webpack_require__(786); -var set = __webpack_require__(780); +var isObject = __webpack_require__(747); +var Emitter = __webpack_require__(771); +var visit = __webpack_require__(772); +var toPath = __webpack_require__(775); +var union = __webpack_require__(776); +var del = __webpack_require__(780); +var get = __webpack_require__(778); +var has = __webpack_require__(785); +var set = __webpack_require__(779); /** * Create a `Cache` constructor that when instantiated will @@ -89680,7 +89605,7 @@ module.exports.namespace = namespace; /***/ }), -/* 772 */ +/* 771 */ /***/ (function(module, exports, __webpack_require__) { @@ -89849,7 +89774,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 773 */ +/* 772 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89862,8 +89787,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(774); -var mapVisit = __webpack_require__(775); +var visit = __webpack_require__(773); +var mapVisit = __webpack_require__(774); module.exports = function(collection, method, val) { var result; @@ -89886,7 +89811,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 774 */ +/* 773 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89899,7 +89824,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(748); +var isObject = __webpack_require__(747); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -89926,14 +89851,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 775 */ +/* 774 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(774); +var visit = __webpack_require__(773); /** * Map `visit` over an array of objects. @@ -89970,7 +89895,7 @@ function isObject(val) { /***/ }), -/* 776 */ +/* 775 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89983,7 +89908,7 @@ function isObject(val) { -var typeOf = __webpack_require__(753); +var typeOf = __webpack_require__(752); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -90010,16 +89935,16 @@ function filter(arr) { /***/ }), -/* 777 */ +/* 776 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(739); -var union = __webpack_require__(778); -var get = __webpack_require__(779); -var set = __webpack_require__(780); +var isObject = __webpack_require__(738); +var union = __webpack_require__(777); +var get = __webpack_require__(778); +var set = __webpack_require__(779); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -90047,7 +89972,7 @@ function arrayify(val) { /***/ }), -/* 778 */ +/* 777 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90083,7 +90008,7 @@ module.exports = function union(init) { /***/ }), -/* 779 */ +/* 778 */ /***/ (function(module, exports) { /*! @@ -90139,7 +90064,7 @@ function toString(val) { /***/ }), -/* 780 */ +/* 779 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90152,10 +90077,10 @@ function toString(val) { -var split = __webpack_require__(744); -var extend = __webpack_require__(738); -var isPlainObject = __webpack_require__(747); -var isObject = __webpack_require__(739); +var split = __webpack_require__(743); +var extend = __webpack_require__(737); +var isPlainObject = __webpack_require__(746); +var isObject = __webpack_require__(738); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -90201,7 +90126,7 @@ function isValidKey(key) { /***/ }), -/* 781 */ +/* 780 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90214,8 +90139,8 @@ function isValidKey(key) { -var isObject = __webpack_require__(748); -var has = __webpack_require__(782); +var isObject = __webpack_require__(747); +var has = __webpack_require__(781); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -90240,7 +90165,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 782 */ +/* 781 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90253,9 +90178,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(783); -var hasValues = __webpack_require__(785); -var get = __webpack_require__(779); +var isObject = __webpack_require__(782); +var hasValues = __webpack_require__(784); +var get = __webpack_require__(778); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -90266,7 +90191,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 783 */ +/* 782 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90279,7 +90204,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(784); +var isArray = __webpack_require__(783); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -90287,7 +90212,7 @@ module.exports = function isObject(val) { /***/ }), -/* 784 */ +/* 783 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -90298,7 +90223,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 785 */ +/* 784 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90341,7 +90266,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 786 */ +/* 785 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90354,9 +90279,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(748); -var hasValues = __webpack_require__(787); -var get = __webpack_require__(779); +var isObject = __webpack_require__(747); +var hasValues = __webpack_require__(786); +var get = __webpack_require__(778); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -90364,7 +90289,7 @@ module.exports = function(val, prop) { /***/ }), -/* 787 */ +/* 786 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90377,8 +90302,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(788); -var isNumber = __webpack_require__(752); +var typeOf = __webpack_require__(787); +var isNumber = __webpack_require__(751); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -90431,10 +90356,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 788 */ +/* 787 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(735); +var isBuffer = __webpack_require__(734); var toString = Object.prototype.toString; /** @@ -90556,14 +90481,14 @@ module.exports = function kindOf(val) { /***/ }), -/* 789 */ +/* 788 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(790); -var forIn = __webpack_require__(791); +var isExtendable = __webpack_require__(789); +var forIn = __webpack_require__(790); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -90627,7 +90552,7 @@ module.exports = mixinDeep; /***/ }), -/* 790 */ +/* 789 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90640,7 +90565,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -90648,7 +90573,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 791 */ +/* 790 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90671,7 +90596,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 792 */ +/* 791 */ /***/ (function(module, exports) { /*! @@ -90698,14 +90623,14 @@ module.exports = pascalcase; /***/ }), -/* 793 */ +/* 792 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(794); +var utils = __webpack_require__(793); /** * Expose class utils @@ -91070,7 +90995,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 794 */ +/* 793 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91084,10 +91009,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(778); -utils.define = __webpack_require__(730); -utils.isObj = __webpack_require__(748); -utils.staticExtend = __webpack_require__(795); +utils.union = __webpack_require__(777); +utils.define = __webpack_require__(729); +utils.isObj = __webpack_require__(747); +utils.staticExtend = __webpack_require__(794); /** @@ -91098,7 +91023,7 @@ module.exports = utils; /***/ }), -/* 795 */ +/* 794 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91111,8 +91036,8 @@ module.exports = utils; -var copy = __webpack_require__(796); -var define = __webpack_require__(730); +var copy = __webpack_require__(795); +var define = __webpack_require__(729); var util = __webpack_require__(29); /** @@ -91195,15 +91120,15 @@ module.exports = extend; /***/ }), -/* 796 */ +/* 795 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(753); -var copyDescriptor = __webpack_require__(797); -var define = __webpack_require__(730); +var typeOf = __webpack_require__(752); +var copyDescriptor = __webpack_require__(796); +var define = __webpack_require__(729); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -91376,7 +91301,7 @@ module.exports.has = has; /***/ }), -/* 797 */ +/* 796 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91464,16 +91389,16 @@ function isObject(val) { /***/ }), -/* 798 */ +/* 797 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(799); -var define = __webpack_require__(730); -var debug = __webpack_require__(801)('snapdragon:compiler'); -var utils = __webpack_require__(807); +var use = __webpack_require__(798); +var define = __webpack_require__(729); +var debug = __webpack_require__(800)('snapdragon:compiler'); +var utils = __webpack_require__(806); /** * Create a new `Compiler` with the given `options`. @@ -91627,7 +91552,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(826); + var sourcemaps = __webpack_require__(825); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -91648,7 +91573,7 @@ module.exports = Compiler; /***/ }), -/* 799 */ +/* 798 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91661,7 +91586,7 @@ module.exports = Compiler; -var utils = __webpack_require__(800); +var utils = __webpack_require__(799); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -91776,7 +91701,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 800 */ +/* 799 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91790,8 +91715,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(730); -utils.isObject = __webpack_require__(748); +utils.define = __webpack_require__(729); +utils.isObject = __webpack_require__(747); utils.isString = function(val) { @@ -91806,7 +91731,7 @@ module.exports = utils; /***/ }), -/* 801 */ +/* 800 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -91815,14 +91740,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(802); + module.exports = __webpack_require__(801); } else { - module.exports = __webpack_require__(805); + module.exports = __webpack_require__(804); } /***/ }), -/* 802 */ +/* 801 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -91831,7 +91756,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(803); +exports = module.exports = __webpack_require__(802); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -92013,7 +91938,7 @@ function localstorage() { /***/ }), -/* 803 */ +/* 802 */ /***/ (function(module, exports, __webpack_require__) { @@ -92029,7 +91954,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(804); +exports.humanize = __webpack_require__(803); /** * The currently active debug mode names, and names to skip. @@ -92221,7 +92146,7 @@ function coerce(val) { /***/ }), -/* 804 */ +/* 803 */ /***/ (function(module, exports) { /** @@ -92379,7 +92304,7 @@ function plural(ms, n, name) { /***/ }), -/* 805 */ +/* 804 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -92395,7 +92320,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(803); +exports = module.exports = __webpack_require__(802); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -92574,7 +92499,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(806); + var net = __webpack_require__(805); stream = new net.Socket({ fd: fd, readable: false, @@ -92633,13 +92558,13 @@ exports.enable(load()); /***/ }), -/* 806 */ +/* 805 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 807 */ +/* 806 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92649,9 +92574,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(738); -exports.SourceMap = __webpack_require__(808); -exports.sourceMapResolve = __webpack_require__(819); +exports.extend = __webpack_require__(737); +exports.SourceMap = __webpack_require__(807); +exports.sourceMapResolve = __webpack_require__(818); /** * Convert backslash in the given string to forward slashes @@ -92694,7 +92619,7 @@ exports.last = function(arr, n) { /***/ }), -/* 808 */ +/* 807 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -92702,13 +92627,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(815).SourceMapConsumer; -exports.SourceNode = __webpack_require__(818).SourceNode; +exports.SourceMapGenerator = __webpack_require__(808).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(814).SourceMapConsumer; +exports.SourceNode = __webpack_require__(817).SourceNode; /***/ }), -/* 809 */ +/* 808 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -92718,10 +92643,10 @@ exports.SourceNode = __webpack_require__(818).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(810); -var util = __webpack_require__(812); -var ArraySet = __webpack_require__(813).ArraySet; -var MappingList = __webpack_require__(814).MappingList; +var base64VLQ = __webpack_require__(809); +var util = __webpack_require__(811); +var ArraySet = __webpack_require__(812).ArraySet; +var MappingList = __webpack_require__(813).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -93130,7 +93055,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 810 */ +/* 809 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93170,7 +93095,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(811); +var base64 = __webpack_require__(810); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -93276,7 +93201,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 811 */ +/* 810 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93349,7 +93274,7 @@ exports.decode = function (charCode) { /***/ }), -/* 812 */ +/* 811 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93772,7 +93697,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 813 */ +/* 812 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93782,7 +93707,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(812); +var util = __webpack_require__(811); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -93899,7 +93824,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 814 */ +/* 813 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93909,7 +93834,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(812); +var util = __webpack_require__(811); /** * Determine whether mappingB is after mappingA with respect to generated @@ -93984,7 +93909,7 @@ exports.MappingList = MappingList; /***/ }), -/* 815 */ +/* 814 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -93994,11 +93919,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(812); -var binarySearch = __webpack_require__(816); -var ArraySet = __webpack_require__(813).ArraySet; -var base64VLQ = __webpack_require__(810); -var quickSort = __webpack_require__(817).quickSort; +var util = __webpack_require__(811); +var binarySearch = __webpack_require__(815); +var ArraySet = __webpack_require__(812).ArraySet; +var base64VLQ = __webpack_require__(809); +var quickSort = __webpack_require__(816).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -95072,7 +94997,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 816 */ +/* 815 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95189,7 +95114,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 817 */ +/* 816 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95309,7 +95234,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 818 */ +/* 817 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95319,8 +95244,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; -var util = __webpack_require__(812); +var SourceMapGenerator = __webpack_require__(808).SourceMapGenerator; +var util = __webpack_require__(811); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -95728,17 +95653,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 819 */ +/* 818 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(820) -var resolveUrl = __webpack_require__(821) -var decodeUriComponent = __webpack_require__(822) -var urix = __webpack_require__(824) -var atob = __webpack_require__(825) +var sourceMappingURL = __webpack_require__(819) +var resolveUrl = __webpack_require__(820) +var decodeUriComponent = __webpack_require__(821) +var urix = __webpack_require__(823) +var atob = __webpack_require__(824) @@ -96036,7 +95961,7 @@ module.exports = { /***/ }), -/* 820 */ +/* 819 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -96099,7 +96024,7 @@ void (function(root, factory) { /***/ }), -/* 821 */ +/* 820 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -96117,13 +96042,13 @@ module.exports = resolveUrl /***/ }), -/* 822 */ +/* 821 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(823) +var decodeUriComponent = __webpack_require__(822) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -96134,7 +96059,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 823 */ +/* 822 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -96235,7 +96160,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 824 */ +/* 823 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -96258,7 +96183,7 @@ module.exports = urix /***/ }), -/* 825 */ +/* 824 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -96272,7 +96197,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 826 */ +/* 825 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -96280,8 +96205,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(730); -var utils = __webpack_require__(807); +var define = __webpack_require__(729); +var utils = __webpack_require__(806); /** * Expose `mixin()`. @@ -96424,19 +96349,19 @@ exports.comment = function(node) { /***/ }), -/* 827 */ +/* 826 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(799); +var use = __webpack_require__(798); var util = __webpack_require__(29); -var Cache = __webpack_require__(828); -var define = __webpack_require__(730); -var debug = __webpack_require__(801)('snapdragon:parser'); -var Position = __webpack_require__(829); -var utils = __webpack_require__(807); +var Cache = __webpack_require__(827); +var define = __webpack_require__(729); +var debug = __webpack_require__(800)('snapdragon:parser'); +var Position = __webpack_require__(828); +var utils = __webpack_require__(806); /** * Create a new `Parser` with the given `input` and `options`. @@ -96964,7 +96889,7 @@ module.exports = Parser; /***/ }), -/* 828 */ +/* 827 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97071,13 +96996,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 829 */ +/* 828 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(730); +var define = __webpack_require__(729); /** * Store position for a node @@ -97092,16 +97017,16 @@ module.exports = function Position(start, parser) { /***/ }), -/* 830 */ +/* 829 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(831); -var define = __webpack_require__(837); -var extend = __webpack_require__(838); -var not = __webpack_require__(840); +var safe = __webpack_require__(830); +var define = __webpack_require__(836); +var extend = __webpack_require__(837); +var not = __webpack_require__(839); var MAX_LENGTH = 1024 * 64; /** @@ -97254,10 +97179,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 831 */ +/* 830 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(832); +var parse = __webpack_require__(831); var types = parse.types; module.exports = function (re, opts) { @@ -97303,13 +97228,13 @@ function isRegExp (x) { /***/ }), -/* 832 */ +/* 831 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(833); -var types = __webpack_require__(834); -var sets = __webpack_require__(835); -var positions = __webpack_require__(836); +var util = __webpack_require__(832); +var types = __webpack_require__(833); +var sets = __webpack_require__(834); +var positions = __webpack_require__(835); module.exports = function(regexpStr) { @@ -97591,11 +97516,11 @@ module.exports.types = types; /***/ }), -/* 833 */ +/* 832 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(834); -var sets = __webpack_require__(835); +var types = __webpack_require__(833); +var sets = __webpack_require__(834); // All of these are private and only used by randexp. @@ -97708,7 +97633,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 834 */ +/* 833 */ /***/ (function(module, exports) { module.exports = { @@ -97724,10 +97649,10 @@ module.exports = { /***/ }), -/* 835 */ +/* 834 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(834); +var types = __webpack_require__(833); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -97812,10 +97737,10 @@ exports.anyChar = function() { /***/ }), -/* 836 */ +/* 835 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(834); +var types = __webpack_require__(833); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -97835,7 +97760,7 @@ exports.end = function() { /***/ }), -/* 837 */ +/* 836 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97848,8 +97773,8 @@ exports.end = function() { -var isobject = __webpack_require__(748); -var isDescriptor = __webpack_require__(760); +var isobject = __webpack_require__(747); +var isDescriptor = __webpack_require__(759); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -97880,14 +97805,14 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 838 */ +/* 837 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(839); -var assignSymbols = __webpack_require__(749); +var isExtendable = __webpack_require__(838); +var assignSymbols = __webpack_require__(748); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -97947,7 +97872,7 @@ function isEnum(obj, key) { /***/ }), -/* 839 */ +/* 838 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97960,7 +97885,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -97968,14 +97893,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 840 */ +/* 839 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(838); -var safe = __webpack_require__(831); +var extend = __webpack_require__(837); +var safe = __webpack_require__(830); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -98047,14 +97972,14 @@ module.exports = toRegex; /***/ }), -/* 841 */ +/* 840 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(842); -var extglob = __webpack_require__(857); +var nanomatch = __webpack_require__(841); +var extglob = __webpack_require__(856); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -98131,7 +98056,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 842 */ +/* 841 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -98142,17 +98067,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(29); -var toRegex = __webpack_require__(729); -var extend = __webpack_require__(843); +var toRegex = __webpack_require__(728); +var extend = __webpack_require__(842); /** * Local dependencies */ -var compilers = __webpack_require__(845); -var parsers = __webpack_require__(846); -var cache = __webpack_require__(849); -var utils = __webpack_require__(851); +var compilers = __webpack_require__(844); +var parsers = __webpack_require__(845); +var cache = __webpack_require__(848); +var utils = __webpack_require__(850); var MAX_LENGTH = 1024 * 64; /** @@ -98976,14 +98901,14 @@ module.exports = nanomatch; /***/ }), -/* 843 */ +/* 842 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(844); -var assignSymbols = __webpack_require__(749); +var isExtendable = __webpack_require__(843); +var assignSymbols = __webpack_require__(748); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -99043,7 +98968,7 @@ function isEnum(obj, key) { /***/ }), -/* 844 */ +/* 843 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99056,7 +98981,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(747); +var isPlainObject = __webpack_require__(746); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -99064,7 +98989,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 845 */ +/* 844 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99410,15 +99335,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 846 */ +/* 845 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(740); -var toRegex = __webpack_require__(729); -var isOdd = __webpack_require__(847); +var regexNot = __webpack_require__(739); +var toRegex = __webpack_require__(728); +var isOdd = __webpack_require__(846); /** * Characters to use in negation regex (we want to "not" match @@ -99804,7 +99729,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 847 */ +/* 846 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99817,7 +99742,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(848); +var isNumber = __webpack_require__(847); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -99831,7 +99756,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 848 */ +/* 847 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99859,14 +99784,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 849 */ +/* 848 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(850))(); +module.exports = new (__webpack_require__(849))(); /***/ }), -/* 850 */ +/* 849 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99879,7 +99804,7 @@ module.exports = new (__webpack_require__(850))(); -var MapCache = __webpack_require__(828); +var MapCache = __webpack_require__(827); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -100001,7 +99926,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 851 */ +/* 850 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100014,14 +99939,14 @@ var path = __webpack_require__(16); * Module dependencies */ -var isWindows = __webpack_require__(852)(); -var Snapdragon = __webpack_require__(768); -utils.define = __webpack_require__(853); -utils.diff = __webpack_require__(854); -utils.extend = __webpack_require__(843); -utils.pick = __webpack_require__(855); -utils.typeOf = __webpack_require__(856); -utils.unique = __webpack_require__(741); +var isWindows = __webpack_require__(851)(); +var Snapdragon = __webpack_require__(767); +utils.define = __webpack_require__(852); +utils.diff = __webpack_require__(853); +utils.extend = __webpack_require__(842); +utils.pick = __webpack_require__(854); +utils.typeOf = __webpack_require__(855); +utils.unique = __webpack_require__(740); /** * Returns true if the given value is effectively an empty string @@ -100387,7 +100312,7 @@ utils.unixify = function(options) { /***/ }), -/* 852 */ +/* 851 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -100415,7 +100340,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 853 */ +/* 852 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100428,8 +100353,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(748); -var isDescriptor = __webpack_require__(760); +var isobject = __webpack_require__(747); +var isDescriptor = __webpack_require__(759); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -100460,7 +100385,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 854 */ +/* 853 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100514,7 +100439,7 @@ function diffArray(one, two) { /***/ }), -/* 855 */ +/* 854 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100527,7 +100452,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(748); +var isObject = __webpack_require__(747); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -100556,7 +100481,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 856 */ +/* 855 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -100691,7 +100616,7 @@ function isBuffer(val) { /***/ }), -/* 857 */ +/* 856 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100701,18 +100626,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(738); -var unique = __webpack_require__(741); -var toRegex = __webpack_require__(729); +var extend = __webpack_require__(737); +var unique = __webpack_require__(740); +var toRegex = __webpack_require__(728); /** * Local dependencies */ -var compilers = __webpack_require__(858); -var parsers = __webpack_require__(864); -var Extglob = __webpack_require__(867); -var utils = __webpack_require__(866); +var compilers = __webpack_require__(857); +var parsers = __webpack_require__(863); +var Extglob = __webpack_require__(866); +var utils = __webpack_require__(865); var MAX_LENGTH = 1024 * 64; /** @@ -101029,13 +100954,13 @@ module.exports = extglob; /***/ }), -/* 858 */ +/* 857 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(859); +var brackets = __webpack_require__(858); /** * Extglob compilers @@ -101205,7 +101130,7 @@ module.exports = function(extglob) { /***/ }), -/* 859 */ +/* 858 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101215,17 +101140,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(860); -var parsers = __webpack_require__(862); +var compilers = __webpack_require__(859); +var parsers = __webpack_require__(861); /** * Module dependencies */ -var debug = __webpack_require__(801)('expand-brackets'); -var extend = __webpack_require__(738); -var Snapdragon = __webpack_require__(768); -var toRegex = __webpack_require__(729); +var debug = __webpack_require__(800)('expand-brackets'); +var extend = __webpack_require__(737); +var Snapdragon = __webpack_require__(767); +var toRegex = __webpack_require__(728); /** * Parses the given POSIX character class `pattern` and returns a @@ -101423,13 +101348,13 @@ module.exports = brackets; /***/ }), -/* 860 */ +/* 859 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(861); +var posix = __webpack_require__(860); module.exports = function(brackets) { brackets.compiler @@ -101517,7 +101442,7 @@ module.exports = function(brackets) { /***/ }), -/* 861 */ +/* 860 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101546,14 +101471,14 @@ module.exports = { /***/ }), -/* 862 */ +/* 861 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(863); -var define = __webpack_require__(730); +var utils = __webpack_require__(862); +var define = __webpack_require__(729); /** * Text regex @@ -101772,14 +101697,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 863 */ +/* 862 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(729); -var regexNot = __webpack_require__(740); +var toRegex = __webpack_require__(728); +var regexNot = __webpack_require__(739); var cached; /** @@ -101813,15 +101738,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 864 */ +/* 863 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(859); -var define = __webpack_require__(865); -var utils = __webpack_require__(866); +var brackets = __webpack_require__(858); +var define = __webpack_require__(864); +var utils = __webpack_require__(865); /** * Characters to use in text regex (we want to "not" match @@ -101976,7 +101901,7 @@ module.exports = parsers; /***/ }), -/* 865 */ +/* 864 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101989,7 +101914,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(760); +var isDescriptor = __webpack_require__(759); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -102014,14 +101939,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 866 */ +/* 865 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(740); -var Cache = __webpack_require__(850); +var regex = __webpack_require__(739); +var Cache = __webpack_require__(849); /** * Utils @@ -102090,7 +102015,7 @@ utils.createRegex = function(str) { /***/ }), -/* 867 */ +/* 866 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102100,16 +102025,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(768); -var define = __webpack_require__(865); -var extend = __webpack_require__(738); +var Snapdragon = __webpack_require__(767); +var define = __webpack_require__(864); +var extend = __webpack_require__(737); /** * Local dependencies */ -var compilers = __webpack_require__(858); -var parsers = __webpack_require__(864); +var compilers = __webpack_require__(857); +var parsers = __webpack_require__(863); /** * Customize Snapdragon parser and renderer @@ -102175,16 +102100,16 @@ module.exports = Extglob; /***/ }), -/* 868 */ +/* 867 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(857); -var nanomatch = __webpack_require__(842); -var regexNot = __webpack_require__(740); -var toRegex = __webpack_require__(830); +var extglob = __webpack_require__(856); +var nanomatch = __webpack_require__(841); +var regexNot = __webpack_require__(739); +var toRegex = __webpack_require__(829); var not; /** @@ -102265,14 +102190,14 @@ function textRegex(pattern) { /***/ }), -/* 869 */ +/* 868 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(850))(); +module.exports = new (__webpack_require__(849))(); /***/ }), -/* 870 */ +/* 869 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102285,13 +102210,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(768); -utils.define = __webpack_require__(837); -utils.diff = __webpack_require__(854); -utils.extend = __webpack_require__(838); -utils.pick = __webpack_require__(855); -utils.typeOf = __webpack_require__(871); -utils.unique = __webpack_require__(741); +var Snapdragon = __webpack_require__(767); +utils.define = __webpack_require__(836); +utils.diff = __webpack_require__(853); +utils.extend = __webpack_require__(837); +utils.pick = __webpack_require__(854); +utils.typeOf = __webpack_require__(870); +utils.unique = __webpack_require__(740); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -102588,7 +102513,7 @@ utils.unixify = function(options) { /***/ }), -/* 871 */ +/* 870 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -102723,7 +102648,7 @@ function isBuffer(val) { /***/ }), -/* 872 */ +/* 871 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102742,9 +102667,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(873); -var reader_1 = __webpack_require__(886); -var fs_stream_1 = __webpack_require__(890); +var readdir = __webpack_require__(872); +var reader_1 = __webpack_require__(885); +var fs_stream_1 = __webpack_require__(889); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -102805,15 +102730,15 @@ exports.default = ReaderAsync; /***/ }), -/* 873 */ +/* 872 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(874); -const readdirAsync = __webpack_require__(882); -const readdirStream = __webpack_require__(885); +const readdirSync = __webpack_require__(873); +const readdirAsync = __webpack_require__(881); +const readdirStream = __webpack_require__(884); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -102897,7 +102822,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 874 */ +/* 873 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102905,11 +102830,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(875); +const DirectoryReader = __webpack_require__(874); let syncFacade = { - fs: __webpack_require__(880), - forEach: __webpack_require__(881), + fs: __webpack_require__(879), + forEach: __webpack_require__(880), sync: true }; @@ -102938,7 +102863,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 875 */ +/* 874 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102947,9 +102872,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(27).Readable; const EventEmitter = __webpack_require__(379).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(876); -const stat = __webpack_require__(878); -const call = __webpack_require__(879); +const normalizeOptions = __webpack_require__(875); +const stat = __webpack_require__(877); +const call = __webpack_require__(878); /** * Asynchronously reads the contents of a directory and streams the results @@ -103325,14 +103250,14 @@ module.exports = DirectoryReader; /***/ }), -/* 876 */ +/* 875 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(877); +const globToRegExp = __webpack_require__(876); module.exports = normalizeOptions; @@ -103509,7 +103434,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 877 */ +/* 876 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -103646,13 +103571,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 878 */ +/* 877 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(879); +const call = __webpack_require__(878); module.exports = stat; @@ -103727,7 +103652,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 879 */ +/* 878 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103788,14 +103713,14 @@ function callOnce (fn) { /***/ }), -/* 880 */ +/* 879 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(879); +const call = __webpack_require__(878); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -103859,7 +103784,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 881 */ +/* 880 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103888,7 +103813,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 882 */ +/* 881 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103896,12 +103821,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(883); -const DirectoryReader = __webpack_require__(875); +const maybe = __webpack_require__(882); +const DirectoryReader = __webpack_require__(874); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(884), + forEach: __webpack_require__(883), async: true }; @@ -103943,7 +103868,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 883 */ +/* 882 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103970,7 +103895,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 884 */ +/* 883 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104006,7 +103931,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 885 */ +/* 884 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104014,11 +103939,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(875); +const DirectoryReader = __webpack_require__(874); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(884), + forEach: __webpack_require__(883), async: true }; @@ -104038,16 +103963,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 886 */ +/* 885 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(887); -var entry_1 = __webpack_require__(889); -var pathUtil = __webpack_require__(888); +var deep_1 = __webpack_require__(886); +var entry_1 = __webpack_require__(888); +var pathUtil = __webpack_require__(887); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -104113,14 +104038,14 @@ exports.default = Reader; /***/ }), -/* 887 */ +/* 886 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(888); -var patternUtils = __webpack_require__(722); +var pathUtils = __webpack_require__(887); +var patternUtils = __webpack_require__(721); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -104203,7 +104128,7 @@ exports.default = DeepFilter; /***/ }), -/* 888 */ +/* 887 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104234,14 +104159,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 889 */ +/* 888 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(888); -var patternUtils = __webpack_require__(722); +var pathUtils = __webpack_require__(887); +var patternUtils = __webpack_require__(721); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -104326,7 +104251,7 @@ exports.default = EntryFilter; /***/ }), -/* 890 */ +/* 889 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104346,8 +104271,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var fsStat = __webpack_require__(891); -var fs_1 = __webpack_require__(895); +var fsStat = __webpack_require__(890); +var fs_1 = __webpack_require__(894); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -104397,14 +104322,14 @@ exports.default = FileSystemStream; /***/ }), -/* 891 */ +/* 890 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(892); -const statProvider = __webpack_require__(894); +const optionsManager = __webpack_require__(891); +const statProvider = __webpack_require__(893); /** * Asynchronous API. */ @@ -104435,13 +104360,13 @@ exports.statSync = statSync; /***/ }), -/* 892 */ +/* 891 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(893); +const fsAdapter = __webpack_require__(892); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -104454,7 +104379,7 @@ exports.prepare = prepare; /***/ }), -/* 893 */ +/* 892 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104477,7 +104402,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 894 */ +/* 893 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104529,7 +104454,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 895 */ +/* 894 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104560,7 +104485,7 @@ exports.default = FileSystem; /***/ }), -/* 896 */ +/* 895 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104580,9 +104505,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var readdir = __webpack_require__(873); -var reader_1 = __webpack_require__(886); -var fs_stream_1 = __webpack_require__(890); +var readdir = __webpack_require__(872); +var reader_1 = __webpack_require__(885); +var fs_stream_1 = __webpack_require__(889); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -104650,7 +104575,7 @@ exports.default = ReaderStream; /***/ }), -/* 897 */ +/* 896 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104669,9 +104594,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(873); -var reader_1 = __webpack_require__(886); -var fs_sync_1 = __webpack_require__(898); +var readdir = __webpack_require__(872); +var reader_1 = __webpack_require__(885); +var fs_sync_1 = __webpack_require__(897); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -104731,7 +104656,7 @@ exports.default = ReaderSync; /***/ }), -/* 898 */ +/* 897 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104750,8 +104675,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(891); -var fs_1 = __webpack_require__(895); +var fsStat = __webpack_require__(890); +var fs_1 = __webpack_require__(894); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -104797,7 +104722,7 @@ exports.default = FileSystemSync; /***/ }), -/* 899 */ +/* 898 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104813,13 +104738,13 @@ exports.flatten = flatten; /***/ }), -/* 900 */ +/* 899 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(589); +var merge2 = __webpack_require__(588); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -104834,13 +104759,13 @@ exports.merge = merge; /***/ }), -/* 901 */ +/* 900 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(902); +const pathType = __webpack_require__(901); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -104906,13 +104831,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 902 */ +/* 901 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(903); +const pify = __webpack_require__(902); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -104955,7 +104880,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 903 */ +/* 902 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105046,17 +104971,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 904 */ +/* 903 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(718); -const gitIgnore = __webpack_require__(905); -const pify = __webpack_require__(906); -const slash = __webpack_require__(907); +const fastGlob = __webpack_require__(717); +const gitIgnore = __webpack_require__(904); +const pify = __webpack_require__(905); +const slash = __webpack_require__(906); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -105154,7 +105079,7 @@ module.exports.sync = options => { /***/ }), -/* 905 */ +/* 904 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -105623,7 +105548,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 906 */ +/* 905 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105698,7 +105623,7 @@ module.exports = (input, options) => { /***/ }), -/* 907 */ +/* 906 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105716,17 +105641,17 @@ module.exports = input => { /***/ }), -/* 908 */ +/* 907 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const pEvent = __webpack_require__(909); -const CpFileError = __webpack_require__(912); -const fs = __webpack_require__(916); -const ProgressEmitter = __webpack_require__(919); +const pEvent = __webpack_require__(908); +const CpFileError = __webpack_require__(911); +const fs = __webpack_require__(915); +const ProgressEmitter = __webpack_require__(918); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -105840,12 +105765,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 909 */ +/* 908 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(910); +const pTimeout = __webpack_require__(909); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -106136,12 +106061,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 910 */ +/* 909 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(911); +const pFinally = __webpack_require__(910); class TimeoutError extends Error { constructor(message) { @@ -106187,7 +106112,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 911 */ +/* 910 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106209,12 +106134,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 912 */ +/* 911 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(913); +const NestedError = __webpack_require__(912); class CpFileError extends NestedError { constructor(message, nested) { @@ -106228,10 +106153,10 @@ module.exports = CpFileError; /***/ }), -/* 913 */ +/* 912 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(914); +var inherits = __webpack_require__(913); var NestedError = function (message, nested) { this.nested = nested; @@ -106282,7 +106207,7 @@ module.exports = NestedError; /***/ }), -/* 914 */ +/* 913 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -106290,12 +106215,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(915); + module.exports = __webpack_require__(914); } /***/ }), -/* 915 */ +/* 914 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -106324,16 +106249,16 @@ if (typeof Object.create === 'function') { /***/ }), -/* 916 */ +/* 915 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const fs = __webpack_require__(22); -const makeDir = __webpack_require__(917); -const pEvent = __webpack_require__(909); -const CpFileError = __webpack_require__(912); +const makeDir = __webpack_require__(916); +const pEvent = __webpack_require__(908); +const CpFileError = __webpack_require__(911); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -106430,7 +106355,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 917 */ +/* 916 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106438,7 +106363,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const {promisify} = __webpack_require__(29); -const semver = __webpack_require__(918); +const semver = __webpack_require__(917); const defaults = { mode: 0o777 & (~process.umask()), @@ -106587,7 +106512,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 918 */ +/* 917 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -108189,7 +108114,7 @@ function coerce (version, options) { /***/ }), -/* 919 */ +/* 918 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108230,7 +108155,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 920 */ +/* 919 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108276,12 +108201,12 @@ exports.default = module.exports; /***/ }), -/* 921 */ +/* 920 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(922); +const NestedError = __webpack_require__(921); class CpyError extends NestedError { constructor(message, nested) { @@ -108295,7 +108220,7 @@ module.exports = CpyError; /***/ }), -/* 922 */ +/* 921 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -108351,7 +108276,7 @@ module.exports = NestedError; /***/ }), -/* 923 */ +/* 922 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/yarn.lock b/yarn.lock index 20e33fdefc996..11abd95498c8d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -61,7 +61,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.0.0", "@babel/core@^7.0.1", "@babel/core@^7.1.0", "@babel/core@^7.4.3", "@babel/core@^7.9.0": +"@babel/core@^7.0.0", "@babel/core@^7.0.1", "@babel/core@^7.1.0", "@babel/core@^7.4.3", "@babel/core@^7.7.5", "@babel/core@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== @@ -83,7 +83,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.4.0", "@babel/generator@^7.5.5", "@babel/generator@^7.9.0": +"@babel/generator@^7.0.0", "@babel/generator@^7.5.5", "@babel/generator@^7.9.0": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.4.tgz#12441e90c3b3c4159cdecf312075bf1a8ce2dbce" integrity sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA== @@ -93,6 +93,16 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" + integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== + dependencies: + "@babel/types" "^7.9.5" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" @@ -183,6 +193,15 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" +"@babel/helper-function-name@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" + integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.9.5" + "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" @@ -284,6 +303,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== +"@babel/helper-validator-identifier@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" + integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== + "@babel/helper-wrap-function@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" @@ -312,7 +336,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.2.0", "@babel/parser@^7.4.3", "@babel/parser@^7.5.5", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0", "@babel/parser@^7.9.3": +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.2.0", "@babel/parser@^7.5.5", "@babel/parser@^7.7.5", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0", "@babel/parser@^7.9.3": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== @@ -1101,7 +1125,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.0.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": +"@babel/template@^7.0.0", "@babel/template@^7.4.4", "@babel/template@^7.7.4", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== @@ -1110,7 +1134,7 @@ "@babel/parser" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.5", "@babel/traverse@^7.5.5", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.4.5", "@babel/traverse@^7.5.5", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.0.tgz#d3882c2830e513f4fe4cec9fe76ea1cc78747892" integrity sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w== @@ -1125,6 +1149,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.7.4": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" + integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.9.5" + "@babel/helper-function-name" "^7.9.5" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.9.0" + "@babel/types" "^7.9.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.0.tgz#00b064c3df83ad32b2dbf5ff07312b15c7f1efb5" @@ -1134,6 +1173,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.9.5": + version "7.9.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" + integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" @@ -1542,6 +1590,21 @@ resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" + integrity sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + "@jest/console@^24.7.1": version "24.7.1" resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" @@ -6109,12 +6172,12 @@ append-buffer@^1.0.2: dependencies: buffer-equal "^1.0.0" -append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== dependencies: - default-require-extensions "^2.0.0" + default-require-extensions "^3.0.0" aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" @@ -6867,15 +6930,16 @@ babel-plugin-istanbul@^5.1.0: istanbul-lib-instrument "^3.0.0" test-exclude "^5.0.0" -babel-plugin-istanbul@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854" - integrity sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw== +babel-plugin-istanbul@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" + integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - find-up "^3.0.0" - istanbul-lib-instrument "^3.3.0" - test-exclude "^5.2.3" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^4.0.0" + test-exclude "^6.0.0" babel-plugin-jest-hoist@^24.9.0: version "24.9.0" @@ -8129,15 +8193,15 @@ cachedir@2.3.0: resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== -caching-transform@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70" - integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w== +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== dependencies: - hasha "^3.0.0" - make-dir "^2.0.0" - package-hash "^3.0.0" - write-file-atomic "^2.4.2" + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" call-me-maybe@^1.0.1: version "1.0.1" @@ -9564,7 +9628,7 @@ convert-source-map@^0.3.3: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA= -convert-source-map@^1.5.1, convert-source-map@^1.6.0: +convert-source-map@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== @@ -9768,17 +9832,6 @@ cosmiconfig@^5.2.0, cosmiconfig@^5.2.1: js-yaml "^3.13.1" parse-json "^4.0.0" -cp-file@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d" - integrity sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA== - dependencies: - graceful-fs "^4.1.2" - make-dir "^2.0.0" - nested-error-stacks "^2.0.0" - pify "^4.0.1" - safe-buffer "^5.0.1" - cp-file@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" @@ -9948,7 +10001,7 @@ cross-spawn@^3.0.0: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^4, cross-spawn@^4.0.2: +cross-spawn@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= @@ -10847,12 +10900,12 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" -default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== dependencies: - strip-bom "^3.0.0" + strip-bom "^4.0.0" default-resolution@^2.0.0: version "2.0.0" @@ -13842,13 +13895,13 @@ foreachasync@^3.0.0: resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6" integrity sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY= -foreground-child@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" - integrity sha1-T9ca0t/elnibmApcCilZN8svXOk= +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== dependencies: - cross-spawn "^4" - signal-exit "^3.0.0" + cross-spawn "^7.0.0" + signal-exit "^3.0.2" forever-agent@~0.6.1: version "0.6.1" @@ -13954,6 +14007,11 @@ from2@^2.1.0, from2@^2.1.1, from2@^2.3.0: inherits "^2.0.1" readable-stream "^2.0.0" +fromentries@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897" + integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ== + front-matter@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.1.2.tgz#f75983b9f2f413be658c93dfd7bd8ce4078f5cdb" @@ -15636,12 +15694,13 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.0" -hasha@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/hasha/-/hasha-3.0.0.tgz#52a32fab8569d41ca69a61ff1a214f8eb7c8bd39" - integrity sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk= +hasha@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.0.tgz#33094d1f69c40a4a6ac7be53d5fe3ff95a269e0c" + integrity sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw== dependencies: - is-stream "^1.0.1" + is-stream "^2.0.0" + type-fest "^0.8.0" hast-util-from-parse5@^5.0.0: version "5.0.0" @@ -15845,6 +15904,11 @@ html-entities@^1.2.0, html-entities@^1.2.1: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-loader@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-0.5.5.tgz#6356dbeb0c49756d8ebd5ca327f16ff06ab5faea" @@ -17320,7 +17384,7 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.0" -is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -17482,17 +17546,17 @@ istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba" integrity sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw== -istanbul-lib-coverage@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" - integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-hook@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" - integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== dependencies: - append-transform "^1.0.0" + append-transform "^2.0.0" istanbul-lib-instrument@^1.7.3: version "1.10.2" @@ -17520,18 +17584,31 @@ istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1: istanbul-lib-coverage "^2.0.3" semver "^5.5.0" -istanbul-lib-instrument@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" - integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== +istanbul-lib-instrument@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz#61f13ac2c96cfefb076fe7131156cc05907874e6" + integrity sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg== + dependencies: + "@babel/core" "^7.7.5" + "@babel/parser" "^7.7.5" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-processinfo@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" + integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== dependencies: - "@babel/generator" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - istanbul-lib-coverage "^2.0.5" - semver "^6.0.0" + archy "^1.0.0" + cross-spawn "^7.0.0" + istanbul-lib-coverage "^3.0.0-alpha.1" + make-dir "^3.0.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^3.3.3" istanbul-lib-report@^2.0.4: version "2.0.4" @@ -17542,14 +17619,14 @@ istanbul-lib-report@^2.0.4: make-dir "^1.3.0" supports-color "^6.0.0" -istanbul-lib-report@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" - integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - supports-color "^6.1.0" + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" istanbul-lib-source-maps@^3.0.1: version "3.0.2" @@ -17562,24 +17639,30 @@ istanbul-lib-source-maps@^3.0.1: rimraf "^2.6.2" source-map "^0.6.1" -istanbul-lib-source-maps@^3.0.6: - version "3.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" - integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== dependencies: debug "^4.1.1" - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - rimraf "^2.6.3" + istanbul-lib-coverage "^3.0.0" source-map "^0.6.1" -istanbul-reports@^2.2.4, istanbul-reports@^2.2.6: +istanbul-reports@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== dependencies: handlebars "^4.1.2" +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + istanbul@^0.4.0: version "0.4.5" resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" @@ -20121,13 +20204,6 @@ merge-source-map@1.0.4: dependencies: source-map "^0.5.6" -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - merge-stream@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" @@ -21224,6 +21300,13 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + node-releases@^1.1.25, node-releases@^1.1.46: version "1.1.47" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.47.tgz#c59ef739a1fd7ecbd9f0b7cf5b7871e8a8b591e4" @@ -21490,36 +21573,37 @@ nwsapi@^2.2.0: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== -nyc@^14.1.1: - version "14.1.1" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.1.1.tgz#151d64a6a9f9f5908a1b73233931e4a0a3075eeb" - integrity sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw== +nyc@^15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.0.1.tgz#bd4d5c2b17f2ec04370365a5ca1fc0ed26f9f93d" + integrity sha512-n0MBXYBYRqa67IVt62qW1r/d9UH/Qtr7SF1w/nQLJ9KxvWF6b2xCHImRAixHN9tnMMYHC2P14uo6KddNGwMgGg== dependencies: - archy "^1.0.0" - caching-transform "^3.0.2" - convert-source-map "^1.6.0" - cp-file "^6.2.0" - find-cache-dir "^2.1.0" - find-up "^3.0.0" - foreground-child "^1.5.6" - glob "^7.1.3" - istanbul-lib-coverage "^2.0.5" - istanbul-lib-hook "^2.0.7" - istanbul-lib-instrument "^3.3.0" - istanbul-lib-report "^2.0.8" - istanbul-lib-source-maps "^3.0.6" - istanbul-reports "^2.2.4" - js-yaml "^3.13.1" - make-dir "^2.1.0" - merge-source-map "^1.1.0" - resolve-from "^4.0.0" - rimraf "^2.6.3" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" signal-exit "^3.0.2" - spawn-wrap "^1.4.2" - test-exclude "^5.2.3" - uuid "^3.3.2" - yargs "^13.2.2" - yargs-parser "^13.0.0" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" @@ -21958,7 +22042,7 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= @@ -22200,13 +22284,13 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -package-hash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-3.0.0.tgz#50183f2d36c9e3e528ea0a8605dff57ce976f88e" - integrity sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA== +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== dependencies: graceful-fs "^4.1.15" - hasha "^3.0.0" + hasha "^5.0.0" lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" @@ -23202,6 +23286,13 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" @@ -27207,17 +27298,17 @@ spawn-sync@^1.0.15: concat-stream "^1.4.7" os-shim "^0.1.2" -spawn-wrap@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" - integrity sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg== +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== dependencies: - foreground-child "^1.5.6" - mkdirp "^0.5.0" - os-homedir "^1.0.1" - rimraf "^2.6.2" + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" signal-exit "^3.0.2" - which "^1.3.0" + which "^2.0.1" spdx-compare@^0.1.2: version "0.1.2" @@ -28536,7 +28627,7 @@ terser@^4.4.3: source-map "~0.6.1" source-map-support "~0.5.12" -test-exclude@^5.0.0, test-exclude@^5.2.3: +test-exclude@^5.0.0: version "5.2.3" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== @@ -28546,6 +28637,15 @@ test-exclude@^5.0.0, test-exclude@^5.2.3: read-pkg-up "^4.0.0" require-main-filename "^2.0.0" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" @@ -29688,7 +29788,7 @@ type-fest@^0.6.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== -type-fest@^0.8.1: +type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== @@ -29726,6 +29826,13 @@ typed-styles@^0.0.7: resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -30453,6 +30560,11 @@ uuid@^3.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g== +uuid@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + v8-compile-cache@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" @@ -31713,6 +31825,16 @@ write-file-atomic@^2.4.2: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + write-json-file@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" @@ -31954,7 +32076,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@13.1.2, yargs-parser@^13.0.0, yargs-parser@^13.1.0, yargs-parser@^13.1.1, yargs-parser@^13.1.2: +yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.1, yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== @@ -32121,7 +32243,7 @@ yargs@^13.2.2, yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.1" -yargs@^15.3.1: +yargs@^15.0.2, yargs@^15.3.1: version "15.3.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== From 97d1685c3dea682f80fd1a907bbc1d6f3702ea85 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Thu, 9 Apr 2020 23:18:18 -0400 Subject: [PATCH 029/121] Sharing saved-objects phase 1 (#54605) Co-authored-by: kobelb --- docs/api/saved-objects/bulk_create.asciidoc | 2 +- .../kibana-plugin-core-public.savedobject.md | 1 + ...ugin-core-public.savedobject.namespaces.md | 13 + ...in-core-server.isavedobjecttyperegistry.md | 2 +- .../core/server/kibana-plugin-core-server.md | 3 + .../kibana-plugin-core-server.savedobject.md | 1 + ...ugin-core-server.savedobject.namespaces.md | 13 + ...rver.savedobjectsaddtonamespacesoptions.md | 20 + ...edobjectsaddtonamespacesoptions.refresh.md | 13 + ...edobjectsaddtonamespacesoptions.version.md | 13 + ...rver.savedobjectsclient.addtonamespaces.md | 27 + ...savedobjectsclient.deletefromnamespaces.md | 27 + ...a-plugin-core-server.savedobjectsclient.md | 2 + ...savedobjectsdeletefromnamespacesoptions.md | 19 + ...ectsdeletefromnamespacesoptions.refresh.md | 13 + ...objectserrorhelpers.createconflicterror.md | 23 + ...pers.decorateescannotexecutescripterror.md | 23 + ...rorhelpers.isescannotexecutescripterror.md | 22 + ...in-core-server.savedobjectserrorhelpers.md | 3 + ...n-core-server.savedobjectsnamespacetype.md | 15 + ....savedobjectsrepository.addtonamespaces.md | 27 + ...dobjectsrepository.deletefromnamespaces.md | 27 + ...ugin-core-server.savedobjectsrepository.md | 2 + ...r.savedobjectsservicesetup.registertype.md | 2 +- ...ana-plugin-core-server.savedobjectstype.md | 3 +- ...rver.savedobjectstype.namespaceagnostic.md | 9 +- ...e-server.savedobjectstype.namespacetype.md | 13 + ...avedobjecttyperegistry.ismultinamespace.md | 24 + ...dobjecttyperegistry.isnamespaceagnostic.md | 2 +- ...vedobjecttyperegistry.issinglenamespace.md | 24 + ...gin-core-server.savedobjecttyperegistry.md | 4 +- src/core/public/public.api.md | 1 + src/core/server/index.ts | 3 + .../__snapshots__/utils.test.ts.snap | 48 +- src/core/server/saved_objects/index.ts | 1 + .../build_active_mappings.test.ts.snap | 8 + .../migrations/core/build_active_mappings.ts | 3 + .../migrations/core/index_migrator.test.ts | 4 + .../kibana_migrator.test.ts.snap | 4 + .../routes/integration_tests/import.test.ts | 2 +- .../saved_objects_service.test.ts | 4 +- .../saved_objects/saved_objects_service.ts | 2 +- .../saved_objects_type_registry.mock.ts | 6 + .../saved_objects_type_registry.test.ts | 98 +- .../saved_objects_type_registry.ts | 37 +- .../saved_objects/schema/schema.test.ts | 98 +- .../server/saved_objects/schema/schema.ts | 33 +- .../serialization/serializer.test.ts | 1710 +++--- .../saved_objects/serialization/serializer.ts | 15 +- .../saved_objects/serialization/types.ts | 2 + .../lib/__snapshots__/repository.test.js.snap | 5 - .../service/lib/decorate_es_error.test.ts | 32 + .../service/lib/decorate_es_error.ts | 10 +- .../saved_objects/service/lib/errors.test.ts | 172 +- .../saved_objects/service/lib/errors.ts | 16 + .../service/lib/included_fields.test.ts | 26 +- .../service/lib/included_fields.ts | 1 + .../service/lib/repository.mock.ts | 2 + .../service/lib/repository.test.js | 4970 +++++++++-------- .../saved_objects/service/lib/repository.ts | 769 ++- .../lib/search_dsl/query_params.test.ts | 1460 +---- .../service/lib/search_dsl/query_params.ts | 14 +- .../service/saved_objects_client.mock.ts | 2 + .../service/saved_objects_client.test.js | 34 + .../service/saved_objects_client.ts | 54 + src/core/server/saved_objects/types.ts | 24 +- src/core/server/saved_objects/utils.test.ts | 63 +- src/core/server/saved_objects/utils.ts | 11 +- src/core/server/server.api.md | 37 +- src/core/types/saved_objects.ts | 2 + .../apis/saved_objects/bulk_create.js | 4 +- .../apis/saved_objects/bulk_get.js | 13 +- .../apis/saved_objects/export.js | 3 +- ...ypted_saved_objects_client_wrapper.test.ts | 308 +- .../encrypted_saved_objects_client_wrapper.ts | 42 +- .../server/saved_objects/index.ts | 3 +- .../server/audit/audit_logger.test.ts | 36 +- .../security/server/audit/audit_logger.ts | 17 +- .../check_privileges.test.ts.snap | 27 - .../authorization/check_privileges.test.ts | 1216 ++-- .../server/authorization/check_privileges.ts | 95 +- .../check_privileges_dynamically.ts | 4 +- .../check_saved_objects_privileges.test.ts | 132 +- .../check_saved_objects_privileges.ts | 34 +- .../disable_ui_capabilities.test.ts | 47 +- .../authorization/disable_ui_capabilities.ts | 8 +- x-pack/plugins/security/server/plugin.ts | 1 + .../security/server/saved_objects/index.ts | 10 +- ...ecure_saved_objects_client_wrapper.test.ts | 1448 +++-- .../secure_saved_objects_client_wrapper.ts | 212 +- .../edit_space/delete_spaces_button.tsx | 11 +- .../spaces_grid/spaces_grid_page.tsx | 11 +- .../lib/copy_to_spaces/copy_to_spaces.test.ts | 6 + .../resolve_copy_conflicts.test.ts | 6 + .../lib/spaces_client/spaces_client.test.ts | 24 +- .../server/lib/spaces_client/spaces_client.ts | 14 +- .../server/routes/api/external/delete.test.ts | 30 +- .../server/routes/api/external/delete.ts | 10 +- .../server/routes/api/external/index.ts | 4 + .../routes/api/external/share_add_spaces.ts | 62 + .../api/external/share_remove_spaces.ts | 62 + .../spaces_saved_objects_client.test.ts.snap | 29 - .../spaces_saved_objects_client.test.ts | 314 +- .../spaces_saved_objects_client.ts | 46 + .../plugins/uptime/server/rest_api/types.ts | 15 +- .../apis/spaces/saved_objects.ts | 2 +- .../common/config.ts | 2 + .../saved_objects/spaces/data.json | 103 +- .../saved_objects/spaces/mappings.json | 78 +- .../fixtures/hidden_type_plugin/index.js | 2 + .../fixtures/hidden_type_plugin/mappings.json | 2 +- .../fixtures/isolated_type_plugin/index.js | 26 + .../isolated_type_plugin/mappings.json | 31 + .../isolated_type_plugin/package.json | 7 + .../mappings.json | 2 +- .../fixtures/shared_type_plugin/index.js | 27 + .../fixtures/shared_type_plugin/mappings.json | 15 + .../fixtures/shared_type_plugin/package.json | 7 + .../common/lib/saved_object_test_cases.ts | 40 + .../common/lib/saved_object_test_utils.ts | 302 + .../common/lib/space_test_utils.ts | 24 - .../common/lib/types.ts | 27 +- .../common/suites/bulk_create.ts | 293 +- .../common/suites/bulk_get.ts | 257 +- .../common/suites/bulk_update.ts | 291 +- .../common/suites/create.ts | 259 +- .../common/suites/delete.ts | 190 +- .../common/suites/export.ts | 291 +- .../common/suites/find.ts | 401 +- .../common/suites/get.ts | 226 +- .../common/suites/import.ts | 285 +- .../common/suites/resolve_import_errors.ts | 312 +- .../common/suites/update.ts | 246 +- .../security_and_spaces/apis/bulk_create.ts | 278 +- .../security_and_spaces/apis/bulk_get.ts | 260 +- .../security_and_spaces/apis/bulk_update.ts | 347 +- .../security_and_spaces/apis/create.ts | 313 +- .../security_and_spaces/apis/delete.ts | 337 +- .../security_and_spaces/apis/export.ts | 314 +- .../security_and_spaces/apis/find.ts | 766 +-- .../security_and_spaces/apis/get.ts | 339 +- .../security_and_spaces/apis/import.ts | 301 +- .../security_and_spaces/apis/index.ts | 2 +- .../apis/resolve_import_errors.ts | 325 +- .../security_and_spaces/apis/update.ts | 338 +- .../security_only/apis/bulk_create.ts | 232 +- .../security_only/apis/bulk_get.ts | 226 +- .../security_only/apis/bulk_update.ts | 323 +- .../security_only/apis/create.ts | 275 +- .../security_only/apis/delete.ts | 313 +- .../security_only/apis/export.ts | 299 +- .../security_only/apis/find.ts | 791 +-- .../security_only/apis/get.ts | 312 +- .../security_only/apis/import.ts | 278 +- .../security_only/apis/index.ts | 2 +- .../apis/resolve_import_errors.ts | 277 +- .../security_only/apis/update.ts | 314 +- .../spaces_only/apis/bulk_create.ts | 123 +- .../spaces_only/apis/bulk_get.ts | 68 +- .../spaces_only/apis/bulk_update.ts | 110 +- .../spaces_only/apis/create.ts | 118 +- .../spaces_only/apis/delete.ts | 109 +- .../spaces_only/apis/export.ts | 65 +- .../spaces_only/apis/find.ts | 157 +- .../spaces_only/apis/get.ts | 110 +- .../spaces_only/apis/import.ts | 74 +- .../spaces_only/apis/index.ts | 2 +- .../spaces_only/apis/resolve_import_errors.ts | 85 +- .../spaces_only/apis/update.ts | 110 +- .../spaces_api_integration/common/config.ts | 1 + .../saved_objects/spaces/data.json | 120 + .../saved_objects/spaces/mappings.json | 16 + .../fixtures/shared_type_plugin/index.js | 27 + .../fixtures/shared_type_plugin/mappings.json | 15 + .../fixtures/shared_type_plugin/package.json | 7 + .../common/lib/saved_object_test_cases.ts | 40 + .../common/suites/delete.ts | 20 + .../common/suites/share_add.ts | 118 + .../common/suites/share_remove.ts | 116 + .../security_and_spaces/apis/index.ts | 2 + .../security_and_spaces/apis/share_add.ts | 124 + .../security_and_spaces/apis/share_remove.ts | 99 + .../spaces_only/apis/index.ts | 2 + .../spaces_only/apis/share_add.ts | 84 + .../spaces_only/apis/share_remove.ts | 99 + 185 files changed, 12261 insertions(+), 15549 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-core-public.savedobject.namespaces.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobject.namespaces.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.refresh.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.version.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.refresh.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.createconflicterror.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.decorateescannotexecutescripterror.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.isescannotexecutescripterror.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsnamespacetype.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespacetype.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.ismultinamespace.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.issinglenamespace.md delete mode 100644 src/core/server/saved_objects/service/lib/__snapshots__/repository.test.js.snap delete mode 100644 x-pack/plugins/security/server/authorization/__snapshots__/check_privileges.test.ts.snap create mode 100644 x-pack/plugins/spaces/server/routes/api/external/share_add_spaces.ts create mode 100644 x-pack/plugins/spaces/server/routes/api/external/share_remove_spaces.ts delete mode 100644 x-pack/plugins/spaces/server/saved_objects/__snapshots__/spaces_saved_objects_client.test.ts.snap create mode 100644 x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/index.js create mode 100644 x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/mappings.json create mode 100644 x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/package.json create mode 100644 x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/index.js create mode 100644 x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/mappings.json create mode 100644 x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/package.json create mode 100644 x-pack/test/saved_object_api_integration/common/lib/saved_object_test_cases.ts create mode 100644 x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts delete mode 100644 x-pack/test/saved_object_api_integration/common/lib/space_test_utils.ts create mode 100644 x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/index.js create mode 100644 x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/mappings.json create mode 100644 x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/package.json create mode 100644 x-pack/test/spaces_api_integration/common/lib/saved_object_test_cases.ts create mode 100644 x-pack/test/spaces_api_integration/common/suites/share_add.ts create mode 100644 x-pack/test/spaces_api_integration/common/suites/share_remove.ts create mode 100644 x-pack/test/spaces_api_integration/security_and_spaces/apis/share_add.ts create mode 100644 x-pack/test/spaces_api_integration/security_and_spaces/apis/share_remove.ts create mode 100644 x-pack/test/spaces_api_integration/spaces_only/apis/share_add.ts create mode 100644 x-pack/test/spaces_api_integration/spaces_only/apis/share_remove.ts diff --git a/docs/api/saved-objects/bulk_create.asciidoc b/docs/api/saved-objects/bulk_create.asciidoc index 9daba224b317c..fbd4c6e77f8bf 100644 --- a/docs/api/saved-objects/bulk_create.asciidoc +++ b/docs/api/saved-objects/bulk_create.asciidoc @@ -104,7 +104,7 @@ The API returns the following: "type": "dashboard", "error": { "statusCode": 409, - "message": "version conflict, document already exists" + "message": "Saved object [dashboard/be3733a0-9efe-11e7-acb3-3dab96693fab] conflict" } } ] diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobject.md b/docs/development/core/public/kibana-plugin-core-public.savedobject.md index c6bc13b98bc06..b67d0536fb336 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobject.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobject.md @@ -18,6 +18,7 @@ export interface SavedObject | [error](./kibana-plugin-core-public.savedobject.error.md) | {
message: string;
statusCode: number;
} | | | [id](./kibana-plugin-core-public.savedobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | | [migrationVersion](./kibana-plugin-core-public.savedobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [namespaces](./kibana-plugin-core-public.savedobject.namespaces.md) | string[] | Namespace(s) that this saved object exists in. This attribute is only used for multi-namespace saved object types. | | [references](./kibana-plugin-core-public.savedobject.references.md) | SavedObjectReference[] | A reference to another saved object. | | [type](./kibana-plugin-core-public.savedobject.type.md) | string | The type of Saved Object. Each plugin can define it's own custom Saved Object types. | | [updated\_at](./kibana-plugin-core-public.savedobject.updated_at.md) | string | Timestamp of the last time this document had been updated. | diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobject.namespaces.md b/docs/development/core/public/kibana-plugin-core-public.savedobject.namespaces.md new file mode 100644 index 0000000000000..257df45934506 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.savedobject.namespaces.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObject](./kibana-plugin-core-public.savedobject.md) > [namespaces](./kibana-plugin-core-public.savedobject.namespaces.md) + +## SavedObject.namespaces property + +Namespace(s) that this saved object exists in. This attribute is only used for multi-namespace saved object types. + +Signature: + +```typescript +namespaces?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.isavedobjecttyperegistry.md b/docs/development/core/server/kibana-plugin-core-server.isavedobjecttyperegistry.md index 245cb1a56439f..f9c621885c001 100644 --- a/docs/development/core/server/kibana-plugin-core-server.isavedobjecttyperegistry.md +++ b/docs/development/core/server/kibana-plugin-core-server.isavedobjecttyperegistry.md @@ -9,5 +9,5 @@ See [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistr Signature: ```typescript -export declare type ISavedObjectTypeRegistry = Pick; +export declare type ISavedObjectTypeRegistry = Omit; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index accab9bf0cb36..5c0f10cac5179 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -130,6 +130,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectMigrationContext](./kibana-plugin-core-server.savedobjectmigrationcontext.md) | Migration context provided when invoking a [migration handler](./kibana-plugin-core-server.savedobjectmigrationfn.md) | | [SavedObjectMigrationMap](./kibana-plugin-core-server.savedobjectmigrationmap.md) | A map of [migration functions](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used for a given type. The map's keys must be valid semver versions.For a given document, only migrations with a higher version number than that of the document will be applied. Migrations are executed in order, starting from the lowest version and ending with the highest one. | | [SavedObjectReference](./kibana-plugin-core-server.savedobjectreference.md) | A reference to another saved object. | +| [SavedObjectsAddToNamespacesOptions](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md) | | | [SavedObjectsBaseOptions](./kibana-plugin-core-server.savedobjectsbaseoptions.md) | | | [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) | | | [SavedObjectsBulkGetObject](./kibana-plugin-core-server.savedobjectsbulkgetobject.md) | | @@ -143,6 +144,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsCoreFieldMapping](./kibana-plugin-core-server.savedobjectscorefieldmapping.md) | See [SavedObjectsFieldMapping](./kibana-plugin-core-server.savedobjectsfieldmapping.md) for documentation. | | [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md) | | | [SavedObjectsDeleteByNamespaceOptions](./kibana-plugin-core-server.savedobjectsdeletebynamespaceoptions.md) | | +| [SavedObjectsDeleteFromNamespacesOptions](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md) | | | [SavedObjectsDeleteOptions](./kibana-plugin-core-server.savedobjectsdeleteoptions.md) | | | [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) | Options controlling the export operation. | | [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | @@ -262,6 +264,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsClientFactoryProvider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) | Provider to invoke to retrieve a [SavedObjectsClientFactory](./kibana-plugin-core-server.savedobjectsclientfactory.md). | | [SavedObjectsClientWrapperFactory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) | Describes the factory used to create instances of Saved Objects Client Wrappers. | | [SavedObjectsFieldMapping](./kibana-plugin-core-server.savedobjectsfieldmapping.md) | Describe a [saved object type mapping](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) field.Please refer to [elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html) For the mapping documentation | +| [SavedObjectsNamespaceType](./kibana-plugin-core-server.savedobjectsnamespacetype.md) | The namespace type dictates how a saved object can be interacted in relation to namespaces. Each type is mutually exclusive: \* single (default): this type of saved object is namespace-isolated, e.g., it exists in only one namespace. \* multiple: this type of saved object is shareable, e.g., it can exist in one or more namespaces. \* agnostic: this type of saved object is global.Note: do not write logic that uses this value directly; instead, use the appropriate accessors in the [type registry](./kibana-plugin-core-server.savedobjecttyperegistry.md). | | [ScopeableRequest](./kibana-plugin-core-server.scopeablerequest.md) | A user credentials container. It accommodates the necessary auth credentials to impersonate the current user.See [KibanaRequest](./kibana-plugin-core-server.kibanarequest.md). | | [ServiceStatusLevel](./kibana-plugin-core-server.servicestatuslevel.md) | A convenience type that represents the union of each value in [ServiceStatusLevels](./kibana-plugin-core-server.servicestatuslevels.md). | | [SharedGlobalConfig](./kibana-plugin-core-server.sharedglobalconfig.md) | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobject.md index 0df97b0d4221a..94d1c378899df 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobject.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobject.md @@ -18,6 +18,7 @@ export interface SavedObject | [error](./kibana-plugin-core-server.savedobject.error.md) | {
message: string;
statusCode: number;
} | | | [id](./kibana-plugin-core-server.savedobject.id.md) | string | The ID of this Saved Object, guaranteed to be unique for all objects of the same type | | [migrationVersion](./kibana-plugin-core-server.savedobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | +| [namespaces](./kibana-plugin-core-server.savedobject.namespaces.md) | string[] | Namespace(s) that this saved object exists in. This attribute is only used for multi-namespace saved object types. | | [references](./kibana-plugin-core-server.savedobject.references.md) | SavedObjectReference[] | A reference to another saved object. | | [type](./kibana-plugin-core-server.savedobject.type.md) | string | The type of Saved Object. Each plugin can define it's own custom Saved Object types. | | [updated\_at](./kibana-plugin-core-server.savedobject.updated_at.md) | string | Timestamp of the last time this document had been updated. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobject.namespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobject.namespaces.md new file mode 100644 index 0000000000000..2a555db01df3b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobject.namespaces.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObject](./kibana-plugin-core-server.savedobject.md) > [namespaces](./kibana-plugin-core-server.savedobject.namespaces.md) + +## SavedObject.namespaces property + +Namespace(s) that this saved object exists in. This attribute is only used for multi-namespace saved object types. + +Signature: + +```typescript +namespaces?: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md new file mode 100644 index 0000000000000..711588bdd608c --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsAddToNamespacesOptions](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md) + +## SavedObjectsAddToNamespacesOptions interface + + +Signature: + +```typescript +export interface SavedObjectsAddToNamespacesOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [refresh](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | +| [version](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.refresh.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.refresh.md new file mode 100644 index 0000000000000..c0a1008ab5331 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.refresh.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsAddToNamespacesOptions](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md) > [refresh](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.refresh.md) + +## SavedObjectsAddToNamespacesOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.version.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.version.md new file mode 100644 index 0000000000000..9432b4bf80da6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.version.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsAddToNamespacesOptions](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.md) > [version](./kibana-plugin-core-server.savedobjectsaddtonamespacesoptions.version.md) + +## SavedObjectsAddToNamespacesOptions.version property + +An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. + +Signature: + +```typescript +version?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md new file mode 100644 index 0000000000000..45c9c39f9626a --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) > [addToNamespaces](./kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md) + +## SavedObjectsClient.addToNamespaces() method + +Adds namespaces to a SavedObject + +Signature: + +```typescript +addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| namespaces | string[] | | +| options | SavedObjectsAddToNamespacesOptions | | + +Returns: + +`Promise<{}>` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md new file mode 100644 index 0000000000000..80b58d29d393b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) > [deleteFromNamespaces](./kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md) + +## SavedObjectsClient.deleteFromNamespaces() method + +Removes namespaces from a SavedObject + +Signature: + +```typescript +deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| namespaces | string[] | | +| options | SavedObjectsDeleteFromNamespacesOptions | | + +Returns: + +`Promise<{}>` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.md index 5a8a213d2bccc..7038c0c07012f 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsclient.md @@ -25,11 +25,13 @@ The constructor for this class is marked as internal. Third-party code should no | Method | Modifiers | Description | | --- | --- | --- | +| [addToNamespaces(type, id, namespaces, options)](./kibana-plugin-core-server.savedobjectsclient.addtonamespaces.md) | | Adds namespaces to a SavedObject | | [bulkCreate(objects, options)](./kibana-plugin-core-server.savedobjectsclient.bulkcreate.md) | | Persists multiple documents batched together as a single request | | [bulkGet(objects, options)](./kibana-plugin-core-server.savedobjectsclient.bulkget.md) | | Returns an array of objects by id | | [bulkUpdate(objects, options)](./kibana-plugin-core-server.savedobjectsclient.bulkupdate.md) | | Bulk Updates multiple SavedObject at once | | [create(type, attributes, options)](./kibana-plugin-core-server.savedobjectsclient.create.md) | | Persists a SavedObject | | [delete(type, id, options)](./kibana-plugin-core-server.savedobjectsclient.delete.md) | | Deletes a SavedObject | +| [deleteFromNamespaces(type, id, namespaces, options)](./kibana-plugin-core-server.savedobjectsclient.deletefromnamespaces.md) | | Removes namespaces from a SavedObject | | [find(options)](./kibana-plugin-core-server.savedobjectsclient.find.md) | | Find all SavedObjects matching the search query | | [get(type, id, options)](./kibana-plugin-core-server.savedobjectsclient.get.md) | | Retrieves a single object | | [update(type, id, attributes, options)](./kibana-plugin-core-server.savedobjectsclient.update.md) | | Updates an SavedObject | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md new file mode 100644 index 0000000000000..8a2afe6656fa4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsDeleteFromNamespacesOptions](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md) + +## SavedObjectsDeleteFromNamespacesOptions interface + + +Signature: + +```typescript +export interface SavedObjectsDeleteFromNamespacesOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [refresh](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.refresh.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.refresh.md new file mode 100644 index 0000000000000..1175b79bc1abd --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.refresh.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsDeleteFromNamespacesOptions](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md) > [refresh](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.refresh.md) + +## SavedObjectsDeleteFromNamespacesOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.createconflicterror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.createconflicterror.md new file mode 100644 index 0000000000000..8e04282ce0c71 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.createconflicterror.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) > [createConflictError](./kibana-plugin-core-server.savedobjectserrorhelpers.createconflicterror.md) + +## SavedObjectsErrorHelpers.createConflictError() method + +Signature: + +```typescript +static createConflictError(type: string, id: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.decorateescannotexecutescripterror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.decorateescannotexecutescripterror.md new file mode 100644 index 0000000000000..94060bba50067 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.decorateescannotexecutescripterror.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) > [decorateEsCannotExecuteScriptError](./kibana-plugin-core-server.savedobjectserrorhelpers.decorateescannotexecutescripterror.md) + +## SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError() method + +Signature: + +```typescript +static decorateEsCannotExecuteScriptError(error: Error, reason?: string): DecoratedError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | | +| reason | string | | + +Returns: + +`DecoratedError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.isescannotexecutescripterror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.isescannotexecutescripterror.md new file mode 100644 index 0000000000000..debb94fe4f8d8 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.isescannotexecutescripterror.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) > [isEsCannotExecuteScriptError](./kibana-plugin-core-server.savedobjectserrorhelpers.isescannotexecutescripterror.md) + +## SavedObjectsErrorHelpers.isEsCannotExecuteScriptError() method + +Signature: + +```typescript +static isEsCannotExecuteScriptError(error: Error | DecoratedError): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| error | Error | DecoratedError | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md index 55a42e4f4eb7a..250b9d3899670 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md @@ -16,12 +16,14 @@ export declare class SavedObjectsErrorHelpers | Method | Modifiers | Description | | --- | --- | --- | | [createBadRequestError(reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.createbadrequesterror.md) | static | | +| [createConflictError(type, id)](./kibana-plugin-core-server.savedobjectserrorhelpers.createconflicterror.md) | static | | | [createEsAutoCreateIndexError()](./kibana-plugin-core-server.savedobjectserrorhelpers.createesautocreateindexerror.md) | static | | | [createGenericNotFoundError(type, id)](./kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfounderror.md) | static | | | [createInvalidVersionError(versionInput)](./kibana-plugin-core-server.savedobjectserrorhelpers.createinvalidversionerror.md) | static | | | [createUnsupportedTypeError(type)](./kibana-plugin-core-server.savedobjectserrorhelpers.createunsupportedtypeerror.md) | static | | | [decorateBadRequestError(error, reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.decoratebadrequesterror.md) | static | | | [decorateConflictError(error, reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.decorateconflicterror.md) | static | | +| [decorateEsCannotExecuteScriptError(error, reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.decorateescannotexecutescripterror.md) | static | | | [decorateEsUnavailableError(error, reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.decorateesunavailableerror.md) | static | | | [decorateForbiddenError(error, reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.decorateforbiddenerror.md) | static | | | [decorateGeneralError(error, reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.decorategeneralerror.md) | static | | @@ -30,6 +32,7 @@ export declare class SavedObjectsErrorHelpers | [isBadRequestError(error)](./kibana-plugin-core-server.savedobjectserrorhelpers.isbadrequesterror.md) | static | | | [isConflictError(error)](./kibana-plugin-core-server.savedobjectserrorhelpers.isconflicterror.md) | static | | | [isEsAutoCreateIndexError(error)](./kibana-plugin-core-server.savedobjectserrorhelpers.isesautocreateindexerror.md) | static | | +| [isEsCannotExecuteScriptError(error)](./kibana-plugin-core-server.savedobjectserrorhelpers.isescannotexecutescripterror.md) | static | | | [isEsUnavailableError(error)](./kibana-plugin-core-server.savedobjectserrorhelpers.isesunavailableerror.md) | static | | | [isForbiddenError(error)](./kibana-plugin-core-server.savedobjectserrorhelpers.isforbiddenerror.md) | static | | | [isInvalidVersionError(error)](./kibana-plugin-core-server.savedobjectserrorhelpers.isinvalidversionerror.md) | static | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsnamespacetype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsnamespacetype.md new file mode 100644 index 0000000000000..173b9e19321d0 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsnamespacetype.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsNamespaceType](./kibana-plugin-core-server.savedobjectsnamespacetype.md) + +## SavedObjectsNamespaceType type + +The namespace type dictates how a saved object can be interacted in relation to namespaces. Each type is mutually exclusive: \* single (default): this type of saved object is namespace-isolated, e.g., it exists in only one namespace. \* multiple: this type of saved object is shareable, e.g., it can exist in one or more namespaces. \* agnostic: this type of saved object is global. + +Note: do not write logic that uses this value directly; instead, use the appropriate accessors in the [type registry](./kibana-plugin-core-server.savedobjecttyperegistry.md). + +Signature: + +```typescript +export declare type SavedObjectsNamespaceType = 'single' | 'multiple' | 'agnostic'; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md new file mode 100644 index 0000000000000..bbb20d2bc3b96 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) > [addToNamespaces](./kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md) + +## SavedObjectsRepository.addToNamespaces() method + +Adds one or more namespaces to a given multi-namespace saved object. This method and \[`deleteFromNamespaces`\][SavedObjectsRepository.deleteFromNamespaces()](./kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md) are the only ways to change which Spaces a multi-namespace saved object is shared to. + +Signature: + +```typescript +addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| namespaces | string[] | | +| options | SavedObjectsAddToNamespacesOptions | | + +Returns: + +`Promise<{}>` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md new file mode 100644 index 0000000000000..471c3e3c5092d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) > [deleteFromNamespaces](./kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md) + +## SavedObjectsRepository.deleteFromNamespaces() method + +Removes one or more namespaces from a given multi-namespace saved object. If no namespaces remain, the saved object is deleted entirely. This method and \[`addToNamespaces`\][SavedObjectsRepository.addToNamespaces()](./kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md) are the only ways to change which Spaces a multi-namespace saved object is shared to. + +Signature: + +```typescript +deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| id | string | | +| namespaces | string[] | | +| options | SavedObjectsDeleteFromNamespacesOptions | | + +Returns: + +`Promise<{}>` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md index 37547af2497e9..bd86ff3abbe9b 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsrepository.md @@ -15,12 +15,14 @@ export declare class SavedObjectsRepository | Method | Modifiers | Description | | --- | --- | --- | +| [addToNamespaces(type, id, namespaces, options)](./kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md) | | Adds one or more namespaces to a given multi-namespace saved object. This method and \[deleteFromNamespaces\][SavedObjectsRepository.deleteFromNamespaces()](./kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md) are the only ways to change which Spaces a multi-namespace saved object is shared to. | | [bulkCreate(objects, options)](./kibana-plugin-core-server.savedobjectsrepository.bulkcreate.md) | | Creates multiple documents at once | | [bulkGet(objects, options)](./kibana-plugin-core-server.savedobjectsrepository.bulkget.md) | | Returns an array of objects by id | | [bulkUpdate(objects, options)](./kibana-plugin-core-server.savedobjectsrepository.bulkupdate.md) | | Updates multiple objects in bulk | | [create(type, attributes, options)](./kibana-plugin-core-server.savedobjectsrepository.create.md) | | Persists an object | | [delete(type, id, options)](./kibana-plugin-core-server.savedobjectsrepository.delete.md) | | Deletes an object | | [deleteByNamespace(namespace, options)](./kibana-plugin-core-server.savedobjectsrepository.deletebynamespace.md) | | Deletes all objects from the provided namespace. | +| [deleteFromNamespaces(type, id, namespaces, options)](./kibana-plugin-core-server.savedobjectsrepository.deletefromnamespaces.md) | | Removes one or more namespaces from a given multi-namespace saved object. If no namespaces remain, the saved object is deleted entirely. This method and \[addToNamespaces\][SavedObjectsRepository.addToNamespaces()](./kibana-plugin-core-server.savedobjectsrepository.addtonamespaces.md) are the only ways to change which Spaces a multi-namespace saved object is shared to. | | [find({ search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, })](./kibana-plugin-core-server.savedobjectsrepository.find.md) | | | | [get(type, id, options)](./kibana-plugin-core-server.savedobjectsrepository.get.md) | | Gets a single object | | [incrementCounter(type, id, counterFieldName, options)](./kibana-plugin-core-server.savedobjectsrepository.incrementcounter.md) | | Increases a counter field by one. Creates the document if one doesn't exist for the given id. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md index c24fa7e7038c6..57c9e04966c1b 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md @@ -29,7 +29,7 @@ import * as migrations from './migrations'; export const myType: SavedObjectsType = { name: 'MyType', hidden: false, - namespaceAgnostic: true, + namespaceType: 'multiple', mappings: { properties: { textField: { diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md index ad7bf9a0f00d0..d8202545f0eae 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md @@ -25,5 +25,6 @@ This is only internal for now, and will only be public when we expose the regist | [mappings](./kibana-plugin-core-server.savedobjectstype.mappings.md) | SavedObjectsTypeMappingDefinition | The [mapping definition](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) for the type. | | [migrations](./kibana-plugin-core-server.savedobjectstype.migrations.md) | SavedObjectMigrationMap | An optional map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used to migrate the type. | | [name](./kibana-plugin-core-server.savedobjectstype.name.md) | string | The name of the type, which is also used as the internal id. | -| [namespaceAgnostic](./kibana-plugin-core-server.savedobjectstype.namespaceagnostic.md) | boolean | Is the type global (true), or namespaced (false). | +| [namespaceAgnostic](./kibana-plugin-core-server.savedobjectstype.namespaceagnostic.md) | boolean | Is the type global (true), or not (false). | +| [namespaceType](./kibana-plugin-core-server.savedobjectstype.namespacetype.md) | SavedObjectsNamespaceType | The [namespace type](./kibana-plugin-core-server.savedobjectsnamespacetype.md) for the type. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespaceagnostic.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespaceagnostic.md index 8f43db86449d0..e347421590482 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespaceagnostic.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespaceagnostic.md @@ -4,10 +4,15 @@ ## SavedObjectsType.namespaceAgnostic property -Is the type global (true), or namespaced (false). +> Warning: This API is now obsolete. +> +> Use `namespaceType` instead. +> + +Is the type global (true), or not (false). Signature: ```typescript -namespaceAgnostic: boolean; +namespaceAgnostic?: boolean; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespacetype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespacetype.md new file mode 100644 index 0000000000000..69912f9144980 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.namespacetype.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsType](./kibana-plugin-core-server.savedobjectstype.md) > [namespaceType](./kibana-plugin-core-server.savedobjectstype.namespacetype.md) + +## SavedObjectsType.namespaceType property + +The [namespace type](./kibana-plugin-core-server.savedobjectsnamespacetype.md) for the type. + +Signature: + +```typescript +namespaceType?: SavedObjectsNamespaceType; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.ismultinamespace.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.ismultinamespace.md new file mode 100644 index 0000000000000..6532c5251d816 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.ismultinamespace.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) > [isMultiNamespace](./kibana-plugin-core-server.savedobjecttyperegistry.ismultinamespace.md) + +## SavedObjectTypeRegistry.isMultiNamespace() method + +Returns whether the type is multi-namespace (shareable); resolves to `false` if the type is not registered + +Signature: + +```typescript +isMultiNamespace(type: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.isnamespaceagnostic.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.isnamespaceagnostic.md index 92dfa5465235a..859c7b9711816 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.isnamespaceagnostic.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.isnamespaceagnostic.md @@ -4,7 +4,7 @@ ## SavedObjectTypeRegistry.isNamespaceAgnostic() method -Returns the `namespaceAgnostic` property for given type, or `false` if the type is not registered. +Returns whether the type is namespace-agnostic (global); resolves to `false` if the type is not registered Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.issinglenamespace.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.issinglenamespace.md new file mode 100644 index 0000000000000..18146b2fd6ea1 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.issinglenamespace.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) > [isSingleNamespace](./kibana-plugin-core-server.savedobjecttyperegistry.issinglenamespace.md) + +## SavedObjectTypeRegistry.isSingleNamespace() method + +Returns whether the type is single-namespace (isolated); resolves to `true` if the type is not registered + +Signature: + +```typescript +isSingleNamespace(type: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.md b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.md index 410b709252b72..69a94e4ad8c88 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjecttyperegistry.md @@ -22,6 +22,8 @@ export declare class SavedObjectTypeRegistry | [getType(type)](./kibana-plugin-core-server.savedobjecttyperegistry.gettype.md) | | Return the [type](./kibana-plugin-core-server.savedobjectstype.md) definition for given type name. | | [isHidden(type)](./kibana-plugin-core-server.savedobjecttyperegistry.ishidden.md) | | Returns the hidden property for given type, or false if the type is not registered. | | [isImportableAndExportable(type)](./kibana-plugin-core-server.savedobjecttyperegistry.isimportableandexportable.md) | | Returns the management.importableAndExportable property for given type, or false if the type is not registered or does not define a management section. | -| [isNamespaceAgnostic(type)](./kibana-plugin-core-server.savedobjecttyperegistry.isnamespaceagnostic.md) | | Returns the namespaceAgnostic property for given type, or false if the type is not registered. | +| [isMultiNamespace(type)](./kibana-plugin-core-server.savedobjecttyperegistry.ismultinamespace.md) | | Returns whether the type is multi-namespace (shareable); resolves to false if the type is not registered | +| [isNamespaceAgnostic(type)](./kibana-plugin-core-server.savedobjecttyperegistry.isnamespaceagnostic.md) | | Returns whether the type is namespace-agnostic (global); resolves to false if the type is not registered | +| [isSingleNamespace(type)](./kibana-plugin-core-server.savedobjecttyperegistry.issinglenamespace.md) | | Returns whether the type is single-namespace (isolated); resolves to true if the type is not registered | | [registerType(type)](./kibana-plugin-core-server.savedobjecttyperegistry.registertype.md) | | Register a [type](./kibana-plugin-core-server.savedobjectstype.md) inside the registry. A type can only be registered once. subsequent calls with the same type name will throw an error. | diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 9f7f649f1e2a5..a5aa37becabc2 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -956,6 +956,7 @@ export interface SavedObject { }; id: string; migrationVersion?: SavedObjectsMigrationVersion; + namespaces?: string[]; references: SavedObjectReference[]; type: string; updated_at?: string; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index a298f80f96d8f..039988fa08968 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -227,6 +227,8 @@ export { SavedObjectsLegacyService, SavedObjectsUpdateOptions, SavedObjectsUpdateResponse, + SavedObjectsAddToNamespacesOptions, + SavedObjectsDeleteFromNamespacesOptions, SavedObjectsServiceStart, SavedObjectsServiceSetup, SavedObjectStatusMeta, @@ -242,6 +244,7 @@ export { SavedObjectsMappingProperties, SavedObjectTypeRegistry, ISavedObjectTypeRegistry, + SavedObjectsNamespaceType, SavedObjectsType, SavedObjectsTypeManagementDefinition, SavedObjectMigrationMap, diff --git a/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap b/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap index 5431d2ca47892..7cd0297e57857 100644 --- a/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap +++ b/src/core/server/saved_objects/__snapshots__/utils.test.ts.snap @@ -16,7 +16,7 @@ Array [ }, "migrations": Object {}, "name": "typeA", - "namespaceAgnostic": false, + "namespaceType": "single", }, Object { "convertToAliasScript": undefined, @@ -32,7 +32,7 @@ Array [ }, "migrations": Object {}, "name": "typeB", - "namespaceAgnostic": false, + "namespaceType": "single", }, Object { "convertToAliasScript": undefined, @@ -48,7 +48,7 @@ Array [ }, "migrations": Object {}, "name": "typeC", - "namespaceAgnostic": false, + "namespaceType": "single", }, ] `; @@ -72,7 +72,7 @@ Array [ "2.0.4": [Function], }, "name": "typeA", - "namespaceAgnostic": true, + "namespaceType": "agnostic", }, Object { "convertToAliasScript": "some alias script", @@ -91,7 +91,7 @@ Array [ }, "migrations": Object {}, "name": "typeB", - "namespaceAgnostic": false, + "namespaceType": "single", }, Object { "convertToAliasScript": undefined, @@ -109,7 +109,7 @@ Array [ "1.5.3": [Function], }, "name": "typeC", - "namespaceAgnostic": false, + "namespaceType": "single", }, ] `; @@ -130,7 +130,23 @@ Array [ }, "migrations": Object {}, "name": "typeA", - "namespaceAgnostic": true, + "namespaceType": "agnostic", + }, + Object { + "convertToAliasScript": undefined, + "hidden": false, + "indexPattern": "barBaz", + "management": undefined, + "mappings": Object { + "properties": Object { + "fieldB": Object { + "type": "text", + }, + }, + }, + "migrations": Object {}, + "name": "typeB", + "namespaceType": "multiple", }, Object { "convertToAliasScript": undefined, @@ -146,7 +162,23 @@ Array [ }, "migrations": Object {}, "name": "typeC", - "namespaceAgnostic": false, + "namespaceType": "single", + }, + Object { + "convertToAliasScript": undefined, + "hidden": false, + "indexPattern": "bazQux", + "management": undefined, + "mappings": Object { + "properties": Object { + "fieldD": Object { + "type": "text", + }, + }, + }, + "migrations": Object {}, + "name": "typeD", + "namespaceType": "agnostic", }, ] `; diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index fe4795cad11a5..a294b28753f7b 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -69,6 +69,7 @@ export { } from './migrations'; export { + SavedObjectsNamespaceType, SavedObjectStatusMeta, SavedObjectsType, SavedObjectsTypeManagementDefinition, diff --git a/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap b/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap index fc26d7e9cf6e9..bc9a66926e880 100644 --- a/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap +++ b/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap @@ -8,6 +8,7 @@ Object { "bbb": "18c78c995965207ed3f6e7fc5c6e55fe", "migrationVersion": "4a1746014a75ade3a714e1db5763276f", "namespace": "2f4316de49999235636386fe51dc06c1", + "namespaces": "2f4316de49999235636386fe51dc06c1", "references": "7997cf5a56cc02bdc9c93361bde732b0", "type": "2f4316de49999235636386fe51dc06c1", "updated_at": "00da57df13e94e9d98437d13ace4bfe0", @@ -28,6 +29,9 @@ Object { "namespace": Object { "type": "keyword", }, + "namespaces": Object { + "type": "keyword", + }, "references": Object { "properties": Object { "id": Object { @@ -59,6 +63,7 @@ Object { "firstType": "635418ab953d81d93f1190b70a8d3f57", "migrationVersion": "4a1746014a75ade3a714e1db5763276f", "namespace": "2f4316de49999235636386fe51dc06c1", + "namespaces": "2f4316de49999235636386fe51dc06c1", "references": "7997cf5a56cc02bdc9c93361bde732b0", "secondType": "72d57924f415fbadb3ee293b67d233ab", "thirdType": "510f1f0adb69830cf8a1c5ce2923ed82", @@ -83,6 +88,9 @@ Object { "namespace": Object { "type": "keyword", }, + "namespaces": Object { + "type": "keyword", + }, "references": Object { "properties": Object { "id": Object { diff --git a/src/core/server/saved_objects/migrations/core/build_active_mappings.ts b/src/core/server/saved_objects/migrations/core/build_active_mappings.ts index 4d1a607414ca6..418ed95f14e05 100644 --- a/src/core/server/saved_objects/migrations/core/build_active_mappings.ts +++ b/src/core/server/saved_objects/migrations/core/build_active_mappings.ts @@ -142,6 +142,9 @@ function defaultMapping(): IndexMapping { namespace: { type: 'keyword', }, + namespaces: { + type: 'keyword', + }, updated_at: { type: 'date', }, diff --git a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts index 1c2d3f501ff80..19208e6c83596 100644 --- a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts @@ -61,6 +61,7 @@ describe('IndexMigrator', () => { foo: '18c78c995965207ed3f6e7fc5c6e55fe', migrationVersion: '4a1746014a75ade3a714e1db5763276f', namespace: '2f4316de49999235636386fe51dc06c1', + namespaces: '2f4316de49999235636386fe51dc06c1', references: '7997cf5a56cc02bdc9c93361bde732b0', type: '2f4316de49999235636386fe51dc06c1', updated_at: '00da57df13e94e9d98437d13ace4bfe0', @@ -70,6 +71,7 @@ describe('IndexMigrator', () => { foo: { type: 'long' }, migrationVersion: { dynamic: 'true', type: 'object' }, namespace: { type: 'keyword' }, + namespaces: { type: 'keyword' }, type: { type: 'keyword' }, updated_at: { type: 'date' }, references: { @@ -178,6 +180,7 @@ describe('IndexMigrator', () => { foo: '625b32086eb1d1203564cf85062dd22e', migrationVersion: '4a1746014a75ade3a714e1db5763276f', namespace: '2f4316de49999235636386fe51dc06c1', + namespaces: '2f4316de49999235636386fe51dc06c1', references: '7997cf5a56cc02bdc9c93361bde732b0', type: '2f4316de49999235636386fe51dc06c1', updated_at: '00da57df13e94e9d98437d13ace4bfe0', @@ -188,6 +191,7 @@ describe('IndexMigrator', () => { foo: { type: 'text' }, migrationVersion: { dynamic: 'true', type: 'object' }, namespace: { type: 'keyword' }, + namespaces: { type: 'keyword' }, type: { type: 'keyword' }, updated_at: { type: 'date' }, references: { diff --git a/src/core/server/saved_objects/migrations/kibana/__snapshots__/kibana_migrator.test.ts.snap b/src/core/server/saved_objects/migrations/kibana/__snapshots__/kibana_migrator.test.ts.snap index 507c0b0d9339f..3453f3fc80310 100644 --- a/src/core/server/saved_objects/migrations/kibana/__snapshots__/kibana_migrator.test.ts.snap +++ b/src/core/server/saved_objects/migrations/kibana/__snapshots__/kibana_migrator.test.ts.snap @@ -8,6 +8,7 @@ Object { "bmap": "510f1f0adb69830cf8a1c5ce2923ed82", "migrationVersion": "4a1746014a75ade3a714e1db5763276f", "namespace": "2f4316de49999235636386fe51dc06c1", + "namespaces": "2f4316de49999235636386fe51dc06c1", "references": "7997cf5a56cc02bdc9c93361bde732b0", "type": "2f4316de49999235636386fe51dc06c1", "updated_at": "00da57df13e94e9d98437d13ace4bfe0", @@ -36,6 +37,9 @@ Object { "namespace": Object { "type": "keyword", }, + "namespaces": Object { + "type": "keyword", + }, "references": Object { "properties": Object { "id": Object { diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts index c72d3e241b882..c4a03a0e2e7d2 100644 --- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts @@ -187,7 +187,7 @@ describe('POST /internal/saved_objects/_import', () => { references: [], error: { statusCode: 409, - message: 'version conflict, document already exists', + message: 'Saved object [index-pattern/my-pattern] conflict', }, }, { diff --git a/src/core/server/saved_objects/saved_objects_service.test.ts b/src/core/server/saved_objects/saved_objects_service.test.ts index 018117776dcc8..819d79803f371 100644 --- a/src/core/server/saved_objects/saved_objects_service.test.ts +++ b/src/core/server/saved_objects/saved_objects_service.test.ts @@ -138,7 +138,7 @@ describe('SavedObjectsService', () => { const type = { name: 'someType', hidden: false, - namespaceAgnostic: false, + namespaceType: 'single' as 'single', mappings: { properties: {} }, }; setup.registerType(type); @@ -251,7 +251,7 @@ describe('SavedObjectsService', () => { setup.registerType({ name: 'someType', hidden: false, - namespaceAgnostic: false, + namespaceType: 'single' as 'single', mappings: { properties: {} }, }); }).toThrowErrorMatchingInlineSnapshot( diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index 62027928c0bb5..ed4ffef5729ab 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -124,7 +124,7 @@ export interface SavedObjectsServiceSetup { * export const myType: SavedObjectsType = { * name: 'MyType', * hidden: false, - * namespaceAgnostic: true, + * namespaceType: 'multiple', * mappings: { * properties: { * textField: { diff --git a/src/core/server/saved_objects/saved_objects_type_registry.mock.ts b/src/core/server/saved_objects/saved_objects_type_registry.mock.ts index 8c8458d7a5ce4..8bb66859feca2 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.mock.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.mock.ts @@ -27,6 +27,8 @@ const createRegistryMock = (): jest.Mocked type === 'global'); + mock.isSingleNamespace.mockImplementation( + (type: string) => type !== 'global' && type !== 'shared' + ); + mock.isMultiNamespace.mockImplementation((type: string) => type === 'shared'); mock.isImportableAndExportable.mockReturnValue(true); return mock; diff --git a/src/core/server/saved_objects/saved_objects_type_registry.test.ts b/src/core/server/saved_objects/saved_objects_type_registry.test.ts index 4d1d5c1eacc25..84337474f3ee3 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.test.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.test.ts @@ -23,7 +23,7 @@ import { SavedObjectsType } from './types'; const createType = (type: Partial): SavedObjectsType => ({ name: 'unknown', hidden: false, - namespaceAgnostic: false, + namespaceType: 'single' as 'single', mappings: { properties: {} }, migrations: {}, ...type, @@ -164,18 +164,92 @@ describe('SavedObjectTypeRegistry', () => { }); describe('#isNamespaceAgnostic', () => { - it('returns correct value for the type', () => { - registry.registerType(createType({ name: 'typeA', namespaceAgnostic: true })); - registry.registerType(createType({ name: 'typeB', namespaceAgnostic: false })); + const expectResult = (expected: boolean, schemaDefinition?: Partial) => { + registry = new SavedObjectTypeRegistry(); + registry.registerType(createType({ name: 'foo', ...schemaDefinition })); + expect(registry.isNamespaceAgnostic('foo')).toBe(expected); + }; - expect(registry.isNamespaceAgnostic('typeA')).toEqual(true); - expect(registry.isNamespaceAgnostic('typeB')).toEqual(false); + it(`returns false when the type is not registered`, () => { + expect(registry.isNamespaceAgnostic('unknownType')).toEqual(false); }); - it('returns false when the type is not registered', () => { - registry.registerType(createType({ name: 'typeA', namespaceAgnostic: true })); - registry.registerType(createType({ name: 'typeB', namespaceAgnostic: false })); - expect(registry.isNamespaceAgnostic('unknownType')).toEqual(false); + it(`returns true for namespaceType 'agnostic'`, () => { + expectResult(true, { namespaceType: 'agnostic' }); + }); + + it(`returns false for other namespaceType`, () => { + expectResult(false, { namespaceType: 'multiple' }); + expectResult(false, { namespaceType: 'single' }); + expectResult(false, { namespaceType: undefined }); + }); + + // deprecated test cases + it(`returns true when namespaceAgnostic is true`, () => { + expectResult(true, { namespaceAgnostic: true, namespaceType: 'agnostic' }); + expectResult(true, { namespaceAgnostic: true, namespaceType: 'multiple' }); + expectResult(true, { namespaceAgnostic: true, namespaceType: 'single' }); + expectResult(true, { namespaceAgnostic: true, namespaceType: undefined }); + }); + }); + + describe('#isSingleNamespace', () => { + const expectResult = (expected: boolean, schemaDefinition?: Partial) => { + registry = new SavedObjectTypeRegistry(); + registry.registerType(createType({ name: 'foo', ...schemaDefinition })); + expect(registry.isSingleNamespace('foo')).toBe(expected); + }; + + it(`returns true when the type is not registered`, () => { + expect(registry.isSingleNamespace('unknownType')).toEqual(true); + }); + + it(`returns true for namespaceType 'single'`, () => { + expectResult(true, { namespaceType: 'single' }); + expectResult(true, { namespaceType: undefined }); + }); + + it(`returns false for other namespaceType`, () => { + expectResult(false, { namespaceType: 'agnostic' }); + expectResult(false, { namespaceType: 'multiple' }); + }); + + // deprecated test cases + it(`returns false when namespaceAgnostic is true`, () => { + expectResult(false, { namespaceAgnostic: true, namespaceType: 'agnostic' }); + expectResult(false, { namespaceAgnostic: true, namespaceType: 'multiple' }); + expectResult(false, { namespaceAgnostic: true, namespaceType: 'single' }); + expectResult(false, { namespaceAgnostic: true, namespaceType: undefined }); + }); + }); + + describe('#isMultiNamespace', () => { + const expectResult = (expected: boolean, schemaDefinition?: Partial) => { + registry = new SavedObjectTypeRegistry(); + registry.registerType(createType({ name: 'foo', ...schemaDefinition })); + expect(registry.isMultiNamespace('foo')).toBe(expected); + }; + + it(`returns false when the type is not registered`, () => { + expect(registry.isMultiNamespace('unknownType')).toEqual(false); + }); + + it(`returns true for namespaceType 'multiple'`, () => { + expectResult(true, { namespaceType: 'multiple' }); + }); + + it(`returns false for other namespaceType`, () => { + expectResult(false, { namespaceType: 'agnostic' }); + expectResult(false, { namespaceType: 'single' }); + expectResult(false, { namespaceType: undefined }); + }); + + // deprecated test cases + it(`returns false when namespaceAgnostic is true`, () => { + expectResult(false, { namespaceAgnostic: true, namespaceType: 'agnostic' }); + expectResult(false, { namespaceAgnostic: true, namespaceType: 'multiple' }); + expectResult(false, { namespaceAgnostic: true, namespaceType: 'single' }); + expectResult(false, { namespaceAgnostic: true, namespaceType: undefined }); }); }); @@ -206,8 +280,8 @@ describe('SavedObjectTypeRegistry', () => { expect(registry.getIndex('typeWithNoIndex')).toBeUndefined(); }); it('returns undefined when the type is not registered', () => { - registry.registerType(createType({ name: 'typeA', namespaceAgnostic: true })); - registry.registerType(createType({ name: 'typeB', namespaceAgnostic: false })); + registry.registerType(createType({ name: 'typeA', namespaceType: 'agnostic' })); + registry.registerType(createType({ name: 'typeB', namespaceType: 'single' })); expect(registry.getIndex('unknownType')).toBeUndefined(); }); diff --git a/src/core/server/saved_objects/saved_objects_type_registry.ts b/src/core/server/saved_objects/saved_objects_type_registry.ts index 5580ce3815d0d..be3fdb86a994c 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.ts @@ -25,16 +25,7 @@ import { SavedObjectsType } from './types'; * * @public */ -export type ISavedObjectTypeRegistry = Pick< - SavedObjectTypeRegistry, - | 'getType' - | 'getAllTypes' - | 'getIndex' - | 'isNamespaceAgnostic' - | 'isHidden' - | 'getImportableAndExportableTypes' - | 'isImportableAndExportable' ->; +export type ISavedObjectTypeRegistry = Omit; /** * Registry holding information about all the registered {@link SavedObjectsType | saved object types}. @@ -77,11 +68,31 @@ export class SavedObjectTypeRegistry { } /** - * Returns the `namespaceAgnostic` property for given type, or `false` if - * the type is not registered. + * Returns whether the type is namespace-agnostic (global); + * resolves to `false` if the type is not registered */ public isNamespaceAgnostic(type: string) { - return this.types.get(type)?.namespaceAgnostic ?? false; + return ( + this.types.get(type)?.namespaceType === 'agnostic' || + this.types.get(type)?.namespaceAgnostic || + false + ); + } + + /** + * Returns whether the type is single-namespace (isolated); + * resolves to `true` if the type is not registered + */ + public isSingleNamespace(type: string) { + return !this.isNamespaceAgnostic(type) && !this.isMultiNamespace(type); + } + + /** + * Returns whether the type is multi-namespace (shareable); + * resolves to `false` if the type is not registered + */ + public isMultiNamespace(type: string) { + return !this.isNamespaceAgnostic(type) && this.types.get(type)?.namespaceType === 'multiple'; } /** diff --git a/src/core/server/saved_objects/schema/schema.test.ts b/src/core/server/saved_objects/schema/schema.test.ts index 43cf27fbae790..f2daa13e43fce 100644 --- a/src/core/server/saved_objects/schema/schema.test.ts +++ b/src/core/server/saved_objects/schema/schema.test.ts @@ -17,32 +17,90 @@ * under the License. */ -import { SavedObjectsSchema } from './schema'; +import { SavedObjectsSchema, SavedObjectsSchemaDefinition } from './schema'; describe('#isNamespaceAgnostic', () => { + const expectResult = (expected: boolean, schemaDefinition?: SavedObjectsSchemaDefinition) => { + const schema = new SavedObjectsSchema(schemaDefinition); + const result = schema.isNamespaceAgnostic('foo'); + expect(result).toBe(expected); + }; + + it(`returns false when no schema is defined`, () => { + expectResult(false); + }); + it(`returns false for unknown types`, () => { - const schema = new SavedObjectsSchema(); - const result = schema.isNamespaceAgnostic('bar'); - expect(result).toBe(false); + expectResult(false, { bar: {} }); }); - it(`returns true for explicitly namespace agnostic type`, () => { - const schema = new SavedObjectsSchema({ - foo: { - isNamespaceAgnostic: true, - }, - }); - const result = schema.isNamespaceAgnostic('foo'); - expect(result).toBe(true); + it(`returns false for non-namespace-agnostic type`, () => { + expectResult(false, { foo: { isNamespaceAgnostic: false } }); + expectResult(false, { foo: { isNamespaceAgnostic: undefined } }); }); - it(`returns false for explicitly namespaced type`, () => { - const schema = new SavedObjectsSchema({ - foo: { - isNamespaceAgnostic: false, - }, - }); - const result = schema.isNamespaceAgnostic('foo'); - expect(result).toBe(false); + it(`returns true for explicitly namespace-agnostic type`, () => { + expectResult(true, { foo: { isNamespaceAgnostic: true } }); + }); +}); + +describe('#isSingleNamespace', () => { + const expectResult = (expected: boolean, schemaDefinition?: SavedObjectsSchemaDefinition) => { + const schema = new SavedObjectsSchema(schemaDefinition); + const result = schema.isSingleNamespace('foo'); + expect(result).toBe(expected); + }; + + it(`returns true when no schema is defined`, () => { + expectResult(true); + }); + + it(`returns true for unknown types`, () => { + expectResult(true, { bar: {} }); + }); + + it(`returns false for explicitly namespace-agnostic type`, () => { + expectResult(false, { foo: { isNamespaceAgnostic: true } }); + }); + + it(`returns false for explicitly multi-namespace type`, () => { + expectResult(false, { foo: { multiNamespace: true } }); + }); + + it(`returns true for non-namespace-agnostic and non-multi-namespace type`, () => { + expectResult(true, { foo: { isNamespaceAgnostic: false, multiNamespace: false } }); + expectResult(true, { foo: { isNamespaceAgnostic: false, multiNamespace: undefined } }); + expectResult(true, { foo: { isNamespaceAgnostic: undefined, multiNamespace: false } }); + expectResult(true, { foo: { isNamespaceAgnostic: undefined, multiNamespace: undefined } }); + }); +}); + +describe('#isMultiNamespace', () => { + const expectResult = (expected: boolean, schemaDefinition?: SavedObjectsSchemaDefinition) => { + const schema = new SavedObjectsSchema(schemaDefinition); + const result = schema.isMultiNamespace('foo'); + expect(result).toBe(expected); + }; + + it(`returns false when no schema is defined`, () => { + expectResult(false); + }); + + it(`returns false for unknown types`, () => { + expectResult(false, { bar: {} }); + }); + + it(`returns false for explicitly namespace-agnostic type`, () => { + expectResult(false, { foo: { isNamespaceAgnostic: true } }); + }); + + it(`returns false for non-multi-namespace type`, () => { + expectResult(false, { foo: { multiNamespace: false } }); + expectResult(false, { foo: { multiNamespace: undefined } }); + }); + + it(`returns true for non-namespace-agnostic and explicitly multi-namespace type`, () => { + expectResult(true, { foo: { isNamespaceAgnostic: false, multiNamespace: true } }); + expectResult(true, { foo: { isNamespaceAgnostic: undefined, multiNamespace: true } }); }); }); diff --git a/src/core/server/saved_objects/schema/schema.ts b/src/core/server/saved_objects/schema/schema.ts index 17ca406ea109a..ba1905158e822 100644 --- a/src/core/server/saved_objects/schema/schema.ts +++ b/src/core/server/saved_objects/schema/schema.ts @@ -24,7 +24,8 @@ import { LegacyConfig } from '../../legacy'; * @internal **/ interface SavedObjectsSchemaTypeDefinition { - isNamespaceAgnostic: boolean; + isNamespaceAgnostic?: boolean; + multiNamespace?: boolean; hidden?: boolean; indexPattern?: ((config: LegacyConfig) => string) | string; convertToAliasScript?: string; @@ -72,7 +73,7 @@ export class SavedObjectsSchema { } public isNamespaceAgnostic(type: string) { - // if no plugins have registered a uiExports.savedObjectSchemas, + // if no plugins have registered a Saved Objects Schema, // this.schema will be undefined, and no types are namespace agnostic if (!this.definition) { return false; @@ -84,4 +85,32 @@ export class SavedObjectsSchema { } return Boolean(typeSchema.isNamespaceAgnostic); } + + public isSingleNamespace(type: string) { + // if no plugins have registered a Saved Objects Schema, + // this.schema will be undefined, and all types are namespace isolated + if (!this.definition) { + return true; + } + + const typeSchema = this.definition[type]; + if (!typeSchema) { + return true; + } + return !Boolean(typeSchema.isNamespaceAgnostic) && !Boolean(typeSchema.multiNamespace); + } + + public isMultiNamespace(type: string) { + // if no plugins have registered a Saved Objects Schema, + // this.schema will be undefined, and no types are multi-namespace + if (!this.definition) { + return false; + } + + const typeSchema = this.definition[type]; + if (!typeSchema) { + return false; + } + return !Boolean(typeSchema.isNamespaceAgnostic) && Boolean(typeSchema.multiNamespace); + } } diff --git a/src/core/server/saved_objects/serialization/serializer.test.ts b/src/core/server/saved_objects/serialization/serializer.test.ts index 8f09b25bb3908..1a7dfdd2d130e 100644 --- a/src/core/server/saved_objects/serialization/serializer.test.ts +++ b/src/core/server/saved_objects/serialization/serializer.test.ts @@ -19,101 +19,101 @@ import _ from 'lodash'; import { SavedObjectsSerializer } from './serializer'; +import { SavedObjectsRawDoc } from './types'; import { typeRegistryMock } from '../saved_objects_type_registry.mock'; import { encodeVersion } from '../version'; -describe('saved object conversion', () => { - let typeRegistry: ReturnType; - - beforeEach(() => { - typeRegistry = typeRegistryMock.create(); - typeRegistry.isNamespaceAgnostic.mockReturnValue(false); +let typeRegistry = typeRegistryMock.create(); +typeRegistry.isNamespaceAgnostic.mockReturnValue(true); +typeRegistry.isSingleNamespace.mockReturnValue(false); +typeRegistry.isMultiNamespace.mockReturnValue(false); +const namespaceAgnosticSerializer = new SavedObjectsSerializer(typeRegistry); + +typeRegistry = typeRegistryMock.create(); +typeRegistry.isNamespaceAgnostic.mockReturnValue(false); +typeRegistry.isSingleNamespace.mockReturnValue(true); +typeRegistry.isMultiNamespace.mockReturnValue(false); +const singleNamespaceSerializer = new SavedObjectsSerializer(typeRegistry); + +typeRegistry = typeRegistryMock.create(); +typeRegistry.isNamespaceAgnostic.mockReturnValue(false); +typeRegistry.isSingleNamespace.mockReturnValue(false); +typeRegistry.isMultiNamespace.mockReturnValue(true); +const multiNamespaceSerializer = new SavedObjectsSerializer(typeRegistry); + +const sampleTemplate = { + _id: 'foo:bar', + _source: { + type: 'foo', + }, +}; +const createSampleDoc = (raw: any, template = sampleTemplate): SavedObjectsRawDoc => + _.defaultsDeep(raw, template); + +describe('#rawToSavedObject', () => { + test('it copies the _source.type property to type', () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _source: { + type: 'foo', + }, + }); + expect(actual).toHaveProperty('type', 'foo'); }); - describe('#rawToSavedObject', () => { - test('it copies the _source.type property to type', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - }, - }); - expect(actual).toHaveProperty('type', 'foo'); + test('it copies the _source.references property to references', () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _source: { + type: 'foo', + references: [{ name: 'ref_0', type: 'index-pattern', id: 'pattern*' }], + }, }); + expect(actual).toHaveProperty('references', [ + { + name: 'ref_0', + type: 'index-pattern', + id: 'pattern*', + }, + ]); + }); - test('it copies the _source.references property to references', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - references: [{ name: 'ref_0', type: 'index-pattern', id: 'pattern*' }], - }, - }); - expect(actual).toHaveProperty('references', [ - { - name: 'ref_0', - type: 'index-pattern', - id: 'pattern*', + test('if specified it copies the _source.migrationVersion property to migrationVersion', () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _source: { + type: 'foo', + migrationVersion: { + hello: '1.2.3', + acl: '33.3.5', }, - ]); + }, }); - - test('if specified it copies the _source.migrationVersion property to migrationVersion', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - migrationVersion: { - hello: '1.2.3', - acl: '33.3.5', - }, - }, - }); - expect(actual).toHaveProperty('migrationVersion', { - hello: '1.2.3', - acl: '33.3.5', - }); + expect(actual).toHaveProperty('migrationVersion', { + hello: '1.2.3', + acl: '33.3.5', }); + }); - test(`if _source.migrationVersion is unspecified it doesn't set migrationVersion`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - }, - }); - expect(actual).not.toHaveProperty('migrationVersion'); + test(`if _source.migrationVersion is unspecified it doesn't set migrationVersion`, () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _source: { + type: 'foo', + }, }); + expect(actual).not.toHaveProperty('migrationVersion'); + }); - test('it converts the id and type properties, and retains migrationVersion', () => { - const now = String(new Date()); - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'hello:world', - _seq_no: 3, - _primary_term: 1, - _source: { - type: 'hello', - hello: { - a: 'b', - c: 'd', - }, - migrationVersion: { - hello: '1.2.3', - acl: '33.3.5', - }, - updated_at: now, - }, - }); - const expected = { - id: 'world', + test('it converts the id and type properties, and retains migrationVersion', () => { + const now = String(new Date()); + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'hello:world', + _seq_no: 3, + _primary_term: 1, + _source: { type: 'hello', - version: encodeVersion(3, 1), - attributes: { + hello: { a: 'b', c: 'd', }, @@ -122,909 +122,937 @@ describe('saved object conversion', () => { acl: '33.3.5', }, updated_at: now, - references: [], - }; - expect(expected).toEqual(actual); + }, + }); + const expected = { + id: 'world', + type: 'hello', + version: encodeVersion(3, 1), + attributes: { + a: 'b', + c: 'd', + }, + migrationVersion: { + hello: '1.2.3', + acl: '33.3.5', + }, + updated_at: now, + references: [], + }; + expect(expected).toEqual(actual); + }); + + test(`if version is unspecified it doesn't set version`, () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _source: { + type: 'foo', + hello: {}, + }, }); + expect(actual).not.toHaveProperty('version'); + }); - test(`if version is unspecified it doesn't set version`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ + test(`if specified it encodes _seq_no and _primary_term to version`, () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _seq_no: 4, + _primary_term: 1, + _source: { + type: 'foo', + hello: {}, + }, + }); + expect(actual).toHaveProperty('version', encodeVersion(4, 1)); + }); + + test(`if only _seq_no is specified it throws`, () => { + expect(() => + singleNamespaceSerializer.rawToSavedObject({ _id: 'foo:bar', + _seq_no: 4, _source: { type: 'foo', hello: {}, }, - }); - expect(actual).not.toHaveProperty('version'); - }); + }) + ).toThrowErrorMatchingInlineSnapshot(`"_primary_term from elasticsearch must be an integer"`); + }); - test(`if specified it encodes _seq_no and _primary_term to version`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ + test(`if only _primary_term is throws`, () => { + expect(() => + singleNamespaceSerializer.rawToSavedObject({ _id: 'foo:bar', - _seq_no: 4, _primary_term: 1, _source: { type: 'foo', hello: {}, }, - }); - expect(actual).toHaveProperty('version', encodeVersion(4, 1)); - }); + }) + ).toThrowErrorMatchingInlineSnapshot(`"_seq_no from elasticsearch must be an integer"`); + }); - test(`if only _seq_no is specified it throws`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect(() => - serializer.rawToSavedObject({ - _id: 'foo:bar', - _seq_no: 4, - _source: { - type: 'foo', - hello: {}, - }, - }) - ).toThrowErrorMatchingInlineSnapshot(`"_primary_term from elasticsearch must be an integer"`); + test('if specified it copies the _source.updated_at property to updated_at', () => { + const now = Date(); + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _source: { + type: 'foo', + updated_at: now, + }, }); + expect(actual).toHaveProperty('updated_at', now); + }); - test(`if only _primary_term is throws`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect(() => - serializer.rawToSavedObject({ - _id: 'foo:bar', - _primary_term: 1, - _source: { - type: 'foo', - hello: {}, - }, - }) - ).toThrowErrorMatchingInlineSnapshot(`"_seq_no from elasticsearch must be an integer"`); + test(`if _source.updated_at is unspecified it doesn't set updated_at`, () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'foo:bar', + _source: { + type: 'foo', + }, }); + expect(actual).not.toHaveProperty('updated_at'); + }); - test('if specified it copies the _source.updated_at property to updated_at', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const now = Date(); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - updated_at: now, + test('it does not pass unknown properties through', () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'universe', + _source: { + type: 'hello', + hello: { + world: 'earth', }, - }); - expect(actual).toHaveProperty('updated_at', now); + banjo: 'Steve Martin', + }, + }); + expect(actual).toEqual({ + id: 'universe', + type: 'hello', + attributes: { + world: 'earth', + }, + references: [], }); + }); - test(`if _source.updated_at is unspecified it doesn't set updated_at`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - }, - }); - expect(actual).not.toHaveProperty('updated_at'); + test('it does not create attributes if [type] is missing', () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'universe', + _source: { + type: 'hello', + }, }); + expect(actual).toEqual({ + id: 'universe', + type: 'hello', + references: [], + }); + }); - test('it does not pass unknown properties through', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ + test('it fails for documents which do not specify a type', () => { + expect(() => + singleNamespaceSerializer.rawToSavedObject({ _id: 'universe', _source: { - type: 'hello', hello: { world: 'earth', }, - banjo: 'Steve Martin', + } as any, + }) + ).toThrow(/Expected "undefined" to be a saved object type/); + }); + + test('it is complimentary with savedObjectToRaw', () => { + const raw = { + _id: 'foo-namespace:foo:bar', + _primary_term: 24, + _seq_no: 42, + _source: { + type: 'foo', + foo: { + meaning: 42, + nested: { stuff: 'here' }, }, - }); - expect(actual).toEqual({ - id: 'universe', - type: 'hello', - attributes: { - world: 'earth', + migrationVersion: { + foo: '1.2.3', + bar: '9.8.7', }, + namespace: 'foo-namespace', + updated_at: String(new Date()), references: [], - }); - }); + }, + }; + + expect( + singleNamespaceSerializer.savedObjectToRaw( + singleNamespaceSerializer.rawToSavedObject(_.cloneDeep(raw)) + ) + ).toEqual(raw); + }); - test('it does not create attributes if [type] is missing', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'universe', - _source: { - type: 'hello', - }, - }); - expect(actual).toEqual({ - id: 'universe', + test('it handles unprefixed ids', () => { + const actual = singleNamespaceSerializer.rawToSavedObject({ + _id: 'universe', + _source: { type: 'hello', - references: [], - }); + }, }); - test('it fails for documents which do not specify a type', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect(() => - serializer.rawToSavedObject({ - _id: 'universe', - _source: { - hello: { - world: 'earth', - }, - } as any, - }) - ).toThrow(/Expected "undefined" to be a saved object type/); + expect(actual).toHaveProperty('id', 'universe'); + }); + + describe('namespace-agnostic type with a namespace', () => { + const raw = createSampleDoc({ _source: { namespace: 'baz' } }); + const actual = namespaceAgnosticSerializer.rawToSavedObject(raw); + + test(`removes type prefix from _id`, () => { + expect(actual).toHaveProperty('id', 'bar'); }); - test('it is complimentary with savedObjectToRaw', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const raw = { - _id: 'foo-namespace:foo:bar', - _primary_term: 24, - _seq_no: 42, - _source: { - type: 'foo', - foo: { - meaning: 42, - nested: { stuff: 'here' }, - }, - migrationVersion: { - foo: '1.2.3', - bar: '9.8.7', - }, - namespace: 'foo-namespace', - updated_at: String(new Date()), - references: [], - }, - }; + test(`copies _id to id if prefixed by namespace and type`, () => { + const _id = `${raw._source.namespace}:${raw._id}`; + const _actual = namespaceAgnosticSerializer.rawToSavedObject({ ...raw, _id }); + expect(_actual).toHaveProperty('id', _id); + }); - expect(serializer.savedObjectToRaw(serializer.rawToSavedObject(_.cloneDeep(raw)))).toEqual( - raw - ); + test(`doesn't copy _source.namespace to namespace`, () => { + expect(actual).not.toHaveProperty('namespace'); }); + }); - test('it handles unprefixed ids', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'universe', - _source: { - type: 'hello', - }, - }); + describe('namespace-agnostic type with namespaces', () => { + const raw = createSampleDoc({ _source: { namespaces: ['baz'] } }); + const actual = namespaceAgnosticSerializer.rawToSavedObject(raw); - expect(actual).toHaveProperty('id', 'universe'); + test(`doesn't copy _source.namespaces to namespaces`, () => { + expect(actual).not.toHaveProperty('namespaces'); }); + }); - describe('namespaced type without a namespace', () => { - test(`removes type prefix from _id`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - }, - }); + describe('single-namespace type without a namespace', () => { + const raw = createSampleDoc({}); + const actual = singleNamespaceSerializer.rawToSavedObject(raw); - expect(actual).toHaveProperty('id', 'bar'); - }); + test(`removes type prefix from _id`, () => { + expect(actual).toHaveProperty('id', 'bar'); + }); - test(`if prefixed by random prefix and type it copies _id to id`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'random:foo:bar', - _source: { - type: 'foo', - }, - }); + test(`copies _id to id if prefixed by random prefix and type`, () => { + const _id = `random:${raw._id}`; + const _actual = singleNamespaceSerializer.rawToSavedObject({ ...raw, _id }); + expect(_actual).toHaveProperty('id', _id); + }); - expect(actual).toHaveProperty('id', 'random:foo:bar'); - }); + test(`doesn't specify namespace`, () => { + expect(actual).not.toHaveProperty('namespace'); + }); + }); - test(`doesn't specify namespace`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - }, - }); + describe('single-namespace type with a namespace', () => { + const namespace = 'baz'; + const raw = createSampleDoc({ _source: { namespace } }); + const actual = singleNamespaceSerializer.rawToSavedObject(raw); - expect(actual).not.toHaveProperty('namespace'); - }); + test(`removes type and namespace prefix from _id`, () => { + const _id = `${namespace}:${raw._id}`; + const _actual = singleNamespaceSerializer.rawToSavedObject({ ...raw, _id }); + expect(_actual).toHaveProperty('id', 'bar'); }); - describe('namespaced type with a namespace', () => { - test(`removes type and namespace prefix from _id`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'baz:foo:bar', - _source: { - type: 'foo', - namespace: 'baz', - }, - }); + test(`copies _id to id if prefixed only by type`, () => { + expect(actual).toHaveProperty('id', raw._id); + }); - expect(actual).toHaveProperty('id', 'bar'); - }); + test(`copies _id to id if prefixed by random prefix and type`, () => { + const _id = `random:${raw._id}`; + const _actual = singleNamespaceSerializer.rawToSavedObject({ ...raw, _id }); + expect(_actual).toHaveProperty('id', _id); + }); - test(`if prefixed by only type it copies _id to id`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - namespace: 'baz', - }, - }); + test(`copies _source.namespace to namespace`, () => { + expect(actual).toHaveProperty('namespace', 'baz'); + }); + }); - expect(actual).toHaveProperty('id', 'foo:bar'); - }); + describe('single-namespace type with namespaces', () => { + const raw = createSampleDoc({ _source: { namespaces: ['baz'] } }); + const actual = singleNamespaceSerializer.rawToSavedObject(raw); - test(`if prefixed by random prefix and type it copies _id to id`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'random:foo:bar', - _source: { - type: 'foo', - namespace: 'baz', - }, - }); + test(`doesn't copy _source.namespaces to namespaces`, () => { + expect(actual).not.toHaveProperty('namespaces'); + }); + }); - expect(actual).toHaveProperty('id', 'random:foo:bar'); - }); + describe('multi-namespace type with a namespace', () => { + const raw = createSampleDoc({ _source: { namespace: 'baz' } }); + const actual = multiNamespaceSerializer.rawToSavedObject(raw); - test(`copies _source.namespace to namespace`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'baz:foo:bar', - _source: { - type: 'foo', - namespace: 'baz', - }, - }); + test(`removes type prefix from _id`, () => { + expect(actual).toHaveProperty('id', 'bar'); + }); - expect(actual).toHaveProperty('namespace', 'baz'); - }); + test(`copies _id to id if prefixed by namespace and type`, () => { + const _id = `${raw._source.namespace}:${raw._id}`; + const _actual = multiNamespaceSerializer.rawToSavedObject({ ...raw, _id }); + expect(_actual).toHaveProperty('id', _id); }); - describe('namespace agnostic type with a namespace', () => { - beforeEach(() => { - typeRegistry.isNamespaceAgnostic.mockReturnValue(true); - }); + test(`doesn't copy _source.namespace to namespace`, () => { + expect(actual).not.toHaveProperty('namespace'); + }); + }); - test(`removes type prefix from _id`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'foo:bar', - _source: { - type: 'foo', - namespace: 'baz', - }, - }); + describe('multi-namespace type with namespaces', () => { + const raw = createSampleDoc({ _source: { namespaces: ['baz'] } }); + const actual = multiNamespaceSerializer.rawToSavedObject(raw); - expect(actual).toHaveProperty('id', 'bar'); - }); + test(`copies _source.namespaces to namespaces`, () => { + expect(actual).toHaveProperty('namespaces', ['baz']); + }); + }); +}); - test(`if prefixed by namespace and type it copies _id to id`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'baz:foo:bar', - _source: { - type: 'foo', - namespace: 'baz', - }, - }); +describe('#savedObjectToRaw', () => { + test('it copies the type property to _source.type and uses the ROOT_TYPE as _type', () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + attributes: {}, + } as any); - expect(actual).toHaveProperty('id', 'baz:foo:bar'); - }); + expect(actual._source).toHaveProperty('type', 'foo'); + }); - test(`doesn't copy _source.namespace to namespace`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.rawToSavedObject({ - _id: 'baz:foo:bar', - _source: { - type: 'foo', - namespace: 'baz', - }, - }); + test('it copies the references property to _source.references', () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + id: '1', + type: 'foo', + attributes: {}, + references: [{ name: 'ref_0', type: 'index-pattern', id: 'pattern*' }], + }); + expect(actual._source).toHaveProperty('references', [ + { + name: 'ref_0', + type: 'index-pattern', + id: 'pattern*', + }, + ]); + }); + + test('if specified it copies the updated_at property to _source.updated_at', () => { + const now = new Date(); + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: '', + attributes: {}, + updated_at: now, + } as any); + + expect(actual._source).toHaveProperty('updated_at', now); + }); + + test(`if unspecified it doesn't add updated_at property to _source`, () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: '', + attributes: {}, + } as any); - expect(actual).not.toHaveProperty('namespace'); - }); + expect(actual._source).not.toHaveProperty('updated_at'); + }); + + test('it copies the migrationVersion property to _source.migrationVersion', () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: '', + attributes: {}, + migrationVersion: { + foo: '1.2.3', + bar: '9.8.7', + }, + } as any); + + expect(actual._source).toHaveProperty('migrationVersion', { + foo: '1.2.3', + bar: '9.8.7', }); }); - describe('#savedObjectToRaw', () => { - test('it copies the type property to _source.type and uses the ROOT_TYPE as _type', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: 'foo', + test(`if unspecified it doesn't add migrationVersion property to _source`, () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: '', + attributes: {}, + } as any); + + expect(actual._source).not.toHaveProperty('migrationVersion'); + }); + + test('it decodes the version property to _seq_no and _primary_term', () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: '', + attributes: {}, + version: encodeVersion(1, 2), + } as any); + + expect(actual).toHaveProperty('_seq_no', 1); + expect(actual).toHaveProperty('_primary_term', 2); + }); + + test(`if unspecified it doesn't add _seq_no or _primary_term properties`, () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: '', + attributes: {}, + } as any); + + expect(actual).not.toHaveProperty('_seq_no'); + expect(actual).not.toHaveProperty('_primary_term'); + }); + + test(`if version invalid it throws`, () => { + expect(() => + singleNamespaceSerializer.savedObjectToRaw({ + type: '', attributes: {}, - } as any); + version: 'foo', + } as any) + ).toThrowErrorMatchingInlineSnapshot(`"Invalid version [foo]"`); + }); - expect(actual._source).toHaveProperty('type', 'foo'); + test('it copies attributes to _source[type]', () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + attributes: { + foo: true, + bar: 'quz', + }, + } as any); + + expect(actual._source).toHaveProperty('foo', { + foo: true, + bar: 'quz', }); + }); - test('it copies the references property to _source.references', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - id: '1', + describe('single-namespace type without a namespace', () => { + test('generates an id prefixed with type, if no id is specified', () => { + const v1 = singleNamespaceSerializer.savedObjectToRaw({ type: 'foo', - attributes: {}, - references: [{ name: 'ref_0', type: 'index-pattern', id: 'pattern*' }], - }); - expect(actual._source).toHaveProperty('references', [ - { - name: 'ref_0', - type: 'index-pattern', - id: 'pattern*', - }, - ]); + attributes: { bar: true }, + } as any); + + const v2 = singleNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + attributes: { bar: true }, + } as any); + + expect(v1._id).toMatch(/^foo\:[\w-]+$/); + expect(v1._id).not.toEqual(v2._id); }); - test('if specified it copies the updated_at property to _source.updated_at', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const now = new Date(); - const actual = serializer.savedObjectToRaw({ + test(`doesn't specify _source.namespace`, () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ type: '', attributes: {}, - updated_at: now, } as any); - expect(actual._source).toHaveProperty('updated_at', now); + expect(actual._source).not.toHaveProperty('namespace'); }); + }); - test(`if unspecified it doesn't add updated_at property to _source`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: '', + describe('single-namespace type with a namespace', () => { + test('generates an id prefixed with namespace and type, if no id is specified', () => { + const v1 = singleNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', + attributes: { bar: true }, + } as any); + + const v2 = singleNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', + attributes: { bar: true }, + } as any); + + expect(v1._id).toMatch(/^bar\:foo\:[\w-]+$/); + expect(v1._id).not.toEqual(v2._id); + }); + + test(`it copies namespace to _source.namespace`, () => { + const actual = singleNamespaceSerializer.savedObjectToRaw({ + type: 'foo', attributes: {}, + namespace: 'bar', } as any); - expect(actual._source).not.toHaveProperty('updated_at'); + expect(actual._source).toHaveProperty('namespace', 'bar'); }); + }); - test('it copies the migrationVersion property to _source.migrationVersion', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: '', + describe('single-namespace type with namespaces', () => { + test('generates an id prefixed with type, if no id is specified', () => { + const v1 = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], + attributes: { bar: true }, + } as any); + + const v2 = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], + attributes: { bar: true }, + } as any); + + expect(v1._id).toMatch(/^foo\:[\w-]+$/); + expect(v1._id).not.toEqual(v2._id); + }); + + test(`doesn't specify _source.namespaces`, () => { + const actual = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], attributes: {}, - migrationVersion: { - foo: '1.2.3', - bar: '9.8.7', - }, } as any); - expect(actual._source).toHaveProperty('migrationVersion', { - foo: '1.2.3', - bar: '9.8.7', - }); + expect(actual._source).not.toHaveProperty('namespaces'); }); + }); - test(`if unspecified it doesn't add migrationVersion property to _source`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: '', + describe('namespace-agnostic type with a namespace', () => { + test('generates an id prefixed with type, if no id is specified', () => { + const v1 = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', + attributes: { bar: true }, + } as any); + + const v2 = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', + attributes: { bar: true }, + } as any); + + expect(v1._id).toMatch(/^foo\:[\w-]+$/); + expect(v1._id).not.toEqual(v2._id); + }); + + test(`doesn't specify _source.namespace`, () => { + const actual = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', attributes: {}, } as any); - expect(actual._source).not.toHaveProperty('migrationVersion'); + expect(actual._source).not.toHaveProperty('namespace'); }); + }); - test('it decodes the version property to _seq_no and _primary_term', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: '', + describe('namespace-agnostic type with namespaces', () => { + test('generates an id prefixed with type, if no id is specified', () => { + const v1 = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], + attributes: { bar: true }, + } as any); + + const v2 = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], + attributes: { bar: true }, + } as any); + + expect(v1._id).toMatch(/^foo\:[\w-]+$/); + expect(v1._id).not.toEqual(v2._id); + }); + + test(`doesn't specify _source.namespaces`, () => { + const actual = namespaceAgnosticSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], attributes: {}, - version: encodeVersion(1, 2), } as any); - expect(actual).toHaveProperty('_seq_no', 1); - expect(actual).toHaveProperty('_primary_term', 2); + expect(actual._source).not.toHaveProperty('namespaces'); }); + }); - test(`if unspecified it doesn't add _seq_no or _primary_term properties`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: '', + describe('multi-namespace type with a namespace', () => { + test('generates an id prefixed with type, if no id is specified', () => { + const v1 = multiNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', + attributes: { bar: true }, + } as any); + + const v2 = multiNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', + attributes: { bar: true }, + } as any); + + expect(v1._id).toMatch(/^foo\:[\w-]+$/); + expect(v1._id).not.toEqual(v2._id); + }); + + test(`doesn't specify _source.namespace`, () => { + const actual = multiNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + namespace: 'bar', attributes: {}, } as any); - expect(actual).not.toHaveProperty('_seq_no'); - expect(actual).not.toHaveProperty('_primary_term'); + expect(actual._source).not.toHaveProperty('namespace'); }); + }); + + describe('multi-namespace type with namespaces', () => { + test('generates an id prefixed with type, if no id is specified', () => { + const v1 = multiNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], + attributes: { bar: true }, + } as any); + + const v2 = multiNamespaceSerializer.savedObjectToRaw({ + type: 'foo', + namespaces: ['bar'], + attributes: { bar: true }, + } as any); - test(`if version invalid it throws`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect(() => - serializer.savedObjectToRaw({ - type: '', - attributes: {}, - version: 'foo', - } as any) - ).toThrowErrorMatchingInlineSnapshot(`"Invalid version [foo]"`); + expect(v1._id).toMatch(/^foo\:[\w-]+$/); + expect(v1._id).not.toEqual(v2._id); }); - test('it copies attributes to _source[type]', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ + test(`it copies namespaces to _source.namespaces`, () => { + const actual = multiNamespaceSerializer.savedObjectToRaw({ type: 'foo', - attributes: { - foo: true, - bar: 'quz', - }, + namespaces: ['bar'], + attributes: {}, } as any); - expect(actual._source).toHaveProperty('foo', { - foo: true, - bar: 'quz', - }); + expect(actual._source).toHaveProperty('namespaces', ['bar']); }); + }); +}); - describe('namespaced type without a namespace', () => { - test('generates an id prefixed with type, if no id is specified', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const v1 = serializer.savedObjectToRaw({ - type: 'foo', - attributes: { - bar: true, +describe('#isRawSavedObject', () => { + describe('single-namespace type without a namespace', () => { + test('is true if the id is prefixed and the type matches', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'hello', + hello: {}, }, - } as any); + }) + ).toBeTruthy(); + }); - const v2 = serializer.savedObjectToRaw({ - type: 'foo', - attributes: { - bar: true, + test('is false if the id is not prefixed', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'world', + _source: { + type: 'hello', + hello: {}, }, - } as any); + }) + ).toBeFalsy(); + }); - expect(v1._id).toMatch(/foo\:[\w-]+$/); - expect(v1._id).not.toEqual(v2._id); - }); + test('is false if the type attribute is missing', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + hello: {}, + } as any, + }) + ).toBeFalsy(); + }); - test(`doesn't specify _source.namespace`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: '', - attributes: {}, - } as any); + test(`is false if the type prefix omits the :`, () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'helloworld', + _source: { + type: 'hello', + hello: {}, + }, + }) + ).toBeFalsy(); + }); - expect(actual._source).not.toHaveProperty('namespace'); - }); + test('is false if the type attribute does not match the id', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'jam', + jam: {}, + hello: {}, + }, + }) + ).toBeFalsy(); }); - describe('namespaced type with a namespace', () => { - test('generates an id prefixed with namespace and type, if no id is specified', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const v1 = serializer.savedObjectToRaw({ - type: 'foo', - namespace: 'bar', - attributes: { - bar: true, + test('is false if there is no [type] attribute', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'hello', + jam: {}, }, - } as any); + }) + ).toBeFalsy(); + }); + }); - const v2 = serializer.savedObjectToRaw({ - type: 'foo', - namespace: 'bar', - attributes: { - bar: true, + describe('single-namespace type with a namespace', () => { + test('is true if the id is prefixed with type and namespace and the type matches', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'foo:hello:world', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', }, - } as any); + }) + ).toBeTruthy(); + }); - expect(v1._id).toMatch(/bar\:foo\:[\w-]+$/); - expect(v1._id).not.toEqual(v2._id); - }); + test('is false if the id is not prefixed by anything', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'world', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); - test(`it copies namespace to _source.namespace`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: 'foo', - attributes: {}, - namespace: 'bar', - } as any); + test('is false if the id is prefixed only with type and the type matches', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); + + test('is false if the id is prefixed only with namespace and the namespace matches', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'foo:world', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); - expect(actual._source).toHaveProperty('namespace', 'bar'); - }); + test(`is false if the id prefix omits the trailing :`, () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'foo:helloworld', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); }); - describe('namespace agnostic type with a namespace', () => { - beforeEach(() => { - typeRegistry.isNamespaceAgnostic.mockReturnValue(true); - }); + test('is false if the type attribute is missing', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'foo:hello:world', + _source: { + hello: {}, + namespace: 'foo', + } as any, + }) + ).toBeFalsy(); + }); - test('generates an id prefixed with type, if no id is specified', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const v1 = serializer.savedObjectToRaw({ - type: 'foo', - namespace: 'bar', - attributes: { - bar: true, + test('is false if the type attribute does not match the id', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'foo:hello:world', + _source: { + type: 'jam', + jam: {}, + hello: {}, + namespace: 'foo', }, - } as any); + }) + ).toBeFalsy(); + }); - const v2 = serializer.savedObjectToRaw({ - type: 'foo', - namespace: 'bar', - attributes: { - bar: true, + test('is false if the namespace attribute does not match the id', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'bar:jam:world', + _source: { + type: 'jam', + jam: {}, + hello: {}, + namespace: 'foo', }, - } as any); + }) + ).toBeFalsy(); + }); - expect(v1._id).toMatch(/foo\:[\w-]+$/); - expect(v1._id).not.toEqual(v2._id); - }); + test('is false if there is no [type] attribute', () => { + expect( + singleNamespaceSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'hello', + jam: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); + }); - test(`doesn't specify _source.namespace`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const actual = serializer.savedObjectToRaw({ - type: 'foo', - namespace: 'bar', - attributes: {}, - } as any); + describe('namespace-agnostic type with a namespace', () => { + test('is true if the id is prefixed with type and the type matches', () => { + expect( + namespaceAgnosticSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeTruthy(); + }); + + test('is false if the id is not prefixed', () => { + expect( + namespaceAgnosticSerializer.isRawSavedObject({ + _id: 'world', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); + + test('is false if the id is prefixed with type and namespace', () => { + expect( + namespaceAgnosticSerializer.isRawSavedObject({ + _id: 'foo:hello:world', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); + + test(`is false if the type prefix omits the :`, () => { + expect( + namespaceAgnosticSerializer.isRawSavedObject({ + _id: 'helloworld', + _source: { + type: 'hello', + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); + + test('is false if the type attribute is missing', () => { + expect( + namespaceAgnosticSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + hello: {}, + namespace: 'foo', + } as any, + }) + ).toBeFalsy(); + }); + + test('is false if the type attribute does not match the id', () => { + expect( + namespaceAgnosticSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'jam', + jam: {}, + hello: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); + + test('is false if there is no [type] attribute', () => { + expect( + namespaceAgnosticSerializer.isRawSavedObject({ + _id: 'hello:world', + _source: { + type: 'hello', + jam: {}, + namespace: 'foo', + }, + }) + ).toBeFalsy(); + }); + }); +}); - expect(actual._source).not.toHaveProperty('namespace'); - }); +describe('#generateRawId', () => { + describe('single-namespace type without a namespace', () => { + test('generates an id if none is specified', () => { + const id = singleNamespaceSerializer.generateRawId('', 'goodbye'); + expect(id).toMatch(/^goodbye\:[\w-]+$/); + }); + + test('uses the id that is specified', () => { + const id = singleNamespaceSerializer.generateRawId('', 'hello', 'world'); + expect(id).toEqual('hello:world'); }); }); - describe('#isRawSavedObject', () => { - describe('namespaced type without a namespace', () => { - test('is true if the id is prefixed and the type matches', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'hello', - hello: {}, - }, - }) - ).toBeTruthy(); - }); - - test('is false if the id is not prefixed', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'world', - _source: { - type: 'hello', - hello: {}, - }, - }) - ).toBeFalsy(); - }); - - test('is false if the type attribute is missing', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - hello: {}, - } as any, - }) - ).toBeFalsy(); - }); - - test(`is false if the type prefix omits the :`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'helloworld', - _source: { - type: 'hello', - hello: {}, - }, - }) - ).toBeFalsy(); - }); - - test('is false if the type attribute does not match the id', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'jam', - jam: {}, - hello: {}, - }, - }) - ).toBeFalsy(); - }); - - test('is false if there is no [type] attribute', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'hello', - jam: {}, - }, - }) - ).toBeFalsy(); - }); - }); - - describe('namespaced type with a namespace', () => { - test('is true if the id is prefixed with type and namespace and the type matches', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'foo:hello:world', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeTruthy(); - }); - - test('is false if the id is not prefixed by anything', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'world', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if the id is prefixed only with type and the type matches', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if the id is prefixed only with namespace and the namespace matches', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'foo:world', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test(`is false if the id prefix omits the trailing :`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'foo:helloworld', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if the type attribute is missing', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'foo:hello:world', - _source: { - hello: {}, - namespace: 'foo', - } as any, - }) - ).toBeFalsy(); - }); - - test('is false if the type attribute does not match the id', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'foo:hello:world', - _source: { - type: 'jam', - jam: {}, - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if the namespace attribute does not match the id', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'bar:jam:world', - _source: { - type: 'jam', - jam: {}, - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if there is no [type] attribute', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'hello', - jam: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - }); - - describe('namespace agnostic type with a namespace', () => { - beforeEach(() => { - typeRegistry.isNamespaceAgnostic.mockReturnValue(true); - }); - - test('is true if the id is prefixed with type and the type matches', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeTruthy(); - }); - - test('is false if the id is not prefixed', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'world', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if the id is prefixed with type and namespace', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'foo:hello:world', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test(`is false if the type prefix omits the :`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'helloworld', - _source: { - type: 'hello', - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if the type attribute is missing', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - hello: {}, - namespace: 'foo', - } as any, - }) - ).toBeFalsy(); - }); - - test('is false if the type attribute does not match the id', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'jam', - jam: {}, - hello: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); - - test('is false if there is no [type] attribute', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - expect( - serializer.isRawSavedObject({ - _id: 'hello:world', - _source: { - type: 'hello', - jam: {}, - namespace: 'foo', - }, - }) - ).toBeFalsy(); - }); + describe('single-namespace type with a namespace', () => { + test('generates an id if none is specified and prefixes namespace', () => { + const id = singleNamespaceSerializer.generateRawId('foo', 'goodbye'); + expect(id).toMatch(/^foo:goodbye\:[\w-]+$/); + }); + + test('uses the id that is specified and prefixes the namespace', () => { + const id = singleNamespaceSerializer.generateRawId('foo', 'hello', 'world'); + expect(id).toEqual('foo:hello:world'); }); }); - describe('#generateRawId', () => { - describe('namespaced type without a namespace', () => { - test('generates an id if none is specified', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const id = serializer.generateRawId('', 'goodbye'); - expect(id).toMatch(/goodbye\:[\w-]+$/); - }); - - test('uses the id that is specified', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const id = serializer.generateRawId('', 'hello', 'world'); - expect(id).toMatch('hello:world'); - }); - }); - - describe('namespaced type with a namespace', () => { - test('generates an id if none is specified and prefixes namespace', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const id = serializer.generateRawId('foo', 'goodbye'); - expect(id).toMatch(/foo:goodbye\:[\w-]+$/); - }); - - test('uses the id that is specified and prefixes the namespace', () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const id = serializer.generateRawId('foo', 'hello', 'world'); - expect(id).toMatch('foo:hello:world'); - }); - }); - - describe('namespace agnostic type with a namespace', () => { - test(`generates an id if none is specified and doesn't prefix namespace`, () => { - typeRegistry.isNamespaceAgnostic.mockReturnValue(true); - - const serializer = new SavedObjectsSerializer(typeRegistry); - const id = serializer.generateRawId('foo', 'goodbye'); - expect(id).toMatch(/goodbye\:[\w-]+$/); - }); - - test(`uses the id that is specified and doesn't prefix the namespace`, () => { - const serializer = new SavedObjectsSerializer(typeRegistry); - const id = serializer.generateRawId('foo', 'hello', 'world'); - expect(id).toMatch('hello:world'); - }); + describe('namespace-agnostic type with a namespace', () => { + test(`generates an id if none is specified and doesn't prefix namespace`, () => { + const id = namespaceAgnosticSerializer.generateRawId('foo', 'goodbye'); + expect(id).toMatch(/^goodbye\:[\w-]+$/); + }); + + test(`uses the id that is specified and doesn't prefix the namespace`, () => { + const id = namespaceAgnosticSerializer.generateRawId('foo', 'hello', 'world'); + expect(id).toEqual('hello:world'); }); }); }); diff --git a/src/core/server/saved_objects/serialization/serializer.ts b/src/core/server/saved_objects/serialization/serializer.ts index 99d6b0c6b59f9..3b19d494d8ecf 100644 --- a/src/core/server/saved_objects/serialization/serializer.ts +++ b/src/core/server/saved_objects/serialization/serializer.ts @@ -49,7 +49,7 @@ export class SavedObjectsSerializer { public isRawSavedObject(rawDoc: SavedObjectsRawDoc) { const { type, namespace } = rawDoc._source; const namespacePrefix = - namespace && !this.registry.isNamespaceAgnostic(type) ? `${namespace}:` : ''; + namespace && this.registry.isSingleNamespace(type) ? `${namespace}:` : ''; return Boolean( type && rawDoc._id.startsWith(`${namespacePrefix}${type}:`) && @@ -64,7 +64,7 @@ export class SavedObjectsSerializer { */ public rawToSavedObject(doc: SavedObjectsRawDoc): SavedObjectSanitizedDoc { const { _id, _source, _seq_no, _primary_term } = doc; - const { type, namespace } = _source; + const { type, namespace, namespaces } = _source; const version = _seq_no != null || _primary_term != null @@ -74,7 +74,8 @@ export class SavedObjectsSerializer { return { type, id: this.trimIdPrefix(namespace, type, _id), - ...(namespace && !this.registry.isNamespaceAgnostic(type) && { namespace }), + ...(namespace && this.registry.isSingleNamespace(type) && { namespace }), + ...(namespaces && this.registry.isMultiNamespace(type) && { namespaces }), attributes: _source[type], references: _source.references || [], ...(_source.migrationVersion && { migrationVersion: _source.migrationVersion }), @@ -93,6 +94,7 @@ export class SavedObjectsSerializer { id, type, namespace, + namespaces, attributes, migrationVersion, updated_at, @@ -103,7 +105,8 @@ export class SavedObjectsSerializer { [type]: attributes, type, references, - ...(namespace && !this.registry.isNamespaceAgnostic(type) && { namespace }), + ...(namespace && this.registry.isSingleNamespace(type) && { namespace }), + ...(namespaces && this.registry.isMultiNamespace(type) && { namespaces }), ...(migrationVersion && { migrationVersion }), ...(updated_at && { updated_at }), }; @@ -124,7 +127,7 @@ export class SavedObjectsSerializer { */ public generateRawId(namespace: string | undefined, type: string, id?: string) { const namespacePrefix = - namespace && !this.registry.isNamespaceAgnostic(type) ? `${namespace}:` : ''; + namespace && this.registry.isSingleNamespace(type) ? `${namespace}:` : ''; return `${namespacePrefix}${type}:${id || uuid.v1()}`; } @@ -133,7 +136,7 @@ export class SavedObjectsSerializer { assertNonEmptyString(type, 'saved object type'); const namespacePrefix = - namespace && !this.registry.isNamespaceAgnostic(type) ? `${namespace}:` : ''; + namespace && this.registry.isSingleNamespace(type) ? `${namespace}:` : ''; const prefix = `${namespacePrefix}${type}:`; if (!id.startsWith(prefix)) { diff --git a/src/core/server/saved_objects/serialization/types.ts b/src/core/server/saved_objects/serialization/types.ts index dfaec127ba159..7ea61f67e9496 100644 --- a/src/core/server/saved_objects/serialization/types.ts +++ b/src/core/server/saved_objects/serialization/types.ts @@ -36,6 +36,7 @@ export interface SavedObjectsRawDoc { export interface SavedObjectsRawDocSource { type: string; namespace?: string; + namespaces?: string[]; migrationVersion?: SavedObjectsMigrationVersion; updated_at?: string; references?: SavedObjectReference[]; @@ -54,6 +55,7 @@ interface SavedObjectDoc { id?: string; // NOTE: SavedObjectDoc is used for uncreated objects where `id` is optional type: string; namespace?: string; + namespaces?: string[]; migrationVersion?: SavedObjectsMigrationVersion; version?: string; updated_at?: string; diff --git a/src/core/server/saved_objects/service/lib/__snapshots__/repository.test.js.snap b/src/core/server/saved_objects/service/lib/__snapshots__/repository.test.js.snap deleted file mode 100644 index 609906c97d599..0000000000000 --- a/src/core/server/saved_objects/service/lib/__snapshots__/repository.test.js.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`SavedObjectsRepository #deleteByNamespace requires namespace to be a string 1`] = `"namespace is required, and must be a string"`; - -exports[`SavedObjectsRepository #deleteByNamespace requires namespace to be defined 1`] = `"namespace is required, and must be a string"`; diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts index 2fd9b487f470a..1fdebd87397eb 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts @@ -100,6 +100,38 @@ describe('savedObjectsClient/decorateEsError', () => { expect(SavedObjectsErrorHelpers.isBadRequestError(error)).toBe(true); }); + describe('when es.BadRequest has a reason', () => { + it('makes a SavedObjectsClient/esCannotExecuteScriptError error when script context is disabled', () => { + const error = new esErrors.BadRequest(); + (error as Record).body = { + error: { reason: 'cannot execute scripts using [update] context' }, + }; + expect(SavedObjectsErrorHelpers.isEsCannotExecuteScriptError(error)).toBe(false); + expect(decorateEsError(error)).toBe(error); + expect(SavedObjectsErrorHelpers.isEsCannotExecuteScriptError(error)).toBe(true); + expect(SavedObjectsErrorHelpers.isBadRequestError(error)).toBe(false); + }); + + it('makes a SavedObjectsClient/esCannotExecuteScriptError error when inline scripts are disabled', () => { + const error = new esErrors.BadRequest(); + (error as Record).body = { + error: { reason: 'cannot execute [inline] scripts' }, + }; + expect(SavedObjectsErrorHelpers.isEsCannotExecuteScriptError(error)).toBe(false); + expect(decorateEsError(error)).toBe(error); + expect(SavedObjectsErrorHelpers.isEsCannotExecuteScriptError(error)).toBe(true); + expect(SavedObjectsErrorHelpers.isBadRequestError(error)).toBe(false); + }); + + it('makes a SavedObjectsClient/BadRequest error for any other reason', () => { + const error = new esErrors.BadRequest(); + (error as Record).body = { error: { reason: 'some other reason' } }; + expect(SavedObjectsErrorHelpers.isBadRequestError(error)).toBe(false); + expect(decorateEsError(error)).toBe(error); + expect(SavedObjectsErrorHelpers.isBadRequestError(error)).toBe(true); + }); + }); + it('returns other errors as Boom errors', () => { const error = new Error(); expect(error).not.toHaveProperty('isBoom'); diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.ts index eb9bc89636435..e57f08aa7a527 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.ts @@ -35,6 +35,8 @@ const { NotFound, BadRequest, } = legacyElasticsearch.errors; +const SCRIPT_CONTEXT_DISABLED_REGEX = /(?:cannot execute scripts using \[)([a-z]*)(?:\] context)/; +const INLINE_SCRIPTS_DISABLED_MESSAGE = 'cannot execute [inline] scripts'; import { SavedObjectsErrorHelpers } from './errors'; @@ -43,7 +45,7 @@ export function decorateEsError(error: Error) { throw new Error('Expected an instance of Error'); } - const { reason } = get(error, 'body.error', { reason: undefined }); + const { reason } = get(error, 'body.error', { reason: undefined }) as { reason?: string }; if ( error instanceof ConnectionFault || error instanceof ServiceUnavailable || @@ -74,6 +76,12 @@ export function decorateEsError(error: Error) { } if (error instanceof BadRequest) { + if ( + SCRIPT_CONTEXT_DISABLED_REGEX.test(reason || '') || + reason === INLINE_SCRIPTS_DISABLED_MESSAGE + ) { + return SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError(error, reason); + } return SavedObjectsErrorHelpers.decorateBadRequestError(error, reason); } diff --git a/src/core/server/saved_objects/service/lib/errors.test.ts b/src/core/server/saved_objects/service/lib/errors.test.ts index 12fc913f93090..4a43835d795d1 100644 --- a/src/core/server/saved_objects/service/lib/errors.test.ts +++ b/src/core/server/saved_objects/service/lib/errors.test.ts @@ -34,6 +34,7 @@ describe('savedObjectsClient/errorTypes', () => { }); it('has boom properties', () => { + expect(errorObj).toHaveProperty('isBoom', true); expect(errorObj.output.payload).toMatchObject({ statusCode: 400, message: "Unsupported saved object type: 'someType': Bad Request", @@ -57,6 +58,7 @@ describe('savedObjectsClient/errorTypes', () => { }); it('has boom properties', () => { + expect(errorObj).toHaveProperty('isBoom', true); expect(errorObj.output.payload).toMatchObject({ statusCode: 400, message: 'test reason message: Bad Request', @@ -80,14 +82,7 @@ describe('savedObjectsClient/errorTypes', () => { it('adds boom properties', () => { const error = SavedObjectsErrorHelpers.decorateBadRequestError(new Error()); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(400); - }); - - it('preserves boom properties of input', () => { - const error = Boom.notFound(); - SavedObjectsErrorHelpers.decorateBadRequestError(error); - expect(error.output.statusCode).toBe(404); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -95,6 +90,7 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.decorateBadRequestError(new Error('foobar')); expect(error.output.payload).toHaveProperty('message', 'foobar'); }); + it('prefixes message with passed reason', () => { const error = SavedObjectsErrorHelpers.decorateBadRequestError( new Error('foobar'), @@ -102,13 +98,21 @@ describe('savedObjectsClient/errorTypes', () => { ); expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); }); + it('sets statusCode to 400', () => { const error = SavedObjectsErrorHelpers.decorateBadRequestError(new Error('foo')); expect(error.output).toHaveProperty('statusCode', 400); }); + + it('preserves boom properties of input', () => { + const error = Boom.notFound(); + SavedObjectsErrorHelpers.decorateBadRequestError(error); + expect(error.output).toHaveProperty('statusCode', 404); + }); }); }); }); + describe('NotAuthorized error', () => { describe('decorateNotAuthorizedError', () => { it('returns original object', () => { @@ -125,14 +129,7 @@ describe('savedObjectsClient/errorTypes', () => { it('adds boom properties', () => { const error = SavedObjectsErrorHelpers.decorateNotAuthorizedError(new Error()); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(401); - }); - - it('preserves boom properties of input', () => { - const error = Boom.notFound(); - SavedObjectsErrorHelpers.decorateNotAuthorizedError(error); - expect(error.output.statusCode).toBe(404); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -140,6 +137,7 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.decorateNotAuthorizedError(new Error('foobar')); expect(error.output.payload).toHaveProperty('message', 'foobar'); }); + it('prefixes message with passed reason', () => { const error = SavedObjectsErrorHelpers.decorateNotAuthorizedError( new Error('foobar'), @@ -147,13 +145,21 @@ describe('savedObjectsClient/errorTypes', () => { ); expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); }); + it('sets statusCode to 401', () => { const error = SavedObjectsErrorHelpers.decorateNotAuthorizedError(new Error('foo')); expect(error.output).toHaveProperty('statusCode', 401); }); + + it('preserves boom properties of input', () => { + const error = Boom.notFound(); + SavedObjectsErrorHelpers.decorateNotAuthorizedError(error); + expect(error.output).toHaveProperty('statusCode', 404); + }); }); }); }); + describe('Forbidden error', () => { describe('decorateForbiddenError', () => { it('returns original object', () => { @@ -170,14 +176,7 @@ describe('savedObjectsClient/errorTypes', () => { it('adds boom properties', () => { const error = SavedObjectsErrorHelpers.decorateForbiddenError(new Error()); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(403); - }); - - it('preserves boom properties of input', () => { - const error = Boom.notFound(); - SavedObjectsErrorHelpers.decorateForbiddenError(error); - expect(error.output.statusCode).toBe(404); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -185,17 +184,26 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.decorateForbiddenError(new Error('foobar')); expect(error.output.payload).toHaveProperty('message', 'foobar'); }); + it('prefixes message with passed reason', () => { const error = SavedObjectsErrorHelpers.decorateForbiddenError(new Error('foobar'), 'biz'); expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); }); + it('sets statusCode to 403', () => { const error = SavedObjectsErrorHelpers.decorateForbiddenError(new Error('foo')); expect(error.output).toHaveProperty('statusCode', 403); }); + + it('preserves boom properties of input', () => { + const error = Boom.notFound(); + SavedObjectsErrorHelpers.decorateForbiddenError(error); + expect(error.output).toHaveProperty('statusCode', 404); + }); }); }); }); + describe('NotFound error', () => { describe('createGenericNotFoundError', () => { it('makes an error identifiable as a NotFound error', () => { @@ -203,11 +211,9 @@ describe('savedObjectsClient/errorTypes', () => { expect(SavedObjectsErrorHelpers.isNotFoundError(error)).toBe(true); }); - it('is a boom error, has boom properties', () => { + it('returns a boom error', () => { const error = SavedObjectsErrorHelpers.createGenericNotFoundError(); - expect(error).toHaveProperty('isBoom'); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(404); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -215,6 +221,7 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.createGenericNotFoundError(); expect(error.output.payload).toHaveProperty('message', 'Not Found'); }); + it('sets statusCode to 404', () => { const error = SavedObjectsErrorHelpers.createGenericNotFoundError(); expect(error.output).toHaveProperty('statusCode', 404); @@ -222,6 +229,7 @@ describe('savedObjectsClient/errorTypes', () => { }); }); }); + describe('Conflict error', () => { describe('decorateConflictError', () => { it('returns original object', () => { @@ -238,14 +246,7 @@ describe('savedObjectsClient/errorTypes', () => { it('adds boom properties', () => { const error = SavedObjectsErrorHelpers.decorateConflictError(new Error()); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(409); - }); - - it('preserves boom properties of input', () => { - const error = Boom.notFound(); - SavedObjectsErrorHelpers.decorateConflictError(error); - expect(error.output.statusCode).toBe(404); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -253,17 +254,77 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.decorateConflictError(new Error('foobar')); expect(error.output.payload).toHaveProperty('message', 'foobar'); }); + it('prefixes message with passed reason', () => { const error = SavedObjectsErrorHelpers.decorateConflictError(new Error('foobar'), 'biz'); expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); }); + it('sets statusCode to 409', () => { const error = SavedObjectsErrorHelpers.decorateConflictError(new Error('foo')); expect(error.output).toHaveProperty('statusCode', 409); }); + + it('preserves boom properties of input', () => { + const error = Boom.notFound(); + SavedObjectsErrorHelpers.decorateConflictError(error); + expect(error.output).toHaveProperty('statusCode', 404); + }); + }); + }); + }); + + describe('EsCannotExecuteScript error', () => { + describe('decorateEsCannotExecuteScriptError', () => { + it('returns original object', () => { + const error = new Error(); + expect(SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError(error)).toBe(error); + }); + + it('makes the error identifiable as a EsCannotExecuteScript error', () => { + const error = new Error(); + expect(SavedObjectsErrorHelpers.isEsCannotExecuteScriptError(error)).toBe(false); + SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError(error); + expect(SavedObjectsErrorHelpers.isEsCannotExecuteScriptError(error)).toBe(true); + }); + + it('adds boom properties', () => { + const error = SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError(new Error()); + expect(error).toHaveProperty('isBoom', true); + }); + + describe('error.output', () => { + it('defaults to message of error', () => { + const error = SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError( + new Error('foobar') + ); + expect(error.output.payload).toHaveProperty('message', 'foobar'); + }); + + it('prefixes message with passed reason', () => { + const error = SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError( + new Error('foobar'), + 'biz' + ); + expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); + }); + + it('sets statusCode to 501', () => { + const error = SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError( + new Error('foo') + ); + expect(error.output).toHaveProperty('statusCode', 400); + }); + + it('preserves boom properties of input', () => { + const error = Boom.notFound(); + SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError(error); + expect(error.output).toHaveProperty('statusCode', 404); + }); }); }); }); + describe('EsUnavailable error', () => { describe('decorateEsUnavailableError', () => { it('returns original object', () => { @@ -280,14 +341,7 @@ describe('savedObjectsClient/errorTypes', () => { it('adds boom properties', () => { const error = SavedObjectsErrorHelpers.decorateEsUnavailableError(new Error()); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(503); - }); - - it('preserves boom properties of input', () => { - const error = Boom.notFound(); - SavedObjectsErrorHelpers.decorateEsUnavailableError(error); - expect(error.output.statusCode).toBe(404); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -295,6 +349,7 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.decorateEsUnavailableError(new Error('foobar')); expect(error.output.payload).toHaveProperty('message', 'foobar'); }); + it('prefixes message with passed reason', () => { const error = SavedObjectsErrorHelpers.decorateEsUnavailableError( new Error('foobar'), @@ -302,13 +357,21 @@ describe('savedObjectsClient/errorTypes', () => { ); expect(error.output.payload).toHaveProperty('message', 'biz: foobar'); }); + it('sets statusCode to 503', () => { const error = SavedObjectsErrorHelpers.decorateEsUnavailableError(new Error('foo')); expect(error.output).toHaveProperty('statusCode', 503); }); + + it('preserves boom properties of input', () => { + const error = Boom.notFound(); + SavedObjectsErrorHelpers.decorateEsUnavailableError(error); + expect(error.output).toHaveProperty('statusCode', 404); + }); }); }); }); + describe('General error', () => { describe('decorateGeneralError', () => { it('returns original object', () => { @@ -318,14 +381,7 @@ describe('savedObjectsClient/errorTypes', () => { it('adds boom properties', () => { const error = SavedObjectsErrorHelpers.decorateGeneralError(new Error()); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(500); - }); - - it('preserves boom properties of input', () => { - const error = Boom.notFound(); - SavedObjectsErrorHelpers.decorateGeneralError(error); - expect(error.output.statusCode).toBe(404); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -333,10 +389,17 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.decorateGeneralError(new Error('foobar')); expect(error.output.payload.message).toMatch(/internal server error/i); }); + it('sets statusCode to 500', () => { const error = SavedObjectsErrorHelpers.decorateGeneralError(new Error('foo')); expect(error.output).toHaveProperty('statusCode', 500); }); + + it('preserves boom properties of input', () => { + const error = Boom.notFound(); + SavedObjectsErrorHelpers.decorateGeneralError(error); + expect(error.output).toHaveProperty('statusCode', 404); + }); }); }); }); @@ -363,9 +426,7 @@ describe('savedObjectsClient/errorTypes', () => { it('returns a boom error', () => { const error = SavedObjectsErrorHelpers.createEsAutoCreateIndexError(); - expect(error).toHaveProperty('isBoom'); - expect(typeof error.output).toBe('object'); - expect(error.output.statusCode).toBe(503); + expect(error).toHaveProperty('isBoom', true); }); describe('error.output', () => { @@ -373,6 +434,7 @@ describe('savedObjectsClient/errorTypes', () => { const error = SavedObjectsErrorHelpers.createEsAutoCreateIndexError(); expect(error.output.payload).toHaveProperty('message', 'Automatic index creation failed'); }); + it('sets statusCode to 503', () => { const error = SavedObjectsErrorHelpers.createEsAutoCreateIndexError(); expect(error.output).toHaveProperty('statusCode', 503); diff --git a/src/core/server/saved_objects/service/lib/errors.ts b/src/core/server/saved_objects/service/lib/errors.ts index e9138e9b8a347..478c6b6d26d53 100644 --- a/src/core/server/saved_objects/service/lib/errors.ts +++ b/src/core/server/saved_objects/service/lib/errors.ts @@ -33,6 +33,8 @@ const CODE_REQUEST_ENTITY_TOO_LARGE = 'SavedObjectsClient/requestEntityTooLarge' const CODE_NOT_FOUND = 'SavedObjectsClient/notFound'; // 409 - Conflict const CODE_CONFLICT = 'SavedObjectsClient/conflict'; +// 400 - Es Cannot Execute Script +const CODE_ES_CANNOT_EXECUTE_SCRIPT = 'SavedObjectsClient/esCannotExecuteScript'; // 503 - Es Unavailable const CODE_ES_UNAVAILABLE = 'SavedObjectsClient/esUnavailable'; // 503 - Unable to automatically create index because of action.auto_create_index setting @@ -152,10 +154,24 @@ export class SavedObjectsErrorHelpers { return decorate(error, CODE_CONFLICT, 409, reason); } + public static createConflictError(type: string, id: string) { + return SavedObjectsErrorHelpers.decorateConflictError( + Boom.conflict(`Saved object [${type}/${id}] conflict`) + ); + } + public static isConflictError(error: Error | DecoratedError) { return isSavedObjectsClientError(error) && error[code] === CODE_CONFLICT; } + public static decorateEsCannotExecuteScriptError(error: Error, reason?: string) { + return decorate(error, CODE_ES_CANNOT_EXECUTE_SCRIPT, 400, reason); + } + + public static isEsCannotExecuteScriptError(error: Error | DecoratedError) { + return isSavedObjectsClientError(error) && error[code] === CODE_ES_CANNOT_EXECUTE_SCRIPT; + } + public static decorateEsUnavailableError(error: Error, reason?: string) { return decorate(error, CODE_ES_UNAVAILABLE, 503, reason); } diff --git a/src/core/server/saved_objects/service/lib/included_fields.test.ts b/src/core/server/saved_objects/service/lib/included_fields.test.ts index 40d6552c2ad5f..ced99361f1ea0 100644 --- a/src/core/server/saved_objects/service/lib/included_fields.test.ts +++ b/src/core/server/saved_objects/service/lib/included_fields.test.ts @@ -26,7 +26,7 @@ describe('includedFields', () => { it('accepts type string', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(7); + expect(fields).toHaveLength(8); expect(fields).toContain('type'); }); @@ -37,6 +37,7 @@ Array [ "config.foo", "secret.foo", "namespace", + "namespaces", "type", "references", "migrationVersion", @@ -48,14 +49,14 @@ Array [ it('accepts field as string', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(7); + expect(fields).toHaveLength(8); expect(fields).toContain('config.foo'); }); it('accepts fields as an array', () => { const fields = includedFields('config', ['foo', 'bar']); - expect(fields).toHaveLength(9); + expect(fields).toHaveLength(10); expect(fields).toContain('config.foo'); expect(fields).toContain('config.bar'); }); @@ -69,6 +70,7 @@ Array [ "secret.foo", "secret.bar", "namespace", + "namespaces", "type", "references", "migrationVersion", @@ -81,31 +83,37 @@ Array [ it('includes namespace', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(7); + expect(fields).toHaveLength(8); expect(fields).toContain('namespace'); }); + it('includes namespaces', () => { + const fields = includedFields('config', 'foo'); + expect(fields).toHaveLength(8); + expect(fields).toContain('namespaces'); + }); + it('includes references', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(7); + expect(fields).toHaveLength(8); expect(fields).toContain('references'); }); it('includes migrationVersion', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(7); + expect(fields).toHaveLength(8); expect(fields).toContain('migrationVersion'); }); it('includes updated_at', () => { const fields = includedFields('config', 'foo'); - expect(fields).toHaveLength(7); + expect(fields).toHaveLength(8); expect(fields).toContain('updated_at'); }); it('uses wildcard when type is not provided', () => { const fields = includedFields(undefined, 'foo'); - expect(fields).toHaveLength(7); + expect(fields).toHaveLength(8); expect(fields).toContain('*.foo'); }); @@ -113,7 +121,7 @@ Array [ it('includes legacy field path', () => { const fields = includedFields('config', ['foo', 'bar']); - expect(fields).toHaveLength(9); + expect(fields).toHaveLength(10); expect(fields).toContain('foo'); expect(fields).toContain('bar'); }); diff --git a/src/core/server/saved_objects/service/lib/included_fields.ts b/src/core/server/saved_objects/service/lib/included_fields.ts index f372db5a1a635..c50ac22594008 100644 --- a/src/core/server/saved_objects/service/lib/included_fields.ts +++ b/src/core/server/saved_objects/service/lib/included_fields.ts @@ -37,6 +37,7 @@ export function includedFields(type: string | string[] = '*', fields?: string[] return [...acc, ...sourceFields.map(f => `${t}.${f}`)]; }, []) .concat('namespace') + .concat('namespaces') .concat('type') .concat('references') .concat('migrationVersion') diff --git a/src/core/server/saved_objects/service/lib/repository.mock.ts b/src/core/server/saved_objects/service/lib/repository.mock.ts index e69c0ff37d1be..afef378b7307b 100644 --- a/src/core/server/saved_objects/service/lib/repository.mock.ts +++ b/src/core/server/saved_objects/service/lib/repository.mock.ts @@ -28,6 +28,8 @@ const create = (): jest.Mocked => ({ find: jest.fn(), get: jest.fn(), update: jest.fn(), + addToNamespaces: jest.fn(), + deleteFromNamespaces: jest.fn(), deleteByNamespace: jest.fn(), incrementCounter: jest.fn(), }); diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 2e5eeec04e0a8..927171438ae99 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import _ from 'lodash'; import { SavedObjectsRepository } from './repository'; import * as getSearchDslNS from './search_dsl/search_dsl'; @@ -30,162 +29,31 @@ jest.mock('./search_dsl/search_dsl', () => ({ getSearchDsl: jest.fn() })); // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. +const createBadRequestError = (...args) => + SavedObjectsErrorHelpers.createBadRequestError(...args).output.payload; +const createConflictError = (...args) => + SavedObjectsErrorHelpers.createConflictError(...args).output.payload; +const createGenericNotFoundError = (...args) => + SavedObjectsErrorHelpers.createGenericNotFoundError(...args).output.payload; +const createUnsupportedTypeError = (...args) => + SavedObjectsErrorHelpers.createUnsupportedTypeError(...args).output.payload; + describe('SavedObjectsRepository', () => { let callAdminCluster; let savedObjectsRepository; let migrator; + let serializer; const mockTimestamp = '2017-08-14T15:49:14.886Z'; const mockTimestampFields = { updated_at: mockTimestamp }; const mockVersionProps = { _seq_no: 1, _primary_term: 1 }; const mockVersion = encodeHitVersion(mockVersionProps); - const noNamespaceSearchResults = { - hits: { - total: 4, - hits: [ - { - _index: '.kibana', - _id: 'index-pattern:logstash-*', - _score: 1, - ...mockVersionProps, - _source: { - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { - title: 'logstash-*', - timeFieldName: '@timestamp', - notExpandable: true, - }, - }, - }, - { - _index: '.kibana', - _id: 'config:6.0.0-alpha1', - _score: 1, - ...mockVersionProps, - _source: { - type: 'config', - ...mockTimestampFields, - config: { - buildNum: 8467, - defaultIndex: 'logstash-*', - }, - }, - }, - { - _index: '.kibana', - _id: 'index-pattern:stocks-*', - _score: 1, - ...mockVersionProps, - _source: { - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { - title: 'stocks-*', - timeFieldName: '@timestamp', - notExpandable: true, - }, - }, - }, - { - _index: '.kibana', - _id: 'globaltype:something', - _score: 1, - ...mockVersionProps, - _source: { - type: 'globaltype', - ...mockTimestampFields, - globaltype: { - name: 'bar', - }, - }, - }, - ], - }, - }; - - const namespacedSearchResults = { - hits: { - total: 4, - hits: [ - { - _index: '.kibana', - _id: 'foo-namespace:index-pattern:logstash-*', - _score: 1, - ...mockVersionProps, - _source: { - namespace: 'foo-namespace', - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { - title: 'logstash-*', - timeFieldName: '@timestamp', - notExpandable: true, - }, - }, - }, - { - _index: '.kibana', - _id: 'foo-namespace:config:6.0.0-alpha1', - _score: 1, - ...mockVersionProps, - _source: { - namespace: 'foo-namespace', - type: 'config', - ...mockTimestampFields, - config: { - buildNum: 8467, - defaultIndex: 'logstash-*', - }, - }, - }, - { - _index: '.kibana', - _id: 'foo-namespace:index-pattern:stocks-*', - _score: 1, - ...mockVersionProps, - _source: { - namespace: 'foo-namespace', - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { - title: 'stocks-*', - timeFieldName: '@timestamp', - notExpandable: true, - }, - }, - }, - { - _index: '.kibana', - _id: 'globaltype:something', - _score: 1, - ...mockVersionProps, - _source: { - type: 'globaltype', - ...mockTimestampFields, - globaltype: { - name: 'bar', - }, - }, - }, - ], - }, - }; - const deleteByQueryResults = { - took: 27, - timed_out: false, - total: 23, - deleted: 23, - batches: 1, - version_conflicts: 0, - noops: 0, - retries: { bulk: 0, search: 0 }, - throttled_millis: 0, - requests_per_second: -1, - throttled_until_millis: 0, - failures: [], - }; + const CUSTOM_INDEX_TYPE = 'customIndex'; + const NAMESPACE_AGNOSTIC_TYPE = 'globalType'; + const MULTI_NAMESPACE_TYPE = 'shareableType'; + const MULTI_NAMESPACE_CUSTOM_INDEX_TYPE = 'shareableTypeCustomIndex'; + const HIDDEN_TYPE = 'hiddenType'; const mappings = { properties: { @@ -194,43 +62,47 @@ describe('SavedObjectsRepository', () => { type: 'keyword', }, }, - foo: { + 'index-pattern': { properties: { - type: 'keyword', + someField: { + type: 'keyword', + }, }, }, - bar: { + dashboard: { properties: { - type: 'keyword', + otherField: { + type: 'keyword', + }, }, }, - baz: { + [CUSTOM_INDEX_TYPE]: { properties: { type: 'keyword', }, }, - 'index-pattern': { + [NAMESPACE_AGNOSTIC_TYPE]: { properties: { - someField: { + yetAnotherField: { type: 'keyword', }, }, }, - dashboard: { + [MULTI_NAMESPACE_TYPE]: { properties: { - otherField: { + evenYetAnotherField: { type: 'keyword', }, }, }, - globaltype: { + [MULTI_NAMESPACE_CUSTOM_INDEX_TYPE]: { properties: { - yetAnotherField: { + evenYetAnotherField: { type: 'keyword', }, }, }, - hiddenType: { + [HIDDEN_TYPE]: { properties: { someField: { type: 'keyword', @@ -240,96 +112,97 @@ describe('SavedObjectsRepository', () => { }, }; - const typeRegistry = new SavedObjectTypeRegistry(); - typeRegistry.registerType({ - name: 'config', - hidden: false, - namespaceAgnostic: false, - mappings: { - properties: { - type: 'keyword', - }, - }, + const createType = type => ({ + name: type, + mappings: { properties: mappings.properties[type].properties }, }); - typeRegistry.registerType({ - name: 'index-pattern', - hidden: false, - namespaceAgnostic: false, - mappings: { - properties: { - someField: { - type: 'keyword', - }, - }, - }, + + const registry = new SavedObjectTypeRegistry(); + registry.registerType(createType('config')); + registry.registerType(createType('index-pattern')); + registry.registerType(createType('dashboard')); + registry.registerType({ + ...createType(CUSTOM_INDEX_TYPE), + indexPattern: 'custom', }); - typeRegistry.registerType({ - name: 'dashboard', - hidden: false, - namespaceAgnostic: false, - mappings: { - properties: { - otherField: { - type: 'keyword', - }, - }, - }, + registry.registerType({ + ...createType(NAMESPACE_AGNOSTIC_TYPE), + namespaceType: 'agnostic', }); - typeRegistry.registerType({ - name: 'globaltype', - hidden: false, - namespaceAgnostic: true, - mappings: { - properties: { - yetAnotherField: { - type: 'keyword', - }, - }, - }, + registry.registerType({ + ...createType(MULTI_NAMESPACE_TYPE), + namespaceType: 'multiple', }); - typeRegistry.registerType({ - name: 'foo', - hidden: false, - namespaceAgnostic: true, - mappings: { - properties: { - type: 'keyword', - }, - }, + registry.registerType({ + ...createType(MULTI_NAMESPACE_CUSTOM_INDEX_TYPE), + namespaceType: 'multiple', + indexPattern: 'custom', }); - typeRegistry.registerType({ - name: 'bar', - hidden: false, - namespaceAgnostic: true, - mappings: { - properties: { - type: 'keyword', - }, - }, + registry.registerType({ + ...createType(HIDDEN_TYPE), + hidden: true, + namespaceType: 'agnostic', }); - typeRegistry.registerType({ - name: 'baz', - hidden: false, - namespaceAgnostic: false, - indexPattern: 'beats', - mappings: { - properties: { - type: 'keyword', - }, + + const getMockGetResponse = ({ type, id, references, namespace }) => ({ + // NOTE: Elasticsearch returns more fields (_index, _type) but the SavedObjectsRepository method ignores these + found: true, + _id: `${registry.isSingleNamespace(type) && namespace ? `${namespace}:` : ''}${type}:${id}`, + ...mockVersionProps, + _source: { + ...(registry.isSingleNamespace(type) && { namespace }), + ...(registry.isMultiNamespace(type) && { namespaces: [namespace ?? 'default'] }), + type, + [type]: { title: 'Testing' }, + references, + specialProperty: 'specialValue', + ...mockTimestampFields, }, }); - typeRegistry.registerType({ - name: 'hiddenType', - hidden: true, - namespaceAgnostic: true, - mappings: { - properties: { - someField: { - type: 'keyword', - }, - }, + + const getMockMgetResponse = (objects, namespace) => ({ + status: 200, + docs: objects.map(obj => + obj.found === false ? obj : getMockGetResponse({ ...obj, namespace }) + ), + }); + + const expectClusterCalls = (...actions) => { + for (let i = 0; i < actions.length; i++) { + expect(callAdminCluster).toHaveBeenNthCalledWith(i + 1, actions[i], expect.any(Object)); + } + expect(callAdminCluster).toHaveBeenCalledTimes(actions.length); + }; + const expectClusterCallArgs = (args, n = 1) => { + expect(callAdminCluster).toHaveBeenNthCalledWith( + n, + expect.any(String), + expect.objectContaining(args) + ); + }; + + expect.extend({ + toBeDocumentWithoutError(received, type, id) { + if (received.type === type && received.id === id && !received.error) { + return { message: () => `expected type and id not to match without error`, pass: true }; + } else { + return { message: () => `expected type and id to match without error`, pass: false }; + } }, }); + const expectSuccess = ({ type, id }) => expect.toBeDocumentWithoutError(type, id); + const expectError = ({ type, id }) => ({ type, id, error: expect.any(Object) }); + const expectErrorResult = ({ type, id }, error) => ({ type, id, error }); + const expectErrorNotFound = obj => + expectErrorResult(obj, createGenericNotFoundError(obj.type, obj.id)); + const expectErrorConflict = obj => expectErrorResult(obj, createConflictError(obj.type, obj.id)); + const expectErrorInvalidType = obj => + expectErrorResult(obj, createUnsupportedTypeError(obj.type, obj.id)); + + const expectMigrationArgs = (args, contains = true, n = 1) => { + const obj = contains ? expect.objectContaining(args) : expect.not.objectContaining(args); + expect(migrator.migrateDocument).toHaveBeenNthCalledWith(n, obj); + }; beforeEach(() => { callAdminCluster = jest.fn(); @@ -338,16 +211,28 @@ describe('SavedObjectsRepository', () => { runMigrations: async () => ({ status: 'skipped' }), }; - const serializer = new SavedObjectsSerializer(typeRegistry); - const allTypes = typeRegistry.getAllTypes().map(type => type.name); - const allowedTypes = [...new Set(allTypes.filter(type => !typeRegistry.isHidden(type)))]; + // create a mock serializer "shim" so we can track function calls, but use the real serializer's implementation + serializer = { + isRawSavedObject: jest.fn(), + rawToSavedObject: jest.fn(), + savedObjectToRaw: jest.fn(), + generateRawId: jest.fn(), + trimIdPrefix: jest.fn(), + }; + const _serializer = new SavedObjectsSerializer(registry); + Object.keys(serializer).forEach(key => { + serializer[key].mockImplementation((...args) => _serializer[key](...args)); + }); + + const allTypes = registry.getAllTypes().map(type => type.name); + const allowedTypes = [...new Set(allTypes.filter(type => !registry.isHidden(type)))]; savedObjectsRepository = new SavedObjectsRepository({ index: '.kibana-test', mappings, callCluster: callAdminCluster, migrator, - typeRegistry, + typeRegistry: registry, serializer, allowedTypes, }); @@ -356,2644 +241,2819 @@ describe('SavedObjectsRepository', () => { getSearchDslNS.getSearchDsl.mockReset(); }); - describe('#create', () => { - beforeEach(() => { - callAdminCluster.mockImplementation((method, params) => ({ - _id: params.id, - ...mockVersionProps, - })); - }); + const mockMigrationVersion = { foo: '2.3.4' }; + const mockMigrateDocument = doc => ({ + ...doc, + attributes: { + ...doc.attributes, + ...(doc.attributes?.title && { title: `${doc.attributes.title}!!` }), + }, + migrationVersion: mockMigrationVersion, + references: [{ name: 'search_0', type: 'search', id: '123' }], + }); - it('waits until migrations are complete before proceeding', async () => { - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); + describe('#addToNamespaces', () => { + const id = 'some-id'; + const type = MULTI_NAMESPACE_TYPE; + const currentNs1 = 'default'; + const currentNs2 = 'foo-namespace'; + const newNs1 = 'bar-namespace'; + const newNs2 = 'baz-namespace'; + + const mockGetResponse = (type, id) => { + // mock a document that exists in two namespaces + const mockResponse = getMockGetResponse({ type, id }); + mockResponse._source.namespaces = [currentNs1, currentNs2]; + callAdminCluster.mockResolvedValueOnce(mockResponse); // this._callCluster('get', ...) + }; - await expect( - savedObjectsRepository.create( - 'index-pattern', - { - title: 'Logstash', - }, - { - id: 'logstash-*', - namespace: 'foo-namespace', - } - ) - ).resolves.toBeDefined(); - expect(migrator.runMigrations).toHaveBeenCalledTimes(1); - }); + const addToNamespacesSuccess = async (type, id, namespaces, options) => { + mockGetResponse(type, id); // this._callCluster('get', ...) + callAdminCluster.mockResolvedValue({ + _id: `${type}:${id}`, + ...mockVersionProps, + result: 'updated', + }); // this._writeToCluster('update', ...) + const result = await savedObjectsRepository.addToNamespaces(type, id, namespaces, options); + expect(callAdminCluster).toHaveBeenCalledTimes(2); + return result; + }; - it('formats Elasticsearch response', async () => { - const response = await savedObjectsRepository.create( - 'index-pattern', - { - title: 'Logstash', - }, - { - id: 'logstash-*', - namespace: 'foo-namespace', - references: [ - { - name: 'ref_0', - type: 'test', - id: '123', - }, - ], - } - ); + describe('cluster calls', () => { + it(`should use ES get action then update action`, async () => { + await addToNamespacesSuccess(type, id, [newNs1, newNs2]); + expectClusterCalls('get', 'update'); + }); - expect(response).toEqual({ - type: 'index-pattern', - id: 'logstash-*', - ...mockTimestampFields, - version: mockVersion, - attributes: { - title: 'Logstash', - }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '123', - }, - ], + it(`defaults to the version of the existing document`, async () => { + await addToNamespacesSuccess(type, id, [newNs1, newNs2]); + const versionProperties = { + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + expectClusterCallArgs(versionProperties, 2); + }); + + it(`accepts version`, async () => { + await addToNamespacesSuccess(type, id, [newNs1, newNs2], { + version: encodeHitVersion({ _seq_no: 100, _primary_term: 200 }), + }); + expectClusterCallArgs({ if_seq_no: 100, if_primary_term: 200 }, 2); }); - }); - it('should use ES index action', async () => { - await savedObjectsRepository.create('index-pattern', { - id: 'logstash-*', - title: 'Logstash', + it(`defaults to a refresh setting of wait_for`, async () => { + await addToNamespacesSuccess(type, id, [newNs1, newNs2]); + expectClusterCallArgs({ refresh: 'wait_for' }, 2); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('index', expect.any(Object)); + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await addToNamespacesSuccess(type, id, [newNs1, newNs2], { refresh }); + expectClusterCallArgs({ refresh }, 2); + }); }); - it('should use default index', async () => { - await savedObjectsRepository.create('index-pattern', { - id: 'logstash-*', - title: 'Logstash', + describe('errors', () => { + const expectNotFoundError = async (type, id, namespaces, options) => { + await expect( + savedObjectsRepository.addToNamespaces(type, id, namespaces, options) + ).rejects.toThrowError(createGenericNotFoundError(type, id)); + }; + const expectBadRequestError = async (type, id, namespaces, message) => { + await expect( + savedObjectsRepository.addToNamespaces(type, id, namespaces) + ).rejects.toThrowError(createBadRequestError(message)); + }; + + it(`throws when type is invalid`, async () => { + await expectNotFoundError('unknownType', id, [newNs1, newNs2]); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'index', - expect.objectContaining({ - index: '.kibana-test', - }) - ); - }); + it(`throws when type is hidden`, async () => { + await expectNotFoundError(HIDDEN_TYPE, id, [newNs1, newNs2]); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); - it('should use custom index', async () => { - await savedObjectsRepository.create('baz', { - id: 'logstash-*', - title: 'Logstash', + it(`throws when type is not multi-namespace`, async () => { + const test = async type => { + const message = `${type} doesn't support multiple namespaces`; + await expectBadRequestError(type, id, [newNs1, newNs2], message); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; + await test('index-pattern'); + await test(NAMESPACE_AGNOSTIC_TYPE); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'index', - expect.objectContaining({ - index: 'beats', - }) - ); - }); + it(`throws when namespaces is an empty array`, async () => { + const test = async namespaces => { + const message = 'namespaces must be a non-empty array of strings'; + await expectBadRequestError(type, id, namespaces, message); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; + await test([]); + }); - it('migrates the doc', async () => { - migrator.migrateDocument = doc => { - doc.attributes.title = doc.attributes.title + '!!'; - doc.migrationVersion = { foo: '2.3.4' }; - doc.references = [{ name: 'search_0', type: 'search', id: '123' }]; - return doc; - }; + it(`throws when ES is unable to find the document during get`, async () => { + callAdminCluster.mockResolvedValue({ found: false }); // this._callCluster('get', ...) + await expectNotFoundError(type, id, [newNs1, newNs2]); + expectClusterCalls('get'); + }); - await savedObjectsRepository.create('index-pattern', { - id: 'logstash-*', - title: 'Logstash', + it(`throws when ES is unable to find the index during get`, async () => { + callAdminCluster.mockResolvedValue({ status: 404 }); // this._callCluster('get', ...) + await expectNotFoundError(type, id, [newNs1, newNs2]); + expectClusterCalls('get'); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - body: { - 'index-pattern': { id: 'logstash-*', title: 'Logstash!!' }, - migrationVersion: { foo: '2.3.4' }, - type: 'index-pattern', - updated_at: '2017-08-14T15:49:14.886Z', - references: [{ name: 'search_0', type: 'search', id: '123' }], - }, + it(`throws when the document exists, but not in this namespace`, async () => { + mockGetResponse(type, id); // this._callCluster('get', ...) + await expectNotFoundError(type, id, [newNs1, newNs2], { + namespace: 'some-other-namespace', + }); + expectClusterCalls('get'); }); - }); - it('defaults to a refresh setting of `wait_for`', async () => { - await savedObjectsRepository.create('index-pattern', { - id: 'logstash-*', - title: 'Logstash', + it(`throws when ES is unable to find the document during update`, async () => { + mockGetResponse(type, id); // this._callCluster('get', ...) + callAdminCluster.mockResolvedValue({ status: 404 }); // this._writeToCluster('update', ...) + await expectNotFoundError(type, id, [newNs1, newNs2]); + expectClusterCalls('get', 'update'); }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: 'wait_for', + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + let callAdminClusterCount = 0; + migrator.runMigrations = jest.fn(async () => + // runMigrations should resolve before callAdminCluster is initiated + expect(callAdminCluster).toHaveBeenCalledTimes(callAdminClusterCount++) + ); + await expect(addToNamespacesSuccess(type, id, [newNs1, newNs2])).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveReturnedTimes(2); }); }); - it('accepts custom refresh settings', async () => { - await savedObjectsRepository.create( - 'index-pattern', - { - id: 'logstash-*', - title: 'Logstash', - }, - { - refresh: true, - } - ); + describe('returns', () => { + it(`returns an empty object on success`, async () => { + const result = await addToNamespacesSuccess(type, id, [newNs1, newNs2]); + expect(result).toEqual({}); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: true, + it(`succeeds when adding existing namespaces`, async () => { + const result = await addToNamespacesSuccess(type, id, [currentNs1]); + expect(result).toEqual({}); }); }); + }); - it('should use create action if ID defined and overwrite=false', async () => { - await savedObjectsRepository.create( - 'index-pattern', - { - title: 'Logstash', - }, - { - id: 'logstash-*', - } - ); + describe('#bulkCreate', () => { + const obj1 = { + type: 'config', + id: '6.0.0-alpha1', + attributes: { title: 'Test One' }, + references: [{ name: 'ref_0', type: 'test', id: '1' }], + }; + const obj2 = { + type: 'index-pattern', + id: 'logstash-*', + attributes: { title: 'Test Two' }, + references: [{ name: 'ref_0', type: 'test', id: '2' }], + }; + const namespace = 'foo-namespace'; - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('create', expect.any(Object)); - }); + const getMockBulkCreateResponse = (objects, namespace) => { + return { + items: objects.map(({ type, id }) => ({ + create: { + _id: `${namespace ? `${namespace}:` : ''}${type}:${id}`, + ...mockVersionProps, + }, + })), + }; + }; - it('allows for id to be provided', async () => { - await savedObjectsRepository.create( - 'index-pattern', - { - title: 'Logstash', - }, - { id: 'logstash-*' } - ); + const bulkCreateSuccess = async (objects, options) => { + const multiNamespaceObjects = + options?.overwrite && + objects.filter(({ type, id }) => registry.isMultiNamespace(type) && id); + if (multiNamespaceObjects?.length) { + const response = getMockMgetResponse(multiNamespaceObjects, options?.namespace); + callAdminCluster.mockResolvedValueOnce(response); // this._callCluster('mget', ...) + } + const response = getMockBulkCreateResponse(objects, options?.namespace); + callAdminCluster.mockResolvedValue(response); // this._writeToCluster('bulk', ...) + const result = await savedObjectsRepository.bulkCreate(objects, options); + expect(callAdminCluster).toHaveBeenCalledTimes(multiNamespaceObjects?.length ? 2 : 1); + return result; + }; - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: 'index-pattern:logstash-*', - }) - ); + // bulk create calls have two objects for each source -- the action, and the source + const expectClusterCallArgsAction = ( + objects, + { method, _index = expect.any(String), getId = () => expect.any(String) } + ) => { + const body = []; + for (const { type, id } of objects) { + body.push({ [method]: { _index, _id: getId(type, id) } }); + body.push(expect.any(Object)); + } + expectClusterCallArgs({ body }); + }; + + const expectObjArgs = ({ type, attributes, references }, overrides) => [ + expect.any(Object), + expect.objectContaining({ + [type]: attributes, + references, + type, + ...overrides, + ...mockTimestampFields, + }), + ]; + + const expectSuccessResult = obj => ({ + ...obj, + migrationVersion: undefined, + version: mockVersion, + ...mockTimestampFields, }); - it('self-generates an ID', async () => { - await savedObjectsRepository.create('index-pattern', { - title: 'Logstash', + describe('cluster calls', () => { + it(`should use the ES bulk action by default`, async () => { + await bulkCreateSuccess([obj1, obj2]); + expectClusterCalls('bulk'); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: expect.objectContaining(/index-pattern:[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}/), - }) - ); - }); + it(`should use the ES mget action before bulk action for any types that are multi-namespace, when overwrite=true`, async () => { + const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_TYPE }]; + await bulkCreateSuccess(objects, { overwrite: true }); + expectClusterCalls('mget', 'bulk'); + const docs = [expect.objectContaining({ _id: `${MULTI_NAMESPACE_TYPE}:${obj2.id}` })]; + expectClusterCallArgs({ body: { docs } }, 1); + }); - it('prepends namespace to the id and adds namespace to body when providing namespace for namespaced type', async () => { - await savedObjectsRepository.create( - 'index-pattern', - { - title: 'Logstash', - }, - { - id: 'foo-id', - namespace: 'foo-namespace', - } - ); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: `foo-namespace:index-pattern:foo-id`, - body: expect.objectContaining({ - [`index-pattern`]: { title: 'Logstash' }, - namespace: 'foo-namespace', - type: 'index-pattern', - updated_at: '2017-08-14T15:49:14.886Z', - }), - }) - ); - }); + it(`should use the ES create method if ID is undefined and overwrite=true`, async () => { + const objects = [obj1, obj2].map(obj => ({ ...obj, id: undefined })); + await bulkCreateSuccess(objects, { overwrite: true }); + expectClusterCallArgsAction(objects, { method: 'create' }); + }); - it(`doesn't prepend namespace to the id or add namespace property when providing no namespace for namespaced type`, async () => { - await savedObjectsRepository.create( - 'index-pattern', - { - title: 'Logstash', - }, - { - id: 'foo-id', - } - ); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: `index-pattern:foo-id`, - body: expect.objectContaining({ - [`index-pattern`]: { title: 'Logstash' }, - type: 'index-pattern', - updated_at: '2017-08-14T15:49:14.886Z', - }), - }) - ); - }); + it(`should use the ES create method if ID is undefined and overwrite=false`, async () => { + const objects = [obj1, obj2].map(obj => ({ ...obj, id: undefined })); + await bulkCreateSuccess(objects); + expectClusterCallArgsAction(objects, { method: 'create' }); + }); - it(`doesn't prepend namespace to the id or add namespace property when providing namespace for namespace agnostic type`, async () => { - await savedObjectsRepository.create( - 'globaltype', - { - title: 'Logstash', - }, - { - id: 'foo-id', - namespace: 'foo-namespace', - } - ); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: `globaltype:foo-id`, - body: expect.objectContaining({ - [`globaltype`]: { title: 'Logstash' }, - type: 'globaltype', - updated_at: '2017-08-14T15:49:14.886Z', - }), - }) - ); - }); - - it('defaults to empty references array if none are provided', async () => { - await savedObjectsRepository.create( - 'index-pattern', - { - title: 'Logstash', - }, - { - id: 'logstash-*', - } - ); + it(`should use the ES index method if ID is defined and overwrite=true`, async () => { + await bulkCreateSuccess([obj1, obj2], { overwrite: true }); + expectClusterCallArgsAction([obj1, obj2], { method: 'index' }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - body: expect.objectContaining({ - references: [], - }), - }) - ); - }); - }); + it(`should use the ES create method if ID is defined and overwrite=false`, async () => { + await bulkCreateSuccess([obj1, obj2]); + expectClusterCallArgsAction([obj1, obj2], { method: 'create' }); + }); - describe('#bulkCreate', () => { - it('waits until migrations are complete before proceeding', async () => { - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); - callAdminCluster.mockReturnValue({ - items: [ - { create: { type: 'config', id: 'config:one', _primary_term: 1, _seq_no: 1 } }, - { - create: { - type: 'index-pattern', - id: 'index-pattern:two', - _primary_term: 1, - _seq_no: 1, - }, - }, - ], + it(`formats the ES request`, async () => { + await bulkCreateSuccess([obj1, obj2]); + const body = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; + expectClusterCallArgs({ body }); }); - await expect( - savedObjectsRepository.bulkCreate([ - { type: 'config', id: 'one', attributes: { title: 'Test One' } }, - { type: 'index-pattern', id: 'two', attributes: { title: 'Test Two' } }, - ]) - ).resolves.toBeDefined(); + it(`adds namespace to request body for any types that are single-namespace`, async () => { + await bulkCreateSuccess([obj1, obj2], { namespace }); + const expected = expect.objectContaining({ namespace }); + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expectClusterCallArgs({ body }); + }); - expect(migrator.runMigrations).toHaveBeenCalledTimes(1); - }); + it(`doesn't add namespace to request body for any types that are not single-namespace`, async () => { + const objects = [ + { ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }, + { ...obj2, type: MULTI_NAMESPACE_TYPE }, + ]; + await bulkCreateSuccess(objects, { namespace }); + const expected = expect.not.objectContaining({ namespace: expect.anything() }); + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expectClusterCallArgs({ body }); + }); - it('formats Elasticsearch request', async () => { - callAdminCluster.mockReturnValue({ - items: [ - { create: { type: 'config', id: 'config:one', _primary_term: 1, _seq_no: 1 } }, - { create: { type: 'index-pattern', id: 'config:two', _primary_term: 1, _seq_no: 1 } }, - ], + it(`adds namespaces to request body for any types that are multi-namespace`, async () => { + const test = async namespace => { + const objects = [obj1, obj2].map(x => ({ ...x, type: MULTI_NAMESPACE_TYPE })); + const namespaces = [namespace ?? 'default']; + await bulkCreateSuccess(objects, { namespace, overwrite: true }); + const expected = expect.objectContaining({ namespaces }); + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expectClusterCallArgs({ body }, 2); + callAdminCluster.mockReset(); + }; + await test(undefined); + await test(namespace); }); - await savedObjectsRepository.bulkCreate([ - { - type: 'config', - id: 'one', - attributes: { title: 'Test One' }, - references: [{ name: 'ref_0', type: 'test', id: '1' }], - }, - { - type: 'index-pattern', - id: 'two', - attributes: { title: 'Test Two' }, - references: [{ name: 'ref_0', type: 'test', id: '2' }], - }, - ]); + it(`doesn't add namespaces to request body for any types that are not multi-namespace`, async () => { + const test = async namespace => { + const objects = [obj1, { ...obj2, type: NAMESPACE_AGNOSTIC_TYPE }]; + await bulkCreateSuccess(objects, { namespace, overwrite: true }); + const expected = expect.not.objectContaining({ namespaces: expect.anything() }); + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expectClusterCallArgs({ body }); + callAdminCluster.mockReset(); + }; + await test(undefined); + await test(namespace); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - const bulkCalls = callAdminCluster.mock.calls.filter(([path]) => path === 'bulk'); + it(`defaults to a refresh setting of wait_for`, async () => { + await bulkCreateSuccess([obj1, obj2]); + expectClusterCallArgs({ refresh: 'wait_for' }); + }); - expect(bulkCalls.length).toEqual(1); + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await bulkCreateSuccess([obj1, obj2], { refresh }); + expectClusterCallArgs({ refresh }); + }); - expect(bulkCalls[0][1].body).toEqual([ - { create: { _index: '.kibana-test', _id: 'config:one' } }, - { - type: 'config', - ...mockTimestampFields, - config: { title: 'Test One' }, - references: [{ name: 'ref_0', type: 'test', id: '1' }], - }, - { create: { _index: '.kibana-test', _id: 'index-pattern:two' } }, - { - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { title: 'Test Two' }, - references: [{ name: 'ref_0', type: 'test', id: '2' }], - }, - ]); - }); + it(`should use default index`, async () => { + await bulkCreateSuccess([obj1, obj2]); + expectClusterCallArgsAction([obj1, obj2], { method: 'create', _index: '.kibana-test' }); + }); - it('defaults to a refresh setting of `wait_for`', async () => { - callAdminCluster.mockReturnValue({ - items: [{ create: { type: 'config', id: 'config:one', _primary_term: 1, _seq_no: 1 } }], + it(`should use custom index`, async () => { + await bulkCreateSuccess([obj1, obj2].map(x => ({ ...x, type: CUSTOM_INDEX_TYPE }))); + expectClusterCallArgsAction([obj1, obj2], { method: 'create', _index: 'custom' }); }); - await savedObjectsRepository.bulkCreate([ - { - type: 'config', - id: 'one', - attributes: { title: 'Test One' }, - references: [{ name: 'ref_0', type: 'test', id: '1' }], - }, - ]); + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + const getId = (type, id) => `${namespace}:${type}:${id}`; + await bulkCreateSuccess([obj1, obj2], { namespace }); + expectClusterCallArgsAction([obj1, obj2], { method: 'create', getId }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + const getId = (type, id) => `${type}:${id}`; + await bulkCreateSuccess([obj1, obj2]); + expectClusterCallArgsAction([obj1, obj2], { method: 'create', getId }); + }); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: 'wait_for', + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + const getId = (type, id) => `${type}:${id}`; + const objects = [ + { ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }, + { ...obj2, type: MULTI_NAMESPACE_TYPE }, + ]; + await bulkCreateSuccess(objects, { namespace }); + expectClusterCallArgsAction(objects, { method: 'create', getId }); }); }); - it('accepts a custom refresh setting', async () => { - callAdminCluster.mockReturnValue({ - items: [ - { create: { type: 'config', id: 'config:one', _primary_term: 1, _seq_no: 1 } }, - { create: { type: 'index-pattern', id: 'config:two', _primary_term: 1, _seq_no: 1 } }, - ], - }); + describe('errors', () => { + const obj3 = { + type: 'dashboard', + id: 'three', + attributes: { title: 'Test Three' }, + references: [{ name: 'ref_0', type: 'test', id: '2' }], + }; - await savedObjectsRepository.bulkCreate( - [ - { - type: 'config', - id: 'one', - attributes: { title: 'Test One' }, - references: [{ name: 'ref_0', type: 'test', id: '1' }], - }, - { - type: 'index-pattern', - id: 'two', - attributes: { title: 'Test Two' }, - references: [{ name: 'ref_0', type: 'test', id: '2' }], - }, - ], - { - refresh: true, + const bulkCreateError = async (obj, esError, expectedError) => { + const objects = [obj1, obj, obj2]; + const response = getMockBulkCreateResponse(objects); + if (esError) { + response.items[1].create = { error: esError }; } - ); - - expect(callAdminCluster).toHaveBeenCalledTimes(1); + callAdminCluster.mockResolvedValue(response); // this._writeToCluster('bulk', ...) + + const result = await savedObjectsRepository.bulkCreate(objects); + expectClusterCalls('bulk'); + const objCall = esError ? expectObjArgs(obj) : []; + const body = [...expectObjArgs(obj1), ...objCall, ...expectObjArgs(obj2)]; + expectClusterCallArgs({ body }); + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectedError, expectSuccess(obj2)], + }); + }; - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: true, + it(`returns error when type is invalid`, async () => { + const obj = { ...obj3, type: 'unknownType' }; + await bulkCreateError(obj, undefined, expectErrorInvalidType(obj)); }); - }); - it('migrates the docs', async () => { - callAdminCluster.mockReturnValue({ - items: [ - { - create: { - error: false, - _id: '1', - _seq_no: 1, - _primary_term: 1, - }, - }, - { - create: { - error: false, - _id: '2', - _seq_no: 1, - _primary_term: 1, - }, - }, - ], + it(`returns error when type is hidden`, async () => { + const obj = { ...obj3, type: HIDDEN_TYPE }; + await bulkCreateError(obj, undefined, expectErrorInvalidType(obj)); }); - migrator.migrateDocument = doc => { - doc.attributes.title = doc.attributes.title + '!!'; - doc.migrationVersion = { foo: '2.3.4' }; - doc.references = [{ name: 'search_0', type: 'search', id: '123' }]; - return doc; - }; - - const bulkCreateResp = await savedObjectsRepository.bulkCreate([ - { type: 'config', id: 'one', attributes: { title: 'Test One' } }, - { type: 'index-pattern', id: 'two', attributes: { title: 'Test Two' } }, - ]); - - expect(callAdminCluster).toHaveBeenCalledWith( - 'bulk', - expect.objectContaining({ - body: [ - { create: { _index: '.kibana-test', _id: 'config:one' } }, - { - type: 'config', - ...mockTimestampFields, - config: { title: 'Test One!!' }, - migrationVersion: { foo: '2.3.4' }, - references: [{ name: 'search_0', type: 'search', id: '123' }], - }, - { create: { _index: '.kibana-test', _id: 'index-pattern:two' } }, + it(`returns error when there is a conflict with an existing multi-namespace saved object (get)`, async () => { + const obj = { ...obj3, type: MULTI_NAMESPACE_TYPE }; + const response1 = { + status: 200, + docs: [ { - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { title: 'Test Two!!' }, - migrationVersion: { foo: '2.3.4' }, - references: [{ name: 'search_0', type: 'search', id: '123' }], + found: true, + _source: { + type: obj.type, + namespaces: ['bar-namespace'], + }, }, ], - }) - ); - - expect(bulkCreateResp).toEqual({ - saved_objects: [ - { - id: 'one', - type: 'config', - version: mockVersion, - updated_at: mockTimestamp, - attributes: { - title: 'Test One!!', - }, - references: [{ name: 'search_0', type: 'search', id: '123' }], - }, - { - id: 'two', - type: 'index-pattern', - version: mockVersion, - updated_at: mockTimestamp, - attributes: { - title: 'Test Two!!', - }, - references: [{ name: 'search_0', type: 'search', id: '123' }], - }, - ], + }; + callAdminCluster.mockResolvedValueOnce(response1); // this._callCluster('mget', ...) + const response2 = getMockBulkCreateResponse([obj1, obj2]); + callAdminCluster.mockResolvedValue(response2); // this._writeToCluster('bulk', ...) + + const options = { overwrite: true }; + const result = await savedObjectsRepository.bulkCreate([obj1, obj, obj2], options); + expectClusterCalls('mget', 'bulk'); + const body1 = { docs: [expect.objectContaining({ _id: `${obj.type}:${obj.id}` })] }; + expectClusterCallArgs({ body: body1 }, 1); + const body2 = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; + expectClusterCallArgs({ body: body2 }, 2); + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectErrorConflict(obj), expectSuccess(obj2)], + }); }); - }); - it('should overwrite objects if overwrite is truthy', async () => { - callAdminCluster.mockReturnValue({ - items: [{ create: { type: 'foo', id: 'bar', _primary_term: 1, _seq_no: 1 } }], + it(`returns error when there is a version conflict (bulk)`, async () => { + const esError = { type: 'version_conflict_engine_exception' }; + await bulkCreateError(obj3, esError, expectErrorConflict(obj3)); }); - await savedObjectsRepository.bulkCreate([{ type: 'foo', id: 'bar', attributes: {} }], { - overwrite: false, + it(`returns error when document is missing`, async () => { + const esError = { type: 'document_missing_exception' }; + await bulkCreateError(obj3, esError, expectErrorNotFound(obj3)); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'bulk', - expect.objectContaining({ - body: [ - // uses create because overwriting is not allowed - { create: { _index: '.kibana-test', _id: 'foo:bar' } }, - { type: 'foo', ...mockTimestampFields, foo: {}, references: [] }, - ], - }) - ); - - callAdminCluster.mockReset(); - callAdminCluster.mockReturnValue({ - items: [{ create: { type: 'foo', id: 'bar', _primary_term: 1, _seq_no: 1 } }], + it(`returns error reason for other errors`, async () => { + const esError = { reason: 'some_other_error' }; + await bulkCreateError(obj3, esError, expectErrorResult(obj3, { message: esError.reason })); }); - await savedObjectsRepository.bulkCreate([{ type: 'foo', id: 'bar', attributes: {} }], { - overwrite: true, + it(`returns error string for other errors if no reason is defined`, async () => { + const esError = { foo: 'some_other_error' }; + const expectedError = expectErrorResult(obj3, { message: JSON.stringify(esError) }); + await bulkCreateError(obj3, esError, expectedError); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'bulk', - expect.objectContaining({ - body: [ - // uses index because overwriting is allowed - { index: { _index: '.kibana-test', _id: 'foo:bar' } }, - { type: 'foo', ...mockTimestampFields, foo: {}, references: [] }, - ], - }) - ); }); - it('mockReturnValue document errors', async () => { - callAdminCluster.mockResolvedValue({ - errors: false, - items: [ - { - create: { - _id: 'config:one', - error: { - reason: 'type[config] missing', - }, - }, - }, - { - create: { - _id: 'index-pattern:two', - ...mockVersionProps, - }, - }, - ], + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect(bulkCreateSuccess([obj1, obj2])).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); }); - const response = await savedObjectsRepository.bulkCreate([ - { type: 'config', id: 'one', attributes: { title: 'Test One' } }, - { type: 'index-pattern', id: 'two', attributes: { title: 'Test Two' } }, - ]); + it(`migrates the docs and serializes the migrated docs`, async () => { + migrator.migrateDocument.mockImplementation(mockMigrateDocument); + await bulkCreateSuccess([obj1, obj2]); + const docs = [obj1, obj2].map(x => ({ ...x, ...mockTimestampFields })); + expectMigrationArgs(docs[0], true, 1); + expectMigrationArgs(docs[1], true, 2); - expect(response).toEqual({ - saved_objects: [ - { - id: 'one', - type: 'config', - error: { message: 'type[config] missing' }, - }, - { - id: 'two', - type: 'index-pattern', - version: mockVersion, - ...mockTimestampFields, - attributes: { title: 'Test Two' }, - references: [], - }, - ], + const migratedDocs = docs.map(x => migrator.migrateDocument(x)); + expect(serializer.savedObjectToRaw).toHaveBeenNthCalledWith(1, migratedDocs[0]); + expect(serializer.savedObjectToRaw).toHaveBeenNthCalledWith(2, migratedDocs[1]); }); - }); - it('formats Elasticsearch response', async () => { - callAdminCluster.mockResolvedValue({ - errors: false, - items: [ - { - create: { - _id: 'config:one', - ...mockVersionProps, - }, - }, - { - create: { - _id: 'index-pattern:two', - ...mockVersionProps, - }, - }, - ], + it(`adds namespace to body when providing namespace for single-namespace type`, async () => { + await bulkCreateSuccess([obj1, obj2], { namespace }); + expectMigrationArgs({ namespace }, true, 1); + expectMigrationArgs({ namespace }, true, 2); }); - const response = await savedObjectsRepository.bulkCreate( - [ - { type: 'config', id: 'one', attributes: { title: 'Test One' } }, - { type: 'index-pattern', id: 'two', attributes: { title: 'Test Two' } }, - ], - { - namespace: 'foo-namespace', - } - ); + it(`doesn't add namespace to body when providing no namespace for single-namespace type`, async () => { + await bulkCreateSuccess([obj1, obj2]); + expectMigrationArgs({ namespace: expect.anything() }, false, 1); + expectMigrationArgs({ namespace: expect.anything() }, false, 2); + }); - expect(response).toEqual({ - saved_objects: [ - { - id: 'one', - type: 'config', - version: mockVersion, - ...mockTimestampFields, - attributes: { title: 'Test One' }, - references: [], - }, - { - id: 'two', - type: 'index-pattern', - version: mockVersion, - ...mockTimestampFields, - attributes: { title: 'Test Two' }, - references: [], - }, - ], + it(`doesn't add namespace to body when not using single-namespace type`, async () => { + const objects = [ + { ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }, + { ...obj2, type: MULTI_NAMESPACE_TYPE }, + ]; + await bulkCreateSuccess(objects, { namespace }); + expectMigrationArgs({ namespace: expect.anything() }, false, 1); + expectMigrationArgs({ namespace: expect.anything() }, false, 2); }); - }); - it('prepends namespace to the id and adds namespace to body when providing namespace for namespaced type', async () => { - callAdminCluster.mockReturnValue({ - items: [ - { - create: { - _id: 'foo-namespace:config:one', - _index: '.kibana-test', - _primary_term: 1, - _seq_no: 2, - }, - }, - { - create: { - _id: 'foo-namespace:index-pattern:two', - _primary_term: 1, - _seq_no: 2, - }, - }, - ], + it(`adds namespaces to body when providing namespace for multi-namespace type`, async () => { + const objects = [obj1, obj2].map(obj => ({ ...obj, type: MULTI_NAMESPACE_TYPE })); + await bulkCreateSuccess(objects, { namespace }); + expectMigrationArgs({ namespaces: [namespace] }, true, 1); + expectMigrationArgs({ namespaces: [namespace] }, true, 2); }); - await savedObjectsRepository.bulkCreate( - [ - { type: 'config', id: 'one', attributes: { title: 'Test One' } }, - { type: 'index-pattern', id: 'two', attributes: { title: 'Test Two' } }, - ], - { - namespace: 'foo-namespace', - } - ); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'bulk', - expect.objectContaining({ - body: [ - { create: { _index: '.kibana-test', _id: 'foo-namespace:config:one' } }, - { - namespace: 'foo-namespace', - type: 'config', - ...mockTimestampFields, - config: { title: 'Test One' }, - references: [], - }, - { create: { _index: '.kibana-test', _id: 'foo-namespace:index-pattern:two' } }, - { - namespace: 'foo-namespace', - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { title: 'Test Two' }, - references: [], - }, - ], - }) - ); - }); - it(`doesn't prepend namespace to the id or add namespace property when providing no namespace for namespaced type`, async () => { - callAdminCluster.mockResolvedValue({ - errors: false, - items: [ - { - create: { - _id: 'config:one', - ...mockVersionProps, - }, - }, - { - create: { - _id: 'index-pattern:two', - ...mockVersionProps, - }, - }, - ], + it(`adds default namespaces to body when providing no namespace for multi-namespace type`, async () => { + const objects = [obj1, obj2].map(obj => ({ ...obj, type: MULTI_NAMESPACE_TYPE })); + await bulkCreateSuccess(objects); + expectMigrationArgs({ namespaces: ['default'] }, true, 1); + expectMigrationArgs({ namespaces: ['default'] }, true, 2); }); - await savedObjectsRepository.bulkCreate([ - { type: 'config', id: 'one', attributes: { title: 'Test One' } }, - { type: 'index-pattern', id: 'two', attributes: { title: 'Test Two' } }, - ]); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'bulk', - expect.objectContaining({ - body: [ - { create: { _id: 'config:one', _index: '.kibana-test' } }, - { - type: 'config', - ...mockTimestampFields, - config: { title: 'Test One' }, - references: [], - }, - { create: { _id: 'index-pattern:two', _index: '.kibana-test' } }, - { - type: 'index-pattern', - ...mockTimestampFields, - 'index-pattern': { title: 'Test Two' }, - references: [], - }, - ], - }) - ); - }); - it(`doesn't prepend namespace to the id or add namespace property when providing namespace for namespace agnostic type`, async () => { - callAdminCluster.mockReturnValue({ - items: [{ create: { _type: '_doc', _id: 'globaltype:one', _primary_term: 1, _seq_no: 2 } }], + it(`doesn't add namespaces to body when not using multi-namespace type`, async () => { + const objects = [obj1, { ...obj2, type: NAMESPACE_AGNOSTIC_TYPE }]; + await bulkCreateSuccess(objects); + expectMigrationArgs({ namespaces: expect.anything() }, false, 1); + expectMigrationArgs({ namespaces: expect.anything() }, false, 2); }); - await savedObjectsRepository.bulkCreate( - [{ type: 'globaltype', id: 'one', attributes: { title: 'Test One' } }], - { - namespace: 'foo-namespace', - } - ); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'bulk', - expect.objectContaining({ - body: [ - { create: { _id: 'globaltype:one', _index: '.kibana-test' } }, - { - type: 'globaltype', - ...mockTimestampFields, - globaltype: { title: 'Test One' }, - references: [], - }, - ], - }) - ); }); - it('should return objects in the same order regardless of type', () => {}); - }); + describe('returns', () => { + it(`formats the ES response`, async () => { + const result = await bulkCreateSuccess([obj1, obj2]); + expect(result).toEqual({ + saved_objects: [obj1, obj2].map(x => expectSuccessResult(x)), + }); + }); - describe('#delete', () => { - it('waits until migrations are complete before proceeding', async () => { - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); - callAdminCluster.mockReturnValue({ result: 'deleted' }); - await expect( - savedObjectsRepository.delete('index-pattern', 'logstash-*', { - namespace: 'foo-namespace', - }) - ).resolves.toBeDefined(); - - expect(migrator.runMigrations).toHaveBeenCalledTimes(1); + it(`should return objects in the same order regardless of type`, async () => { + // TODO + }); + + it(`handles a mix of successful creates and errors`, async () => { + const obj = { + type: 'unknownType', + id: 'three', + }; + const objects = [obj1, obj, obj2]; + const response = getMockBulkCreateResponse(objects); + callAdminCluster.mockResolvedValue(response); // this._writeToCluster('bulk', ...) + const result = await savedObjectsRepository.bulkCreate(objects); + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(result).toEqual({ + saved_objects: [expectSuccessResult(obj1), expectError(obj), expectSuccessResult(obj2)], + }); + }); }); + }); - it('throws notFound when ES is unable to find the document', async () => { - expect.assertions(1); + describe('#bulkGet', () => { + const obj1 = { + type: 'config', + id: '6.0.0-alpha1', + attributes: { title: 'Testing' }, + references: [ + { + name: 'ref_0', + type: 'test', + id: '1', + }, + ], + }; + const obj2 = { + type: 'index-pattern', + id: 'logstash-*', + attributes: { title: 'Testing' }, + references: [ + { + name: 'ref_0', + type: 'test', + id: '2', + }, + ], + }; + const namespace = 'foo-namespace'; - callAdminCluster.mockResolvedValue({ result: 'not_found' }); + const bulkGet = async (objects, options) => + savedObjectsRepository.bulkGet( + objects.map(({ type, id }) => ({ type, id })), // bulkGet only uses type and id + options + ); + const bulkGetSuccess = async (objects, options) => { + const response = getMockMgetResponse(objects, options?.namespace); + callAdminCluster.mockReturnValue(response); + const result = await bulkGet(objects, options); + expect(callAdminCluster).toHaveBeenCalledTimes(1); + return result; + }; - try { - await savedObjectsRepository.delete('index-pattern', 'logstash-*'); - } catch (e) { - expect(e.output.statusCode).toEqual(404); - } - }); + const _expectClusterCallArgs = ( + objects, + { _index = expect.any(String), getId = () => expect.any(String) } + ) => { + expectClusterCallArgs({ + body: { + docs: objects.map(({ type, id }) => + expect.objectContaining({ + _index, + _id: getId(type, id), + }) + ), + }, + }); + }; - it(`prepends namespace to the id when providing namespace for namespaced type`, async () => { - callAdminCluster.mockReturnValue({ result: 'deleted' }); - await savedObjectsRepository.delete('index-pattern', 'logstash-*', { - namespace: 'foo-namespace', + describe('cluster calls', () => { + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + const getId = (type, id) => `${namespace}:${type}:${id}`; + await bulkGetSuccess([obj1, obj2], { namespace }); + _expectClusterCallArgs([obj1, obj2], { getId }); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('delete', { - id: 'foo-namespace:index-pattern:logstash-*', - refresh: 'wait_for', - index: '.kibana-test', - ignore: [404], + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + const getId = (type, id) => `${type}:${id}`; + await bulkGetSuccess([obj1, obj2]); + _expectClusterCallArgs([obj1, obj2], { getId }); }); - }); - it(`doesn't prepend namespace to the id when providing no namespace for namespaced type`, async () => { - callAdminCluster.mockReturnValue({ result: 'deleted' }); - await savedObjectsRepository.delete('index-pattern', 'logstash-*'); + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + const getId = (type, id) => `${type}:${id}`; + let objects = [obj1, obj2].map(obj => ({ ...obj, type: NAMESPACE_AGNOSTIC_TYPE })); + await bulkGetSuccess(objects, { namespace }); + _expectClusterCallArgs(objects, { getId }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('delete', { - id: 'index-pattern:logstash-*', - refresh: 'wait_for', - index: '.kibana-test', - ignore: [404], + callAdminCluster.mockReset(); + objects = [obj1, obj2].map(obj => ({ ...obj, type: MULTI_NAMESPACE_TYPE })); + await bulkGetSuccess(objects, { namespace }); + _expectClusterCallArgs(objects, { getId }); }); }); - it(`doesn't prepend namespace to the id when providing namespace for namespace agnostic type`, async () => { - callAdminCluster.mockReturnValue({ result: 'deleted' }); - await savedObjectsRepository.delete('globaltype', 'logstash-*', { - namespace: 'foo-namespace', - }); + describe('errors', () => { + const bulkGetErrorInvalidType = async ([obj1, obj, obj2]) => { + const response = getMockMgetResponse([obj1, obj2]); + callAdminCluster.mockResolvedValue(response); + const result = await bulkGet([obj1, obj, obj2]); + expectClusterCalls('mget'); + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectErrorInvalidType(obj), expectSuccess(obj2)], + }); + }; - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('delete', { - id: 'globaltype:logstash-*', - refresh: 'wait_for', - index: '.kibana-test', - ignore: [404], - }); - }); + const bulkGetErrorNotFound = async ([obj1, obj, obj2], options, response) => { + callAdminCluster.mockResolvedValue(response); + const result = await bulkGet([obj1, obj, obj2], options); + expectClusterCalls('mget'); + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectErrorNotFound(obj), expectSuccess(obj2)], + }); + }; - it('defaults to a refresh setting of `wait_for`', async () => { - callAdminCluster.mockReturnValue({ result: 'deleted' }); - await savedObjectsRepository.delete('globaltype', 'logstash-*'); + it(`returns error when type is invalid`, async () => { + const obj = { type: 'unknownType', id: 'three' }; + await bulkGetErrorInvalidType([obj1, obj, obj2]); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: 'wait_for', + it(`returns error when type is hidden`, async () => { + const obj = { type: HIDDEN_TYPE, id: 'three' }; + await bulkGetErrorInvalidType([obj1, obj, obj2]); }); - }); - it(`accepts a custom refresh setting`, async () => { - callAdminCluster.mockReturnValue({ result: 'deleted' }); - await savedObjectsRepository.delete('globaltype', 'logstash-*', { - refresh: false, + it(`returns error when document is not found`, async () => { + const obj = { type: 'dashboard', id: 'three', found: false }; + const response = getMockMgetResponse([obj1, obj, obj2]); + await bulkGetErrorNotFound([obj1, obj, obj2], undefined, response); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: false, + it(`handles missing ids gracefully`, async () => { + const obj = { type: 'dashboard', id: undefined, found: false }; + const response = getMockMgetResponse([obj1, obj, obj2]); + await bulkGetErrorNotFound([obj1, obj, obj2], undefined, response); }); - }); - }); - describe('#deleteByNamespace', () => { - it('requires namespace to be defined', async () => { - callAdminCluster.mockReturnValue(deleteByQueryResults); - expect(savedObjectsRepository.deleteByNamespace()).rejects.toThrowErrorMatchingSnapshot(); - expect(callAdminCluster).not.toHaveBeenCalled(); + it(`returns error when type is multi-namespace and the document exists, but not in this namespace`, async () => { + const obj = { type: MULTI_NAMESPACE_TYPE, id: 'three' }; + const response = getMockMgetResponse([obj1, obj, obj2]); + response.docs[1].namespaces = ['bar-namespace']; + await bulkGetErrorNotFound([obj1, obj, obj2], { namespace }, response); + }); }); - it('requires namespace to be a string', async () => { - callAdminCluster.mockReturnValue(deleteByQueryResults); - expect( - savedObjectsRepository.deleteByNamespace(['namespace-1', 'namespace-2']) - ).rejects.toThrowErrorMatchingSnapshot(); - expect(callAdminCluster).not.toHaveBeenCalled(); + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect(bulkGetSuccess([obj1, obj2])).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); + }); }); - it('constructs a deleteByQuery call using all types that are namespace aware', async () => { - callAdminCluster.mockReturnValue(deleteByQueryResults); - const result = await savedObjectsRepository.deleteByNamespace('my-namespace'); - - expect(result).toEqual(deleteByQueryResults); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - - expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, typeRegistry, { - namespace: 'my-namespace', - type: ['config', 'baz', 'index-pattern', 'dashboard'], + describe('returns', () => { + const expectSuccessResult = ({ type, id }, doc) => ({ + type, + id, + ...(doc._source.namespaces && { namespaces: doc._source.namespaces }), + ...(doc._source.updated_at && { updated_at: doc._source.updated_at }), + version: encodeHitVersion(doc), + attributes: doc._source[type], + references: doc._source.references || [], + migrationVersion: doc._source.migrationVersion, }); - expect(callAdminCluster).toHaveBeenCalledWith('deleteByQuery', { - body: { conflicts: 'proceed' }, - ignore: [404], - index: ['.kibana-test', 'beats'], - refresh: 'wait_for', + it(`returns early for empty objects argument`, async () => { + const result = await bulkGet([]); + expect(result).toEqual({ saved_objects: [] }); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - }); - - it('defaults to a refresh setting of `wait_for`', async () => { - callAdminCluster.mockReturnValue(deleteByQueryResults); - await savedObjectsRepository.deleteByNamespace('my-namespace'); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: 'wait_for', + it(`formats the ES response`, async () => { + const response = getMockMgetResponse([obj1, obj2]); + callAdminCluster.mockResolvedValue(response); + const result = await bulkGet([obj1, obj2]); + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(result).toEqual({ + saved_objects: [ + expectSuccessResult(obj1, response.docs[0]), + expectSuccessResult(obj2, response.docs[1]), + ], + }); }); - }); - it('accepts a custom refresh setting', async () => { - callAdminCluster.mockReturnValue(deleteByQueryResults); - await savedObjectsRepository.deleteByNamespace('my-namespace', { refresh: true }); + it(`handles a mix of successful gets and errors`, async () => { + const response = getMockMgetResponse([obj1, obj2]); + callAdminCluster.mockResolvedValue(response); + const obj = { type: 'unknownType', id: 'three' }; + const result = await bulkGet([obj1, obj, obj2]); + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(result).toEqual({ + saved_objects: [ + expectSuccessResult(obj1, response.docs[0]), + expectError(obj), + expectSuccessResult(obj2, response.docs[1]), + ], + }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: true, + it(`includes namespaces property for multi-namespace documents`, async () => { + const obj = { type: MULTI_NAMESPACE_TYPE, id: 'three' }; + const result = await bulkGetSuccess([obj1, obj]); + expect(result).toEqual({ + saved_objects: [ + expect.not.objectContaining({ namespaces: expect.anything() }), + expect.objectContaining({ namespaces: expect.any(Array) }), + ], + }); }); }); }); - describe('#find', () => { - it('waits until migrations are complete before proceeding', async () => { - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); - - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - await expect(savedObjectsRepository.find({ type: 'foo' })).resolves.toBeDefined(); - - expect(migrator.runMigrations).toHaveBeenCalledTimes(1); - }); - - it('requires type to be defined', async () => { - await expect(savedObjectsRepository.find({})).rejects.toThrow(/options\.type must be/); - expect(callAdminCluster).not.toHaveBeenCalled(); + describe('#bulkUpdate', () => { + const obj1 = { + type: 'config', + id: '6.0.0-alpha1', + attributes: { title: 'Test One' }, + }; + const obj2 = { + type: 'index-pattern', + id: 'logstash-*', + attributes: { title: 'Test Two' }, + }; + const references = [{ name: 'ref_0', type: 'test', id: '1' }]; + const namespace = 'foo-namespace'; + + const getMockBulkUpdateResponse = (objects, options) => ({ + items: objects.map(({ type, id }) => ({ + update: { + _id: `${ + registry.isSingleNamespace(type) && options?.namespace ? `${options?.namespace}:` : '' + }${type}:${id}`, + ...mockVersionProps, + result: 'updated', + }, + })), }); - it('requires searchFields be an array if defined', async () => { - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - try { - await savedObjectsRepository.find({ type: 'foo', searchFields: 'string' }); - throw new Error('expected find() to reject'); - } catch (error) { - expect(callAdminCluster).not.toHaveBeenCalled(); - expect(error.message).toMatch('must be an array'); + const bulkUpdateSuccess = async (objects, options) => { + const multiNamespaceObjects = objects.filter(({ type }) => registry.isMultiNamespace(type)); + if (multiNamespaceObjects?.length) { + const response = getMockMgetResponse(multiNamespaceObjects, options?.namespace); + callAdminCluster.mockResolvedValueOnce(response); // this._callCluster('mget', ...) } - }); + const response = getMockBulkUpdateResponse(objects, options?.namespace); + callAdminCluster.mockResolvedValue(response); // this._writeToCluster('bulk', ...) + const result = await savedObjectsRepository.bulkUpdate(objects, options); + expect(callAdminCluster).toHaveBeenCalledTimes(multiNamespaceObjects?.length ? 2 : 1); + return result; + }; - it('requires fields be an array if defined', async () => { - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - try { - await savedObjectsRepository.find({ type: 'foo', fields: 'string' }); - throw new Error('expected find() to reject'); - } catch (error) { - expect(callAdminCluster).not.toHaveBeenCalled(); - expect(error.message).toMatch('must be an array'); + // bulk create calls have two objects for each source -- the action, and the source + const expectClusterCallArgsAction = ( + objects, + { method, _index = expect.any(String), getId = () => expect.any(String), overrides }, + n + ) => { + const body = []; + for (const { type, id } of objects) { + body.push({ + [method]: { + _index, + _id: getId(type, id), + ...overrides, + }, + }); + body.push(expect.any(Object)); } - }); - - it('passes mappings, schema, search, defaultSearchOperator, searchFields, type, sortField, sortOrder and hasReference to getSearchDsl', async () => { - callAdminCluster.mockReturnValue(namespacedSearchResults); - const relevantOpts = { - namespace: 'foo-namespace', - search: 'foo*', - searchFields: ['foo'], - type: ['bar'], - sortField: 'name', - sortOrder: 'desc', - defaultSearchOperator: 'AND', - hasReference: { - type: 'foo', - id: '1', - }, - kueryNode: undefined, - }; + expectClusterCallArgs({ body }, n); + }; - await savedObjectsRepository.find(relevantOpts); - expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledTimes(1); - expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith( - mappings, - typeRegistry, - relevantOpts - ); - }); + const expectObjArgs = ({ type, attributes }) => [ + expect.any(Object), + { + doc: expect.objectContaining({ + [type]: attributes, + ...mockTimestampFields, + }), + }, + ]; - it('accepts KQL filter and passes keuryNode to getSearchDsl', async () => { - callAdminCluster.mockReturnValue(namespacedSearchResults); - const findOpts = { - namespace: 'foo-namespace', - search: 'foo*', - searchFields: ['foo'], - type: ['dashboard'], - sortField: 'name', - sortOrder: 'desc', - defaultSearchOperator: 'AND', - hasReference: { - type: 'foo', - id: '1', - }, - indexPattern: undefined, - filter: 'dashboard.attributes.otherField: *', + describe('cluster calls', () => { + it(`should use the ES bulk action by default`, async () => { + await bulkUpdateSuccess([obj1, obj2]); + expectClusterCalls('bulk'); + }); + + it(`should use the ES mget action before bulk action for any types that are multi-namespace`, async () => { + const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_TYPE }]; + await bulkUpdateSuccess(objects); + expectClusterCalls('mget', 'bulk'); + const docs = [expect.objectContaining({ _id: `${MULTI_NAMESPACE_TYPE}:${obj2.id}` })]; + expectClusterCallArgs({ body: { docs } }, 1); + }); + + it(`formats the ES request`, async () => { + await bulkUpdateSuccess([obj1, obj2]); + const body = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; + expectClusterCallArgs({ body }); + }); + + it(`formats the ES request for any types that are multi-namespace`, async () => { + const _obj2 = { ...obj2, type: MULTI_NAMESPACE_TYPE }; + await bulkUpdateSuccess([obj1, _obj2]); + const body = [...expectObjArgs(obj1), ...expectObjArgs(_obj2)]; + expectClusterCallArgs({ body }, 2); + }); + + it(`doesnt call Elasticsearch if there are no valid objects to update`, async () => { + const objects = [obj1, obj2].map(x => ({ ...x, type: 'unknownType' })); + await savedObjectsRepository.bulkUpdate(objects); + expect(callAdminCluster).toHaveBeenCalledTimes(0); + }); + + it(`defaults to no references`, async () => { + await bulkUpdateSuccess([obj1, obj2]); + const expected = { doc: expect.not.objectContaining({ references: expect.anything() }) }; + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expectClusterCallArgs({ body }); + }); + + it(`accepts custom references array`, async () => { + const test = async references => { + const objects = [obj1, obj2].map(obj => ({ ...obj, references })); + await bulkUpdateSuccess(objects); + const expected = { doc: expect.objectContaining({ references }) }; + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expectClusterCallArgs({ body }); + callAdminCluster.mockReset(); + }; + await test(references); + await test(['string']); + await test([]); + }); + + it(`doesn't accept custom references if not an array`, async () => { + const test = async references => { + const objects = [obj1, obj2].map(obj => ({ ...obj, references })); + await bulkUpdateSuccess(objects); + const expected = { doc: expect.not.objectContaining({ references: expect.anything() }) }; + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expectClusterCallArgs({ body }); + callAdminCluster.mockReset(); + }; + await test('string'); + await test(123); + await test(true); + await test(null); + }); + + it(`defaults to a refresh setting of wait_for`, async () => { + await bulkUpdateSuccess([obj1, obj2]); + expectClusterCallArgs({ refresh: 'wait_for' }); + }); + + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await bulkUpdateSuccess([obj1, obj2], { refresh }); + expectClusterCallArgs({ refresh }); + }); + + it(`defaults to the version of the existing document for multi-namespace types`, async () => { + // only multi-namespace documents are obtained using a pre-flight mget request + const objects = [ + { ...obj1, type: MULTI_NAMESPACE_TYPE }, + { ...obj2, type: MULTI_NAMESPACE_TYPE }, + ]; + await bulkUpdateSuccess(objects); + const overrides = { + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + expectClusterCallArgsAction(objects, { method: 'update', overrides }, 2); + }); + + it(`defaults to no version for types that are not multi-namespace`, async () => { + const objects = [obj1, { ...obj2, type: NAMESPACE_AGNOSTIC_TYPE }]; + await bulkUpdateSuccess(objects); + expectClusterCallArgsAction(objects, { method: 'update' }); + }); + + it(`accepts version`, async () => { + const version = encodeHitVersion({ _seq_no: 100, _primary_term: 200 }); + // test with both non-multi-namespace and multi-namespace types + const objects = [ + { ...obj1, version }, + { ...obj2, type: MULTI_NAMESPACE_TYPE, version }, + ]; + await bulkUpdateSuccess(objects); + const overrides = { if_seq_no: 100, if_primary_term: 200 }; + expectClusterCallArgsAction(objects, { method: 'update', overrides }, 2); + }); + + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + const getId = (type, id) => `${namespace}:${type}:${id}`; + await bulkUpdateSuccess([obj1, obj2], { namespace }); + expectClusterCallArgsAction([obj1, obj2], { method: 'update', getId }); + }); + + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + const getId = (type, id) => `${type}:${id}`; + await bulkUpdateSuccess([obj1, obj2]); + expectClusterCallArgsAction([obj1, obj2], { method: 'update', getId }); + }); + + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + const getId = (type, id) => `${type}:${id}`; + const objects1 = [{ ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }]; + await bulkUpdateSuccess(objects1, { namespace }); + expectClusterCallArgsAction(objects1, { method: 'update', getId }); + callAdminCluster.mockReset(); + const overrides = { + // bulkUpdate uses a preflight `get` request for multi-namespace saved objects, and specifies that version on `update` + // we aren't testing for this here, but we need to include Jest assertions so this test doesn't fail + if_primary_term: expect.any(Number), + if_seq_no: expect.any(Number), + }; + const objects2 = [{ ...obj2, type: MULTI_NAMESPACE_TYPE }]; + await bulkUpdateSuccess(objects2, { namespace }); + expectClusterCallArgsAction(objects2, { method: 'update', getId, overrides }, 2); + }); + }); + + describe('errors', () => { + const obj = { + type: 'dashboard', + id: 'three', }; - await savedObjectsRepository.find(findOpts); - expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledTimes(1); - const { kueryNode } = getSearchDslNS.getSearchDsl.mock.calls[0][2]; - expect(kueryNode).toMatchInlineSnapshot(` - Object { - "arguments": Array [ - Object { - "type": "literal", - "value": "dashboard.otherField", - }, - Object { - "type": "wildcard", - "value": "@kuery-wildcard@", - }, - Object { - "type": "literal", - "value": false, - }, - ], - "function": "is", - "type": "function", + const bulkUpdateError = async (obj, esError, expectedError) => { + const objects = [obj1, obj, obj2]; + const mockResponse = getMockBulkUpdateResponse(objects); + if (esError) { + mockResponse.items[1].update = { error: esError }; } - `); - }); + callAdminCluster.mockResolvedValue(mockResponse); // this._writeToCluster('bulk', ...) + + const result = await savedObjectsRepository.bulkUpdate(objects); + expectClusterCalls('bulk'); + const objCall = esError ? expectObjArgs(obj) : []; + const body = [...expectObjArgs(obj1), ...objCall, ...expectObjArgs(obj2)]; + expectClusterCallArgs({ body }); + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectedError, expectSuccess(obj2)], + }); + }; - it('KQL filter syntax errors rejects with bad request', async () => { - callAdminCluster.mockReturnValue(namespacedSearchResults); - const findOpts = { - namespace: 'foo-namespace', - search: 'foo*', - searchFields: ['foo'], - type: ['dashboard'], - sortField: 'name', - sortOrder: 'desc', - defaultSearchOperator: 'AND', - hasReference: { - type: 'foo', - id: '1', - }, - indexPattern: undefined, - filter: 'dashboard.attributes.otherField:<', + const bulkUpdateMultiError = async ([obj1, _obj, obj2], options, mgetResponse) => { + callAdminCluster.mockResolvedValueOnce(mgetResponse); // this._callCluster('mget', ...) + const bulkResponse = getMockBulkUpdateResponse([obj1, obj2], namespace); + callAdminCluster.mockResolvedValue(bulkResponse); // this._writeToCluster('bulk', ...) + + const result = await savedObjectsRepository.bulkUpdate([obj1, _obj, obj2], options); + expectClusterCalls('mget', 'bulk'); + const body = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; + expectClusterCallArgs({ body }, 2); + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectErrorNotFound(_obj), expectSuccess(obj2)], + }); }; - await expect(savedObjectsRepository.find(findOpts)).rejects.toMatchInlineSnapshot(` - [Error: KQLSyntaxError: Expected "(", "{", value, whitespace but "<" found. - dashboard.attributes.otherField:< - --------------------------------^: Bad Request] - `); - expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledTimes(0); - }); + it(`returns error when type is invalid`, async () => { + const _obj = { ...obj, type: 'unknownType' }; + await bulkUpdateError(_obj, undefined, expectErrorNotFound(_obj)); + }); - it('merges output of getSearchDsl into es request body', async () => { - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - getSearchDslNS.getSearchDsl.mockReturnValue({ query: 1, aggregations: 2 }); - await savedObjectsRepository.find({ type: 'foo' }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - 'search', - expect.objectContaining({ - body: expect.objectContaining({ - query: 1, - aggregations: 2, - }), - }) - ); - }); + it(`returns error when type is hidden`, async () => { + const _obj = { ...obj, type: HIDDEN_TYPE }; + await bulkUpdateError(_obj, undefined, expectErrorNotFound(_obj)); + }); - it('formats Elasticsearch response when there is no namespace', async () => { - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - const count = noNamespaceSearchResults.hits.hits.length; + it(`returns error when ES is unable to find the document (mget)`, async () => { + const _obj = { ...obj, type: MULTI_NAMESPACE_TYPE, found: false }; + const mgetResponse = getMockMgetResponse([_obj]); + await bulkUpdateMultiError([obj1, _obj, obj2], undefined, mgetResponse); + }); - const response = await savedObjectsRepository.find({ type: 'foo' }); + it(`returns error when ES is unable to find the index (mget)`, async () => { + const _obj = { ...obj, type: MULTI_NAMESPACE_TYPE }; + const mgetResponse = { status: 404 }; + await bulkUpdateMultiError([obj1, _obj, obj2], { namespace }, mgetResponse); + }); - expect(response.total).toBe(count); - expect(response.saved_objects).toHaveLength(count); + it(`returns error when there is a conflict with an existing multi-namespace saved object (mget)`, async () => { + const _obj = { ...obj, type: MULTI_NAMESPACE_TYPE }; + const mgetResponse = getMockMgetResponse([_obj], 'bar-namespace'); + await bulkUpdateMultiError([obj1, _obj, obj2], { namespace }, mgetResponse); + }); - noNamespaceSearchResults.hits.hits.forEach((doc, i) => { - expect(response.saved_objects[i]).toEqual({ - id: doc._id.replace(/(index-pattern|config|globaltype)\:/, ''), - type: doc._source.type, - ...mockTimestampFields, - version: mockVersion, - attributes: doc._source[doc._source.type], - references: [], - }); + it(`returns error when there is a version conflict (bulk)`, async () => { + const esError = { type: 'version_conflict_engine_exception' }; + await bulkUpdateError(obj, esError, expectErrorConflict(obj)); }); - }); - it('formats Elasticsearch response when there is a namespace', async () => { - callAdminCluster.mockReturnValue(namespacedSearchResults); - const count = namespacedSearchResults.hits.hits.length; + it(`returns error when document is missing (bulk)`, async () => { + const esError = { type: 'document_missing_exception' }; + await bulkUpdateError(obj, esError, expectErrorNotFound(obj)); + }); - const response = await savedObjectsRepository.find({ - type: 'foo', - namespace: 'foo-namespace', + it(`returns error reason for other errors (bulk)`, async () => { + const esError = { reason: 'some_other_error' }; + await bulkUpdateError(obj, esError, expectErrorResult(obj, { message: esError.reason })); }); - expect(response.total).toBe(count); - expect(response.saved_objects).toHaveLength(count); + it(`returns error string for other errors if no reason is defined (bulk)`, async () => { + const esError = { foo: 'some_other_error' }; + const expectedError = expectErrorResult(obj, { message: JSON.stringify(esError) }); + await bulkUpdateError(obj, esError, expectedError); + }); + }); - namespacedSearchResults.hits.hits.forEach((doc, i) => { - expect(response.saved_objects[i]).toEqual({ - id: doc._id.replace(/(foo-namespace\:)?(index-pattern|config|globaltype)\:/, ''), - type: doc._source.type, - ...mockTimestampFields, - version: mockVersion, - attributes: doc._source[doc._source.type], - references: [], - }); + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect(bulkUpdateSuccess([obj1, obj2])).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveReturnedTimes(1); }); }); - it('accepts per_page/page', async () => { - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - await savedObjectsRepository.find({ type: 'foo', perPage: 10, page: 6 }); + describe('returns', () => { + const expectSuccessResult = ({ type, id, attributes, references }) => ({ + type, + id, + attributes, + references, + version: mockVersion, + ...mockTimestampFields, + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - size: 10, - from: 50, - }) - ); - }); + it(`formats the ES response`, async () => { + const response = await bulkUpdateSuccess([obj1, obj2]); + expect(response).toEqual({ + saved_objects: [obj1, obj2].map(expectSuccessResult), + }); + }); - it('can filter by fields', async () => { - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - await savedObjectsRepository.find({ type: 'foo', fields: ['title'] }); + it(`includes references`, async () => { + const objects = [obj1, obj2].map(obj => ({ ...obj, references })); + const response = await bulkUpdateSuccess(objects); + expect(response).toEqual({ + saved_objects: objects.map(expectSuccessResult), + }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - _source: [ - 'foo.title', - 'namespace', - 'type', - 'references', - 'migrationVersion', - 'updated_at', - 'title', + it(`handles a mix of successful updates and errors`, async () => { + const obj = { + type: 'unknownType', + id: 'three', + }; + const objects = [obj1, obj, obj2]; + const mockResponse = getMockBulkUpdateResponse(objects); + callAdminCluster.mockResolvedValue(mockResponse); // this._writeToCluster('bulk', ...) + const result = await savedObjectsRepository.bulkUpdate(objects); + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(result).toEqual({ + saved_objects: [expectSuccessResult(obj1), expectError(obj), expectSuccessResult(obj2)], + }); + }); + + it(`includes namespaces property for multi-namespace documents`, async () => { + const obj = { type: MULTI_NAMESPACE_TYPE, id: 'three' }; + const result = await bulkUpdateSuccess([obj1, obj]); + expect(result).toEqual({ + saved_objects: [ + expect.not.objectContaining({ namespaces: expect.anything() }), + expect.objectContaining({ namespaces: expect.any(Array) }), ], - }) - ); + }); + }); }); + }); - it('should set rest_total_hits_as_int to true on a request', async () => { - callAdminCluster.mockReturnValue(noNamespaceSearchResults); - await savedObjectsRepository.find({ type: 'foo' }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toHaveProperty('rest_total_hits_as_int', true); + describe('#create', () => { + beforeEach(() => { + callAdminCluster.mockImplementation((method, params) => ({ + _id: params.id, + ...mockVersionProps, + })); }); - }); - describe('#get', () => { - const noNamespaceResult = { - _id: 'index-pattern:logstash-*', - ...mockVersionProps, - _source: { - type: 'index-pattern', - specialProperty: 'specialValue', - ...mockTimestampFields, - 'index-pattern': { - title: 'Testing', - }, - }, - }; - const namespacedResult = { - _id: 'foo-namespace:index-pattern:logstash-*', - ...mockVersionProps, - _source: { - namespace: 'foo-namespace', - type: 'index-pattern', - specialProperty: 'specialValue', - ...mockTimestampFields, - 'index-pattern': { - title: 'Testing', - }, + const type = 'index-pattern'; + const attributes = { title: 'Logstash' }; + const id = 'logstash-*'; + const namespace = 'foo-namespace'; + const references = [ + { + name: 'ref_0', + type: 'test', + id: '123', }, - }; + ]; - it('waits until migrations are complete before proceeding', async () => { - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); + const createSuccess = async (type, attributes, options) => { + const result = await savedObjectsRepository.create(type, attributes, options); + expect(callAdminCluster).toHaveBeenCalledTimes( + registry.isMultiNamespace(type) && options.overwrite ? 2 : 1 + ); + return result; + }; - callAdminCluster.mockResolvedValue(noNamespaceResult); - await expect( - savedObjectsRepository.get('index-pattern', 'logstash-*') - ).resolves.toBeDefined(); + describe('cluster calls', () => { + it(`should use the ES create action if ID is undefined and overwrite=true`, async () => { + await createSuccess(type, attributes, { overwrite: true }); + expectClusterCalls('create'); + }); - expect(migrator.runMigrations).toHaveBeenCalledTimes(1); - }); + it(`should use the ES create action if ID is undefined and overwrite=false`, async () => { + await createSuccess(type, attributes); + expectClusterCalls('create'); + }); - it('formats Elasticsearch response when there is no namespace', async () => { - callAdminCluster.mockResolvedValue(noNamespaceResult); - const response = await savedObjectsRepository.get('index-pattern', 'logstash-*'); - expect(response).toEqual({ - id: 'logstash-*', - type: 'index-pattern', - updated_at: mockTimestamp, - version: mockVersion, - attributes: { - title: 'Testing', - }, - references: [], + it(`should use the ES index action if ID is defined and overwrite=true`, async () => { + await createSuccess(type, attributes, { id, overwrite: true }); + expectClusterCalls('index'); }); - }); - it('formats Elasticsearch response when there are namespaces', async () => { - callAdminCluster.mockResolvedValue(namespacedResult); - const response = await savedObjectsRepository.get('index-pattern', 'logstash-*'); - expect(response).toEqual({ - id: 'logstash-*', - type: 'index-pattern', - updated_at: mockTimestamp, - version: mockVersion, - attributes: { - title: 'Testing', - }, - references: [], + it(`should use the ES create action if ID is defined and overwrite=false`, async () => { + await createSuccess(type, attributes, { id }); + expectClusterCalls('create'); }); - }); - it('prepends namespace and type to the id when providing namespace for namespaced type', async () => { - callAdminCluster.mockResolvedValue(namespacedResult); - await savedObjectsRepository.get('index-pattern', 'logstash-*', { - namespace: 'foo-namespace', + it(`should use the ES get action then index action if type is multi-namespace, ID is defined, and overwrite=true`, async () => { + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id, overwrite: true }); + expectClusterCalls('get', 'index'); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: 'foo-namespace:index-pattern:logstash-*', - }) - ); - }); + it(`defaults to empty references array`, async () => { + await createSuccess(type, attributes, { id }); + expectClusterCallArgs({ + body: expect.objectContaining({ references: [] }), + }); + }); - it(`only prepends type to the id when providing no namespace for namespaced type`, async () => { - callAdminCluster.mockResolvedValue(noNamespaceResult); - await savedObjectsRepository.get('index-pattern', 'logstash-*'); + it(`accepts custom references array`, async () => { + const test = async references => { + await createSuccess(type, attributes, { id, references }); + expectClusterCallArgs({ + body: expect.objectContaining({ references }), + }); + callAdminCluster.mockReset(); + }; + await test(references); + await test(['string']); + await test([]); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: 'index-pattern:logstash-*', - }) - ); - }); + it(`doesn't accept custom references if not an array`, async () => { + const test = async references => { + await createSuccess(type, attributes, { id, references }); + expectClusterCallArgs({ + body: expect.not.objectContaining({ references: expect.anything() }), + }); + callAdminCluster.mockReset(); + }; + await test('string'); + await test(123); + await test(true); + await test(null); + }); - it(`doesn't prepend namespace to the id when providing namespace for namespace agnostic type`, async () => { - callAdminCluster.mockResolvedValue(namespacedResult); - await savedObjectsRepository.get('globaltype', 'logstash-*', { - namespace: 'foo-namespace', + it(`defaults to a refresh setting of wait_for`, async () => { + await createSuccess(type, attributes); + expectClusterCallArgs({ refresh: 'wait_for' }); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - id: 'globaltype:logstash-*', - }) - ); - }); - }); + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await createSuccess(type, attributes, { refresh }); + expectClusterCallArgs({ refresh }); + }); - describe('#bulkGet', () => { - it('waits until migrations are complete before proceeding', async () => { - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); - - callAdminCluster.mockReturnValue({ docs: [] }); - await expect( - savedObjectsRepository.bulkGet([ - { id: 'one', type: 'config' }, - { id: 'two', type: 'index-pattern' }, - { id: 'three', type: 'globaltype' }, - ]) - ).resolves.toBeDefined(); - - expect(migrator.runMigrations).toHaveBeenCalledTimes(1); - }); + it(`should use default index`, async () => { + await createSuccess(type, attributes, { id }); + expectClusterCallArgs({ index: '.kibana-test' }); + }); - it('prepends type to id when getting objects when there is no namespace', async () => { - callAdminCluster.mockReturnValue({ docs: [] }); + it(`should use custom index`, async () => { + await createSuccess(CUSTOM_INDEX_TYPE, attributes, { id }); + expectClusterCallArgs({ index: 'custom' }); + }); - await savedObjectsRepository.bulkGet([ - { id: 'one', type: 'config' }, - { id: 'two', type: 'index-pattern' }, - { id: 'three', type: 'globaltype' }, - ]); + it(`self-generates an id if none is provided`, async () => { + await createSuccess(type, attributes); + expectClusterCallArgs({ + id: expect.objectContaining(/index-pattern:[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}/), + }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - body: { - docs: [ - { _id: 'config:one', _index: '.kibana-test' }, - { _id: 'index-pattern:two', _index: '.kibana-test' }, - { _id: 'globaltype:three', _index: '.kibana-test' }, - ], - }, - }) - ); - }); + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + await createSuccess(type, attributes, { id, namespace }); + expectClusterCallArgs({ id: `${namespace}:${type}:${id}` }); + }); - it('prepends namespace and type appropriately to id when getting objects when there is a namespace', async () => { - callAdminCluster.mockReturnValue({ docs: [] }); + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + await createSuccess(type, attributes, { id }); + expectClusterCallArgs({ id: `${type}:${id}` }); + }); - await savedObjectsRepository.bulkGet( - [ - { id: 'one', type: 'config' }, - { id: 'two', type: 'index-pattern' }, - { id: 'three', type: 'globaltype' }, - ], - { - namespace: 'foo-namespace', - } - ); + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + await createSuccess(NAMESPACE_AGNOSTIC_TYPE, attributes, { id, namespace }); + expectClusterCallArgs({ id: `${NAMESPACE_AGNOSTIC_TYPE}:${id}` }); + callAdminCluster.mockReset(); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - body: { - docs: [ - { _id: 'foo-namespace:config:one', _index: '.kibana-test' }, - { _id: 'foo-namespace:index-pattern:two', _index: '.kibana-test' }, - { _id: 'globaltype:three', _index: '.kibana-test' }, - ], - }, - }) - ); + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id, namespace }); + expectClusterCallArgs({ id: `${MULTI_NAMESPACE_TYPE}:${id}` }); + }); }); - it('mockReturnValue early for empty objects argument', async () => { - callAdminCluster.mockReturnValue({ docs: [] }); + describe('errors', () => { + it(`throws when type is invalid`, async () => { + await expect(savedObjectsRepository.create('unknownType', attributes)).rejects.toThrowError( + createUnsupportedTypeError('unknownType') + ); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); - const response = await savedObjectsRepository.bulkGet([]); + it(`throws when type is hidden`, async () => { + await expect(savedObjectsRepository.create(HIDDEN_TYPE, attributes)).rejects.toThrowError( + createUnsupportedTypeError(HIDDEN_TYPE) + ); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); - expect(response.saved_objects).toHaveLength(0); - expect(callAdminCluster).not.toHaveBeenCalled(); + it(`throws when there is a conflict with an existing multi-namespace saved object (get)`, async () => { + const response = getMockGetResponse({ + type: MULTI_NAMESPACE_TYPE, + id, + namespace: 'bar-namespace', + }); + callAdminCluster.mockResolvedValue(response); // this._callCluster('get', ...) + await expect( + savedObjectsRepository.create(MULTI_NAMESPACE_TYPE, attributes, { + id, + overwrite: true, + namespace, + }) + ).rejects.toThrowError(createConflictError(MULTI_NAMESPACE_TYPE, id)); + expectClusterCalls('get'); + }); + + it(`throws when automatic index creation fails`, async () => { + // TODO + }); + + it(`throws when an unexpected failure occurs`, async () => { + // TODO + }); }); - it('handles missing ids gracefully', async () => { - callAdminCluster.mockResolvedValue({ - docs: [ - { - _id: 'config:good', - found: true, - ...mockVersionProps, - _source: { ...mockTimestampFields, config: { title: 'Test' } }, - }, - { - _id: 'config:bad', - found: false, - }, - ], + describe('migration', () => { + beforeEach(() => { + migrator.migrateDocument.mockImplementation(mockMigrateDocument); }); - const { saved_objects: savedObjects } = await savedObjectsRepository.bulkGet([ - { id: 'good', type: 'config' }, - { type: 'config' }, - ]); + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect(createSuccess(type, attributes, { id, namespace })).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); + }); - expect(savedObjects[1]).toEqual({ - type: 'config', - error: { statusCode: 404, message: 'Not found' }, + it(`migrates a document and serializes the migrated doc`, async () => { + const migrationVersion = mockMigrationVersion; + await createSuccess(type, attributes, { id, references, migrationVersion }); + const doc = { type, id, attributes, references, migrationVersion, ...mockTimestampFields }; + expectMigrationArgs(doc); + + const migratedDoc = migrator.migrateDocument(doc); + expect(serializer.savedObjectToRaw).toHaveBeenLastCalledWith(migratedDoc); }); - }); - it('reports error on missed objects', async () => { - callAdminCluster.mockResolvedValue({ - docs: [ - { - _id: 'config:good', - found: true, - ...mockVersionProps, - _source: { ...mockTimestampFields, config: { title: 'Test' } }, - }, - { - _id: 'config:bad', - found: false, - }, - ], + it(`adds namespace to body when providing namespace for single-namespace type`, async () => { + await createSuccess(type, attributes, { id, namespace }); + expectMigrationArgs({ namespace }); }); - const { saved_objects: savedObjects } = await savedObjectsRepository.bulkGet([ - { id: 'good', type: 'config' }, - { id: 'bad', type: 'config' }, - ]); + it(`doesn't add namespace to body when providing no namespace for single-namespace type`, async () => { + await createSuccess(type, attributes, { id }); + expectMigrationArgs({ namespace: expect.anything() }, false); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`doesn't add namespace to body when not using single-namespace type`, async () => { + await createSuccess(NAMESPACE_AGNOSTIC_TYPE, attributes, { id, namespace }); + expectMigrationArgs({ namespace: expect.anything() }, false, 1); - expect(savedObjects).toHaveLength(2); - expect(savedObjects[0]).toEqual({ - id: 'good', - type: 'config', - ...mockTimestampFields, - version: mockVersion, - attributes: { title: 'Test' }, - references: [], + callAdminCluster.mockReset(); + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id }); + expectMigrationArgs({ namespace: expect.anything() }, false, 2); }); - expect(savedObjects[1]).toEqual({ - id: 'bad', - type: 'config', - error: { statusCode: 404, message: 'Not found' }, + + it(`adds namespaces to body when providing namespace for multi-namespace type`, async () => { + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id, namespace }); + expectMigrationArgs({ namespaces: [namespace] }); }); - }); - it('returns errors when requesting unsupported types', async () => { - callAdminCluster.mockResolvedValue({ - docs: [ - { - _id: 'one', - found: true, - ...mockVersionProps, - _source: { ...mockTimestampFields, config: { title: 'Test1' } }, - }, - { - _id: 'three', - found: true, - ...mockVersionProps, - _source: { ...mockTimestampFields, config: { title: 'Test3' } }, - }, - { - _id: 'five', - found: true, - ...mockVersionProps, - _source: { ...mockTimestampFields, config: { title: 'Test5' } }, - }, - ], + it(`adds default namespaces to body when providing no namespace for multi-namespace type`, async () => { + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id }); + expectMigrationArgs({ namespaces: ['default'] }); }); - const { saved_objects: savedObjects } = await savedObjectsRepository.bulkGet([ - { id: 'one', type: 'config' }, - { id: 'two', type: 'invalidtype' }, - { id: 'three', type: 'config' }, - { id: 'four', type: 'invalidtype' }, - { id: 'five', type: 'config' }, - ]); + it(`doesn't add namespaces to body when not using multi-namespace type`, async () => { + await createSuccess(type, attributes, { id }); + expectMigrationArgs({ namespaces: expect.anything() }, false, 1); - expect(savedObjects).toEqual([ - { - attributes: { title: 'Test1' }, - id: 'one', - ...mockTimestampFields, - references: [], - type: 'config', - version: mockVersion, - migrationVersion: undefined, - }, - { - attributes: { title: 'Test3' }, - id: 'three', - ...mockTimestampFields, - references: [], - type: 'config', - version: mockVersion, - migrationVersion: undefined, - }, - { - attributes: { title: 'Test5' }, - id: 'five', + callAdminCluster.mockReset(); + await createSuccess(NAMESPACE_AGNOSTIC_TYPE, attributes, { id }); + expectMigrationArgs({ namespaces: expect.anything() }, false, 2); + }); + }); + + describe('returns', () => { + it(`formats the ES response`, async () => { + const result = await createSuccess(type, attributes, { id, namespace, references }); + expect(result).toEqual({ + type, + id, ...mockTimestampFields, - references: [], - type: 'config', version: mockVersion, - migrationVersion: undefined, - }, - { - error: { - error: 'Bad Request', - message: "Unsupported saved object type: 'invalidtype': Bad Request", - statusCode: 400, - }, - id: 'two', - type: 'invalidtype', - }, - { - error: { - error: 'Bad Request', - message: "Unsupported saved object type: 'invalidtype': Bad Request", - statusCode: 400, - }, - id: 'four', - type: 'invalidtype', - }, - ]); + attributes, + references, + }); + }); }); }); - describe('#update', () => { - const id = 'logstash-*'; + describe('#delete', () => { const type = 'index-pattern'; - const attributes = { title: 'Testing' }; + const id = 'logstash-*'; + const namespace = 'foo-namespace'; - beforeEach(() => { - callAdminCluster.mockResolvedValue({ - _id: `${type}:${id}`, - ...mockVersionProps, - result: 'updated', + const deleteSuccess = async (type, id, options) => { + if (registry.isMultiNamespace(type)) { + const mockGetResponse = getMockGetResponse({ type, id, namespace: options?.namespace }); + callAdminCluster.mockResolvedValueOnce(mockGetResponse); // this._callCluster('get', ...) + } + callAdminCluster.mockResolvedValue({ result: 'deleted' }); // this._writeToCluster('delete', ...) + const result = await savedObjectsRepository.delete(type, id, options); + expect(callAdminCluster).toHaveBeenCalledTimes(registry.isMultiNamespace(type) ? 2 : 1); + return result; + }; + + describe('cluster calls', () => { + it(`should use the ES delete action when not using a multi-namespace type`, async () => { + await deleteSuccess(type, id); + expectClusterCalls('delete'); }); - }); - it('waits until migrations are complete before proceeding', async () => { - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); + it(`should use ES get action then delete action when using a multi-namespace type with no namespaces remaining`, async () => { + await deleteSuccess(MULTI_NAMESPACE_TYPE, id); + expectClusterCalls('get', 'delete'); + }); - await expect( - savedObjectsRepository.update('index-pattern', 'logstash-*', attributes, { - namespace: 'foo-namespace', - }) - ).resolves.toBeDefined(); + it(`should use ES get action then update action when using a multi-namespace type with one or more namespaces remaining`, async () => { + const mockResponse = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }); + mockResponse._source.namespaces = ['default', 'some-other-nameespace']; + callAdminCluster + .mockResolvedValueOnce(mockResponse) // this._callCluster('get', ...) + .mockResolvedValue({ result: 'updated' }); // this._writeToCluster('update', ...) + await savedObjectsRepository.delete(MULTI_NAMESPACE_TYPE, id); + expectClusterCalls('get', 'update'); + }); - expect(migrator.runMigrations).toHaveReturnedTimes(1); - }); + it(`includes the version of the existing document when type is multi-namespace`, async () => { + await deleteSuccess(MULTI_NAMESPACE_TYPE, id); + const versionProperties = { + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + expectClusterCallArgs(versionProperties, 2); + }); - it('mockReturnValue current ES document _seq_no and _primary_term encoded as version', async () => { - const response = await savedObjectsRepository.update( - 'index-pattern', - 'logstash-*', - attributes, - { - namespace: 'foo-namespace', - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - } - ); - expect(response).toEqual({ - id, - type, - ...mockTimestampFields, - version: mockVersion, - attributes, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], + it(`defaults to a refresh setting of wait_for`, async () => { + await deleteSuccess(type, id); + expectClusterCallArgs({ refresh: 'wait_for' }); }); - }); - it('accepts version', async () => { - await savedObjectsRepository.update( - type, - id, - { title: 'Testing' }, - { - version: encodeHitVersion({ - _seq_no: 100, - _primary_term: 200, - }), - } - ); + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await deleteSuccess(type, id, { refresh }); + expectClusterCallArgs({ refresh }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - if_seq_no: 100, - if_primary_term: 200, - }) - ); + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + await deleteSuccess(type, id, { namespace }); + expectClusterCallArgs({ id: `${namespace}:${type}:${id}` }); + }); + + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + await deleteSuccess(type, id); + expectClusterCallArgs({ id: `${type}:${id}` }); + }); + + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + await deleteSuccess(NAMESPACE_AGNOSTIC_TYPE, id, { namespace }); + expectClusterCallArgs({ id: `${NAMESPACE_AGNOSTIC_TYPE}:${id}` }); + + callAdminCluster.mockReset(); + await deleteSuccess(MULTI_NAMESPACE_TYPE, id, { namespace }); + expectClusterCallArgs({ id: `${MULTI_NAMESPACE_TYPE}:${id}` }); + }); }); - it('does not pass references if omitted', async () => { - await savedObjectsRepository.update(type, id, { title: 'Testing' }); + describe('errors', () => { + const expectNotFoundError = async (type, id, options) => { + await expect(savedObjectsRepository.delete(type, id, options)).rejects.toThrowError( + createGenericNotFoundError(type, id) + ); + }; + + it(`throws when type is invalid`, async () => { + await expectNotFoundError('unknownType', id); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); + + it(`throws when type is hidden`, async () => { + await expectNotFoundError(HIDDEN_TYPE, id); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); + + it(`throws when ES is unable to find the document during get`, async () => { + callAdminCluster.mockResolvedValue({ found: false }); // this._callCluster('get', ...) + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id); + expectClusterCalls('get'); + }); + + it(`throws when ES is unable to find the index during get`, async () => { + callAdminCluster.mockResolvedValue({ status: 404 }); // this._callCluster('get', ...) + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id); + expectClusterCalls('get'); + }); + + it(`throws when the type is multi-namespace and the document exists, but not in this namespace`, async () => { + const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace }); + callAdminCluster.mockResolvedValue(response); // this._callCluster('get', ...) + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id, { namespace: 'bar-namespace' }); + expectClusterCalls('get'); + }); + + it(`throws when ES is unable to find the document during update`, async () => { + const mockResponse = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id }); + mockResponse._source.namespaces = ['default', 'some-other-nameespace']; + callAdminCluster + .mockResolvedValueOnce(mockResponse) // this._callCluster('get', ...) + .mockResolvedValue({ status: 404 }); // this._writeToCluster('update', ...) + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id); + expectClusterCalls('get', 'update'); + }); + + it(`throws when ES is unable to find the document during delete`, async () => { + callAdminCluster.mockResolvedValue({ result: 'not_found' }); // this._writeToCluster('delete', ...) + await expectNotFoundError(type, id); + expectClusterCalls('delete'); + }); + + it(`throws when ES is unable to find the index during delete`, async () => { + callAdminCluster.mockResolvedValue({ error: { type: 'index_not_found_exception' } }); // this._writeToCluster('delete', ...) + await expectNotFoundError(type, id); + expectClusterCalls('delete'); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).not.toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - body: { - doc: expect.objectContaining({ - references: [], - }), - }, - }) - ); + it(`throws when ES returns an unexpected response`, async () => { + callAdminCluster.mockResolvedValue({ result: 'something unexpected' }); // this._writeToCluster('delete', ...) + await expect(savedObjectsRepository.delete(type, id)).rejects.toThrowError( + 'Unexpected Elasticsearch DELETE response' + ); + expectClusterCalls('delete'); + }); }); - it('passes references if they are provided', async () => { - await savedObjectsRepository.update(type, id, { title: 'Testing' }, { references: ['foo'] }); + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + let callAdminClusterCount = 0; + migrator.runMigrations = jest.fn(async () => + // runMigrations should resolve before callAdminCluster is initiated + expect(callAdminCluster).toHaveBeenCalledTimes(callAdminClusterCount++) + ); + await expect(deleteSuccess(type, id)).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); + }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - body: { - doc: expect.objectContaining({ - references: ['foo'], - }), - }, - }) - ); + describe('returns', () => { + it(`returns an empty object on success`, async () => { + const result = await deleteSuccess(type, id); + expect(result).toEqual({}); + }); }); + }); - it('passes empty references array if empty references array is provided', async () => { - await savedObjectsRepository.update(type, id, { title: 'Testing' }, { references: [] }); + describe('#deleteByNamespace', () => { + const namespace = 'foo-namespace'; + const mockUpdateResults = { + took: 15, + timed_out: false, + total: 3, + updated: 2, + deleted: 1, + batches: 1, + version_conflicts: 0, + noops: 0, + retries: { bulk: 0, search: 0 }, + throttled_millis: 0, + requests_per_second: -1.0, + throttled_until_millis: 0, + failures: [], + }; + const deleteByNamespaceSuccess = async (namespace, options) => { + callAdminCluster.mockResolvedValue(mockUpdateResults); + const result = await savedObjectsRepository.deleteByNamespace(namespace, options); + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledTimes(1); expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith( - expect.any(String), - expect.objectContaining({ - body: { - doc: expect.objectContaining({ - references: [], - }), - }, - }) - ); - }); + return result; + }; - it(`prepends namespace to the id but doesn't add namespace to body when providing namespace for namespaced type`, async () => { - await savedObjectsRepository.update( - 'index-pattern', - 'logstash-*', - { - title: 'Testing', - }, - { - namespace: 'foo-namespace', - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - } - ); + describe('cluster calls', () => { + it(`should use the ES updateByQuery action`, async () => { + await deleteByNamespaceSuccess(namespace); + expectClusterCalls('updateByQuery'); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('update', { - id: 'foo-namespace:index-pattern:logstash-*', - body: { - doc: { - updated_at: mockTimestamp, - 'index-pattern': { title: 'Testing' }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - }, - }, - ignore: [404], - refresh: 'wait_for', - index: '.kibana-test', + it(`defaults to a refresh setting of wait_for`, async () => { + await deleteByNamespaceSuccess(namespace); + expectClusterCallArgs({ refresh: 'wait_for' }); }); - }); - it(`doesn't prepend namespace to the id or add namespace property when providing no namespace for namespaced type`, async () => { - await savedObjectsRepository.update( - 'index-pattern', - 'logstash-*', - { - title: 'Testing', - }, - { - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - } - ); + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await deleteByNamespaceSuccess(namespace, { refresh }); + expectClusterCallArgs({ refresh }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('update', { - id: 'index-pattern:logstash-*', - body: { - doc: { - updated_at: mockTimestamp, - 'index-pattern': { title: 'Testing' }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - }, - }, - ignore: [404], - refresh: 'wait_for', - index: '.kibana-test', + it(`should use all indices for types that are not namespace-agnostic`, async () => { + await deleteByNamespaceSuccess(namespace); + expectClusterCallArgs({ index: ['.kibana-test', 'custom'] }, 1); }); }); - it(`doesn't prepend namespace to the id or add namespace property when providing namespace for namespace agnostic type`, async () => { - await savedObjectsRepository.update( - 'globaltype', - 'foo', - { - name: 'bar', - }, - { - namespace: 'foo-namespace', - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - } - ); - - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster).toHaveBeenCalledWith('update', { - id: 'globaltype:foo', - body: { - doc: { - updated_at: mockTimestamp, - globaltype: { name: 'bar' }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - }, - }, - ignore: [404], - refresh: 'wait_for', - index: '.kibana-test', + describe('errors', () => { + it(`throws when namespace is not a string`, async () => { + const test = async namespace => { + await expect(savedObjectsRepository.deleteByNamespace(namespace)).rejects.toThrowError( + `namespace is required, and must be a string` + ); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; + await test(undefined); + await test(['namespace']); + await test(123); + await test(true); }); }); - it('defaults to a refresh setting of `wait_for`', async () => { - await savedObjectsRepository.update('globaltype', 'foo', { - name: 'bar', + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect(deleteByNamespaceSuccess(namespace)).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: 'wait_for', + describe('returns', () => { + it(`returns the query results on success`, async () => { + const result = await deleteByNamespaceSuccess(namespace); + expect(result).toEqual(mockUpdateResults); }); }); - it('accepts a custom refresh setting', async () => { - await savedObjectsRepository.update( - 'globaltype', - 'foo', - { - name: 'bar', - }, - { - refresh: true, - namespace: 'foo-namespace', - } - ); - - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: true, + describe('search dsl', () => { + it(`constructs a query using all multi-namespace types, and another using all single-namespace types`, async () => { + await deleteByNamespaceSuccess(namespace); + const allTypes = registry.getAllTypes().map(type => type.name); + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, { + namespace, + type: allTypes.filter(type => !registry.isNamespaceAgnostic(type)), + }); }); }); }); - describe('#bulkUpdate', () => { - const { generateSavedObject, reset } = (() => { - let count = 0; + describe('#find', () => { + const generateSearchResults = namespace => { return { - generateSavedObject(overrides) { - count++; - return _.merge( + hits: { + total: 4, + hits: [ { - type: 'index-pattern', - id: `logstash-${count}`, - attributes: { title: `Testing ${count}` }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', + _index: '.kibana', + _id: `${namespace ? `${namespace}:` : ''}index-pattern:logstash-*`, + _score: 1, + ...mockVersionProps, + _source: { + namespace, + type: 'index-pattern', + ...mockTimestampFields, + 'index-pattern': { + title: 'logstash-*', + timeFieldName: '@timestamp', + notExpandable: true, }, - ], + }, }, - overrides - ); - }, - reset() { - count = 0; + { + _index: '.kibana', + _id: `${namespace ? `${namespace}:` : ''}config:6.0.0-alpha1`, + _score: 1, + ...mockVersionProps, + _source: { + namespace, + type: 'config', + ...mockTimestampFields, + config: { + buildNum: 8467, + defaultIndex: 'logstash-*', + }, + }, + }, + { + _index: '.kibana', + _id: `${namespace ? `${namespace}:` : ''}index-pattern:stocks-*`, + _score: 1, + ...mockVersionProps, + _source: { + namespace, + type: 'index-pattern', + ...mockTimestampFields, + 'index-pattern': { + title: 'stocks-*', + timeFieldName: '@timestamp', + notExpandable: true, + }, + }, + }, + { + _index: '.kibana', + _id: `${NAMESPACE_AGNOSTIC_TYPE}:something`, + _score: 1, + ...mockVersionProps, + _source: { + type: NAMESPACE_AGNOSTIC_TYPE, + ...mockTimestampFields, + [NAMESPACE_AGNOSTIC_TYPE]: { + name: 'bar', + }, + }, + }, + ], }, }; - })(); + }; - beforeEach(() => { - reset(); - }); + const type = 'index-pattern'; + const namespace = 'foo-namespace'; - const mockValidResponse = objects => - callAdminCluster.mockReturnValue({ - items: objects.map(items => ({ - update: { - _id: `${items.type}:${items.id}`, - ...mockVersionProps, - result: 'updated', - }, - })), + const findSuccess = async (options, namespace) => { + callAdminCluster.mockResolvedValue(generateSearchResults(namespace)); + const result = await savedObjectsRepository.find(options); + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledTimes(1); + expect(callAdminCluster).toHaveBeenCalledTimes(1); + return result; + }; + + describe('cluster calls', () => { + it(`should use the ES search action`, async () => { + await findSuccess({ type }); + expectClusterCalls('search'); + }); + + it(`merges output of getSearchDsl into es request body`, async () => { + const query = { query: 1, aggregations: 2 }; + getSearchDslNS.getSearchDsl.mockReturnValue(query); + await findSuccess({ type }); + expectClusterCallArgs({ body: expect.objectContaining({ ...query }) }); }); - it('waits until migrations are complete before proceeding', async () => { - const objects = [generateSavedObject(), generateSavedObject()]; + it(`accepts per_page/page`, async () => { + await findSuccess({ type, perPage: 10, page: 6 }); + expectClusterCallArgs({ + size: 10, + from: 50, + }); + }); - migrator.runMigrations = jest.fn(async () => expect(callAdminCluster).not.toHaveBeenCalled()); + it(`can filter by fields`, async () => { + await findSuccess({ type, fields: ['title'] }); + expectClusterCallArgs({ + _source: [ + `${type}.title`, + 'namespace', + 'namespaces', + 'type', + 'references', + 'migrationVersion', + 'updated_at', + 'title', + ], + }); + }); - mockValidResponse(objects); + it(`should set rest_total_hits_as_int to true on a request`, async () => { + await findSuccess({ type }); + expectClusterCallArgs({ rest_total_hits_as_int: true }); + }); - await expect( - savedObjectsRepository.bulkUpdate([generateSavedObject()]) - ).resolves.toBeDefined(); + it(`should not make a cluster call when attempting to find only invalid or hidden types`, async () => { + const test = async types => { + await savedObjectsRepository.find({ type: types }); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; - expect(migrator.runMigrations).toHaveReturnedTimes(1); + await test('unknownType'); + await test(HIDDEN_TYPE); + await test(['unknownType', HIDDEN_TYPE]); + }); }); - it('returns current ES document, _seq_no and _primary_term encoded as version', async () => { - const objects = [generateSavedObject(), generateSavedObject()]; - - mockValidResponse(objects); + describe('errors', () => { + it(`throws when type is not defined`, async () => { + await expect(savedObjectsRepository.find({})).rejects.toThrowError( + 'options.type must be a string or an array of strings' + ); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); - const response = await savedObjectsRepository.bulkUpdate(objects); + it(`throws when searchFields is defined but not an array`, async () => { + await expect( + savedObjectsRepository.find({ type, searchFields: 'string' }) + ).rejects.toThrowError('options.searchFields must be an array'); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); - expect(response.saved_objects[0]).toMatchObject({ - ..._.pick(objects[0], 'id', 'type', 'attributes'), - version: mockVersion, - references: objects[0].references, + it(`throws when fields is defined but not an array`, async () => { + await expect(savedObjectsRepository.find({ type, fields: 'string' })).rejects.toThrowError( + 'options.fields must be an array' + ); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - expect(response.saved_objects[1]).toMatchObject({ - ..._.pick(objects[1], 'id', 'type', 'attributes'), - version: mockVersion, - references: objects[1].references, + + it(`throws when KQL filter syntax is invalid`, async () => { + const findOpts = { + namespace, + search: 'foo*', + searchFields: ['foo'], + type: ['dashboard'], + sortField: 'name', + sortOrder: 'desc', + defaultSearchOperator: 'AND', + hasReference: { + type: 'foo', + id: '1', + }, + indexPattern: undefined, + filter: 'dashboard.attributes.otherField:<', + }; + + await expect(savedObjectsRepository.find(findOpts)).rejects.toMatchInlineSnapshot(` + [Error: KQLSyntaxError: Expected "(", "{", value, whitespace but "<" found. + dashboard.attributes.otherField:< + --------------------------------^: Bad Request] + `); + expect(getSearchDslNS.getSearchDsl).not.toHaveBeenCalled(); + expect(callAdminCluster).not.toHaveBeenCalled(); }); }); - it('handles a mix of succesfull updates and errors', async () => { - const objects = [ - generateSavedObject(), - { - type: 'invalid-type', - id: 'invalid', - attributes: { title: 'invalid' }, - }, - generateSavedObject(), - generateSavedObject({ - id: 'version_clash', - }), - ]; - - callAdminCluster.mockReturnValue({ - items: objects - // remove invalid from mocks - .filter(item => item.id !== 'invalid') - .map(items => { - switch (items.id) { - case 'version_clash': - return { - update: { - _id: `${items.type}:${items.id}`, - error: { - type: 'version_conflict_engine_exception', - }, - }, - }; - default: - return { - update: { - _id: `${items.type}:${items.id}`, - ...mockVersionProps, - result: 'updated', - }, - }; - } - }), - }); - - const { - saved_objects: [firstUpdatedObject, invalidType, secondUpdatedObject, versionClashObject], - } = await savedObjectsRepository.bulkUpdate(objects); - - expect(firstUpdatedObject).toMatchObject({ - ..._.pick(objects[0], 'id', 'type', 'attributes', 'references'), - version: mockVersion, + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect(findSuccess({ type })).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); }); + }); - expect(invalidType).toMatchObject({ - ..._.pick(objects[1], 'id', 'type'), - error: SavedObjectsErrorHelpers.createGenericNotFoundError('invalid-type', 'invalid').output - .payload, - }); + describe('returns', () => { + it(`formats the ES response when there is no namespace`, async () => { + const noNamespaceSearchResults = generateSearchResults(); + callAdminCluster.mockReturnValue(noNamespaceSearchResults); + const count = noNamespaceSearchResults.hits.hits.length; - expect(secondUpdatedObject).toMatchObject({ - ..._.pick(objects[2], 'id', 'type', 'attributes', 'references'), - version: mockVersion, - }); + const response = await savedObjectsRepository.find({ type }); + + expect(response.total).toBe(count); + expect(response.saved_objects).toHaveLength(count); - expect(versionClashObject).toMatchObject({ - ..._.pick(objects[3], 'id', 'type'), - error: { statusCode: 409, message: 'version conflict, document already exists' }, + noNamespaceSearchResults.hits.hits.forEach((doc, i) => { + expect(response.saved_objects[i]).toEqual({ + id: doc._id.replace(/(index-pattern|config|globalType)\:/, ''), + type: doc._source.type, + ...mockTimestampFields, + version: mockVersion, + attributes: doc._source[doc._source.type], + references: [], + }); + }); }); - }); - it('doesnt call Elasticsearch if there are no valid objects to update', async () => { - const objects = [ - { - type: 'invalid-type', - id: 'invalid', - attributes: { title: 'invalid' }, - }, - { - type: 'invalid-type', - id: 'invalid 2', - attributes: { title: 'invalid' }, - }, - ]; + it(`formats the ES response when there is a namespace`, async () => { + const namespacedSearchResults = generateSearchResults(namespace); + callAdminCluster.mockReturnValue(namespacedSearchResults); + const count = namespacedSearchResults.hits.hits.length; - const { - saved_objects: [invalidType, invalidType2], - } = await savedObjectsRepository.bulkUpdate(objects); + const response = await savedObjectsRepository.find({ type, namespace }); - expect(callAdminCluster).not.toHaveBeenCalled(); + expect(response.total).toBe(count); + expect(response.saved_objects).toHaveLength(count); - expect(invalidType).toMatchObject({ - ..._.pick(objects[0], 'id', 'type'), - error: SavedObjectsErrorHelpers.createGenericNotFoundError('invalid-type', 'invalid').output - .payload, + namespacedSearchResults.hits.hits.forEach((doc, i) => { + expect(response.saved_objects[i]).toEqual({ + id: doc._id.replace(/(foo-namespace\:)?(index-pattern|config|globalType)\:/, ''), + type: doc._source.type, + ...mockTimestampFields, + version: mockVersion, + attributes: doc._source[doc._source.type], + references: [], + }); + }); }); - expect(invalidType2).toMatchObject({ - ..._.pick(objects[1], 'id', 'type'), - error: SavedObjectsErrorHelpers.createGenericNotFoundError('invalid-type', 'invalid 2') - .output.payload, + it(`should return empty results when attempting to find only invalid or hidden types`, async () => { + const test = async types => { + const result = await savedObjectsRepository.find({ type: types }); + expect(result).toEqual(expect.objectContaining({ saved_objects: [] })); + }; + + await test('unknownType'); + await test(HIDDEN_TYPE); + await test(['unknownType', HIDDEN_TYPE]); }); }); - it('accepts version', async () => { - const objects = [ - generateSavedObject({ - version: encodeHitVersion({ - _seq_no: 100, - _primary_term: 200, - }), - }), - generateSavedObject({ - version: encodeHitVersion({ - _seq_no: 300, - _primary_term: 400, - }), - }), - ]; + describe('search dsl', () => { + it(`passes mappings, registry, search, defaultSearchOperator, searchFields, type, sortField, sortOrder and hasReference to getSearchDsl`, async () => { + const relevantOpts = { + namespace, + search: 'foo*', + searchFields: ['foo'], + type: [type], + sortField: 'name', + sortOrder: 'desc', + defaultSearchOperator: 'AND', + hasReference: { + type: 'foo', + id: '1', + }, + kueryNode: undefined, + }; - mockValidResponse(objects); + await findSuccess(relevantOpts, namespace); + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith(mappings, registry, relevantOpts); + }); + + it(`accepts KQL filter and passes kueryNode to getSearchDsl`, async () => { + const findOpts = { + namespace, + search: 'foo*', + searchFields: ['foo'], + type: ['dashboard'], + sortField: 'name', + sortOrder: 'desc', + defaultSearchOperator: 'AND', + hasReference: { + type: 'foo', + id: '1', + }, + indexPattern: undefined, + filter: 'dashboard.attributes.otherField: *', + }; + + await findSuccess(findOpts, namespace); + const { kueryNode } = getSearchDslNS.getSearchDsl.mock.calls[0][2]; + expect(kueryNode).toMatchInlineSnapshot(` + Object { + "arguments": Array [ + Object { + "type": "literal", + "value": "dashboard.otherField", + }, + Object { + "type": "wildcard", + "value": "@kuery-wildcard@", + }, + Object { + "type": "literal", + "value": false, + }, + ], + "function": "is", + "type": "function", + } + `); + }); - await savedObjectsRepository.bulkUpdate(objects); + it(`supports multiple types`, async () => { + const types = ['config', 'index-pattern']; + await findSuccess({ type: types }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith( + mappings, + registry, + expect.objectContaining({ + type: types, + }) + ); + }); - const [ - , - { - body: [{ update: firstUpdate }, , { update: secondUpdate }], - }, - ] = callAdminCluster.mock.calls[0]; + it(`filters out invalid types`, async () => { + const types = ['config', 'unknownType', 'index-pattern']; + await findSuccess({ type: types }); - expect(firstUpdate).toMatchObject({ - if_seq_no: 100, - if_primary_term: 200, + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith( + mappings, + registry, + expect.objectContaining({ + type: ['config', 'index-pattern'], + }) + ); }); - expect(secondUpdate).toMatchObject({ - if_seq_no: 300, - if_primary_term: 400, + it(`filters out hidden types`, async () => { + const types = ['config', HIDDEN_TYPE, 'index-pattern']; + await findSuccess({ type: types }); + + expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledWith( + mappings, + registry, + expect.objectContaining({ + type: ['config', 'index-pattern'], + }) + ); }); }); + }); - it('does not pass references if omitted', async () => { - const objects = [ - { - type: 'index-pattern', - id: `logstash-no-ref`, - attributes: { title: `Testing no-ref` }, - }, - ]; + describe('#get', () => { + const type = 'index-pattern'; + const id = 'logstash-*'; + const namespace = 'foo-namespace'; + + const getSuccess = async (type, id, options) => { + const response = getMockGetResponse({ type, id, namespace: options?.namespace }); + callAdminCluster.mockResolvedValue(response); + const result = await savedObjectsRepository.get(type, id, options); + expect(callAdminCluster).toHaveBeenCalledTimes(1); + return result; + }; - mockValidResponse(objects); + describe('cluster calls', () => { + it(`should use the ES get action`, async () => { + await getSuccess(type, id); + expectClusterCalls('get'); + }); - await savedObjectsRepository.bulkUpdate(objects); + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + await getSuccess(type, id, { namespace }); + expectClusterCallArgs({ id: `${namespace}:${type}:${id}` }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + await getSuccess(type, id); + expectClusterCallArgs({ id: `${type}:${id}` }); + }); - const [ - , - { - body: [, { doc: firstDoc }], - }, - ] = callAdminCluster.mock.calls[0]; + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + await getSuccess(NAMESPACE_AGNOSTIC_TYPE, id, { namespace }); + expectClusterCallArgs({ id: `${NAMESPACE_AGNOSTIC_TYPE}:${id}` }); - expect(firstDoc).not.toMatchObject({ - references: [], + callAdminCluster.mockReset(); + await getSuccess(MULTI_NAMESPACE_TYPE, id, { namespace }); + expectClusterCallArgs({ id: `${MULTI_NAMESPACE_TYPE}:${id}` }); }); }); - it('passes references if they are provided', async () => { - const objects = [ - generateSavedObject({ - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], - }), - ]; + describe('errors', () => { + const expectNotFoundError = async (type, id, options) => { + await expect(savedObjectsRepository.get(type, id, options)).rejects.toThrowError( + createGenericNotFoundError(type, id) + ); + }; - mockValidResponse(objects); + it(`throws when type is invalid`, async () => { + await expectNotFoundError('unknownType', id); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); - await savedObjectsRepository.bulkUpdate(objects); + it(`throws when type is hidden`, async () => { + await expectNotFoundError(HIDDEN_TYPE, id); + expect(callAdminCluster).not.toHaveBeenCalled(); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`throws when ES is unable to find the document during get`, async () => { + callAdminCluster.mockResolvedValue({ found: false }); + await expectNotFoundError(type, id); + expectClusterCalls('get'); + }); - const [ - , - { - body: [, { doc }], - }, - ] = callAdminCluster.mock.calls[0]; + it(`throws when ES is unable to find the index during get`, async () => { + callAdminCluster.mockResolvedValue({ status: 404 }); + await expectNotFoundError(type, id); + expectClusterCalls('get'); + }); - expect(doc).toMatchObject({ - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], + it(`throws when type is multi-namespace and the document exists, but not in this namespace`, async () => { + const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace }); + callAdminCluster.mockResolvedValue(response); + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id, { namespace: 'bar-namespace' }); + expectClusterCalls('get'); }); }); - it('passes empty references array if empty references array is provided', async () => { - const objects = [ - { - type: 'index-pattern', - id: `logstash-no-ref`, - attributes: { title: `Testing no-ref` }, - references: [], - }, - ]; - - mockValidResponse(objects); - - await savedObjectsRepository.bulkUpdate(objects); + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect(getSuccess(type, id)).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); + }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + describe('returns', () => { + it(`formats the ES response`, async () => { + const result = await getSuccess(type, id); + expect(result).toEqual({ + id, + type, + updated_at: mockTimestamp, + version: mockVersion, + attributes: { + title: 'Testing', + }, + references: [], + }); + }); - const [ - , - { - body: [, { doc }], - }, - ] = callAdminCluster.mock.calls[0]; + it(`includes namespaces if type is multi-namespace`, async () => { + const result = await getSuccess(MULTI_NAMESPACE_TYPE, id); + expect(result).toMatchObject({ + namespaces: expect.any(Array), + }); + }); - expect(doc).toMatchObject({ - references: [], + it(`doesn't include namespaces if type is not multi-namespace`, async () => { + const result = await getSuccess(type, id); + expect(result).not.toMatchObject({ + namespaces: expect.anything(), + }); }); }); + }); - it('defaults to a refresh setting of `wait_for`', async () => { - const objects = [ - { - type: 'index-pattern', - id: `logstash-no-ref`, - attributes: { title: `Testing no-ref` }, - references: [], + describe('#incrementCounter', () => { + const type = 'config'; + const id = 'one'; + const field = 'buildNum'; + const namespace = 'foo-namespace'; + + const incrementCounterSuccess = async (type, id, field, options) => { + const isMultiNamespace = registry.isMultiNamespace(type); + if (isMultiNamespace) { + const response = getMockGetResponse({ type, id, namespace: options?.namespace }); + callAdminCluster.mockResolvedValueOnce(response); // this._callCluster('get', ...) + } + callAdminCluster.mockImplementation((method, params) => ({ + _id: params.id, + ...mockVersionProps, + _index: '.kibana', + get: { + found: true, + _source: { + type, + ...mockTimestampFields, + [type]: { + [field]: 8468, + defaultIndex: 'logstash-*', + }, + }, }, - ]; - - mockValidResponse(objects); + })); + const result = await savedObjectsRepository.incrementCounter(type, id, field, options); + expect(callAdminCluster).toHaveBeenCalledTimes(isMultiNamespace ? 2 : 1); + return result; + }; - await savedObjectsRepository.bulkUpdate(objects); + describe('cluster calls', () => { + it(`should use the ES update action if type is not multi-namespace`, async () => { + await incrementCounterSuccess(type, id, field, { namespace }); + expectClusterCalls('update'); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`should use the ES get action then update action if type is multi-namespace, ID is defined, and overwrite=true`, async () => { + await incrementCounterSuccess(MULTI_NAMESPACE_TYPE, id, field, { namespace }); + expectClusterCalls('get', 'update'); + }); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ refresh: 'wait_for' }); - }); + it(`defaults to a refresh setting of wait_for`, async () => { + await incrementCounterSuccess(type, id, field, { namespace }); + expectClusterCallArgs({ refresh: 'wait_for' }); + }); - it('accepts a custom refresh setting', async () => { - const objects = [ - { - type: 'index-pattern', - id: `logstash-no-ref`, - attributes: { title: `Testing no-ref` }, - references: [], - }, - ]; + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await incrementCounterSuccess(type, id, field, { namespace, refresh }); + expectClusterCallArgs({ refresh }); + }); - mockValidResponse(objects); + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + await incrementCounterSuccess(type, id, field, { namespace }); + expectClusterCallArgs({ id: `${namespace}:${type}:${id}` }); + }); - await savedObjectsRepository.bulkUpdate(objects, { refresh: true }); + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + await incrementCounterSuccess(type, id, field); + expectClusterCallArgs({ id: `${type}:${id}` }); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + await incrementCounterSuccess(NAMESPACE_AGNOSTIC_TYPE, id, field, { namespace }); + expectClusterCallArgs({ id: `${NAMESPACE_AGNOSTIC_TYPE}:${id}` }); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ refresh: true }); + callAdminCluster.mockReset(); + await incrementCounterSuccess(MULTI_NAMESPACE_TYPE, id, field, { namespace }); + expectClusterCallArgs({ id: `${MULTI_NAMESPACE_TYPE}:${id}` }); + }); }); - it(`prepends namespace to the id but doesn't add namespace to body when providing namespace for namespaced type`, async () => { - const objects = [generateSavedObject(), generateSavedObject()]; + describe('errors', () => { + const expectUnsupportedTypeError = async (type, id, field) => { + await expect(savedObjectsRepository.incrementCounter(type, id, field)).rejects.toThrowError( + createUnsupportedTypeError(type) + ); + }; - mockValidResponse(objects); + it(`throws when type is not a string`, async () => { + const test = async type => { + await expect( + savedObjectsRepository.incrementCounter(type, id, field) + ).rejects.toThrowError(`"type" argument must be a string`); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; - await savedObjectsRepository.bulkUpdate(objects, { - namespace: 'foo-namespace', + await test(null); + await test(42); + await test(false); + await test({}); }); - const [ - , - { - body: [ - { update: firstUpdate }, - { doc: firstUpdateDoc }, - { update: secondUpdate }, - { doc: secondUpdateDoc }, - ], - }, - ] = callAdminCluster.mock.calls[0]; + it(`throws when counterFieldName is not a string`, async () => { + const test = async field => { + await expect( + savedObjectsRepository.incrementCounter(type, id, field) + ).rejects.toThrowError(`"counterFieldName" argument must be a string`); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; - expect(firstUpdate).toMatchObject({ - _id: 'foo-namespace:index-pattern:logstash-1', - _index: '.kibana-test', + await test(null); + await test(42); + await test(false); + await test({}); }); - expect(firstUpdateDoc).toMatchObject({ - updated_at: mockTimestamp, - 'index-pattern': { title: 'Testing 1' }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], + it(`throws when type is invalid`, async () => { + await expectUnsupportedTypeError('unknownType', id, field); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - expect(secondUpdate).toMatchObject({ - _id: 'foo-namespace:index-pattern:logstash-2', - _index: '.kibana-test', + it(`throws when type is hidden`, async () => { + await expectUnsupportedTypeError(HIDDEN_TYPE, id, field); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - expect(secondUpdateDoc).toMatchObject({ - updated_at: mockTimestamp, - 'index-pattern': { title: 'Testing 2' }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], + it(`throws when there is a conflict with an existing multi-namespace saved object (get)`, async () => { + const response = getMockGetResponse({ + type: MULTI_NAMESPACE_TYPE, + id, + namespace: 'bar-namespace', + }); + callAdminCluster.mockResolvedValue(response); // this._callCluster('get', ...) + await expect( + savedObjectsRepository.incrementCounter(MULTI_NAMESPACE_TYPE, id, field, { namespace }) + ).rejects.toThrowError(createConflictError(MULTI_NAMESPACE_TYPE, id)); + expectClusterCalls('get'); }); }); - it(`doesn't prepend namespace to the id or add namespace property when providing no namespace for namespaced type`, async () => { - const objects = [generateSavedObject(), generateSavedObject()]; - - mockValidResponse(objects); + describe('migration', () => { + beforeEach(() => { + migrator.migrateDocument.mockImplementation(mockMigrateDocument); + }); - await savedObjectsRepository.bulkUpdate(objects); + it(`waits until migrations are complete before proceeding`, async () => { + migrator.runMigrations = jest.fn(async () => + expect(callAdminCluster).not.toHaveBeenCalled() + ); + await expect( + incrementCounterSuccess(type, id, field, { namespace }) + ).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveBeenCalledTimes(1); + }); - const [ - , - { - body: [ - { update: firstUpdate }, - { doc: firstUpdateDoc }, - { update: secondUpdate }, - { doc: secondUpdateDoc }, - ], - }, - ] = callAdminCluster.mock.calls[0]; + it(`migrates a document and serializes the migrated doc`, async () => { + const migrationVersion = mockMigrationVersion; + await incrementCounterSuccess(type, id, field, { migrationVersion }); + const attributes = { buildNum: 1 }; // this is added by the incrementCounter function + const doc = { type, id, attributes, migrationVersion, ...mockTimestampFields }; + expectMigrationArgs(doc); - expect(firstUpdate).toMatchObject({ - _id: 'index-pattern:logstash-1', - _index: '.kibana-test', + const migratedDoc = migrator.migrateDocument(doc); + expect(serializer.savedObjectToRaw).toHaveBeenLastCalledWith(migratedDoc); }); + }); - expect(firstUpdateDoc).toMatchObject({ - updated_at: mockTimestamp, - 'index-pattern': { title: 'Testing 1' }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', + describe('returns', () => { + it(`formats the ES response`, async () => { + callAdminCluster.mockImplementation((method, params) => ({ + _id: params.id, + ...mockVersionProps, + _index: '.kibana', + get: { + found: true, + _source: { + type: 'config', + ...mockTimestampFields, + config: { + buildNum: 8468, + defaultIndex: 'logstash-*', + }, + }, }, - ], - }); - - expect(secondUpdate).toMatchObject({ - _id: 'index-pattern:logstash-2', - _index: '.kibana-test', - }); + })); - expect(secondUpdateDoc).toMatchObject({ - updated_at: mockTimestamp, - 'index-pattern': { title: 'Testing 2' }, - references: [ + const response = await savedObjectsRepository.incrementCounter( + 'config', + '6.0.0-alpha1', + 'buildNum', { - name: 'ref_0', - type: 'test', - id: '1', + namespace: 'foo-namespace', + } + ); + + expect(response).toEqual({ + type: 'config', + id: '6.0.0-alpha1', + ...mockTimestampFields, + version: mockVersion, + attributes: { + buildNum: 8468, + defaultIndex: 'logstash-*', }, - ], + }); }); }); + }); - it(`doesn't prepend namespace to the id or add namespace property when providing namespace for namespace agnostic type`, async () => { - const objects = [ - generateSavedObject({ - type: 'globaltype', - id: 'foo', - namespace: 'foo-namespace', - }), - ]; + describe('#deleteFromNamespaces', () => { + const id = 'some-id'; + const type = MULTI_NAMESPACE_TYPE; + const namespace1 = 'default'; + const namespace2 = 'foo-namespace'; + const namespace3 = 'bar-namespace'; + + const mockGetResponse = (type, id, namespaces) => { + // mock a document that exists in two namespaces + const mockResponse = getMockGetResponse({ type, id }); + mockResponse._source.namespaces = namespaces; + callAdminCluster.mockResolvedValueOnce(mockResponse); // this._callCluster('get', ...) + }; + + const deleteFromNamespacesSuccess = async ( + type, + id, + namespaces, + currentNamespaces, + options + ) => { + mockGetResponse(type, id, currentNamespaces); // this._callCluster('get', ...) + const isDelete = currentNamespaces.every(namespace => namespaces.includes(namespace)); + callAdminCluster.mockResolvedValue({ + _id: `${type}:${id}`, + ...mockVersionProps, + result: isDelete ? 'deleted' : 'updated', + }); // this._writeToCluster('delete', ...) *or* this._writeToCluster('update', ...) + const result = await savedObjectsRepository.deleteFromNamespaces( + type, + id, + namespaces, + options + ); + expect(callAdminCluster).toHaveBeenCalledTimes(2); + return result; + }; - mockValidResponse(objects); + describe('cluster calls', () => { + describe('delete action', () => { + const deleteFromNamespacesSuccessDelete = async (expectFn, options, _type = type) => { + const test = async namespaces => { + await deleteFromNamespacesSuccess(_type, id, namespaces, namespaces, options); + expectFn(); + callAdminCluster.mockReset(); + }; + await test([namespace1]); + await test([namespace1, namespace2]); + }; + + it(`should use ES get action then delete action if the object has no namespaces remaining`, async () => { + const expectFn = () => expectClusterCalls('get', 'delete'); + await deleteFromNamespacesSuccessDelete(expectFn); + }); - await savedObjectsRepository.bulkUpdate(objects); + it(`formats the ES requests`, async () => { + const expectFn = () => { + expectClusterCallArgs({ id: `${type}:${id}` }, 1); + const versionProperties = { + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + expectClusterCallArgs({ id: `${type}:${id}`, ...versionProperties }, 2); + }; + await deleteFromNamespacesSuccessDelete(expectFn); + }); - const [ - , - { - body: [{ update }, { doc }], - }, - ] = callAdminCluster.mock.calls[0]; + it(`defaults to a refresh setting of wait_for`, async () => { + await deleteFromNamespacesSuccessDelete(() => + expectClusterCallArgs({ refresh: 'wait_for' }, 2) + ); + }); - expect(update).toMatchObject({ - _id: 'globaltype:foo', - _index: '.kibana-test', - }); + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + const expectFn = () => expectClusterCallArgs({ refresh }, 2); + await deleteFromNamespacesSuccessDelete(expectFn, { refresh }); + }); - expect(doc).toMatchObject({ - updated_at: mockTimestamp, - globaltype: { title: 'Testing 1' }, - references: [ - { - name: 'ref_0', - type: 'test', - id: '1', - }, - ], + it(`should use default index`, async () => { + const expectFn = () => expectClusterCallArgs({ index: '.kibana-test' }, 2); + await deleteFromNamespacesSuccessDelete(expectFn); + }); + + it(`should use custom index`, async () => { + const expectFn = () => expectClusterCallArgs({ index: 'custom' }, 2); + await deleteFromNamespacesSuccessDelete(expectFn, {}, MULTI_NAMESPACE_CUSTOM_INDEX_TYPE); + }); }); - }); - }); - describe('#incrementCounter', () => { - beforeEach(() => { - callAdminCluster.mockImplementation((method, params) => ({ - _id: params.id, - ...mockVersionProps, - _index: '.kibana', - get: { - found: true, - _source: { - type: 'config', - ...mockTimestampFields, - config: { - buildNum: 8468, - defaultIndex: 'logstash-*', - }, - }, - }, - })); - }); + describe('update action', () => { + const deleteFromNamespacesSuccessUpdate = async (expectFn, options, _type = type) => { + const test = async remaining => { + const currentNamespaces = [namespace1].concat(remaining); + await deleteFromNamespacesSuccess(_type, id, [namespace1], currentNamespaces, options); + expectFn(); + callAdminCluster.mockReset(); + }; + await test([namespace2]); + await test([namespace2, namespace3]); + }; + + it(`should use ES get action then update action if the object has one or more namespaces remaining`, async () => { + await deleteFromNamespacesSuccessUpdate(() => expectClusterCalls('get', 'update')); + }); - it('formats Elasticsearch response', async () => { - callAdminCluster.mockImplementation((method, params) => ({ - _id: params.id, - ...mockVersionProps, - _index: '.kibana', - get: { - found: true, - _source: { - type: 'config', - ...mockTimestampFields, - config: { - buildNum: 8468, - defaultIndex: 'logstash-*', - }, - }, - }, - })); + it(`formats the ES requests`, async () => { + let ctr = 0; + const expectFn = () => { + expectClusterCallArgs({ id: `${type}:${id}` }, 1); + const namespaces = ctr++ === 0 ? [namespace2] : [namespace2, namespace3]; + const versionProperties = { + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + expectClusterCallArgs( + { + id: `${type}:${id}`, + ...versionProperties, + body: { doc: { ...mockTimestampFields, namespaces } }, + }, + 2 + ); + }; + await deleteFromNamespacesSuccessUpdate(expectFn); + }); - const response = await savedObjectsRepository.incrementCounter( - 'config', - '6.0.0-alpha1', - 'buildNum', - { - namespace: 'foo-namespace', - } - ); + it(`defaults to a refresh setting of wait_for`, async () => { + const expectFn = () => expectClusterCallArgs({ refresh: 'wait_for' }, 2); + await deleteFromNamespacesSuccessUpdate(expectFn); + }); - expect(response).toEqual({ - type: 'config', - id: '6.0.0-alpha1', - ...mockTimestampFields, - version: mockVersion, - attributes: { - buildNum: 8468, - defaultIndex: 'logstash-*', - }, + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + const expectFn = () => expectClusterCallArgs({ refresh }, 2); + await deleteFromNamespacesSuccessUpdate(expectFn, { refresh }); + }); + + it(`should use default index`, async () => { + const expectFn = () => expectClusterCallArgs({ index: '.kibana-test' }, 2); + await deleteFromNamespacesSuccessUpdate(expectFn); + }); + + it(`should use custom index`, async () => { + const expectFn = () => expectClusterCallArgs({ index: 'custom' }, 2); + await deleteFromNamespacesSuccessUpdate(expectFn, {}, MULTI_NAMESPACE_CUSTOM_INDEX_TYPE); + }); }); }); - it('migrates the doc if an upsert is required', async () => { - migrator.migrateDocument = doc => { - doc.attributes.buildNum = 42; - doc.migrationVersion = { foo: '2.3.4' }; - doc.references = [{ name: 'search_0', type: 'search', id: '123' }]; - return doc; + describe('errors', () => { + const expectNotFoundError = async (type, id, namespaces, options) => { + await expect( + savedObjectsRepository.deleteFromNamespaces(type, id, namespaces, options) + ).rejects.toThrowError(createGenericNotFoundError(type, id)); + }; + const expectBadRequestError = async (type, id, namespaces, message) => { + await expect( + savedObjectsRepository.deleteFromNamespaces(type, id, namespaces) + ).rejects.toThrowError(createBadRequestError(message)); }; - await savedObjectsRepository.incrementCounter('config', 'doesnotexist', 'buildNum', { - namespace: 'foo-namespace', + it(`throws when type is invalid`, async () => { + await expectNotFoundError('unknownType', id, [namespace1, namespace2]); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - body: { - upsert: { - config: { buildNum: 42 }, - migrationVersion: { foo: '2.3.4' }, - type: 'config', - ...mockTimestampFields, - references: [{ name: 'search_0', type: 'search', id: '123' }], - }, - }, + it(`throws when type is hidden`, async () => { + await expectNotFoundError(HIDDEN_TYPE, id, [namespace1, namespace2]); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - }); - it('defaults to a refresh setting of `wait_for`', async () => { - await savedObjectsRepository.incrementCounter('config', 'doesnotexist', 'buildNum', { - namespace: 'foo-namespace', + it(`throws when type is not namespace-agnostic`, async () => { + const test = async type => { + const message = `${type} doesn't support multiple namespaces`; + await expectBadRequestError(type, id, [namespace1, namespace2], message); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; + await test('index-pattern'); + await test(NAMESPACE_AGNOSTIC_TYPE); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: 'wait_for', + it(`throws when namespaces is an empty array`, async () => { + const test = async namespaces => { + const message = 'namespaces must be a non-empty array of strings'; + await expectBadRequestError(type, id, namespaces, message); + expect(callAdminCluster).not.toHaveBeenCalled(); + }; + await test([]); }); - }); - it('accepts a custom refresh setting', async () => { - await savedObjectsRepository.incrementCounter('config', 'doesnotexist', 'buildNum', { - namespace: 'foo-namespace', - refresh: true, + it(`throws when ES is unable to find the document during get`, async () => { + callAdminCluster.mockResolvedValue({ found: false }); // this._callCluster('get', ...) + await expectNotFoundError(type, id, [namespace1, namespace2]); + expectClusterCalls('get'); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); - expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ - refresh: true, + it(`throws when ES is unable to find the index during get`, async () => { + callAdminCluster.mockResolvedValue({ status: 404 }); // this._callCluster('get', ...) + await expectNotFoundError(type, id, [namespace1, namespace2]); + expectClusterCalls('get'); }); - }); - it(`prepends namespace to the id but doesn't add namespace to body when providing namespace for namespaced type`, async () => { - await savedObjectsRepository.incrementCounter('config', '6.0.0-alpha1', 'buildNum', { - namespace: 'foo-namespace', + it(`throws when the document exists, but not in this namespace`, async () => { + mockGetResponse(type, id, [namespace1]); // this._callCluster('get', ...) + await expectNotFoundError(type, id, [namespace1], { namespace: 'some-other-namespace' }); + expectClusterCalls('get'); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`throws when ES is unable to find the document during delete`, async () => { + mockGetResponse(type, id, [namespace1]); // this._callCluster('get', ...) + callAdminCluster.mockResolvedValue({ result: 'not_found' }); // this._writeToCluster('delete', ...) + await expectNotFoundError(type, id, [namespace1]); + expectClusterCalls('get', 'delete'); + }); + + it(`throws when ES is unable to find the index during delete`, async () => { + mockGetResponse(type, id, [namespace1]); // this._callCluster('get', ...) + callAdminCluster.mockResolvedValue({ error: { type: 'index_not_found_exception' } }); // this._writeToCluster('delete', ...) + await expectNotFoundError(type, id, [namespace1]); + expectClusterCalls('get', 'delete'); + }); + + it(`throws when ES returns an unexpected response`, async () => { + mockGetResponse(type, id, [namespace1]); // this._callCluster('get', ...) + callAdminCluster.mockResolvedValue({ result: 'something unexpected' }); // this._writeToCluster('delete', ...) + await expect( + savedObjectsRepository.deleteFromNamespaces(type, id, [namespace1]) + ).rejects.toThrowError('Unexpected Elasticsearch DELETE response'); + expectClusterCalls('get', 'delete'); + }); + + it(`throws when ES is unable to find the document during update`, async () => { + mockGetResponse(type, id, [namespace1, namespace2]); // this._callCluster('get', ...) + callAdminCluster.mockResolvedValue({ status: 404 }); // this._writeToCluster('update', ...) + await expectNotFoundError(type, id, [namespace1]); + expectClusterCalls('get', 'update'); + }); + }); - const requestDoc = callAdminCluster.mock.calls[0][1]; - expect(requestDoc.id).toBe('foo-namespace:config:6.0.0-alpha1'); - expect(requestDoc.body.script.params.type).toBe('config'); - expect(requestDoc.body.upsert.type).toBe('config'); - expect(requestDoc).toHaveProperty('body.upsert.config'); + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + let callAdminClusterCount = 0; + migrator.runMigrations = jest.fn(async () => + // runMigrations should resolve before callAdminCluster is initiated + expect(callAdminCluster).toHaveBeenCalledTimes(callAdminClusterCount++) + ); + await expect( + deleteFromNamespacesSuccess(type, id, [namespace1], [namespace1]) + ).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveReturnedTimes(2); + }); }); - it(`doesn't prepend namespace to the id or add namespace property when providing no namespace for namespaced type`, async () => { - await savedObjectsRepository.incrementCounter('config', '6.0.0-alpha1', 'buildNum'); + describe('returns', () => { + it(`returns an empty object on success (delete)`, async () => { + const test = async namespaces => { + const result = await deleteFromNamespacesSuccess(type, id, namespaces, namespaces); + expect(result).toEqual({}); + callAdminCluster.mockReset(); + }; + await test([namespace1]); + await test([namespace1, namespace2]); + }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`returns an empty object on success (update)`, async () => { + const test = async remaining => { + const currentNamespaces = [namespace1].concat(remaining); + const result = await deleteFromNamespacesSuccess( + type, + id, + [namespace1], + currentNamespaces + ); + expect(result).toEqual({}); + callAdminCluster.mockReset(); + }; + await test([namespace2]); + await test([namespace2, namespace3]); + }); - const requestDoc = callAdminCluster.mock.calls[0][1]; - expect(requestDoc.id).toBe('config:6.0.0-alpha1'); - expect(requestDoc.body.script.params.type).toBe('config'); - expect(requestDoc.body.upsert.type).toBe('config'); - expect(requestDoc).toHaveProperty('body.upsert.config'); + it(`succeeds when the document doesn't exist in all of the targeted namespaces`, async () => { + const namespaces = [namespace2]; + const currentNamespaces = [namespace1]; + const result = await deleteFromNamespacesSuccess(type, id, namespaces, currentNamespaces); + expect(result).toEqual({}); + }); }); + }); - it(`doesn't prepend namespace to the id or add namespace property when providing namespace for namespace agnostic type`, async () => { - callAdminCluster.mockImplementation((method, params) => ({ - _id: params.id, + describe('#update', () => { + const id = 'logstash-*'; + const type = 'index-pattern'; + const attributes = { title: 'Testing' }; + const namespace = 'foo-namespace'; + const references = [ + { + name: 'ref_0', + type: 'test', + id: '1', + }, + ]; + + const updateSuccess = async (type, id, attributes, options) => { + if (registry.isMultiNamespace(type)) { + const mockGetResponse = getMockGetResponse({ type, id, namespace: options?.namespace }); + callAdminCluster.mockResolvedValueOnce(mockGetResponse); // this._callCluster('get', ...) + } + callAdminCluster.mockResolvedValue({ + _id: `${type}:${id}`, ...mockVersionProps, - _index: '.kibana', - get: { - found: true, - _source: { - type: 'globaltype', - ...mockTimestampFields, - globaltype: { - counter: 1, - }, - }, - }, - })); + result: 'updated', + ...(registry.isMultiNamespace(type) && { + // don't need the rest of the source for test purposes, just the namespaces attribute + get: { _source: { namespaces: [options?.namespace ?? 'default'] } }, + }), + }); // this._writeToCluster('update', ...) + const result = await savedObjectsRepository.update(type, id, attributes, options); + expect(callAdminCluster).toHaveBeenCalledTimes(registry.isMultiNamespace(type) ? 2 : 1); + return result; + }; - await savedObjectsRepository.incrementCounter('globaltype', 'foo', 'counter', { - namespace: 'foo-namespace', + describe('cluster calls', () => { + it(`should use the ES get action then update action when type is multi-namespace`, async () => { + await updateSuccess(MULTI_NAMESPACE_TYPE, id, attributes); + expectClusterCalls('get', 'update'); }); - expect(callAdminCluster).toHaveBeenCalledTimes(1); + it(`should use the ES update action when type is not multi-namespace`, async () => { + await updateSuccess(type, id, attributes); + expectClusterCalls('update'); + }); - const requestDoc = callAdminCluster.mock.calls[0][1]; - expect(requestDoc.id).toBe('globaltype:foo'); - expect(requestDoc.body.script.params.type).toBe('globaltype'); - expect(requestDoc.body.upsert.type).toBe('globaltype'); - expect(requestDoc).toHaveProperty('body.upsert.globaltype'); - }); + it(`defaults to no references array`, async () => { + await updateSuccess(type, id, attributes); + expectClusterCallArgs({ + body: { doc: expect.not.objectContaining({ references: expect.anything() }) }, + }); + }); - it('should assert that the "type" and "counterFieldName" arguments are strings', () => { - expect.assertions(6); - - expect( - savedObjectsRepository.incrementCounter(null, '6.0.0-alpha1', 'buildNum', { - namespace: 'foo-namespace', - }) - ).rejects.toEqual(new Error('"type" argument must be a string')); - - expect( - savedObjectsRepository.incrementCounter(42, '6.0.0-alpha1', 'buildNum', { - namespace: 'foo-namespace', - }) - ).rejects.toEqual(new Error('"type" argument must be a string')); - - expect( - savedObjectsRepository.incrementCounter({}, '6.0.0-alpha1', 'buildNum', { - namespace: 'foo-namespace', - }) - ).rejects.toEqual(new Error('"type" argument must be a string')); - - expect( - savedObjectsRepository.incrementCounter('config', '6.0.0-alpha1', null, { - namespace: 'foo-namespace', - }) - ).rejects.toEqual(new Error('"counterFieldName" argument must be a string')); - - expect( - savedObjectsRepository.incrementCounter('config', '6.0.0-alpha1', 42, { - namespace: 'foo-namespace', - }) - ).rejects.toEqual(new Error('"counterFieldName" argument must be a string')); - - expect( - savedObjectsRepository.incrementCounter( - 'config', - '6.0.0-alpha1', - {}, - { - namespace: 'foo-namespace', - } - ) - ).rejects.toEqual(new Error('"counterFieldName" argument must be a string')); - }); - }); + it(`accepts custom references array`, async () => { + const test = async references => { + await updateSuccess(type, id, attributes, { references }); + expectClusterCallArgs({ + body: { doc: expect.objectContaining({ references }) }, + }); + callAdminCluster.mockReset(); + }; + await test(references); + await test(['string']); + await test([]); + }); + + it(`doesn't accept custom references if not an array`, async () => { + const test = async references => { + await updateSuccess(type, id, attributes, { references }); + expectClusterCallArgs({ + body: { doc: expect.not.objectContaining({ references: expect.anything() }) }, + }); + callAdminCluster.mockReset(); + }; + await test('string'); + await test(123); + await test(true); + await test(null); + }); + + it(`defaults to a refresh setting of wait_for`, async () => { + await updateSuccess(type, id, { foo: 'bar' }); + expectClusterCallArgs({ refresh: 'wait_for' }); + }); + + it(`accepts a custom refresh setting`, async () => { + const refresh = 'foo'; + await updateSuccess(type, id, { foo: 'bar' }, { refresh }); + expectClusterCallArgs({ refresh }); + }); + + it(`defaults to the version of the existing document when type is multi-namespace`, async () => { + await updateSuccess(MULTI_NAMESPACE_TYPE, id, attributes, { references }); + const versionProperties = { + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + expectClusterCallArgs(versionProperties, 2); + }); + + it(`accepts version`, async () => { + await updateSuccess(type, id, attributes, { + version: encodeHitVersion({ _seq_no: 100, _primary_term: 200 }), + }); + expectClusterCallArgs({ if_seq_no: 100, if_primary_term: 200 }); + }); - describe('types on custom index', () => { - it("should error when attempting to 'update' an unsupported type", async () => { - await expect( - savedObjectsRepository.update('hiddenType', 'bogus', { title: 'some title' }) - ).rejects.toEqual(new Error('Saved object [hiddenType/bogus] not found')); - }); - }); + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + await updateSuccess(type, id, attributes, { namespace }); + expectClusterCallArgs({ id: expect.stringMatching(`${namespace}:${type}:${id}`) }); + }); - describe('unsupported types', () => { - it("should error when attempting to 'update' an unsupported type", async () => { - await expect( - savedObjectsRepository.update('hiddenType', 'bogus', { title: 'some title' }) - ).rejects.toEqual(new Error('Saved object [hiddenType/bogus] not found')); - }); + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + await updateSuccess(type, id, attributes, { references }); + expectClusterCallArgs({ id: expect.stringMatching(`${type}:${id}`) }); + }); - it("should error when attempting to 'get' an unsupported type", async () => { - await expect(savedObjectsRepository.get('hiddenType')).rejects.toEqual( - new Error('Not Found') - ); - }); + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + await updateSuccess(NAMESPACE_AGNOSTIC_TYPE, id, attributes, { namespace }); + expectClusterCallArgs({ id: expect.stringMatching(`${NAMESPACE_AGNOSTIC_TYPE}:${id}`) }); - it("should return an error object when attempting to 'create' an unsupported type", async () => { - await expect( - savedObjectsRepository.create('hiddenType', { title: 'some title' }) - ).rejects.toEqual(new Error("Unsupported saved object type: 'hiddenType': Bad Request")); - }); + callAdminCluster.mockReset(); + await updateSuccess(MULTI_NAMESPACE_TYPE, id, attributes, { namespace }); + expectClusterCallArgs({ id: expect.stringMatching(`${MULTI_NAMESPACE_TYPE}:${id}`) }, 2); + }); - it("should not return hidden saved ojects when attempting to 'find' support and unsupported types", async () => { - callAdminCluster.mockReturnValue({ - hits: { - total: 1, - hits: [ - { - _id: 'one', - _source: { - updated_at: mockTimestamp, - type: 'config', - }, - references: [], - }, - ], - }, + it(`includes _sourceIncludes when type is multi-namespace`, async () => { + await updateSuccess(MULTI_NAMESPACE_TYPE, id, attributes); + expectClusterCallArgs({ _sourceIncludes: ['namespaces'] }, 2); }); - const results = await savedObjectsRepository.find({ type: ['hiddenType', 'config'] }); - expect(results).toEqual({ - total: 1, - saved_objects: [ - { - id: 'one', - references: [], - type: 'config', - updated_at: mockTimestamp, - }, - ], - page: 1, - per_page: 20, + + it(`doesn't include _sourceIncludes when type is not multi-namespace`, async () => { + await updateSuccess(type, id, attributes); + expect(callAdminCluster).toHaveBeenLastCalledWith( + expect.any(String), + expect.not.objectContaining({ + _sourceIncludes: expect.anything(), + }) + ); }); }); - it("should return empty results when attempting to 'find' an unsupported type", async () => { - callAdminCluster.mockReturnValue({ - hits: { - total: 0, - hits: [], - }, + describe('errors', () => { + const expectNotFoundError = async (type, id) => { + await expect(savedObjectsRepository.update(type, id)).rejects.toThrowError( + createGenericNotFoundError(type, id) + ); + }; + + it(`throws when type is invalid`, async () => { + await expectNotFoundError('unknownType', id); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - const results = await savedObjectsRepository.find({ type: 'hiddenType' }); - expect(results).toEqual({ - total: 0, - saved_objects: [], - page: 1, - per_page: 20, + + it(`throws when type is hidden`, async () => { + await expectNotFoundError(HIDDEN_TYPE, id); + expect(callAdminCluster).not.toHaveBeenCalled(); }); - }); - it("should return empty results when attempting to 'find' more than one unsupported types", async () => { - const findParams = { type: ['hiddenType', 'hiddenType2'] }; - callAdminCluster.mockReturnValue({ - status: 200, - hits: { - total: 0, - hits: [], - }, + it(`throws when ES is unable to find the document during get`, async () => { + callAdminCluster.mockResolvedValue({ found: false }); // this._callCluster('get', ...) + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id); + expectClusterCalls('get'); }); - const results = await savedObjectsRepository.find(findParams); - expect(results).toEqual({ - total: 0, - saved_objects: [], - page: 1, - per_page: 20, + + it(`throws when ES is unable to find the index during get`, async () => { + callAdminCluster.mockResolvedValue({ status: 404 }); // this._callCluster('get', ...) + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id); + expectClusterCalls('get'); }); - }); - it("should error when attempting to 'delete' hidden types", async () => { - await expect(savedObjectsRepository.delete('hiddenType')).rejects.toEqual( - new Error('Not Found') - ); + it(`throws when type is multi-namespace and the document exists, but not in this namespace`, async () => { + const response = getMockGetResponse({ type: MULTI_NAMESPACE_TYPE, id, namespace }); + callAdminCluster.mockResolvedValue(response); // this._callCluster('get', ...) + await expectNotFoundError(MULTI_NAMESPACE_TYPE, id, { namespace: 'bar-namespace' }); + expectClusterCalls('get'); + }); + + it(`throws when ES is unable to find the document during update`, async () => { + callAdminCluster.mockResolvedValue({ status: 404 }); // this._writeToCluster('update', ...) + await expectNotFoundError(type, id); + expectClusterCalls('update'); + }); }); - it("should error when attempting to 'bulkCreate' an unsupported type", async () => { - callAdminCluster.mockReturnValue({ - items: [ - { - index: { - _id: 'one', - _seq_no: 1, - _primary_term: 1, - _type: 'config', - attributes: { - title: 'Test One', - }, - }, - }, - ], - }); - const results = await savedObjectsRepository.bulkCreate([ - { type: 'config', id: 'one', attributes: { title: 'Test One' } }, - { type: 'hiddenType', id: 'two', attributes: { title: 'Test Two' } }, - ]); - expect(results).toEqual({ - saved_objects: [ - { - type: 'config', - id: 'one', - attributes: { title: 'Test One' }, - references: [], - version: 'WzEsMV0=', - updated_at: mockTimestamp, - }, - { - error: { - error: 'Bad Request', - message: "Unsupported saved object type: 'hiddenType': Bad Request", - statusCode: 400, - }, - id: 'two', - type: 'hiddenType', - }, - ], + describe('migration', () => { + it(`waits until migrations are complete before proceeding`, async () => { + let callAdminClusterCount = 0; + migrator.runMigrations = jest.fn(async () => + // runMigrations should resolve before callAdminCluster is initiated + expect(callAdminCluster).toHaveBeenCalledTimes(callAdminClusterCount++) + ); + await expect(updateSuccess(type, id, attributes)).resolves.toBeDefined(); + expect(migrator.runMigrations).toHaveReturnedTimes(1); }); }); - it("should error when attempting to 'incrementCounter' for an unsupported type", async () => { - await expect( - savedObjectsRepository.incrementCounter('hiddenType', 'doesntmatter', 'fieldArg') - ).rejects.toEqual(new Error("Unsupported saved object type: 'hiddenType': Bad Request")); + describe('returns', () => { + it(`returns _seq_no and _primary_term encoded as version`, async () => { + const result = await updateSuccess(type, id, attributes, { + namespace, + references, + }); + expect(result).toEqual({ + id, + type, + ...mockTimestampFields, + version: mockVersion, + attributes, + references, + }); + }); + + it(`includes namespaces if type is multi-namespace`, async () => { + const result = await updateSuccess(MULTI_NAMESPACE_TYPE, id, attributes); + expect(result).toMatchObject({ + namespaces: expect.any(Array), + }); + }); + + it(`doesn't include namespaces if type is not multi-namespace`, async () => { + const result = await updateSuccess(type, id, attributes); + expect(result).not.toMatchObject({ + namespaces: expect.anything(), + }); + }); }); }); }); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 72a7867854b60..5f17c11792763 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -45,6 +45,8 @@ import { SavedObjectsBulkUpdateObject, SavedObjectsBulkUpdateOptions, SavedObjectsDeleteOptions, + SavedObjectsAddToNamespacesOptions, + SavedObjectsDeleteFromNamespacesOptions, } from '../saved_objects_client'; import { SavedObject, @@ -60,20 +62,12 @@ import { validateConvertFilterToKueryNode } from './filter_utils'; // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -type Left = { - tag: 'Left'; - error: T; -}; +type Left = { tag: 'Left'; error: Record }; // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -type Right = { - tag: 'Right'; - value: T; -}; - -type Either = Left | Right; -const isLeft = (either: Either): either is Left => { - return either.tag === 'Left'; -}; +type Right = { tag: 'Right'; value: Record }; +type Either = Left | Right; +const isLeft = (either: Either): either is Left => either.tag === 'Left'; +const isRight = (either: Either): either is Right => either.tag === 'Right'; export interface SavedObjectsRepositoryOptions { index: string; @@ -220,8 +214,8 @@ export class SavedObjectsRepository { const { id, migrationVersion, - overwrite = false, namespace, + overwrite = false, references = [], refresh = DEFAULT_REFRESH_SETTING, } = options; @@ -230,22 +224,36 @@ export class SavedObjectsRepository { throw SavedObjectsErrorHelpers.createUnsupportedTypeError(type); } - const method = id && !overwrite ? 'create' : 'index'; const time = this._getCurrentTime(); + let savedObjectNamespace; + let savedObjectNamespaces: string[] | undefined; + + if (this._registry.isSingleNamespace(type) && namespace) { + savedObjectNamespace = namespace; + } else if (this._registry.isMultiNamespace(type)) { + if (id && overwrite) { + // we will overwrite a multi-namespace saved object if it exists; if that happens, ensure we preserve its included namespaces + savedObjectNamespaces = await this.preflightGetNamespaces(type, id, namespace); + } else { + savedObjectNamespaces = getSavedObjectNamespaces(namespace); + } + } try { const migrated = this._migrator.migrateDocument({ id, type, - namespace, + ...(savedObjectNamespace && { namespace: savedObjectNamespace }), + ...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }), attributes, migrationVersion, updated_at: time, - references, + ...(Array.isArray(references) && { references }), }); const raw = this._serializer.savedObjectToRaw(migrated as SavedObjectSanitizedDoc); + const method = id && overwrite ? 'index' : 'create'; const response = await this._writeToCluster(method, { id: raw._id, index: this.getIndexForType(type), @@ -282,10 +290,9 @@ export class SavedObjectsRepository { ): Promise> { const { namespace, overwrite = false, refresh = DEFAULT_REFRESH_SETTING } = options; const time = this._getCurrentTime(); - const bulkCreateParams: object[] = []; - let requestIndexCounter = 0; - const expectedResults: Array> = objects.map(object => { + let bulkGetRequestIndexCounter = 0; + const expectedResults: Either[] = objects.map(object => { if (!this._allowedTypes.includes(object.type)) { return { tag: 'Left' as 'Left', @@ -297,9 +304,73 @@ export class SavedObjectsRepository { }; } - const method = object.id && !overwrite ? 'create' : 'index'; + const method = object.id && overwrite ? 'index' : 'create'; + const requiresNamespacesCheck = + method === 'index' && this._registry.isMultiNamespace(object.type); + + return { + tag: 'Right' as 'Right', + value: { + method, + object, + ...(requiresNamespacesCheck && { esRequestIndex: bulkGetRequestIndexCounter++ }), + }, + }; + }); + + const bulkGetDocs = expectedResults + .filter(isRight) + .filter(({ value }) => value.esRequestIndex !== undefined) + .map(({ value: { object: { type, id } } }) => ({ + _id: this._serializer.generateRawId(namespace, type, id), + _index: this.getIndexForType(type), + _source: ['type', 'namespaces'], + })); + const bulkGetResponse = bulkGetDocs.length + ? await this._callCluster('mget', { + body: { + docs: bulkGetDocs, + }, + ignore: [404], + }) + : undefined; + + let bulkRequestIndexCounter = 0; + const bulkCreateParams: object[] = []; + const expectedBulkResults: Either[] = expectedResults.map(expectedBulkGetResult => { + if (isLeft(expectedBulkGetResult)) { + return expectedBulkGetResult; + } + + let savedObjectNamespace; + let savedObjectNamespaces; + const { esRequestIndex, object, method } = expectedBulkGetResult.value; + if (esRequestIndex !== undefined) { + const indexFound = bulkGetResponse.status !== 404; + const actualResult = indexFound ? bulkGetResponse.docs[esRequestIndex] : undefined; + const docFound = indexFound && actualResult.found === true; + if (docFound && !this.rawDocExistsInNamespace(actualResult, namespace)) { + const { id, type } = object; + return { + tag: 'Left' as 'Left', + error: { + id, + type, + error: SavedObjectsErrorHelpers.createConflictError(type, id).output.payload, + }, + }; + } + savedObjectNamespaces = getSavedObjectNamespaces(namespace, docFound && actualResult); + } else { + if (this._registry.isSingleNamespace(object.type)) { + savedObjectNamespace = namespace; + } else if (this._registry.isMultiNamespace(object.type)) { + savedObjectNamespaces = getSavedObjectNamespaces(namespace); + } + } + const expectedResult = { - esRequestIndex: requestIndexCounter++, + esRequestIndex: bulkRequestIndexCounter++, requestedId: object.id, rawMigratedDoc: this._serializer.savedObjectToRaw( this._migrator.migrateDocument({ @@ -307,7 +378,8 @@ export class SavedObjectsRepository { type: object.type, attributes: object.attributes, migrationVersion: object.migrationVersion, - namespace, + ...(savedObjectNamespace && { namespace: savedObjectNamespace }), + ...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }), updated_at: time, references: object.references || [], }) as SavedObjectSanitizedDoc @@ -327,19 +399,21 @@ export class SavedObjectsRepository { return { tag: 'Right' as 'Right', value: expectedResult }; }); - const esResponse = await this._writeToCluster('bulk', { - refresh, - body: bulkCreateParams, - }); + const bulkResponse = bulkCreateParams.length + ? await this._writeToCluster('bulk', { + refresh, + body: bulkCreateParams, + }) + : undefined; return { - saved_objects: expectedResults.map(expectedResult => { + saved_objects: expectedBulkResults.map(expectedResult => { if (isLeft(expectedResult)) { - return expectedResult.error; + return expectedResult.error as any; } const { requestedId, rawMigratedDoc, esRequestIndex } = expectedResult.value; - const response = esResponse.items[esRequestIndex]; + const response = bulkResponse.items[esRequestIndex]; const { error, _id: responseId, @@ -348,7 +422,7 @@ export class SavedObjectsRepository { } = Object.values(response)[0] as any; const { - _source: { type, [type]: attributes, references = [] }, + _source: { type, [type]: attributes, references = [], namespaces }, } = rawMigratedDoc; const id = requestedId || responseId; @@ -362,6 +436,7 @@ export class SavedObjectsRepository { return { id, type, + ...(namespaces && { namespaces }), updated_at: time, version: encodeVersion(seqNo, primaryTerm), attributes, @@ -382,32 +457,76 @@ export class SavedObjectsRepository { */ async delete(type: string, id: string, options: SavedObjectsDeleteOptions = {}): Promise<{}> { if (!this._allowedTypes.includes(type)) { - throw SavedObjectsErrorHelpers.createGenericNotFoundError(); + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } const { namespace, refresh = DEFAULT_REFRESH_SETTING } = options; - const response = await this._writeToCluster('delete', { - id: this._serializer.generateRawId(namespace, type, id), + const rawId = this._serializer.generateRawId(namespace, type, id); + let preflightResult: SavedObjectsRawDoc | undefined; + + if (this._registry.isMultiNamespace(type)) { + preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace); + const existingNamespaces = getSavedObjectNamespaces(undefined, preflightResult); + const remainingNamespaces = existingNamespaces?.filter( + x => x !== getNamespaceString(namespace) + ); + + if (remainingNamespaces?.length) { + // if there is 1 or more namespace remaining, update the saved object + const time = this._getCurrentTime(); + + const doc = { + updated_at: time, + namespaces: remainingNamespaces, + }; + + const updateResponse = await this._writeToCluster('update', { + id: rawId, + index: this.getIndexForType(type), + ...getExpectedVersionProperties(undefined, preflightResult), + refresh, + ignore: [404], + body: { + doc, + }, + }); + + if (updateResponse.status === 404) { + // see "404s from missing index" above + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + return {}; + } + } + + const deleteResponse = await this._writeToCluster('delete', { + id: rawId, index: this.getIndexForType(type), + ...getExpectedVersionProperties(undefined, preflightResult), refresh, ignore: [404], }); - const deleted = response.result === 'deleted'; + const deleted = deleteResponse.result === 'deleted'; if (deleted) { return {}; } - const docNotFound = response.result === 'not_found'; - const indexNotFound = response.error && response.error.type === 'index_not_found_exception'; - if (docNotFound || indexNotFound) { + const deleteDocNotFound = deleteResponse.result === 'not_found'; + const deleteIndexNotFound = + deleteResponse.error && deleteResponse.error.type === 'index_not_found_exception'; + if (deleteDocNotFound || deleteIndexNotFound) { // see "404s from missing index" above throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } throw new Error( - `Unexpected Elasticsearch DELETE response: ${JSON.stringify({ type, id, response })}` + `Unexpected Elasticsearch DELETE response: ${JSON.stringify({ + type, + id, + response: deleteResponse, + })}` ); } @@ -426,25 +545,37 @@ export class SavedObjectsRepository { } const { refresh = DEFAULT_REFRESH_SETTING } = options; - const allTypes = Object.keys(getRootPropertiesObjects(this._mappings)); + const typesToUpdate = allTypes.filter(type => !this._registry.isNamespaceAgnostic(type)); - const typesToDelete = allTypes.filter(type => !this._registry.isNamespaceAgnostic(type)); - - const esOptions = { - index: this.getIndicesForTypes(typesToDelete), + const updateOptions = { + index: this.getIndicesForTypes(typesToUpdate), ignore: [404], refresh, body: { + script: { + source: ` + if (!ctx._source.containsKey('namespaces')) { + ctx.op = "delete"; + } else { + ctx._source['namespaces'].removeAll(Collections.singleton(params['namespace'])); + if (ctx._source['namespaces'].empty) { + ctx.op = "delete"; + } + } + `, + lang: 'painless', + params: { namespace: getNamespaceString(namespace) }, + }, conflicts: 'proceed', ...getSearchDsl(this._mappings, this._registry, { namespace, - type: typesToDelete, + type: typesToUpdate, }), }, }; - return await this._writeToCluster('deleteByQuery', esOptions); + return await this._writeToCluster('updateByQuery', updateOptions); } /** @@ -586,55 +717,77 @@ export class SavedObjectsRepository { return { saved_objects: [] }; } - const unsupportedTypeObjects = objects - .filter(o => !this._allowedTypes.includes(o.type)) - .map(({ type, id }) => { - return ({ - id, - type, - error: SavedObjectsErrorHelpers.createUnsupportedTypeError(type).output.payload, - } as any) as SavedObject; - }); + let bulkGetRequestIndexCounter = 0; + const expectedBulkGetResults: Either[] = objects.map(object => { + const { type, id, fields } = object; - const supportedTypeObjects = objects.filter(o => this._allowedTypes.includes(o.type)); + if (!this._allowedTypes.includes(type)) { + return { + tag: 'Left' as 'Left', + error: { + id, + type, + error: SavedObjectsErrorHelpers.createUnsupportedTypeError(type).output.payload, + }, + }; + } - const response = await this._callCluster('mget', { - body: { - docs: supportedTypeObjects.map(({ type, id, fields }) => { - return { - _id: this._serializer.generateRawId(namespace, type, id), - _index: this.getIndexForType(type), - _source: includedFields(type, fields), - }; - }), - }, + return { + tag: 'Right' as 'Right', + value: { + type, + id, + fields, + esRequestIndex: bulkGetRequestIndexCounter++, + }, + }; }); + const bulkGetDocs = expectedBulkGetResults + .filter(isRight) + .map(({ value: { type, id, fields } }) => ({ + _id: this._serializer.generateRawId(namespace, type, id), + _index: this.getIndexForType(type), + _source: includedFields(type, fields), + })); + const bulkGetResponse = bulkGetDocs.length + ? await this._callCluster('mget', { + body: { + docs: bulkGetDocs, + }, + ignore: [404], + }) + : undefined; + return { - saved_objects: (response.docs as any[]) - .map((doc, i) => { - const { id, type } = supportedTypeObjects[i]; + saved_objects: expectedBulkGetResults.map(expectedResult => { + if (isLeft(expectedResult)) { + return expectedResult.error as any; + } - if (!doc.found) { - return ({ - id, - type, - error: { statusCode: 404, message: 'Not found' }, - } as any) as SavedObject; - } + const { type, id, esRequestIndex } = expectedResult.value; + const doc = bulkGetResponse.docs[esRequestIndex]; - const time = doc._source.updated_at; - return { + if (!doc.found || !this.rawDocExistsInNamespace(doc, namespace)) { + return ({ id, type, - ...(time && { updated_at: time }), - version: encodeHitVersion(doc), - attributes: doc._source[type], - references: doc._source.references || [], - migrationVersion: doc._source.migrationVersion, - }; - }) - .concat(unsupportedTypeObjects), + error: SavedObjectsErrorHelpers.createGenericNotFoundError(type, id).output.payload, + } as any) as SavedObject; + } + + const time = doc._source.updated_at; + return { + id, + type, + ...(doc._source.namespaces && { namespaces: doc._source.namespaces }), + ...(time && { updated_at: time }), + version: encodeHitVersion(doc), + attributes: doc._source[type], + references: doc._source.references || [], + migrationVersion: doc._source.migrationVersion, + }; + }), }; } @@ -666,7 +819,7 @@ export class SavedObjectsRepository { const docNotFound = response.found === false; const indexNotFound = response.status === 404; - if (docNotFound || indexNotFound) { + if (docNotFound || indexNotFound || !this.rawDocExistsInNamespace(response, namespace)) { // see "404s from missing index" above throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } @@ -676,6 +829,7 @@ export class SavedObjectsRepository { return { id, type, + ...(response._source.namespaces && { namespaces: response._source.namespaces }), ...(updatedAt && { updated_at: updatedAt }), version: encodeHitVersion(response), attributes: response._source[type], @@ -707,29 +861,32 @@ export class SavedObjectsRepository { const { version, namespace, references, refresh = DEFAULT_REFRESH_SETTING } = options; + let preflightResult: SavedObjectsRawDoc | undefined; + if (this._registry.isMultiNamespace(type)) { + preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace); + } + const time = this._getCurrentTime(); const doc = { [type]: attributes, updated_at: time, - references, + ...(Array.isArray(references) && { references }), }; - if (!Array.isArray(doc.references)) { - delete doc.references; - } - const response = await this._writeToCluster('update', { + const updateResponse = await this._writeToCluster('update', { id: this._serializer.generateRawId(namespace, type, id), index: this.getIndexForType(type), - ...(version && decodeRequestVersion(version)), + ...getExpectedVersionProperties(version, preflightResult), refresh, ignore: [404], body: { doc, }, + ...(this._registry.isMultiNamespace(type) && { _sourceIncludes: ['namespaces'] }), }); - if (response.status === 404) { + if (updateResponse.status === 404) { // see "404s from missing index" above throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } @@ -738,12 +895,168 @@ export class SavedObjectsRepository { id, type, updated_at: time, - version: encodeHitVersion(response), + version: encodeHitVersion(updateResponse), + ...(this._registry.isMultiNamespace(type) && { + namespaces: updateResponse.get._source.namespaces, + }), references, attributes, }; } + /** + * Adds one or more namespaces to a given multi-namespace saved object. This method and + * [`deleteFromNamespaces`]{@link SavedObjectsRepository.deleteFromNamespaces} are the only ways to change which Spaces a multi-namespace + * saved object is shared to. + */ + async addToNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsAddToNamespacesOptions = {} + ): Promise<{}> { + if (!this._allowedTypes.includes(type)) { + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + + if (!this._registry.isMultiNamespace(type)) { + throw SavedObjectsErrorHelpers.createBadRequestError( + `${type} doesn't support multiple namespaces` + ); + } + + if (!namespaces.length) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'namespaces must be a non-empty array of strings' + ); + } + + const { version, namespace, refresh = DEFAULT_REFRESH_SETTING } = options; + + const rawId = this._serializer.generateRawId(undefined, type, id); + const preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace); + const existingNamespaces = getSavedObjectNamespaces(undefined, preflightResult); + // there should never be a case where a multi-namespace object does not have any existing namespaces + // however, it is a possibility if someone manually modifies the document in Elasticsearch + const time = this._getCurrentTime(); + + const doc = { + updated_at: time, + namespaces: existingNamespaces ? unique(existingNamespaces.concat(namespaces)) : namespaces, + }; + + const updateResponse = await this._writeToCluster('update', { + id: rawId, + index: this.getIndexForType(type), + ...getExpectedVersionProperties(version, preflightResult), + refresh, + ignore: [404], + body: { + doc, + }, + }); + + if (updateResponse.status === 404) { + // see "404s from missing index" above + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + + return {}; + } + + /** + * Removes one or more namespaces from a given multi-namespace saved object. If no namespaces remain, the saved object is deleted + * entirely. This method and [`addToNamespaces`]{@link SavedObjectsRepository.addToNamespaces} are the only ways to change which Spaces a + * multi-namespace saved object is shared to. + */ + async deleteFromNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsDeleteFromNamespacesOptions = {} + ): Promise<{}> { + if (!this._allowedTypes.includes(type)) { + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + + if (!this._registry.isMultiNamespace(type)) { + throw SavedObjectsErrorHelpers.createBadRequestError( + `${type} doesn't support multiple namespaces` + ); + } + + if (!namespaces.length) { + throw SavedObjectsErrorHelpers.createBadRequestError( + 'namespaces must be a non-empty array of strings' + ); + } + + const { namespace, refresh = DEFAULT_REFRESH_SETTING } = options; + + const rawId = this._serializer.generateRawId(undefined, type, id); + const preflightResult = await this.preflightCheckIncludesNamespace(type, id, namespace); + const existingNamespaces = getSavedObjectNamespaces(undefined, preflightResult); + // if there are somehow no existing namespaces, allow the operation to proceed and delete this saved object + const remainingNamespaces = existingNamespaces?.filter(x => !namespaces.includes(x)); + + if (remainingNamespaces?.length) { + // if there is 1 or more namespace remaining, update the saved object + const time = this._getCurrentTime(); + + const doc = { + updated_at: time, + namespaces: remainingNamespaces, + }; + + const updateResponse = await this._writeToCluster('update', { + id: rawId, + index: this.getIndexForType(type), + ...getExpectedVersionProperties(undefined, preflightResult), + refresh, + ignore: [404], + body: { + doc, + }, + }); + + if (updateResponse.status === 404) { + // see "404s from missing index" above + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + return {}; + } else { + // if there are no namespaces remaining, delete the saved object + const deleteResponse = await this._writeToCluster('delete', { + id: this._serializer.generateRawId(undefined, type, id), + index: this.getIndexForType(type), + ...getExpectedVersionProperties(undefined, preflightResult), + refresh, + ignore: [404], + }); + + const deleted = deleteResponse.result === 'deleted'; + if (deleted) { + return {}; + } + + const deleteDocNotFound = deleteResponse.result === 'not_found'; + const deleteIndexNotFound = + deleteResponse.error && deleteResponse.error.type === 'index_not_found_exception'; + if (deleteDocNotFound || deleteIndexNotFound) { + // see "404s from missing index" above + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + + throw new Error( + `Unexpected Elasticsearch DELETE response: ${JSON.stringify({ + type, + id, + response: deleteResponse, + })}` + ); + } + } + /** * Updates multiple objects in bulk * @@ -757,10 +1070,10 @@ export class SavedObjectsRepository { options: SavedObjectsBulkUpdateOptions = {} ): Promise> { const time = this._getCurrentTime(); - const bulkUpdateParams: object[] = []; + const { namespace } = options; - let requestIndexCounter = 0; - const expectedResults: Array> = objects.map(object => { + let bulkGetRequestIndexCounter = 0; + const expectedBulkGetResults: Either[] = objects.map(object => { const { type, id } = object; if (!this._allowedTypes.includes(type)) { @@ -775,41 +1088,100 @@ export class SavedObjectsRepository { } const { attributes, references, version } = object; - const { namespace } = options; const documentToSave = { [type]: attributes, updated_at: time, - references, + ...(Array.isArray(references) && { references }), }; - if (!Array.isArray(documentToSave.references)) { - delete documentToSave.references; - } + const requiresNamespacesCheck = this._registry.isMultiNamespace(object.type); - const expectedResult = { - type, - id, - esRequestIndex: requestIndexCounter++, - documentToSave, + return { + tag: 'Right' as 'Right', + value: { + type, + id, + version, + documentToSave, + ...(requiresNamespacesCheck && { esRequestIndex: bulkGetRequestIndexCounter++ }), + }, }; + }); - bulkUpdateParams.push( - { - update: { - _id: this._serializer.generateRawId(namespace, type, id), - _index: this.getIndexForType(type), - ...(version && decodeRequestVersion(version)), + const bulkGetDocs = expectedBulkGetResults + .filter(isRight) + .filter(({ value }) => value.esRequestIndex !== undefined) + .map(({ value: { type, id } }) => ({ + _id: this._serializer.generateRawId(namespace, type, id), + _index: this.getIndexForType(type), + _source: ['type', 'namespaces'], + })); + const bulkGetResponse = bulkGetDocs.length + ? await this._callCluster('mget', { + body: { + docs: bulkGetDocs, }, - }, - { doc: documentToSave } - ); + ignore: [404], + }) + : undefined; - return { tag: 'Right' as 'Right', value: expectedResult }; - }); + let bulkUpdateRequestIndexCounter = 0; + const bulkUpdateParams: object[] = []; + const expectedBulkUpdateResults: Either[] = expectedBulkGetResults.map( + expectedBulkGetResult => { + if (isLeft(expectedBulkGetResult)) { + return expectedBulkGetResult; + } + + const { esRequestIndex, id, type, version, documentToSave } = expectedBulkGetResult.value; + let namespaces; + let versionProperties; + if (esRequestIndex !== undefined) { + const indexFound = bulkGetResponse.status !== 404; + const actualResult = indexFound ? bulkGetResponse.docs[esRequestIndex] : undefined; + const docFound = indexFound && actualResult.found === true; + if (!docFound || !this.rawDocExistsInNamespace(actualResult, namespace)) { + return { + tag: 'Left' as 'Left', + error: { + id, + type, + error: SavedObjectsErrorHelpers.createGenericNotFoundError(type, id).output.payload, + }, + }; + } + namespaces = actualResult._source.namespaces; + versionProperties = getExpectedVersionProperties(version, actualResult); + } else { + versionProperties = getExpectedVersionProperties(version); + } + + const expectedResult = { + type, + id, + namespaces, + esRequestIndex: bulkUpdateRequestIndexCounter++, + documentToSave: expectedBulkGetResult.value.documentToSave, + }; + + bulkUpdateParams.push( + { + update: { + _id: this._serializer.generateRawId(namespace, type, id), + _index: this.getIndexForType(type), + ...versionProperties, + }, + }, + { doc: documentToSave } + ); + + return { tag: 'Right' as 'Right', value: expectedResult }; + } + ); const { refresh = DEFAULT_REFRESH_SETTING } = options; - const esResponse = bulkUpdateParams.length + const bulkUpdateResponse = bulkUpdateParams.length ? await this._writeToCluster('bulk', { refresh, body: bulkUpdateParams, @@ -817,13 +1189,13 @@ export class SavedObjectsRepository { : {}; return { - saved_objects: expectedResults.map(expectedResult => { + saved_objects: expectedBulkUpdateResults.map(expectedResult => { if (isLeft(expectedResult)) { - return expectedResult.error; + return expectedResult.error as any; } - const { type, id, documentToSave, esRequestIndex } = expectedResult.value; - const response = esResponse.items[esRequestIndex]; + const { type, id, namespaces, documentToSave, esRequestIndex } = expectedResult.value; + const response = bulkUpdateResponse.items[esRequestIndex]; const { error, _seq_no: seqNo, _primary_term: primaryTerm } = Object.values( response )[0] as any; @@ -839,6 +1211,7 @@ export class SavedObjectsRepository { return { id, type, + ...(namespaces && { namespaces }), updated_at, version: encodeVersion(seqNo, primaryTerm), attributes, @@ -877,10 +1250,20 @@ export class SavedObjectsRepository { const { migrationVersion, namespace, refresh = DEFAULT_REFRESH_SETTING } = options; const time = this._getCurrentTime(); + let savedObjectNamespace; + let savedObjectNamespaces: string[] | undefined; + + if (this._registry.isSingleNamespace(type) && namespace) { + savedObjectNamespace = namespace; + } else if (this._registry.isMultiNamespace(type)) { + savedObjectNamespaces = await this.preflightGetNamespaces(type, id, namespace); + } const migrated = this._migrator.migrateDocument({ id, type, + ...(savedObjectNamespace && { namespace: savedObjectNamespace }), + ...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }), attributes: { [counterFieldName]: 1 }, migrationVersion, updated_at: time, @@ -889,7 +1272,7 @@ export class SavedObjectsRepository { const raw = this._serializer.savedObjectToRaw(migrated as SavedObjectSanitizedDoc); const response = await this._writeToCluster('update', { - id: this._serializer.generateRawId(namespace, type, id), + id: raw._id, index: this.getIndexForType(type), refresh, _source: true, @@ -952,14 +1335,13 @@ export class SavedObjectsRepository { } /** - * Returns an array of indices as specified in `this._schema` for each of the + * Returns an array of indices as specified in `this._registry` for each of the * given `types`. If any of the types don't have an associated index, the * default index `this._index` will be included. * * @param types The types whose indices should be retrieved */ private getIndicesForTypes(types: string[]) { - const unique = (array: string[]) => [...new Set(array)]; return unique(types.map(t => this.getIndexForType(t))); } @@ -975,12 +1357,97 @@ export class SavedObjectsRepository { const savedObject = this._serializer.rawToSavedObject(raw); return omit(savedObject, 'namespace'); } + + /** + * Check to ensure that a raw document exists in a namespace. If the document is not a multi-namespace type, then this returns `true` as + * we rely on the guarantees of the document ID format. If the document is a multi-namespace type, this checks to ensure that the + * document's `namespaces` value includes the string representation of the given namespace. + * + * WARNING: This should only be used for documents that were retrieved from Elasticsearch. Otherwise, the guarantees of the document ID + * format mentioned above do not apply. + */ + private rawDocExistsInNamespace(raw: SavedObjectsRawDoc, namespace?: string) { + const rawDocType = raw._source.type; + + // if the type is namespace isolated, or namespace agnostic, we can continue to rely on the guarantees + // of the document ID format and don't need to check this + if (!this._registry.isMultiNamespace(rawDocType)) { + return true; + } + + const namespaces = raw._source.namespaces; + return namespaces?.includes(getNamespaceString(namespace)) ?? false; + } + + /** + * Pre-flight check to get a multi-namespace saved object's included namespaces. This ensures that, if the saved object exists, it + * includes the target namespace. + * + * @param type The type of the saved object. + * @param id The ID of the saved object. + * @param namespace The target namespace. + * @returns Array of namespaces that this saved object currently includes, or (if the object does not exist yet) the namespaces that a + * newly-created object will include. Value may be undefined if an existing saved object has no namespaces attribute; this should not + * happen in normal operations, but it is possible if the Elasticsearch document is manually modified. + * @throws Will throw an error if the saved object exists and it does not include the target namespace. + */ + private async preflightGetNamespaces(type: string, id: string, namespace?: string) { + if (!this._registry.isMultiNamespace(type)) { + throw new Error(`Cannot make preflight get request for non-multi-namespace type '${type}'.`); + } + + const response = await this._callCluster('get', { + id: this._serializer.generateRawId(undefined, type, id), + index: this.getIndexForType(type), + ignore: [404], + }); + + const indexFound = response.status !== 404; + const docFound = indexFound && response.found === true; + if (docFound) { + if (!this.rawDocExistsInNamespace(response, namespace)) { + throw SavedObjectsErrorHelpers.createConflictError(type, id); + } + return getSavedObjectNamespaces(namespace, response); + } + return getSavedObjectNamespaces(namespace); + } + + /** + * Pre-flight check for a multi-namespace saved object's namespaces. This ensures that, if the saved object exists, it includes the target + * namespace. + * + * @param type The type of the saved object. + * @param id The ID of the saved object. + * @param namespace The target namespace. + * @returns Raw document from Elasticsearch. + * @throws Will throw an error if the saved object is not found, or if it doesn't include the target namespace. + */ + private async preflightCheckIncludesNamespace(type: string, id: string, namespace?: string) { + if (!this._registry.isMultiNamespace(type)) { + throw new Error(`Cannot make preflight get request for non-multi-namespace type '${type}'.`); + } + + const rawId = this._serializer.generateRawId(undefined, type, id); + const response = await this._callCluster('get', { + id: rawId, + index: this.getIndexForType(type), + ignore: [404], + }); + + const indexFound = response.status !== 404; + const docFound = indexFound && response.found === true; + if (!docFound || !this.rawDocExistsInNamespace(response, namespace)) { + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } + return response as SavedObjectsRawDoc; + } } function getBulkOperationError(error: { type: string; reason?: string }, type: string, id: string) { switch (error.type) { case 'version_conflict_engine_exception': - return { statusCode: 409, message: 'version conflict, document already exists' }; + return SavedObjectsErrorHelpers.createConflictError(type, id).output.payload; case 'document_missing_exception': return SavedObjectsErrorHelpers.createGenericNotFoundError(type, id).output.payload; default: @@ -989,3 +1456,49 @@ function getBulkOperationError(error: { type: string; reason?: string }, type: s }; } } + +/** + * Returns an object with the expected version properties. This facilitates Elasticsearch's Optimistic Concurrency Control. + * + * @param version Optional version specified by the consumer. + * @param document Optional existing document that was obtained in a preflight operation. + */ +function getExpectedVersionProperties(version?: string, document?: SavedObjectsRawDoc) { + if (version) { + return decodeRequestVersion(version); + } else if (document) { + return { + if_seq_no: document._seq_no, + if_primary_term: document._primary_term, + }; + } + return {}; +} + +/** + * Returns the string representation of a namespace. + * The default namespace is undefined, and is represented by the string 'default'. + */ +function getNamespaceString(namespace?: string) { + return namespace ?? 'default'; +} + +/** + * Returns a string array of namespaces for a given saved object. If the saved object is undefined, the result is an array that contains the + * current namespace. Value may be undefined if an existing saved object has no namespaces attribute; this should not happen in normal + * operations, but it is possible if the Elasticsearch document is manually modified. + * + * @param namespace The current namespace. + * @param document Optional existing saved object that was obtained in a preflight operation. + */ +function getSavedObjectNamespaces( + namespace?: string, + document?: SavedObjectsRawDoc +): string[] | undefined { + if (document) { + return document._source?.namespaces; + } + return [getNamespaceString(namespace)]; +} + +const unique = (array: string[]) => [...new Set(array)]; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts index b2129765ee426..a72c21dd5eee4 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.test.ts @@ -17,6 +17,9 @@ * under the License. */ +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { esKuery, KueryNode } from '../../../../../../plugins/data/server'; + import { typeRegistryMock } from '../../../saved_objects_type_registry.mock'; import { getQueryParams } from './query_params'; @@ -24,1268 +27,329 @@ const registry = typeRegistryMock.create(); const MAPPINGS = { properties: { - type: { - type: 'keyword', - }, - pending: { - properties: { - title: { - type: 'text', - }, - }, - }, + pending: { properties: { title: { type: 'text' } } }, saved: { properties: { - title: { - type: 'text', - fields: { - raw: { - type: 'keyword', - }, - }, - }, - obj: { - properties: { - key1: { - type: 'text', - }, - }, - }, - }, - }, - global: { - properties: { - name: { - type: 'keyword', - }, + title: { type: 'text', fields: { raw: { type: 'keyword' } } }, + obj: { properties: { key1: { type: 'text' } } }, }, }, + // mock registry returns isMultiNamespace=true for 'shared' type + shared: { properties: { name: { type: 'keyword' } } }, + // mock registry returns isNamespaceAgnostic=true for 'global' type + global: { properties: { name: { type: 'keyword' } } }, }, }; +const ALL_TYPES = Object.keys(MAPPINGS.properties); +// get all possible subsets (combination) of all types +const ALL_TYPE_SUBSETS = ALL_TYPES.reduce( + (subsets, value) => subsets.concat(subsets.map(set => [...set, value])), + [[] as string[]] +) + .filter(x => x.length) // exclude empty set + .map(x => (x.length === 1 ? x[0] : x)); // if a subset is a single string, destructure it -// create a type clause to be used within the "should", if a namespace is specified -// the clause will ensure the namespace matches; otherwise, the clause will ensure -// that there isn't a namespace field. -const createTypeClause = (type: string, namespace?: string) => { - if (namespace) { - return { - bool: { - must: [{ term: { type } }, { term: { namespace } }], - }, - }; - } +/** + * Note: these tests cases are defined in the order they appear in the source code, for readability's sake + */ +describe('#getQueryParams', () => { + const mappings = MAPPINGS; + type Result = ReturnType; - return { - bool: { - must: [{ term: { type } }], - must_not: [{ exists: { field: 'namespace' } }], - }, - }; -}; + describe('kueryNode filter clause (query.bool.filter[...]', () => { + const expectResult = (result: Result, expected: any) => { + expect(result.query.bool.filter).toEqual(expect.arrayContaining([expected])); + }; -describe('searchDsl/queryParams', () => { - describe('no parameters', () => { - it('searches for all known types without a namespace specified', () => { - expect(getQueryParams({ mappings: MAPPINGS, registry })).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending'), - createTypeClause('saved'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, + describe('`kueryNode` parameter', () => { + it('does not include the clause when `kueryNode` is not specified', () => { + const result = getQueryParams({ mappings, registry, kueryNode: undefined }); + expect(result.query.bool.filter).toHaveLength(1); }); - }); - }); - describe('namespace', () => { - it('filters namespaced types for namespace, and ensures namespace agnostic types have no namespace', () => { - expect(getQueryParams({ mappings: MAPPINGS, registry, namespace: 'foo-namespace' })).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending', 'foo-namespace'), - createTypeClause('saved', 'foo-namespace'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, - }); - }); - }); + it('includes the specified Kuery clause', () => { + const test = (kueryNode: KueryNode) => { + const result = getQueryParams({ mappings, registry, kueryNode }); + const expected = esKuery.toElasticsearchQuery(kueryNode); + expect(result.query.bool.filter).toHaveLength(2); + expectResult(result, expected); + }; - describe('type (singular, namespaced)', () => { - it('includes a terms filter for type and namespace not being specified', () => { - expect( - getQueryParams({ mappings: MAPPINGS, registry, namespace: undefined, type: 'saved' }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved')], - minimum_should_match: 1, - }, - }, - ], - }, - }, - }); - }); - }); + const simpleClause = { + type: 'function', + function: 'is', + arguments: [ + { type: 'literal', value: 'global.name' }, + { type: 'literal', value: 'GLOBAL' }, + { type: 'literal', value: false }, + ], + } as KueryNode; + test(simpleClause); - describe('type (singular, global)', () => { - it('includes a terms filter for type and namespace not being specified', () => { - expect( - getQueryParams({ mappings: MAPPINGS, registry, namespace: undefined, type: 'global' }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('global')], - minimum_should_match: 1, + const complexClause = { + type: 'function', + function: 'and', + arguments: [ + simpleClause, + { + type: 'function', + function: 'not', + arguments: [ + { + type: 'function', + function: 'is', + arguments: [ + { type: 'literal', value: 'saved.obj.key1' }, + { type: 'literal', value: 'key' }, + { type: 'literal', value: true }, + ], }, - }, - ], - }, - }, + ], + }, + ], + } as KueryNode; + test(complexClause); }); }); }); - describe('type (plural, namespaced and global)', () => { - it('includes term filters for types and namespace not being specified', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: undefined, - type: ['saved', 'global'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - }, - }, - }); - }); - }); + describe('reference filter clause (query.bool.filter[bool.must])', () => { + describe('`hasReference` parameter', () => { + const expectResult = (result: Result, expected: any) => { + expect(result.query.bool.filter).toEqual( + expect.arrayContaining([{ bool: expect.objectContaining({ must: expected }) }]) + ); + }; - describe('namespace, type (plural, namespaced and global)', () => { - it('includes a terms filter for type and namespace not being specified', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + it('does not include the clause when `hasReference` is not specified', () => { + const result = getQueryParams({ + mappings, registry, - namespace: 'foo-namespace', - type: ['saved', 'global'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved', 'foo-namespace'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - }, - }, + hasReference: undefined, + }); + expectResult(result, undefined); }); - }); - }); - describe('search', () => { - it('includes a sqs query and all known types without a namespace specified', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + it('creates a clause with query for specified reference', () => { + const hasReference = { id: 'foo', type: 'bar' }; + const result = getQueryParams({ + mappings, registry, - namespace: undefined, - type: undefined, - search: 'us*', - }) - ).toEqual({ - query: { - bool: { - filter: [ - { + hasReference, + }); + expectResult(result, [ + { + nested: { + path: 'references', + query: { bool: { - should: [ - createTypeClause('pending'), - createTypeClause('saved'), - createTypeClause('global'), + must: [ + { term: { 'references.id': hasReference.id } }, + { term: { 'references.type': hasReference.type } }, ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'us*', - lenient: true, - fields: ['*'], }, }, - ], + }, }, - }, + ]); }); }); }); - describe('namespace, search', () => { - it('includes a sqs query and namespaced types with the namespace and global types without a namespace', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - type: undefined, - search: 'us*', - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending', 'foo-namespace'), - createTypeClause('saved', 'foo-namespace'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'us*', - lenient: true, - fields: ['*'], - }, - }, - ], - }, - }, - }); - }); - }); + describe('type filter clauses (query.bool.filter[bool.should])', () => { + describe('`type` parameter', () => { + const expectResult = (result: Result, ...types: string[]) => { + expect(result.query.bool.filter).toEqual( + expect.arrayContaining([ + { + bool: expect.objectContaining({ + should: types.map(type => ({ + bool: expect.objectContaining({ + must: expect.arrayContaining([{ term: { type } }]), + }), + })), + minimum_should_match: 1, + }), + }, + ]) + ); + }; - describe('type (plural, namespaced and global), search', () => { - it('includes a sqs query and types without a namespace', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: undefined, - type: ['saved', 'global'], - search: 'us*', - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'us*', - lenient: true, - fields: ['*'], - }, - }, - ], - }, - }, + it('searches for all known types when `type` is not specified', () => { + const result = getQueryParams({ mappings, registry, type: undefined }); + expectResult(result, ...ALL_TYPES); }); - }); - }); - describe('namespace, type (plural, namespaced and global), search', () => { - it('includes a sqs query and namespace type with a namespace and global type without a namespace', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - type: ['saved', 'global'], - search: 'us*', - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved', 'foo-namespace'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'us*', - lenient: true, - fields: ['*'], - }, - }, - ], - }, - }, + it('searches for specified type/s', () => { + const test = (typeOrTypes: string | string[]) => { + const result = getQueryParams({ + mappings, + registry, + type: typeOrTypes, + }); + const type = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; + expectResult(result, ...type); + }; + for (const typeOrTypes of ALL_TYPE_SUBSETS) { + test(typeOrTypes); + } }); }); - }); - describe('search, searchFields', () => { - it('includes all types for field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: undefined, - type: undefined, - search: 'y*', - searchFields: ['title'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending'), - createTypeClause('saved'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['pending.title', 'saved.title', 'global.title'], - }, - }, - ], - }, - }, - }); - }); - it('supports field boosting', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: undefined, - type: undefined, - search: 'y*', - searchFields: ['title^3'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending'), - createTypeClause('saved'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['pending.title^3', 'saved.title^3', 'global.title^3'], - }, - }, - ], - }, - }, + describe('`namespace` parameter', () => { + const createTypeClause = (type: string, namespace?: string) => { + if (registry.isMultiNamespace(type)) { + return { + bool: { + must: expect.arrayContaining([{ term: { namespaces: namespace ?? 'default' } }]), + must_not: [{ exists: { field: 'namespace' } }], + }, + }; + } else if (namespace && registry.isSingleNamespace(type)) { + return { + bool: { + must: expect.arrayContaining([{ term: { namespace } }]), + must_not: [{ exists: { field: 'namespaces' } }], + }, + }; + } + // isNamespaceAgnostic + return { + bool: expect.objectContaining({ + must_not: [{ exists: { field: 'namespace' } }, { exists: { field: 'namespaces' } }], + }), + }; + }; + + const expectResult = (result: Result, ...typeClauses: any) => { + expect(result.query.bool.filter).toEqual( + expect.arrayContaining([ + { bool: expect.objectContaining({ should: typeClauses, minimum_should_match: 1 }) }, + ]) + ); + }; + + const test = (namespace?: string) => { + for (const typeOrTypes of ALL_TYPE_SUBSETS) { + const result = getQueryParams({ mappings, registry, type: typeOrTypes, namespace }); + const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; + expectResult(result, ...types.map(x => createTypeClause(x, namespace))); + } + // also test with no specified type/s + const result = getQueryParams({ mappings, registry, type: undefined, namespace }); + expectResult(result, ...ALL_TYPES.map(x => createTypeClause(x, namespace))); + }; + + it('filters results with "namespace" field when `namespace` is not specified', () => { + test(undefined); }); - }); - it('supports field and multi-field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: undefined, - type: undefined, - search: 'y*', - searchFields: ['title', 'title.raw'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending'), - createTypeClause('saved'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: [ - 'pending.title', - 'saved.title', - 'global.title', - 'pending.title.raw', - 'saved.title.raw', - 'global.title.raw', - ], - }, - }, - ], - }, - }, + + it('filters results for specified namespace for appropriate type/s', () => { + test('foo-namespace'); }); }); }); - describe('namespace, search, searchFields', () => { - it('includes all types for field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + describe('search clause (query.bool.must.simple_query_string)', () => { + const search = 'foo*'; + + const expectResult = (result: Result, sqsClause: any) => { + expect(result.query.bool.must).toEqual([{ simple_query_string: sqsClause }]); + }; + + describe('`search` parameter', () => { + it('does not include clause when `search` is not specified', () => { + const result = getQueryParams({ + mappings, registry, - namespace: 'foo-namespace', - type: undefined, - search: 'y*', - searchFields: ['title'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending', 'foo-namespace'), - createTypeClause('saved', 'foo-namespace'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['pending.title', 'saved.title', 'global.title'], - }, - }, - ], - }, - }, + search: undefined, + }); + expect(result.query.bool.must).toBeUndefined(); }); - }); - it('supports field boosting', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + + it('creates a clause with query for specified search', () => { + const result = getQueryParams({ + mappings, registry, - namespace: 'foo-namespace', - type: undefined, - search: 'y*', - searchFields: ['title^3'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending', 'foo-namespace'), - createTypeClause('saved', 'foo-namespace'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['pending.title^3', 'saved.title^3', 'global.title^3'], - }, - }, - ], - }, - }, + search, + }); + expectResult(result, expect.objectContaining({ query: search })); }); }); - it('supports field and multi-field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + + describe('`searchFields` parameter', () => { + const getExpectedFields = (searchFields: string[], typeOrTypes: string | string[]) => { + const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; + return searchFields.map(x => types.map(y => `${y}.${x}`)).flat(); + }; + + const test = (searchFields: string[]) => { + for (const typeOrTypes of ALL_TYPE_SUBSETS) { + const result = getQueryParams({ + mappings, + registry, + type: typeOrTypes, + search, + searchFields, + }); + const fields = getExpectedFields(searchFields, typeOrTypes); + expectResult(result, expect.objectContaining({ fields })); + } + // also test with no specified type/s + const result = getQueryParams({ + mappings, registry, - namespace: 'foo-namespace', type: undefined, - search: 'y*', - searchFields: ['title', 'title.raw'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - createTypeClause('pending', 'foo-namespace'), - createTypeClause('saved', 'foo-namespace'), - createTypeClause('global'), - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: [ - 'pending.title', - 'saved.title', - 'global.title', - 'pending.title.raw', - 'saved.title.raw', - 'global.title.raw', - ], - }, - }, - ], - }, - }, - }); - }); - }); + search, + searchFields, + }); + const fields = getExpectedFields(searchFields, ALL_TYPES); + expectResult(result, expect.objectContaining({ fields })); + }; - describe('type (plural, namespaced and global), search, searchFields', () => { - it('includes all types for field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: undefined, - type: ['saved', 'global'], - search: 'y*', - searchFields: ['title'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['saved.title', 'global.title'], - }, - }, - ], - }, - }, - }); - }); - it('supports field boosting', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: undefined, - type: ['saved', 'global'], - search: 'y*', - searchFields: ['title^3'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['saved.title^3', 'global.title^3'], - }, - }, - ], - }, - }, - }); - }); - it('supports field and multi-field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + it('includes lenient flag and all fields when `searchFields` is not specified', () => { + const result = getQueryParams({ + mappings, registry, - namespace: undefined, - type: ['saved', 'global'], - search: 'y*', - searchFields: ['title', 'title.raw'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['saved.title', 'global.title', 'saved.title.raw', 'global.title.raw'], - }, - }, - ], - }, - }, + search, + searchFields: undefined, + }); + expectResult(result, expect.objectContaining({ lenient: true, fields: ['*'] })); }); - }); - }); - describe('namespace, type (plural, namespaced and global), search, searchFields', () => { - it('includes all types for field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - type: ['saved', 'global'], - search: 'y*', - searchFields: ['title'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved', 'foo-namespace'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['saved.title', 'global.title'], - }, - }, - ], - }, - }, - }); - }); - it('supports field boosting', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - type: ['saved', 'global'], - search: 'y*', - searchFields: ['title^3'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved', 'foo-namespace'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['saved.title^3', 'global.title^3'], - }, - }, - ], - }, - }, - }); - }); - it('supports field and multi-field', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - type: ['saved', 'global'], - search: 'y*', - searchFields: ['title', 'title.raw'], - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [createTypeClause('saved', 'foo-namespace'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['saved.title', 'global.title', 'saved.title.raw', 'global.title.raw'], - }, - }, - ], - }, - }, + it('includes specified search fields for appropriate type/s', () => { + test(['title']); }); - }); - }); - describe('type (plural, namespaced and global), search, defaultSearchOperator', () => { - it('supports defaultSearchOperator', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - type: ['saved', 'global'], - search: 'foo', - searchFields: undefined, - defaultSearchOperator: 'AND', - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - minimum_should_match: 1, - should: [ - { - bool: { - must: [ - { - term: { - type: 'saved', - }, - }, - { - term: { - namespace: 'foo-namespace', - }, - }, - ], - }, - }, - { - bool: { - must: [ - { - term: { - type: 'global', - }, - }, - ], - must_not: [ - { - exists: { - field: 'namespace', - }, - }, - ], - }, - }, - ], - }, - }, - ], - must: [ - { - simple_query_string: { - lenient: true, - fields: ['*'], - default_operator: 'AND', - query: 'foo', - }, - }, - ], - }, - }, + it('supports boosting', () => { + test(['title^3']); }); - }); - }); - describe('type (plural, namespaced and global), hasReference', () => { - it('supports hasReference', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - type: ['saved', 'global'], - search: undefined, - searchFields: undefined, - defaultSearchOperator: 'OR', - hasReference: { - type: 'bar', - id: '1', - }, - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - must: [ - { - nested: { - path: 'references', - query: { - bool: { - must: [ - { - term: { - 'references.id': '1', - }, - }, - { - term: { - 'references.type': 'bar', - }, - }, - ], - }, - }, - }, - }, - ], - should: [createTypeClause('saved', 'foo-namespace'), createTypeClause('global')], - minimum_should_match: 1, - }, - }, - ], - }, - }, + it('supports multiple fields', () => { + test(['title, title.raw']); }); }); - }); - describe('type filter', () => { - it(' with namespace', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, - registry, - namespace: 'foo-namespace', - kueryNode: { - type: 'function', - function: 'is', - arguments: [ - { type: 'literal', value: 'global.name' }, - { type: 'literal', value: 'GLOBAL' }, - { type: 'literal', value: false }, - ], - }, - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - { - match: { - 'global.name': 'GLOBAL', - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - bool: { - must: [ - { - term: { - type: 'pending', - }, - }, - { - term: { - namespace: 'foo-namespace', - }, - }, - ], - }, - }, - { - bool: { - must: [ - { - term: { - type: 'saved', - }, - }, - { - term: { - namespace: 'foo-namespace', - }, - }, - ], - }, - }, - { - bool: { - must: [ - { - term: { - type: 'global', - }, - }, - ], - must_not: [ - { - exists: { - field: 'namespace', - }, - }, - ], - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, - }); - }); - it(' with namespace and more complex filter', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + describe('`defaultSearchOperator` parameter', () => { + it('does not include default_operator when `defaultSearchOperator` is not specified', () => { + const result = getQueryParams({ + mappings, registry, - namespace: 'foo-namespace', - kueryNode: { - type: 'function', - function: 'and', - arguments: [ - { - type: 'function', - function: 'is', - arguments: [ - { type: 'literal', value: 'global.name' }, - { type: 'literal', value: 'GLOBAL' }, - { type: 'literal', value: false }, - ], - }, - { - type: 'function', - function: 'not', - arguments: [ - { - type: 'function', - function: 'is', - arguments: [ - { type: 'literal', value: 'saved.obj.key1' }, - { type: 'literal', value: 'key' }, - { type: 'literal', value: true }, - ], - }, - ], - }, - ], - }, - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - filter: [ - { - bool: { - should: [ - { - match: { - 'global.name': 'GLOBAL', - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - must_not: { - bool: { - should: [ - { - match_phrase: { - 'saved.obj.key1': 'key', - }, - }, - ], - minimum_should_match: 1, - }, - }, - }, - }, - ], - }, - }, - { - bool: { - should: [ - { - bool: { - must: [ - { - term: { - type: 'pending', - }, - }, - { - term: { - namespace: 'foo-namespace', - }, - }, - ], - }, - }, - { - bool: { - must: [ - { - term: { - type: 'saved', - }, - }, - { - term: { - namespace: 'foo-namespace', - }, - }, - ], - }, - }, - { - bool: { - must: [ - { - term: { - type: 'global', - }, - }, - ], - must_not: [ - { - exists: { - field: 'namespace', - }, - }, - ], - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - }, - }, + search, + defaultSearchOperator: undefined, + }); + expectResult(result, expect.not.objectContaining({ default_operator: expect.anything() })); }); - }); - it(' with search and searchFields', () => { - expect( - getQueryParams({ - mappings: MAPPINGS, + + it('includes specified default operator', () => { + const defaultSearchOperator = 'AND'; + const result = getQueryParams({ + mappings, registry, - namespace: 'foo-namespace', - search: 'y*', - searchFields: ['title'], - kueryNode: { - type: 'function', - function: 'is', - arguments: [ - { type: 'literal', value: 'global.name' }, - { type: 'literal', value: 'GLOBAL' }, - { type: 'literal', value: false }, - ], - }, - }) - ).toEqual({ - query: { - bool: { - filter: [ - { - bool: { - should: [ - { - match: { - 'global.name': 'GLOBAL', - }, - }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - should: [ - { - bool: { - must: [ - { - term: { - type: 'pending', - }, - }, - { - term: { - namespace: 'foo-namespace', - }, - }, - ], - }, - }, - { - bool: { - must: [ - { - term: { - type: 'saved', - }, - }, - { - term: { - namespace: 'foo-namespace', - }, - }, - ], - }, - }, - { - bool: { - must: [ - { - term: { - type: 'global', - }, - }, - ], - must_not: [ - { - exists: { - field: 'namespace', - }, - }, - ], - }, - }, - ], - minimum_should_match: 1, - }, - }, - ], - must: [ - { - simple_query_string: { - query: 'y*', - fields: ['pending.title', 'saved.title', 'global.title'], - }, - }, - ], - }, - }, + search, + defaultSearchOperator, + }); + expectResult(result, expect.objectContaining({ default_operator: defaultSearchOperator })); }); }); }); diff --git a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts index e6c06208ca1a5..967ce8bceaf84 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/query_params.ts @@ -66,18 +66,26 @@ function getClauseForType( namespace: string | undefined, type: string ) { - if (namespace && !registry.isNamespaceAgnostic(type)) { + if (registry.isMultiNamespace(type)) { + return { + bool: { + must: [{ term: { type } }, { term: { namespaces: namespace ?? 'default' } }], + must_not: [{ exists: { field: 'namespace' } }], + }, + }; + } else if (namespace && registry.isSingleNamespace(type)) { return { bool: { must: [{ term: { type } }, { term: { namespace } }], + must_not: [{ exists: { field: 'namespaces' } }], }, }; } - + // isSingleNamespace in the default namespace, or isNamespaceAgnostic return { bool: { must: [{ term: { type } }], - must_not: [{ exists: { field: 'namespace' } }], + must_not: [{ exists: { field: 'namespace' } }, { exists: { field: 'namespaces' } }], }, }; } diff --git a/src/core/server/saved_objects/service/saved_objects_client.mock.ts b/src/core/server/saved_objects/service/saved_objects_client.mock.ts index c6de9fa94291c..b209c9ca54f63 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.mock.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.mock.ts @@ -31,6 +31,8 @@ const create = () => find: jest.fn(), get: jest.fn(), update: jest.fn(), + addToNamespaces: jest.fn(), + deleteFromNamespaces: jest.fn(), } as unknown) as jest.Mocked); export const savedObjectsClientMock = { create }; diff --git a/src/core/server/saved_objects/service/saved_objects_client.test.js b/src/core/server/saved_objects/service/saved_objects_client.test.js index 1794d9ae86c17..53bb31369adbf 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.test.js +++ b/src/core/server/saved_objects/service/saved_objects_client.test.js @@ -147,3 +147,37 @@ test(`#bulkUpdate`, async () => { }); expect(result).toBe(returnValue); }); + +test(`#addToNamespaces`, async () => { + const returnValue = Symbol(); + const mockRepository = { + addToNamespaces: jest.fn().mockResolvedValue(returnValue), + }; + const client = new SavedObjectsClient(mockRepository); + + const type = Symbol(); + const id = Symbol(); + const namespaces = Symbol(); + const options = Symbol(); + const result = await client.addToNamespaces(type, id, namespaces, options); + + expect(mockRepository.addToNamespaces).toHaveBeenCalledWith(type, id, namespaces, options); + expect(result).toBe(returnValue); +}); + +test(`#deleteFromNamespaces`, async () => { + const returnValue = Symbol(); + const mockRepository = { + deleteFromNamespaces: jest.fn().mockResolvedValue(returnValue), + }; + const client = new SavedObjectsClient(mockRepository); + + const type = Symbol(); + const id = Symbol(); + const namespaces = Symbol(); + const options = Symbol(); + const result = await client.deleteFromNamespaces(type, id, namespaces, options); + + expect(mockRepository.deleteFromNamespaces).toHaveBeenCalledWith(type, id, namespaces, options); + expect(result).toBe(returnValue); +}); diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index 70d69374ba8fe..8780f07cc3091 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -107,6 +107,26 @@ export interface SavedObjectsUpdateOptions extends SavedObjectsBaseOptions { refresh?: MutatingOperationRefreshSetting; } +/** + * + * @public + */ +export interface SavedObjectsAddToNamespacesOptions extends SavedObjectsBaseOptions { + /** An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. */ + version?: string; + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; +} + +/** + * + * @public + */ +export interface SavedObjectsDeleteFromNamespacesOptions extends SavedObjectsBaseOptions { + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; +} + /** * * @public @@ -270,6 +290,40 @@ export class SavedObjectsClient { return await this._repository.update(type, id, attributes, options); } + /** + * Adds namespaces to a SavedObject + * + * @param type + * @param id + * @param namespaces + * @param options + */ + async addToNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsAddToNamespacesOptions = {} + ): Promise<{}> { + return await this._repository.addToNamespaces(type, id, namespaces, options); + } + + /** + * Removes namespaces from a SavedObject + * + * @param type + * @param id + * @param namespaces + * @param options + */ + async deleteFromNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsDeleteFromNamespacesOptions = {} + ): Promise<{}> { + return await this._repository.deleteFromNamespaces(type, id, namespaces, options); + } + /** * Bulk Updates multiple SavedObject at once * diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index f14e9d9efb5e3..9efc82603b179 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -172,6 +172,19 @@ export type MutatingOperationRefreshSetting = boolean | 'wait_for'; */ export type SavedObjectsClientContract = Pick; +/** + * The namespace type dictates how a saved object can be interacted in relation to namespaces. Each type is mutually exclusive: + * * single (default): this type of saved object is namespace-isolated, e.g., it exists in only one namespace. + * * multiple: this type of saved object is shareable, e.g., it can exist in one or more namespaces. + * * agnostic: this type of saved object is global. + * + * Note: do not write logic that uses this value directly; instead, use the appropriate accessors in the + * {@link SavedObjectTypeRegistry | type registry}. + * + * @public + */ +export type SavedObjectsNamespaceType = 'single' | 'multiple' | 'agnostic'; + /** * @remarks This is only internal for now, and will only be public when we expose the registerType API * @@ -190,9 +203,14 @@ export interface SavedObjectsType { */ hidden: boolean; /** - * Is the type global (true), or namespaced (false). + * Is the type global (true), or not (false). + * @deprecated Use `namespaceType` instead. + */ + namespaceAgnostic?: boolean; + /** + * The {@link SavedObjectsNamespaceType | namespace type} for the type. */ - namespaceAgnostic: boolean; + namespaceType?: SavedObjectsNamespaceType; /** * If defined, the type instances will be stored in the given index instead of the default one. */ @@ -329,6 +347,8 @@ export type SavedObjectLegacyMigrationFn = ( */ interface SavedObjectsLegacyTypeSchema { isNamespaceAgnostic?: boolean; + /** Cannot be used in conjunction with `isNamespaceAgnostic` */ + multiNamespace?: boolean; hidden?: boolean; indexPattern?: ((config: LegacyConfig) => string) | string; convertToAliasScript?: string; diff --git a/src/core/server/saved_objects/utils.test.ts b/src/core/server/saved_objects/utils.test.ts index 0719fe7138e8a..64bdf1771decc 100644 --- a/src/core/server/saved_objects/utils.test.ts +++ b/src/core/server/saved_objects/utils.test.ts @@ -84,6 +84,16 @@ describe('convertLegacyTypes', () => { }, { pluginId: 'pluginB', + properties: { + typeB: { + properties: { + fieldB: { type: 'text' }, + }, + }, + }, + }, + { + pluginId: 'pluginC', properties: { typeC: { properties: { @@ -92,6 +102,16 @@ describe('convertLegacyTypes', () => { }, }, }, + { + pluginId: 'pluginD', + properties: { + typeD: { + properties: { + fieldD: { type: 'text' }, + }, + }, + }, + }, ], savedObjectMigrations: {}, savedObjectSchemas: { @@ -100,6 +120,18 @@ describe('convertLegacyTypes', () => { hidden: true, isNamespaceAgnostic: true, }, + typeB: { + indexPattern: 'barBaz', + hidden: false, + multiNamespace: true, + }, + typeD: { + indexPattern: 'bazQux', + hidden: false, + // if both isNamespaceAgnostic and multiNamespace are true, the resulting namespaceType is 'agnostic' + isNamespaceAgnostic: true, + multiNamespace: true, + }, }, savedObjectValidations: {}, savedObjectsManagement: {}, @@ -372,29 +404,56 @@ describe('convertTypesToLegacySchema', () => { { name: 'typeA', hidden: false, - namespaceAgnostic: true, + namespaceType: 'agnostic', mappings: { properties: {} }, convertToAliasScript: 'some script', }, { name: 'typeB', hidden: true, - namespaceAgnostic: false, + namespaceType: 'single', indexPattern: 'myIndex', mappings: { properties: {} }, }, + { + name: 'typeC', + hidden: false, + namespaceType: 'multiple', + mappings: { properties: {} }, + }, + // deprecated test case + { + name: 'typeD', + hidden: false, + namespaceAgnostic: true, + namespaceType: 'multiple', // if namespaceAgnostic and namespaceType are both set, namespaceAgnostic takes precedence + mappings: { properties: {} }, + }, ]; expect(convertTypesToLegacySchema(types)).toEqual({ typeA: { hidden: false, isNamespaceAgnostic: true, + multiNamespace: false, convertToAliasScript: 'some script', }, typeB: { hidden: true, isNamespaceAgnostic: false, + multiNamespace: false, indexPattern: 'myIndex', }, + typeC: { + hidden: false, + isNamespaceAgnostic: false, + multiNamespace: true, + }, + // deprecated test case + typeD: { + hidden: false, + isNamespaceAgnostic: true, + multiNamespace: false, + }, }); }); }); diff --git a/src/core/server/saved_objects/utils.ts b/src/core/server/saved_objects/utils.ts index ea90efd8b9fbd..5348963812629 100644 --- a/src/core/server/saved_objects/utils.ts +++ b/src/core/server/saved_objects/utils.ts @@ -20,6 +20,7 @@ import { LegacyConfig } from '../legacy'; import { SavedObjectMigrationMap } from './migrations'; import { + SavedObjectsNamespaceType, SavedObjectsType, SavedObjectsLegacyUiExports, SavedObjectLegacyMigrationMap, @@ -48,10 +49,15 @@ export const convertLegacyTypes = ( const schema = savedObjectSchemas[type]; const migrations = savedObjectMigrations[type]; const management = savedObjectsManagement[type]; + const namespaceType = (schema?.isNamespaceAgnostic + ? 'agnostic' + : schema?.multiNamespace + ? 'multiple' + : 'single') as SavedObjectsNamespaceType; return { name: type, hidden: schema?.hidden ?? false, - namespaceAgnostic: schema?.isNamespaceAgnostic ?? false, + namespaceType, mappings, indexPattern: typeof schema?.indexPattern === 'function' @@ -76,7 +82,8 @@ export const convertTypesToLegacySchema = ( return { ...schema, [type.name]: { - isNamespaceAgnostic: type.namespaceAgnostic, + isNamespaceAgnostic: type.namespaceAgnostic || type.namespaceType === 'agnostic', + multiNamespace: !type.namespaceAgnostic && type.namespaceType === 'multiple', hidden: type.hidden, indexPattern: type.indexPattern, convertToAliasScript: type.convertToAliasScript, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index f3e3b7736d8d3..a35bca7375286 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -1003,7 +1003,7 @@ export type IsAuthenticated = (request: KibanaRequest | LegacyRequest) => boolea export type ISavedObjectsRepository = Pick; // @public -export type ISavedObjectTypeRegistry = Pick; +export type ISavedObjectTypeRegistry = Omit; // @public export type IScopedClusterClient = Pick; @@ -1643,6 +1643,7 @@ export interface SavedObject { }; id: string; migrationVersion?: SavedObjectsMigrationVersion; + namespaces?: string[]; references: SavedObjectReference[]; type: string; updated_at?: string; @@ -1687,6 +1688,12 @@ export interface SavedObjectReference { type: string; } +// @public (undocumented) +export interface SavedObjectsAddToNamespacesOptions extends SavedObjectsBaseOptions { + refresh?: MutatingOperationRefreshSetting; + version?: string; +} + // Warning: (ae-forgotten-export) The symbol "SavedObjectDoc" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Referencable" needs to be exported by the entry point index.d.ts // @@ -1754,11 +1761,13 @@ export interface SavedObjectsBulkUpdateResponse { export class SavedObjectsClient { // @internal constructor(repository: ISavedObjectsRepository); + addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>; delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; + deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; // (undocumented) static errors: typeof SavedObjectsErrorHelpers; // (undocumented) @@ -1839,6 +1848,11 @@ export interface SavedObjectsDeleteByNamespaceOptions extends SavedObjectsBaseOp refresh?: MutatingOperationRefreshSetting; } +// @public (undocumented) +export interface SavedObjectsDeleteFromNamespacesOptions extends SavedObjectsBaseOptions { + refresh?: MutatingOperationRefreshSetting; +} + // @public (undocumented) export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions { refresh?: MutatingOperationRefreshSetting; @@ -1849,6 +1863,8 @@ export class SavedObjectsErrorHelpers { // (undocumented) static createBadRequestError(reason?: string): DecoratedError; // (undocumented) + static createConflictError(type: string, id: string): DecoratedError; + // (undocumented) static createEsAutoCreateIndexError(): DecoratedError; // (undocumented) static createGenericNotFoundError(type?: string | null, id?: string | null): DecoratedError; @@ -1861,6 +1877,8 @@ export class SavedObjectsErrorHelpers { // (undocumented) static decorateConflictError(error: Error, reason?: string): DecoratedError; // (undocumented) + static decorateEsCannotExecuteScriptError(error: Error, reason?: string): DecoratedError; + // (undocumented) static decorateEsUnavailableError(error: Error, reason?: string): DecoratedError; // (undocumented) static decorateForbiddenError(error: Error, reason?: string): DecoratedError; @@ -1877,6 +1895,8 @@ export class SavedObjectsErrorHelpers { // (undocumented) static isEsAutoCreateIndexError(error: Error | DecoratedError): boolean; // (undocumented) + static isEsCannotExecuteScriptError(error: Error | DecoratedError): boolean; + // (undocumented) static isEsUnavailableError(error: Error | DecoratedError): boolean; // (undocumented) static isForbiddenError(error: Error | DecoratedError): boolean; @@ -2106,6 +2126,9 @@ export interface SavedObjectsMigrationVersion { [pluginName: string]: string; } +// @public +export type SavedObjectsNamespaceType = 'single' | 'multiple' | 'agnostic'; + // @public export interface SavedObjectsRawDoc { // (undocumented) @@ -2124,6 +2147,7 @@ export interface SavedObjectsRawDoc { // @public (undocumented) export class SavedObjectsRepository { + addToNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsAddToNamespacesOptions): Promise<{}>; bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; @@ -2134,6 +2158,7 @@ export class SavedObjectsRepository { static createRepository(migrator: KibanaMigrator, typeRegistry: SavedObjectTypeRegistry, indexName: string, callCluster: APICaller, extraTypes?: string[], injectedConstructor?: any): ISavedObjectsRepository; delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; deleteByNamespace(namespace: string, options?: SavedObjectsDeleteByNamespaceOptions): Promise; + deleteFromNamespaces(type: string, id: string, namespaces: string[], options?: SavedObjectsDeleteFromNamespacesOptions): Promise<{}>; // (undocumented) find({ search, defaultSearchOperator, searchFields, hasReference, page, perPage, sortField, sortOrder, fields, namespace, type, filter, }: SavedObjectsFindOptions): Promise>; get(type: string, id: string, options?: SavedObjectsBaseOptions): Promise>; @@ -2175,7 +2200,11 @@ export class SavedObjectsSchema { // (undocumented) isHiddenType(type: string): boolean; // (undocumented) + isMultiNamespace(type: string): boolean; + // (undocumented) isNamespaceAgnostic(type: string): boolean; + // (undocumented) + isSingleNamespace(type: string): boolean; } // @public @@ -2224,7 +2253,9 @@ export interface SavedObjectsType { mappings: SavedObjectsTypeMappingDefinition; migrations?: SavedObjectMigrationMap; name: string; - namespaceAgnostic: boolean; + // @deprecated + namespaceAgnostic?: boolean; + namespaceType?: SavedObjectsNamespaceType; } // @public @@ -2269,7 +2300,9 @@ export class SavedObjectTypeRegistry { getType(type: string): SavedObjectsType | undefined; isHidden(type: string): boolean; isImportableAndExportable(type: string): boolean; + isMultiNamespace(type: string): boolean; isNamespaceAgnostic(type: string): boolean; + isSingleNamespace(type: string): boolean; registerType(type: SavedObjectsType): void; } diff --git a/src/core/types/saved_objects.ts b/src/core/types/saved_objects.ts index d3faab6c557cd..04aaacc3cf31a 100644 --- a/src/core/types/saved_objects.ts +++ b/src/core/types/saved_objects.ts @@ -96,4 +96,6 @@ export interface SavedObject { references: SavedObjectReference[]; /** {@inheritdoc SavedObjectsMigrationVersion} */ migrationVersion?: SavedObjectsMigrationVersion; + /** Namespace(s) that this saved object exists in. This attribute is only used for multi-namespace saved object types. */ + namespaces?: string[]; } diff --git a/test/api_integration/apis/saved_objects/bulk_create.js b/test/api_integration/apis/saved_objects/bulk_create.js index afa5153336ff7..2d77fdf266793 100644 --- a/test/api_integration/apis/saved_objects/bulk_create.js +++ b/test/api_integration/apis/saved_objects/bulk_create.js @@ -58,7 +58,9 @@ export default function({ getService }) { type: 'visualization', id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', error: { - message: 'version conflict, document already exists', + error: 'Conflict', + message: + 'Saved object [visualization/dd7caf20-9efd-11e7-acb3-3dab96693fab] conflict', statusCode: 409, }, }, diff --git a/test/api_integration/apis/saved_objects/bulk_get.js b/test/api_integration/apis/saved_objects/bulk_get.js index 984ac781d3e46..67e511f2bf548 100644 --- a/test/api_integration/apis/saved_objects/bulk_get.js +++ b/test/api_integration/apis/saved_objects/bulk_get.js @@ -80,8 +80,9 @@ export default function({ getService }) { id: 'does not exist', type: 'dashboard', error: { + error: 'Not Found', + message: 'Saved object [dashboard/does not exist] not found', statusCode: 404, - message: 'Not found', }, }, { @@ -123,24 +124,28 @@ export default function({ getService }) { id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', type: 'visualization', error: { + error: 'Not Found', + message: + 'Saved object [visualization/dd7caf20-9efd-11e7-acb3-3dab96693fab] not found', statusCode: 404, - message: 'Not found', }, }, { id: 'does not exist', type: 'dashboard', error: { + error: 'Not Found', + message: 'Saved object [dashboard/does not exist] not found', statusCode: 404, - message: 'Not found', }, }, { id: '7.0.0-alpha1', type: 'config', error: { + error: 'Not Found', + message: 'Saved object [config/7.0.0-alpha1] not found', statusCode: 404, - message: 'Not found', }, }, ], diff --git a/test/api_integration/apis/saved_objects/export.js b/test/api_integration/apis/saved_objects/export.js index fc9ab8140869c..9558e82880deb 100644 --- a/test/api_integration/apis/saved_objects/export.js +++ b/test/api_integration/apis/saved_objects/export.js @@ -170,8 +170,9 @@ export default function({ getService }) { id: '1', type: 'dashboard', error: { + error: 'Not Found', + message: 'Saved object [dashboard/1] not found', statusCode: 404, - message: 'Not found', }, }, ], diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts index f691e62b9352a..2caf3a7055df9 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.test.ts @@ -10,14 +10,16 @@ import { SavedObjectsClientContract } from 'src/core/server'; import { EncryptedSavedObjectsService } from '../crypto'; import { EncryptedSavedObjectsClientWrapper } from './encrypted_saved_objects_client_wrapper'; -import { savedObjectsClientMock } from 'src/core/server/mocks'; +import { savedObjectsClientMock, savedObjectsTypeRegistryMock } from 'src/core/server/mocks'; import { encryptedSavedObjectsServiceMock } from '../crypto/index.mock'; let wrapper: EncryptedSavedObjectsClientWrapper; let mockBaseClient: jest.Mocked; +let mockBaseTypeRegistry: ReturnType; let encryptedSavedObjectsServiceMockInstance: jest.Mocked; beforeEach(() => { mockBaseClient = savedObjectsClientMock.create(); + mockBaseTypeRegistry = savedObjectsTypeRegistryMock.create(); encryptedSavedObjectsServiceMockInstance = encryptedSavedObjectsServiceMock.create([ { type: 'known-type', @@ -28,6 +30,7 @@ beforeEach(() => { wrapper = new EncryptedSavedObjectsClientWrapper({ service: encryptedSavedObjectsServiceMockInstance, baseClient: mockBaseClient, + baseTypeRegistry: mockBaseTypeRegistry, } as any); }); @@ -91,35 +94,50 @@ describe('#create', () => { ); }); - it('uses `namespace` to encrypt attributes if it is specified', async () => { - const attributes = { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' }; - const options = { overwrite: true, namespace: 'some-namespace' }; - const mockedResponse = { - id: 'uuid-v4-id', - type: 'known-type', - attributes: { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, - references: [], - }; + describe('namespace', () => { + const doTest = async (namespace: string, expectNamespaceInDescriptor: boolean) => { + const attributes = { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' }; + const options = { overwrite: true, namespace }; + const mockedResponse = { + id: 'uuid-v4-id', + type: 'known-type', + attributes: { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, + references: [], + }; - mockBaseClient.create.mockResolvedValue(mockedResponse); + mockBaseClient.create.mockResolvedValue(mockedResponse); - expect(await wrapper.create('known-type', attributes, options)).toEqual({ - ...mockedResponse, - attributes: { attrOne: 'one', attrThree: 'three' }, - }); + expect(await wrapper.create('known-type', attributes, options)).toEqual({ + ...mockedResponse, + attributes: { attrOne: 'one', attrThree: 'three' }, + }); - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( - { type: 'known-type', id: 'uuid-v4-id', namespace: 'some-namespace' }, - { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } - ); + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( + { + type: 'known-type', + id: 'uuid-v4-id', + namespace: expectNamespaceInDescriptor ? namespace : undefined, + }, + { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } + ); - expect(mockBaseClient.create).toHaveBeenCalledTimes(1); - expect(mockBaseClient.create).toHaveBeenCalledWith( - 'known-type', - { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, - { id: 'uuid-v4-id', overwrite: true, namespace: 'some-namespace' } - ); + expect(mockBaseClient.create).toHaveBeenCalledTimes(1); + expect(mockBaseClient.create).toHaveBeenCalledWith( + 'known-type', + { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, + { id: 'uuid-v4-id', overwrite: true, namespace } + ); + }; + + it('uses `namespace` to encrypt attributes if it is specified when type is single-namespace', async () => { + await doTest('some-namespace', true); + }); + + it('does not use `namespace` to encrypt attributes if it is specified when type is not single-namespace', async () => { + mockBaseTypeRegistry.isSingleNamespace.mockReturnValue(false); + await doTest('some-namespace', false); + }); }); it('fails if base client fails', async () => { @@ -190,14 +208,13 @@ describe('#bulkCreate', () => { it('fails if ID is specified for registered type', async () => { const attributes = { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' }; - const options = { namespace: 'some-namespace' }; const bulkCreateParams = [ { id: 'some-id', type: 'known-type', attributes }, { type: 'unknown-type', attributes }, ]; - await expect(wrapper.bulkCreate(bulkCreateParams, options)).rejects.toThrowError( + await expect(wrapper.bulkCreate(bulkCreateParams)).rejects.toThrowError( 'Predefined IDs are not allowed for saved objects with encrypted attributes.' ); @@ -257,39 +274,57 @@ describe('#bulkCreate', () => { ); }); - it('uses `namespace` to encrypt attributes if it is specified', async () => { - const attributes = { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' }; - const options = { namespace: 'some-namespace' }; - const mockedResponse = { - saved_objects: [{ id: 'uuid-v4-id', type: 'known-type', attributes, references: [] }], - }; + describe('namespace', () => { + const doTest = async (namespace: string, expectNamespaceInDescriptor: boolean) => { + const attributes = { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' }; + const options = { namespace }; + const mockedResponse = { + saved_objects: [{ id: 'uuid-v4-id', type: 'known-type', attributes, references: [] }], + }; + + mockBaseClient.bulkCreate.mockResolvedValue(mockedResponse); + + const bulkCreateParams = [{ type: 'known-type', attributes }]; + await expect(wrapper.bulkCreate(bulkCreateParams, options)).resolves.toEqual({ + saved_objects: [ + { + ...mockedResponse.saved_objects[0], + attributes: { attrOne: 'one', attrThree: 'three' }, + }, + ], + }); - mockBaseClient.bulkCreate.mockResolvedValue(mockedResponse); + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( + { + type: 'known-type', + id: 'uuid-v4-id', + namespace: expectNamespaceInDescriptor ? namespace : undefined, + }, + { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } + ); + + expect(mockBaseClient.bulkCreate).toHaveBeenCalledTimes(1); + expect(mockBaseClient.bulkCreate).toHaveBeenCalledWith( + [ + { + ...bulkCreateParams[0], + id: 'uuid-v4-id', + attributes: { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, + }, + ], + options + ); + }; - const bulkCreateParams = [{ type: 'known-type', attributes }]; - await expect(wrapper.bulkCreate(bulkCreateParams, options)).resolves.toEqual({ - saved_objects: [ - { ...mockedResponse.saved_objects[0], attributes: { attrOne: 'one', attrThree: 'three' } }, - ], + it('uses `namespace` to encrypt attributes if it is specified when type is single-namespace', async () => { + await doTest('some-namespace', true); }); - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( - { type: 'known-type', id: 'uuid-v4-id', namespace: 'some-namespace' }, - { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } - ); - - expect(mockBaseClient.bulkCreate).toHaveBeenCalledTimes(1); - expect(mockBaseClient.bulkCreate).toHaveBeenCalledWith( - [ - { - ...bulkCreateParams[0], - id: 'uuid-v4-id', - attributes: { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, - }, - ], - options - ); + it('does not use `namespace` to encrypt attributes if it is specified when type is not single-namespace', async () => { + mockBaseTypeRegistry.isSingleNamespace.mockReturnValue(false); + await doTest('some-namespace', false); + }); }); it('fails if base client fails', async () => { @@ -432,63 +467,79 @@ describe('#bulkUpdate', () => { ); }); - it('uses `namespace` to encrypt attributes if it is specified', async () => { - const docs = [ - { - id: 'some-id', - type: 'known-type', - attributes: { - attrOne: 'one', - attrSecret: 'secret', - attrThree: 'three', - }, - version: 'some-version', - }, - ]; - - mockBaseClient.bulkUpdate.mockResolvedValue({ - saved_objects: docs.map(doc => ({ ...doc, references: undefined })), - }); - - await expect(wrapper.bulkUpdate(docs, { namespace: 'some-namespace' })).resolves.toEqual({ - saved_objects: [ + describe('namespace', () => { + const doTest = async (namespace: string, expectNamespaceInDescriptor: boolean) => { + const docs = [ { id: 'some-id', type: 'known-type', attributes: { attrOne: 'one', + attrSecret: 'secret', attrThree: 'three', }, version: 'some-version', - references: undefined, }, - ], - }); - - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( - { type: 'known-type', id: 'some-id', namespace: 'some-namespace' }, - { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } - ); + ]; + const options = { namespace }; + + mockBaseClient.bulkUpdate.mockResolvedValue({ + saved_objects: docs.map(doc => ({ ...doc, references: undefined })), + }); + + await expect(wrapper.bulkUpdate(docs, options)).resolves.toEqual({ + saved_objects: [ + { + id: 'some-id', + type: 'known-type', + attributes: { + attrOne: 'one', + attrThree: 'three', + }, + version: 'some-version', + references: undefined, + }, + ], + }); - expect(mockBaseClient.bulkUpdate).toHaveBeenCalledTimes(1); - expect(mockBaseClient.bulkUpdate).toHaveBeenCalledWith( - [ + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( { - id: 'some-id', type: 'known-type', - attributes: { - attrOne: 'one', - attrSecret: '*secret*', - attrThree: 'three', + id: 'some-id', + namespace: expectNamespaceInDescriptor ? namespace : undefined, + }, + { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } + ); + + expect(mockBaseClient.bulkUpdate).toHaveBeenCalledTimes(1); + expect(mockBaseClient.bulkUpdate).toHaveBeenCalledWith( + [ + { + id: 'some-id', + type: 'known-type', + attributes: { + attrOne: 'one', + attrSecret: '*secret*', + attrThree: 'three', + }, + version: 'some-version', + + references: undefined, }, - version: 'some-version', + ], + options + ); + }; - references: undefined, - }, - ], - { namespace: 'some-namespace' } - ); + it('uses `namespace` to encrypt attributes if it is specified when type is single-namespace', async () => { + await doTest('some-namespace', true); + }); + + it('does not use `namespace` to encrypt attributes if it is specified when type is not single-namespace', async () => { + mockBaseTypeRegistry.isSingleNamespace.mockReturnValue(false); + await doTest('some-namespace', false); + }); }); it('fails if base client fails', async () => { @@ -871,31 +922,46 @@ describe('#update', () => { ); }); - it('uses `namespace` to encrypt attributes if it is specified', async () => { - const attributes = { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' }; - const options = { version: 'some-version', namespace: 'some-namespace' }; - const mockedResponse = { id: 'some-id', type: 'known-type', attributes, references: [] }; + describe('namespace', () => { + const doTest = async (namespace: string, expectNamespaceInDescriptor: boolean) => { + const attributes = { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' }; + const options = { version: 'some-version', namespace }; + const mockedResponse = { id: 'some-id', type: 'known-type', attributes, references: [] }; - mockBaseClient.update.mockResolvedValue(mockedResponse); + mockBaseClient.update.mockResolvedValue(mockedResponse); - await expect(wrapper.update('known-type', 'some-id', attributes, options)).resolves.toEqual({ - ...mockedResponse, - attributes: { attrOne: 'one', attrThree: 'three' }, - }); + await expect(wrapper.update('known-type', 'some-id', attributes, options)).resolves.toEqual({ + ...mockedResponse, + attributes: { attrOne: 'one', attrThree: 'three' }, + }); - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); - expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( - { type: 'known-type', id: 'some-id', namespace: 'some-namespace' }, - { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } - ); + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledTimes(1); + expect(encryptedSavedObjectsServiceMockInstance.encryptAttributes).toHaveBeenCalledWith( + { + type: 'known-type', + id: 'some-id', + namespace: expectNamespaceInDescriptor ? namespace : undefined, + }, + { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' } + ); + + expect(mockBaseClient.update).toHaveBeenCalledTimes(1); + expect(mockBaseClient.update).toHaveBeenCalledWith( + 'known-type', + 'some-id', + { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, + options + ); + }; - expect(mockBaseClient.update).toHaveBeenCalledTimes(1); - expect(mockBaseClient.update).toHaveBeenCalledWith( - 'known-type', - 'some-id', - { attrOne: 'one', attrSecret: '*secret*', attrThree: 'three' }, - options - ); + it('uses `namespace` to encrypt attributes if it is specified when type is single-namespace', async () => { + await doTest('some-namespace', true); + }); + + it('does not use `namespace` to encrypt attributes if it is specified when type is not single-namespace', async () => { + mockBaseTypeRegistry.isSingleNamespace.mockReturnValue(false); + await doTest('some-namespace', false); + }); }); it('fails if base client fails', async () => { diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts index b4f1de52c9ce3..e8197536d29d9 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/encrypted_saved_objects_client_wrapper.ts @@ -19,11 +19,15 @@ import { SavedObjectsFindResponse, SavedObjectsUpdateOptions, SavedObjectsUpdateResponse, + SavedObjectsAddToNamespacesOptions, + SavedObjectsDeleteFromNamespacesOptions, + ISavedObjectTypeRegistry, } from 'src/core/server'; import { EncryptedSavedObjectsService } from '../crypto'; interface EncryptedSavedObjectsClientOptions { baseClient: SavedObjectsClientContract; + baseTypeRegistry: ISavedObjectTypeRegistry; service: Readonly; } @@ -41,6 +45,10 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon public readonly errors = options.baseClient.errors ) {} + // only include namespace in AAD descriptor if the specified type is single-namespace + private getDescriptorNamespace = (type: string, namespace?: string) => + this.options.baseTypeRegistry.isSingleNamespace(type) ? namespace : undefined; + public async create( type: string, attributes: T = {} as T, @@ -60,11 +68,12 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon } const id = generateID(); + const namespace = this.getDescriptorNamespace(type, options.namespace); return this.stripEncryptedAttributesFromResponse( await this.options.baseClient.create( type, await this.options.service.encryptAttributes( - { type, id, namespace: options.namespace }, + { type, id, namespace }, attributes as Record ), { ...options, id } @@ -95,11 +104,12 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon } const id = generateID(); + const namespace = this.getDescriptorNamespace(object.type, options?.namespace); return { ...object, id, attributes: await this.options.service.encryptAttributes( - { type: object.type, id, namespace: options && options.namespace }, + { type: object.type, id, namespace }, object.attributes as Record ), } as SavedObjectsBulkCreateObject; @@ -124,10 +134,11 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon if (!this.options.service.isRegistered(type)) { return object; } + const namespace = this.getDescriptorNamespace(type, options?.namespace); return { ...object, attributes: await this.options.service.encryptAttributes( - { type, id, namespace: options && options.namespace }, + { type, id, namespace }, attributes ), }; @@ -173,20 +184,35 @@ export class EncryptedSavedObjectsClientWrapper implements SavedObjectsClientCon if (!this.options.service.isRegistered(type)) { return await this.options.baseClient.update(type, id, attributes, options); } - + const namespace = this.getDescriptorNamespace(type, options?.namespace); return this.stripEncryptedAttributesFromResponse( await this.options.baseClient.update( type, id, - await this.options.service.encryptAttributes( - { type, id, namespace: options && options.namespace }, - attributes - ), + await this.options.service.encryptAttributes({ type, id, namespace }, attributes), options ) ); } + public async addToNamespaces( + type: string, + id: string, + namespaces: string[], + options?: SavedObjectsAddToNamespacesOptions + ) { + return await this.options.baseClient.addToNamespaces(type, id, namespaces, options); + } + + public async deleteFromNamespaces( + type: string, + id: string, + namespaces: string[], + options?: SavedObjectsDeleteFromNamespacesOptions + ) { + return await this.options.baseClient.deleteFromNamespaces(type, id, namespaces, options); + } + /** * Strips encrypted attributes from any non-bulk Saved Objects API response. If type isn't * registered, response is returned as is. diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts index c76477cd8da43..10599ae3a1798 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts @@ -40,7 +40,8 @@ export function setupSavedObjects({ savedObjects.addClientWrapper( Number.MAX_SAFE_INTEGER, 'encryptedSavedObjects', - ({ client: baseClient }) => new EncryptedSavedObjectsClientWrapper({ baseClient, service }) + ({ client: baseClient, typeRegistry: baseTypeRegistry }) => + new EncryptedSavedObjectsClientWrapper({ baseClient, baseTypeRegistry, service }) ); const internalRepositoryPromise = getStartServices().then(([core]) => diff --git a/x-pack/plugins/security/server/audit/audit_logger.test.ts b/x-pack/plugins/security/server/audit/audit_logger.test.ts index 01cde02b7dfdd..f7ee210a21a74 100644 --- a/x-pack/plugins/security/server/audit/audit_logger.test.ts +++ b/x-pack/plugins/security/server/audit/audit_logger.test.ts @@ -18,25 +18,46 @@ describe(`#savedObjectsAuthorizationFailure`, () => { const username = 'foo-user'; const action = 'foo-action'; const types = ['foo-type-1', 'foo-type-2']; - const missing = [`saved_object:${types[0]}/foo-action`, `saved_object:${types[1]}/foo-action`]; + const spaceIds = ['foo-space', 'bar-space']; + const missing = [ + { + spaceId: 'foo-space', + privilege: `saved_object:${types[0]}/${action}`, + }, + { + spaceId: 'foo-space', + privilege: `saved_object:${types[1]}/${action}`, + }, + ]; const args = { foo: 'bar', baz: 'quz', }; - securityAuditLogger.savedObjectsAuthorizationFailure(username, action, types, missing, args); + securityAuditLogger.savedObjectsAuthorizationFailure( + username, + action, + types, + spaceIds, + missing, + args + ); expect(auditLogger.log).toHaveBeenCalledWith( 'saved_objects_authorization_failure', - expect.stringContaining(`${username} unauthorized to ${action}`), + expect.any(String), { username, action, types, + spaceIds, missing, args, } ); + expect(auditLogger.log.mock.calls[0][1]).toMatchInlineSnapshot( + `"foo-user unauthorized to [foo-action] [foo-type-1,foo-type-2] in [foo-space,bar-space]: missing [(foo-space)saved_object:foo-type-1/foo-action,(foo-space)saved_object:foo-type-2/foo-action]"` + ); }); }); @@ -47,22 +68,27 @@ describe(`#savedObjectsAuthorizationSuccess`, () => { const username = 'foo-user'; const action = 'foo-action'; const types = ['foo-type-1', 'foo-type-2']; + const spaceIds = ['foo-space', 'bar-space']; const args = { foo: 'bar', baz: 'quz', }; - securityAuditLogger.savedObjectsAuthorizationSuccess(username, action, types, args); + securityAuditLogger.savedObjectsAuthorizationSuccess(username, action, types, spaceIds, args); expect(auditLogger.log).toHaveBeenCalledWith( 'saved_objects_authorization_success', - expect.stringContaining(`${username} authorized to ${action}`), + expect.any(String), { username, action, types, + spaceIds, args, } ); + expect(auditLogger.log.mock.calls[0][1]).toMatchInlineSnapshot( + `"foo-user authorized to [foo-action] [foo-type-1,foo-type-2] in [foo-space,bar-space]"` + ); }); }); diff --git a/x-pack/plugins/security/server/audit/audit_logger.ts b/x-pack/plugins/security/server/audit/audit_logger.ts index df8df35f97b49..40b525b5d2188 100644 --- a/x-pack/plugins/security/server/audit/audit_logger.ts +++ b/x-pack/plugins/security/server/audit/audit_logger.ts @@ -13,16 +13,23 @@ export class SecurityAuditLogger { username: string, action: string, types: string[], - missing: string[], + spaceIds: string[], + missing: Array<{ spaceId?: string; privilege: string }>, args?: Record ) { + const typesString = types.join(','); + const spacesString = spaceIds.length ? ` in [${spaceIds.join(',')}]` : ''; + const missingString = missing + .map(({ spaceId, privilege }) => `${spaceId ? `(${spaceId})` : ''}${privilege}`) + .join(','); this.getAuditLogger().log( 'saved_objects_authorization_failure', - `${username} unauthorized to ${action} ${types.join(',')}, missing ${missing.join(',')}`, + `${username} unauthorized to [${action}] [${typesString}]${spacesString}: missing [${missingString}]`, { username, action, types, + spaceIds, missing, args, } @@ -33,15 +40,19 @@ export class SecurityAuditLogger { username: string, action: string, types: string[], + spaceIds: string[], args?: Record ) { + const typesString = types.join(','); + const spacesString = spaceIds.length ? ` in [${spaceIds.join(',')}]` : ''; this.getAuditLogger().log( 'saved_objects_authorization_success', - `${username} authorized to ${action} ${types.join(',')}`, + `${username} authorized to [${action}] [${typesString}]${spacesString}`, { username, action, types, + spaceIds, args, } ); diff --git a/x-pack/plugins/security/server/authorization/__snapshots__/check_privileges.test.ts.snap b/x-pack/plugins/security/server/authorization/__snapshots__/check_privileges.test.ts.snap deleted file mode 100644 index 1212c2cd6a5cb..0000000000000 --- a/x-pack/plugins/security/server/authorization/__snapshots__/check_privileges.test.ts.snap +++ /dev/null @@ -1,27 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`#atSpace throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`; - -exports[`#atSpace with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because ["saved_object:bar-type/get" is not allowed]]]]`; - -exports[`#atSpace with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "saved_object:foo-type/get" fails because ["saved_object:foo-type/get" is required]]]]]`; - -exports[`#atSpaces throws error when Elasticsearch returns malformed response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]`; - -exports[`#atSpaces throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`; - -exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when an a space is missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]`; - -exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]`; - -exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when an extra space is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because ["space:space_3" is not allowed]]]`; - -exports[`#atSpaces with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]`; - -exports[`#globally throws error when Elasticsearch returns malformed response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]`; - -exports[`#globally throws error when checking for login and user has login but doesn't have version 1`] = `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]`; - -exports[`#globally with a malformed Elasticsearch response throws a validation error when an extra privilege is present in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because ["saved_object:bar-type/get" is not allowed]]]]`; - -exports[`#globally with a malformed Elasticsearch response throws a validation error when privileges are missing in the response 1`] = `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "saved_object:foo-type/get" fails because ["saved_object:foo-type/get" is required]]]]]`; diff --git a/x-pack/plugins/security/server/authorization/check_privileges.test.ts b/x-pack/plugins/security/server/authorization/check_privileges.test.ts index 8c1241937892e..a64c5d509ca11 100644 --- a/x-pack/plugins/security/server/authorization/check_privileges.test.ts +++ b/x-pack/plugins/security/server/authorization/check_privileges.test.ts @@ -31,123 +31,121 @@ const createMockClusterClient = (response: any) => { }; describe('#atSpace', () => { - const checkPrivilegesAtSpaceTest = ( - description: string, - options: { - spaceId: string; - privilegeOrPrivileges: string | string[]; - esHasPrivilegesResponse: HasPrivilegesResponse; - expectedResult?: any; - expectErrorThrown?: any; + const checkPrivilegesAtSpaceTest = async (options: { + spaceId: string; + privilegeOrPrivileges: string | string[]; + esHasPrivilegesResponse: HasPrivilegesResponse; + }) => { + const { mockClusterClient, mockScopedClusterClient } = createMockClusterClient( + options.esHasPrivilegesResponse + ); + const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory( + mockActions, + mockClusterClient, + application + ); + const request = httpServerMock.createKibanaRequest(); + const checkPrivileges = checkPrivilegesWithRequest(request); + + let actualResult; + let errorThrown = null; + try { + actualResult = await checkPrivileges.atSpace(options.spaceId, options.privilegeOrPrivileges); + } catch (err) { + errorThrown = err; } - ) => { - test(description, async () => { - const { mockClusterClient, mockScopedClusterClient } = createMockClusterClient( - options.esHasPrivilegesResponse - ); - const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory( - mockActions, - mockClusterClient, - application - ); - const request = httpServerMock.createKibanaRequest(); - const checkPrivileges = checkPrivilegesWithRequest(request); - - let actualResult; - let errorThrown = null; - try { - actualResult = await checkPrivileges.atSpace( - options.spaceId, - options.privilegeOrPrivileges - ); - } catch (err) { - errorThrown = err; - } - expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith( - 'shield.hasPrivileges', - { - body: { - applications: [ - { - application, - resources: [`space:${options.spaceId}`], - privileges: uniq([ - mockActions.version, - mockActions.login, - ...(Array.isArray(options.privilegeOrPrivileges) - ? options.privilegeOrPrivileges - : [options.privilegeOrPrivileges]), - ]), - }, - ], + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', { + body: { + applications: [ + { + application, + resources: [`space:${options.spaceId}`], + privileges: uniq([ + mockActions.version, + mockActions.login, + ...(Array.isArray(options.privilegeOrPrivileges) + ? options.privilegeOrPrivileges + : [options.privilegeOrPrivileges]), + ]), }, - } - ); - - if (options.expectedResult) { - expect(errorThrown).toBeNull(); - expect(actualResult).toEqual(options.expectedResult); - } - - if (options.expectErrorThrown) { - expect(errorThrown).toMatchSnapshot(); - } + ], + }, }); + + if (errorThrown) { + return errorThrown; + } + return actualResult; }; - checkPrivilegesAtSpaceTest('successful when checking for login and user has login', { - spaceId: 'space_1', - privilegeOrPrivileges: mockActions.login, - esHasPrivilegesResponse: { - has_all_requested: true, - username: 'foo-username', - application: { - [application]: { - 'space:space_1': { - [mockActions.login]: true, - [mockActions.version]: true, + test('successful when checking for login and user has login', async () => { + const result = await checkPrivilegesAtSpaceTest({ + spaceId: 'space_1', + privilegeOrPrivileges: mockActions.login, + esHasPrivilegesResponse: { + has_all_requested: true, + username: 'foo-username', + application: { + [application]: { + 'space:space_1': { + [mockActions.login]: true, + [mockActions.version]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: true, - username: 'foo-username', - privileges: { - [mockActions.login]: true, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": true, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "mock-action:login", + "resource": "space_1", + }, + ], + "username": "foo-username", + } + `); }); - checkPrivilegesAtSpaceTest(`failure when checking for login and user doesn't have login`, { - spaceId: 'space_1', - privilegeOrPrivileges: mockActions.login, - esHasPrivilegesResponse: { - has_all_requested: false, - username: 'foo-username', - application: { - [application]: { - 'space:space_1': { - [mockActions.login]: false, - [mockActions.version]: true, + test(`failure when checking for login and user doesn't have login`, async () => { + const result = await checkPrivilegesAtSpaceTest({ + spaceId: 'space_1', + privilegeOrPrivileges: mockActions.login, + esHasPrivilegesResponse: { + has_all_requested: false, + username: 'foo-username', + application: { + [application]: { + 'space:space_1': { + [mockActions.login]: false, + [mockActions.version]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - privileges: { - [mockActions.login]: false, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": false, + "privilege": "mock-action:login", + "resource": "space_1", + }, + ], + "username": "foo-username", + } + `); }); - checkPrivilegesAtSpaceTest( - `throws error when checking for login and user has login but doesn't have version`, - { + test(`throws error when checking for login and user has login but doesn't have version`, async () => { + const result = await checkPrivilegesAtSpaceTest({ spaceId: 'space_1', privilegeOrPrivileges: mockActions.login, esHasPrivilegesResponse: { @@ -162,74 +160,99 @@ describe('#atSpace', () => { }, }, }, - expectErrorThrown: true, - } - ); - - checkPrivilegesAtSpaceTest(`successful when checking for two actions and the user has both`, { - spaceId: 'space_1', - privilegeOrPrivileges: [ - `saved_object:${savedObjectTypes[0]}/get`, - `saved_object:${savedObjectTypes[1]}/get`, - ], - esHasPrivilegesResponse: { - has_all_requested: true, - username: 'foo-username', - application: { - [application]: { - 'space:space_1': { - [mockActions.login]: true, - [mockActions.version]: true, - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + }); + expect(result).toMatchInlineSnapshot( + `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]` + ); + }); + + test(`successful when checking for two actions and the user has both`, async () => { + const result = await checkPrivilegesAtSpaceTest({ + spaceId: 'space_1', + privilegeOrPrivileges: [ + `saved_object:${savedObjectTypes[0]}/get`, + `saved_object:${savedObjectTypes[1]}/get`, + ], + esHasPrivilegesResponse: { + has_all_requested: true, + username: 'foo-username', + application: { + [application]: { + 'space:space_1': { + [mockActions.login]: true, + [mockActions.version]: true, + [`saved_object:${savedObjectTypes[0]}/get`]: true, + [`saved_object:${savedObjectTypes[1]}/get`]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: true, - username: 'foo-username', - privileges: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": true, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": "space_1", + }, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": "space_1", + }, + ], + "username": "foo-username", + } + `); }); - checkPrivilegesAtSpaceTest(`failure when checking for two actions and the user has only one`, { - spaceId: 'space_1', - privilegeOrPrivileges: [ - `saved_object:${savedObjectTypes[0]}/get`, - `saved_object:${savedObjectTypes[1]}/get`, - ], - esHasPrivilegesResponse: { - has_all_requested: false, - username: 'foo-username', - application: { - [application]: { - 'space:space_1': { - [mockActions.login]: true, - [mockActions.version]: true, - [`saved_object:${savedObjectTypes[0]}/get`]: false, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + test(`failure when checking for two actions and the user has only one`, async () => { + const result = await checkPrivilegesAtSpaceTest({ + spaceId: 'space_1', + privilegeOrPrivileges: [ + `saved_object:${savedObjectTypes[0]}/get`, + `saved_object:${savedObjectTypes[1]}/get`, + ], + esHasPrivilegesResponse: { + has_all_requested: false, + username: 'foo-username', + application: { + [application]: { + 'space:space_1': { + [mockActions.login]: true, + [mockActions.version]: true, + [`saved_object:${savedObjectTypes[0]}/get`]: false, + [`saved_object:${savedObjectTypes[1]}/get`]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - privileges: { - [`saved_object:${savedObjectTypes[0]}/get`]: false, - [`saved_object:${savedObjectTypes[1]}/get`]: true, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": false, + "privilege": "saved_object:foo-type/get", + "resource": "space_1", + }, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": "space_1", + }, + ], + "username": "foo-username", + } + `); }); describe('with a malformed Elasticsearch response', () => { - checkPrivilegesAtSpaceTest( - `throws a validation error when an extra privilege is present in the response`, - { + test(`throws a validation error when an extra privilege is present in the response`, async () => { + const result = await checkPrivilegesAtSpaceTest({ spaceId: 'space_1', privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { @@ -246,13 +269,14 @@ describe('#atSpace', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because ["saved_object:bar-type/get" is not allowed]]]]` + ); + }); - checkPrivilegesAtSpaceTest( - `throws a validation error when privileges are missing in the response`, - { + test(`throws a validation error when privileges are missing in the response`, async () => { + const result = await checkPrivilegesAtSpaceTest({ spaceId: 'space_1', privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { @@ -267,82 +291,69 @@ describe('#atSpace', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "saved_object:foo-type/get" fails because ["saved_object:foo-type/get" is required]]]]]` + ); + }); }); }); describe('#atSpaces', () => { - const checkPrivilegesAtSpacesTest = ( - description: string, - options: { - spaceIds: string[]; - privilegeOrPrivileges: string | string[]; - esHasPrivilegesResponse: HasPrivilegesResponse; - expectedResult?: any; - expectErrorThrown?: any; - } - ) => { - test(description, async () => { - const { mockClusterClient, mockScopedClusterClient } = createMockClusterClient( - options.esHasPrivilegesResponse - ); - const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory( - mockActions, - mockClusterClient, - application - ); - const request = httpServerMock.createKibanaRequest(); - const checkPrivileges = checkPrivilegesWithRequest(request); - - let actualResult; - let errorThrown = null; - try { - actualResult = await checkPrivileges.atSpaces( - options.spaceIds, - options.privilegeOrPrivileges - ); - } catch (err) { - errorThrown = err; - } + const checkPrivilegesAtSpacesTest = async (options: { + spaceIds: string[]; + privilegeOrPrivileges: string | string[]; + esHasPrivilegesResponse: HasPrivilegesResponse; + }) => { + const { mockClusterClient, mockScopedClusterClient } = createMockClusterClient( + options.esHasPrivilegesResponse + ); + const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory( + mockActions, + mockClusterClient, + application + ); + const request = httpServerMock.createKibanaRequest(); + const checkPrivileges = checkPrivilegesWithRequest(request); - expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith( - 'shield.hasPrivileges', - { - body: { - applications: [ - { - application, - resources: options.spaceIds.map(spaceId => `space:${spaceId}`), - privileges: uniq([ - mockActions.version, - mockActions.login, - ...(Array.isArray(options.privilegeOrPrivileges) - ? options.privilegeOrPrivileges - : [options.privilegeOrPrivileges]), - ]), - }, - ], - }, - } + let actualResult; + let errorThrown = null; + try { + actualResult = await checkPrivileges.atSpaces( + options.spaceIds, + options.privilegeOrPrivileges ); + } catch (err) { + errorThrown = err; + } - if (options.expectedResult) { - expect(errorThrown).toBeNull(); - expect(actualResult).toEqual(options.expectedResult); - } - - if (options.expectErrorThrown) { - expect(errorThrown).toMatchSnapshot(); - } + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', { + body: { + applications: [ + { + application, + resources: options.spaceIds.map(spaceId => `space:${spaceId}`), + privileges: uniq([ + mockActions.version, + mockActions.login, + ...(Array.isArray(options.privilegeOrPrivileges) + ? options.privilegeOrPrivileges + : [options.privilegeOrPrivileges]), + ]), + }, + ], + }, }); + + if (errorThrown) { + return errorThrown; + } + return actualResult; }; - checkPrivilegesAtSpacesTest( - 'successful when checking for login and user has login at both spaces', - { + test('successful when checking for login and user has login at both spaces', async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: mockActions.login, esHasPrivilegesResponse: { @@ -361,24 +372,29 @@ describe('#atSpaces', () => { }, }, }, - expectedResult: { - hasAllRequested: true, - username: 'foo-username', - spacePrivileges: { - space_1: { - [mockActions.login]: true, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": true, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "mock-action:login", + "resource": "space_1", }, - space_2: { - [mockActions.login]: true, + Object { + "authorized": true, + "privilege": "mock-action:login", + "resource": "space_2", }, - }, - }, - } - ); + ], + "username": "foo-username", + } + `); + }); - checkPrivilegesAtSpacesTest( - 'failure when checking for login and user has login at only one space', - { + test('failure when checking for login and user has login at only one space', async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: mockActions.login, esHasPrivilegesResponse: { @@ -397,24 +413,29 @@ describe('#atSpaces', () => { }, }, }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - spacePrivileges: { - space_1: { - [mockActions.login]: true, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "mock-action:login", + "resource": "space_1", }, - space_2: { - [mockActions.login]: false, + Object { + "authorized": false, + "privilege": "mock-action:login", + "resource": "space_2", }, - }, - }, - } - ); + ], + "username": "foo-username", + } + `); + }); - checkPrivilegesAtSpacesTest( - `throws error when checking for login and user has login but doesn't have version`, - { + test(`throws error when checking for login and user has login but doesn't have version`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: mockActions.login, esHasPrivilegesResponse: { @@ -433,38 +454,43 @@ describe('#atSpaces', () => { }, }, }, - expectErrorThrown: true, - } - ); - - checkPrivilegesAtSpacesTest(`throws error when Elasticsearch returns malformed response`, { - spaceIds: ['space_1', 'space_2'], - privilegeOrPrivileges: [ - `saved_object:${savedObjectTypes[0]}/get`, - `saved_object:${savedObjectTypes[1]}/get`, - ], - esHasPrivilegesResponse: { - has_all_requested: true, - username: 'foo-username', - application: { - [application]: { - 'space:space_1': { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, - }, - 'space:space_2': { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + }); + expect(result).toMatchInlineSnapshot( + `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]` + ); + }); + + test(`throws error when Elasticsearch returns malformed response`, async () => { + const result = await checkPrivilegesAtSpacesTest({ + spaceIds: ['space_1', 'space_2'], + privilegeOrPrivileges: [ + `saved_object:${savedObjectTypes[0]}/get`, + `saved_object:${savedObjectTypes[1]}/get`, + ], + esHasPrivilegesResponse: { + has_all_requested: true, + username: 'foo-username', + application: { + [application]: { + 'space:space_1': { + [`saved_object:${savedObjectTypes[0]}/get`]: true, + [`saved_object:${savedObjectTypes[1]}/get`]: true, + }, + 'space:space_2': { + [`saved_object:${savedObjectTypes[0]}/get`]: true, + [`saved_object:${savedObjectTypes[1]}/get`]: true, + }, }, }, }, - }, - expectErrorThrown: true, + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_1" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]` + ); }); - checkPrivilegesAtSpacesTest( - `successful when checking for two actions at two spaces and user has it all`, - { + test(`successful when checking for two actions at two spaces and user has it all`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [ `saved_object:${savedObjectTypes[0]}/get`, @@ -490,26 +516,39 @@ describe('#atSpaces', () => { }, }, }, - expectedResult: { - hasAllRequested: true, - username: 'foo-username', - spacePrivileges: { - space_1: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": true, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": "space_1", }, - space_2: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": "space_1", }, - }, - }, - } - ); + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": "space_2", + }, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": "space_2", + }, + ], + "username": "foo-username", + } + `); + }); - checkPrivilegesAtSpacesTest( - `failure when checking for two actions at two spaces and user has one action at one space`, - { + test(`failure when checking for two actions at two spaces and user has one action at one space`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [ `saved_object:${savedObjectTypes[0]}/get`, @@ -535,26 +574,39 @@ describe('#atSpaces', () => { }, }, }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - spacePrivileges: { - space_1: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: false, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": "space_1", }, - space_2: { - [`saved_object:${savedObjectTypes[0]}/get`]: false, - [`saved_object:${savedObjectTypes[1]}/get`]: false, + Object { + "authorized": false, + "privilege": "saved_object:bar-type/get", + "resource": "space_1", }, - }, - }, - } - ); + Object { + "authorized": false, + "privilege": "saved_object:foo-type/get", + "resource": "space_2", + }, + Object { + "authorized": false, + "privilege": "saved_object:bar-type/get", + "resource": "space_2", + }, + ], + "username": "foo-username", + } + `); + }); - checkPrivilegesAtSpacesTest( - `failure when checking for two actions at two spaces and user has two actions at one space`, - { + test(`failure when checking for two actions at two spaces and user has two actions at one space`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [ `saved_object:${savedObjectTypes[0]}/get`, @@ -580,26 +632,39 @@ describe('#atSpaces', () => { }, }, }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - spacePrivileges: { - space_1: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": "space_1", }, - space_2: { - [`saved_object:${savedObjectTypes[0]}/get`]: false, - [`saved_object:${savedObjectTypes[1]}/get`]: false, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": "space_1", }, - }, - }, - } - ); + Object { + "authorized": false, + "privilege": "saved_object:foo-type/get", + "resource": "space_2", + }, + Object { + "authorized": false, + "privilege": "saved_object:bar-type/get", + "resource": "space_2", + }, + ], + "username": "foo-username", + } + `); + }); - checkPrivilegesAtSpacesTest( - `failure when checking for two actions at two spaces and user has two actions at one space & one action at the other`, - { + test(`failure when checking for two actions at two spaces and user has two actions at one space & one action at the other`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [ `saved_object:${savedObjectTypes[0]}/get`, @@ -625,27 +690,40 @@ describe('#atSpaces', () => { }, }, }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - spacePrivileges: { - space_1: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": "space_1", }, - space_2: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: false, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": "space_1", }, - }, - }, - } - ); + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": "space_2", + }, + Object { + "authorized": false, + "privilege": "saved_object:bar-type/get", + "resource": "space_2", + }, + ], + "username": "foo-username", + } + `); + }); describe('with a malformed Elasticsearch response', () => { - checkPrivilegesAtSpacesTest( - `throws a validation error when an extra privilege is present in the response`, - { + test(`throws a validation error when an extra privilege is present in the response`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { @@ -668,13 +746,14 @@ describe('#atSpaces', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]` + ); + }); - checkPrivilegesAtSpacesTest( - `throws a validation error when privileges are missing in the response`, - { + test(`throws a validation error when privileges are missing in the response`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { @@ -695,13 +774,14 @@ describe('#atSpaces', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]` + ); + }); - checkPrivilegesAtSpacesTest( - `throws a validation error when an extra space is present in the response`, - { + test(`throws a validation error when an extra space is present in the response`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { @@ -727,13 +807,14 @@ describe('#atSpaces', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because ["space:space_3" is not allowed]]]` + ); + }); - checkPrivilegesAtSpacesTest( - `throws a validation error when an a space is missing in the response`, - { + test(`throws a validation error when an a space is missing in the response`, async () => { + const result = await checkPrivilegesAtSpacesTest({ spaceIds: ['space_1', 'space_2'], privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { @@ -749,124 +830,127 @@ describe('#atSpaces', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "space:space_2" fails because ["space:space_2" is required]]]]` + ); + }); }); }); describe('#globally', () => { - const checkPrivilegesGloballyTest = ( - description: string, - options: { - privilegeOrPrivileges: string | string[]; - esHasPrivilegesResponse: HasPrivilegesResponse; - expectedResult?: any; - expectErrorThrown?: any; + const checkPrivilegesGloballyTest = async (options: { + privilegeOrPrivileges: string | string[]; + esHasPrivilegesResponse: HasPrivilegesResponse; + }) => { + const { mockClusterClient, mockScopedClusterClient } = createMockClusterClient( + options.esHasPrivilegesResponse + ); + const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory( + mockActions, + mockClusterClient, + application + ); + const request = httpServerMock.createKibanaRequest(); + const checkPrivileges = checkPrivilegesWithRequest(request); + + let actualResult; + let errorThrown = null; + try { + actualResult = await checkPrivileges.globally(options.privilegeOrPrivileges); + } catch (err) { + errorThrown = err; } - ) => { - test(description, async () => { - const { mockClusterClient, mockScopedClusterClient } = createMockClusterClient( - options.esHasPrivilegesResponse - ); - const checkPrivilegesWithRequest = checkPrivilegesWithRequestFactory( - mockActions, - mockClusterClient, - application - ); - const request = httpServerMock.createKibanaRequest(); - const checkPrivileges = checkPrivilegesWithRequest(request); - - let actualResult; - let errorThrown = null; - try { - actualResult = await checkPrivileges.globally(options.privilegeOrPrivileges); - } catch (err) { - errorThrown = err; - } - expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request); - expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith( - 'shield.hasPrivileges', - { - body: { - applications: [ - { - application, - resources: [GLOBAL_RESOURCE], - privileges: uniq([ - mockActions.version, - mockActions.login, - ...(Array.isArray(options.privilegeOrPrivileges) - ? options.privilegeOrPrivileges - : [options.privilegeOrPrivileges]), - ]), - }, - ], + expect(mockClusterClient.asScoped).toHaveBeenCalledWith(request); + expect(mockScopedClusterClient.callAsCurrentUser).toHaveBeenCalledWith('shield.hasPrivileges', { + body: { + applications: [ + { + application, + resources: [GLOBAL_RESOURCE], + privileges: uniq([ + mockActions.version, + mockActions.login, + ...(Array.isArray(options.privilegeOrPrivileges) + ? options.privilegeOrPrivileges + : [options.privilegeOrPrivileges]), + ]), }, - } - ); - - if (options.expectedResult) { - expect(errorThrown).toBeNull(); - expect(actualResult).toEqual(options.expectedResult); - } - - if (options.expectErrorThrown) { - expect(errorThrown).toMatchSnapshot(); - } + ], + }, }); + + if (errorThrown) { + return errorThrown; + } + return actualResult; }; - checkPrivilegesGloballyTest('successful when checking for login and user has login', { - privilegeOrPrivileges: mockActions.login, - esHasPrivilegesResponse: { - has_all_requested: true, - username: 'foo-username', - application: { - [application]: { - [GLOBAL_RESOURCE]: { - [mockActions.login]: true, - [mockActions.version]: true, + test('successful when checking for login and user has login', async () => { + const result = await checkPrivilegesGloballyTest({ + privilegeOrPrivileges: mockActions.login, + esHasPrivilegesResponse: { + has_all_requested: true, + username: 'foo-username', + application: { + [application]: { + [GLOBAL_RESOURCE]: { + [mockActions.login]: true, + [mockActions.version]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: true, - username: 'foo-username', - privileges: { - [mockActions.login]: true, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": true, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "mock-action:login", + "resource": undefined, + }, + ], + "username": "foo-username", + } + `); }); - checkPrivilegesGloballyTest(`failure when checking for login and user doesn't have login`, { - privilegeOrPrivileges: mockActions.login, - esHasPrivilegesResponse: { - has_all_requested: false, - username: 'foo-username', - application: { - [application]: { - [GLOBAL_RESOURCE]: { - [mockActions.login]: false, - [mockActions.version]: true, + test(`failure when checking for login and user doesn't have login`, async () => { + const result = await checkPrivilegesGloballyTest({ + privilegeOrPrivileges: mockActions.login, + esHasPrivilegesResponse: { + has_all_requested: false, + username: 'foo-username', + application: { + [application]: { + [GLOBAL_RESOURCE]: { + [mockActions.login]: false, + [mockActions.version]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - privileges: { - [mockActions.login]: false, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": false, + "privilege": "mock-action:login", + "resource": undefined, + }, + ], + "username": "foo-username", + } + `); }); - checkPrivilegesGloballyTest( - `throws error when checking for login and user has login but doesn't have version`, - { + test(`throws error when checking for login and user has login but doesn't have version`, async () => { + const result = await checkPrivilegesGloballyTest({ privilegeOrPrivileges: mockActions.login, esHasPrivilegesResponse: { has_all_requested: false, @@ -880,92 +964,121 @@ describe('#globally', () => { }, }, }, - expectErrorThrown: true, - } - ); - - checkPrivilegesGloballyTest(`throws error when Elasticsearch returns malformed response`, { - privilegeOrPrivileges: [ - `saved_object:${savedObjectTypes[0]}/get`, - `saved_object:${savedObjectTypes[1]}/get`, - ], - esHasPrivilegesResponse: { - has_all_requested: false, - username: 'foo-username', - application: { - [application]: { - [GLOBAL_RESOURCE]: { - [`saved_object:${savedObjectTypes[0]}/get`]: false, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + }); + expect(result).toMatchInlineSnapshot( + `[Error: Multiple versions of Kibana are running against the same Elasticsearch cluster, unable to authorize user.]` + ); + }); + + test(`throws error when Elasticsearch returns malformed response`, async () => { + const result = await checkPrivilegesGloballyTest({ + privilegeOrPrivileges: [ + `saved_object:${savedObjectTypes[0]}/get`, + `saved_object:${savedObjectTypes[1]}/get`, + ], + esHasPrivilegesResponse: { + has_all_requested: false, + username: 'foo-username', + application: { + [application]: { + [GLOBAL_RESOURCE]: { + [`saved_object:${savedObjectTypes[0]}/get`]: false, + [`saved_object:${savedObjectTypes[1]}/get`]: true, + }, }, }, }, - }, - expectErrorThrown: true, + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "mock-action:version" fails because ["mock-action:version" is required]]]]]` + ); }); - checkPrivilegesGloballyTest(`successful when checking for two actions and the user has both`, { - privilegeOrPrivileges: [ - `saved_object:${savedObjectTypes[0]}/get`, - `saved_object:${savedObjectTypes[1]}/get`, - ], - esHasPrivilegesResponse: { - has_all_requested: true, - username: 'foo-username', - application: { - [application]: { - [GLOBAL_RESOURCE]: { - [mockActions.login]: true, - [mockActions.version]: true, - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + test(`successful when checking for two actions and the user has both`, async () => { + const result = await checkPrivilegesGloballyTest({ + privilegeOrPrivileges: [ + `saved_object:${savedObjectTypes[0]}/get`, + `saved_object:${savedObjectTypes[1]}/get`, + ], + esHasPrivilegesResponse: { + has_all_requested: true, + username: 'foo-username', + application: { + [application]: { + [GLOBAL_RESOURCE]: { + [mockActions.login]: true, + [mockActions.version]: true, + [`saved_object:${savedObjectTypes[0]}/get`]: true, + [`saved_object:${savedObjectTypes[1]}/get`]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: true, - username: 'foo-username', - privileges: { - [`saved_object:${savedObjectTypes[0]}/get`]: true, - [`saved_object:${savedObjectTypes[1]}/get`]: true, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": true, + "privileges": Array [ + Object { + "authorized": true, + "privilege": "saved_object:foo-type/get", + "resource": undefined, + }, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": undefined, + }, + ], + "username": "foo-username", + } + `); }); - checkPrivilegesGloballyTest(`failure when checking for two actions and the user has only one`, { - privilegeOrPrivileges: [ - `saved_object:${savedObjectTypes[0]}/get`, - `saved_object:${savedObjectTypes[1]}/get`, - ], - esHasPrivilegesResponse: { - has_all_requested: false, - username: 'foo-username', - application: { - [application]: { - [GLOBAL_RESOURCE]: { - [mockActions.login]: true, - [mockActions.version]: true, - [`saved_object:${savedObjectTypes[0]}/get`]: false, - [`saved_object:${savedObjectTypes[1]}/get`]: true, + test(`failure when checking for two actions and the user has only one`, async () => { + const result = await checkPrivilegesGloballyTest({ + privilegeOrPrivileges: [ + `saved_object:${savedObjectTypes[0]}/get`, + `saved_object:${savedObjectTypes[1]}/get`, + ], + esHasPrivilegesResponse: { + has_all_requested: false, + username: 'foo-username', + application: { + [application]: { + [GLOBAL_RESOURCE]: { + [mockActions.login]: true, + [mockActions.version]: true, + [`saved_object:${savedObjectTypes[0]}/get`]: false, + [`saved_object:${savedObjectTypes[1]}/get`]: true, + }, }, }, }, - }, - expectedResult: { - hasAllRequested: false, - username: 'foo-username', - privileges: { - [`saved_object:${savedObjectTypes[0]}/get`]: false, - [`saved_object:${savedObjectTypes[1]}/get`]: true, - }, - }, + }); + expect(result).toMatchInlineSnapshot(` + Object { + "hasAllRequested": false, + "privileges": Array [ + Object { + "authorized": false, + "privilege": "saved_object:foo-type/get", + "resource": undefined, + }, + Object { + "authorized": true, + "privilege": "saved_object:bar-type/get", + "resource": undefined, + }, + ], + "username": "foo-username", + } + `); }); describe('with a malformed Elasticsearch response', () => { - checkPrivilegesGloballyTest( - `throws a validation error when an extra privilege is present in the response`, - { + test(`throws a validation error when an extra privilege is present in the response`, async () => { + const result = await checkPrivilegesGloballyTest({ privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { has_all_requested: false, @@ -981,13 +1094,14 @@ describe('#globally', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because ["saved_object:bar-type/get" is not allowed]]]]` + ); + }); - checkPrivilegesGloballyTest( - `throws a validation error when privileges are missing in the response`, - { + test(`throws a validation error when privileges are missing in the response`, async () => { + const result = await checkPrivilegesGloballyTest({ privilegeOrPrivileges: [`saved_object:${savedObjectTypes[0]}/get`], esHasPrivilegesResponse: { has_all_requested: false, @@ -1001,8 +1115,10 @@ describe('#globally', () => { }, }, }, - expectErrorThrown: true, - } - ); + }); + expect(result).toMatchInlineSnapshot( + `[Error: Invalid response received from Elasticsearch has_privilege endpoint. ValidationError: child "application" fails because [child "kibana-our_application" fails because [child "*" fails because [child "saved_object:foo-type/get" fails because ["saved_object:foo-type/get" is required]]]]]` + ); + }); }); }); diff --git a/x-pack/plugins/security/server/authorization/check_privileges.ts b/x-pack/plugins/security/server/authorization/check_privileges.ts index 3ef7a8f29a0bf..177a49d6defe9 100644 --- a/x-pack/plugins/security/server/authorization/check_privileges.ts +++ b/x-pack/plugins/security/server/authorization/check_privileges.ts @@ -16,32 +16,17 @@ interface CheckPrivilegesActions { version: string; } -interface CheckPrivilegesAtResourcesResponse { +export interface CheckPrivilegesResponse { hasAllRequested: boolean; username: string; - resourcePrivileges: { - [resource: string]: { - [privilege: string]: boolean; - }; - }; -} - -export interface CheckPrivilegesAtResourceResponse { - hasAllRequested: boolean; - username: string; - privileges: { - [privilege: string]: boolean; - }; -} - -export interface CheckPrivilegesAtSpacesResponse { - hasAllRequested: boolean; - username: string; - spacePrivileges: { - [spaceId: string]: { - [privilege: string]: boolean; - }; - }; + privileges: Array<{ + /** + * If this attribute is undefined, this element is a privilege for the global resource. + */ + resource?: string; + privilege: string; + authorized: boolean; + }>; } export type CheckPrivilegesWithRequest = (request: KibanaRequest) => CheckPrivileges; @@ -50,12 +35,12 @@ export interface CheckPrivileges { atSpace( spaceId: string, privilegeOrPrivileges: string | string[] - ): Promise; + ): Promise; atSpaces( spaceIds: string[], privilegeOrPrivileges: string | string[] - ): Promise; - globally(privilegeOrPrivileges: string | string[]): Promise; + ): Promise; + globally(privilegeOrPrivileges: string | string[]): Promise; } export function checkPrivilegesWithRequestFactory( @@ -75,7 +60,7 @@ export function checkPrivilegesWithRequestFactory( const checkPrivilegesAtResources = async ( resources: string[], privilegeOrPrivileges: string | string[] - ): Promise => { + ): Promise => { const privileges = Array.isArray(privilegeOrPrivileges) ? privilegeOrPrivileges : [privilegeOrPrivileges]; @@ -106,55 +91,43 @@ export function checkPrivilegesWithRequestFactory( ); } + // we need to filter out the non requested privileges from the response + const resourcePrivileges = transform(applicationPrivilegesResponse, (result, value, key) => { + result[key!] = pick(value, privileges); + }) as HasPrivilegesResponseApplication; + const privilegeArray = Object.entries(resourcePrivileges) + .map(([key, val]) => { + // we need to turn the resource responses back into the space ids + const resource = + key !== GLOBAL_RESOURCE ? ResourceSerializer.deserializeSpaceResource(key!) : undefined; + return Object.entries(val).map(([privilege, authorized]) => ({ + resource, + privilege, + authorized, + })); + }) + .flat(); + return { hasAllRequested: hasPrivilegesResponse.has_all_requested, username: hasPrivilegesResponse.username, - // we need to filter out the non requested privileges from the response - resourcePrivileges: transform(applicationPrivilegesResponse, (result, value, key) => { - result[key!] = pick(value, privileges); - }), - }; - }; - - const checkPrivilegesAtResource = async ( - resource: string, - privilegeOrPrivileges: string | string[] - ) => { - const { hasAllRequested, username, resourcePrivileges } = await checkPrivilegesAtResources( - [resource], - privilegeOrPrivileges - ); - return { - hasAllRequested, - username, - privileges: resourcePrivileges[resource], + privileges: privilegeArray, }; }; return { async atSpace(spaceId: string, privilegeOrPrivileges: string | string[]) { const spaceResource = ResourceSerializer.serializeSpaceResource(spaceId); - return await checkPrivilegesAtResource(spaceResource, privilegeOrPrivileges); + return await checkPrivilegesAtResources([spaceResource], privilegeOrPrivileges); }, async atSpaces(spaceIds: string[], privilegeOrPrivileges: string | string[]) { const spaceResources = spaceIds.map(spaceId => ResourceSerializer.serializeSpaceResource(spaceId) ); - const { hasAllRequested, username, resourcePrivileges } = await checkPrivilegesAtResources( - spaceResources, - privilegeOrPrivileges - ); - return { - hasAllRequested, - username, - // we need to turn the resource responses back into the space ids - spacePrivileges: transform(resourcePrivileges, (result, value, key) => { - result[ResourceSerializer.deserializeSpaceResource(key!)] = value; - }), - }; + return await checkPrivilegesAtResources(spaceResources, privilegeOrPrivileges); }, async globally(privilegeOrPrivileges: string | string[]) { - return await checkPrivilegesAtResource(GLOBAL_RESOURCE, privilegeOrPrivileges); + return await checkPrivilegesAtResources([GLOBAL_RESOURCE], privilegeOrPrivileges); }, }; }; diff --git a/x-pack/plugins/security/server/authorization/check_privileges_dynamically.ts b/x-pack/plugins/security/server/authorization/check_privileges_dynamically.ts index 0377dd06eb669..6014bad739e77 100644 --- a/x-pack/plugins/security/server/authorization/check_privileges_dynamically.ts +++ b/x-pack/plugins/security/server/authorization/check_privileges_dynamically.ts @@ -6,11 +6,11 @@ import { KibanaRequest } from '../../../../../src/core/server'; import { SpacesService } from '../plugin'; -import { CheckPrivilegesAtResourceResponse, CheckPrivilegesWithRequest } from './check_privileges'; +import { CheckPrivilegesResponse, CheckPrivilegesWithRequest } from './check_privileges'; export type CheckPrivilegesDynamically = ( privilegeOrPrivileges: string | string[] -) => Promise; +) => Promise; export type CheckPrivilegesDynamicallyWithRequest = ( request: KibanaRequest diff --git a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts index 4618e8e6641fc..43b3824500579 100644 --- a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts +++ b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.test.ts @@ -7,57 +7,113 @@ import { checkSavedObjectsPrivilegesWithRequestFactory } from './check_saved_objects_privileges'; import { httpServerMock } from '../../../../../src/core/server/mocks'; +import { CheckPrivileges, CheckPrivilegesWithRequest } from './check_privileges'; +import { SpacesService } from '../plugin'; -test(`checkPrivileges.atSpace when spaces is enabled`, async () => { - const expectedResult = Symbol(); - const spaceId = 'foo-space'; - const mockCheckPrivileges = { - atSpace: jest.fn().mockReturnValue(expectedResult), - }; - const mockCheckPrivilegesWithRequest = jest.fn().mockReturnValue(mockCheckPrivileges); - const request = httpServerMock.createKibanaRequest(); - const privilegeOrPrivileges = ['foo', 'bar']; - const mockSpacesService = { - getSpaceId: jest.fn(), - namespaceToSpaceId: jest.fn().mockReturnValue(spaceId), - }; +let mockCheckPrivileges: jest.Mocked; +let mockCheckPrivilegesWithRequest: jest.Mocked; +let mockSpacesService: jest.Mocked | undefined; +const request = httpServerMock.createKibanaRequest(); - const checkSavedObjectsPrivileges = checkSavedObjectsPrivilegesWithRequestFactory( +const createFactory = () => + checkSavedObjectsPrivilegesWithRequestFactory( mockCheckPrivilegesWithRequest, () => mockSpacesService )(request); - const namespace = 'foo'; - - const result = await checkSavedObjectsPrivileges(privilegeOrPrivileges, namespace); +beforeEach(() => { + mockCheckPrivileges = { + atSpace: jest.fn(), + atSpaces: jest.fn(), + globally: jest.fn(), + }; + mockCheckPrivilegesWithRequest = jest.fn().mockReturnValue(mockCheckPrivileges); - expect(result).toBe(expectedResult); - expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); - expect(mockCheckPrivileges.atSpace).toHaveBeenCalledWith(spaceId, privilegeOrPrivileges); - expect(mockSpacesService.namespaceToSpaceId).toBeCalledWith(namespace); + mockSpacesService = { + getSpaceId: jest.fn(), + namespaceToSpaceId: jest.fn().mockImplementation((namespace: string) => `${namespace}-id`), + }; }); -test(`checkPrivileges.globally when spaces is disabled`, async () => { - const expectedResult = Symbol(); - const mockCheckPrivileges = { - globally: jest.fn().mockReturnValue(expectedResult), - }; - const mockCheckPrivilegesWithRequest = jest.fn().mockReturnValue(mockCheckPrivileges); +describe('#checkSavedObjectsPrivileges', () => { + const actions = ['foo', 'bar']; + const namespace1 = 'baz'; + const namespace2 = 'qux'; - const request = httpServerMock.createKibanaRequest(); + describe('when checking multiple namespaces', () => { + const namespaces = [namespace1, namespace2]; - const privilegeOrPrivileges = ['foo', 'bar']; + test(`throws an error when Spaces is disabled`, async () => { + mockSpacesService = undefined; + const checkSavedObjectsPrivileges = createFactory(); - const checkSavedObjectsPrivileges = checkSavedObjectsPrivilegesWithRequestFactory( - mockCheckPrivilegesWithRequest, - () => undefined - )(request); + await expect( + checkSavedObjectsPrivileges(actions, namespaces) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Can't check saved object privileges for multiple namespaces if Spaces is disabled"` + ); + }); + + test(`throws an error when using an empty namespaces array`, async () => { + const checkSavedObjectsPrivileges = createFactory(); + + await expect( + checkSavedObjectsPrivileges(actions, []) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Can't check saved object privileges for 0 namespaces"` + ); + }); + + test(`uses checkPrivileges.atSpaces when spaces is enabled`, async () => { + const expectedResult = Symbol(); + mockCheckPrivileges.atSpaces.mockReturnValue(expectedResult as any); + const checkSavedObjectsPrivileges = createFactory(); + + const result = await checkSavedObjectsPrivileges(actions, namespaces); + + expect(result).toBe(expectedResult); + expect(mockSpacesService!.namespaceToSpaceId).toHaveBeenCalledTimes(2); + expect(mockSpacesService!.namespaceToSpaceId).toHaveBeenNthCalledWith(1, namespace1); + expect(mockSpacesService!.namespaceToSpaceId).toHaveBeenNthCalledWith(2, namespace2); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledTimes(1); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); + expect(mockCheckPrivileges.atSpaces).toHaveBeenCalledTimes(1); + const spaceIds = mockSpacesService!.namespaceToSpaceId.mock.results.map(x => x.value); + expect(mockCheckPrivileges.atSpaces).toHaveBeenCalledWith(spaceIds, actions); + }); + }); + + describe('when checking a single namespace', () => { + test(`uses checkPrivileges.atSpace when Spaces is enabled`, async () => { + const expectedResult = Symbol(); + mockCheckPrivileges.atSpace.mockReturnValue(expectedResult as any); + const checkSavedObjectsPrivileges = createFactory(); + + const result = await checkSavedObjectsPrivileges(actions, namespace1); + + expect(result).toBe(expectedResult); + expect(mockSpacesService!.namespaceToSpaceId).toHaveBeenCalledTimes(1); + expect(mockSpacesService!.namespaceToSpaceId).toHaveBeenCalledWith(namespace1); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledTimes(1); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); + expect(mockCheckPrivileges.atSpace).toHaveBeenCalledTimes(1); + const spaceId = mockSpacesService!.namespaceToSpaceId.mock.results[0].value; + expect(mockCheckPrivileges.atSpace).toHaveBeenCalledWith(spaceId, actions); + }); - const namespace = 'foo'; + test(`uses checkPrivileges.globally when Spaces is disabled`, async () => { + const expectedResult = Symbol(); + mockCheckPrivileges.globally.mockReturnValue(expectedResult as any); + mockSpacesService = undefined; + const checkSavedObjectsPrivileges = createFactory(); - const result = await checkSavedObjectsPrivileges(privilegeOrPrivileges, namespace); + const result = await checkSavedObjectsPrivileges(actions, namespace1); - expect(result).toBe(expectedResult); - expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); - expect(mockCheckPrivileges.globally).toHaveBeenCalledWith(privilegeOrPrivileges); + expect(result).toBe(expectedResult); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledTimes(1); + expect(mockCheckPrivilegesWithRequest).toHaveBeenCalledWith(request); + expect(mockCheckPrivileges.globally).toHaveBeenCalledTimes(1); + expect(mockCheckPrivileges.globally).toHaveBeenCalledWith(actions); + }); + }); }); diff --git a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts index 02958fe265efa..43140143a1773 100644 --- a/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts +++ b/x-pack/plugins/security/server/authorization/check_saved_objects_privileges.ts @@ -6,32 +6,44 @@ import { KibanaRequest } from '../../../../../src/core/server'; import { SpacesService } from '../plugin'; -import { CheckPrivilegesAtResourceResponse, CheckPrivilegesWithRequest } from './check_privileges'; +import { CheckPrivilegesWithRequest, CheckPrivilegesResponse } from './check_privileges'; export type CheckSavedObjectsPrivilegesWithRequest = ( request: KibanaRequest ) => CheckSavedObjectsPrivileges; + export type CheckSavedObjectsPrivileges = ( actions: string | string[], - namespace?: string -) => Promise; + namespaceOrNamespaces?: string | string[] +) => Promise; export const checkSavedObjectsPrivilegesWithRequestFactory = ( checkPrivilegesWithRequest: CheckPrivilegesWithRequest, getSpacesService: () => SpacesService | undefined ): CheckSavedObjectsPrivilegesWithRequest => { - return function checkSavedObjectsPrivilegesWithRequest(request: KibanaRequest) { + return function checkSavedObjectsPrivilegesWithRequest( + request: KibanaRequest + ): CheckSavedObjectsPrivileges { return async function checkSavedObjectsPrivileges( actions: string | string[], - namespace?: string + namespaceOrNamespaces?: string | string[] ) { const spacesService = getSpacesService(); - return spacesService - ? await checkPrivilegesWithRequest(request).atSpace( - spacesService.namespaceToSpaceId(namespace), - actions - ) - : await checkPrivilegesWithRequest(request).globally(actions); + if (Array.isArray(namespaceOrNamespaces)) { + if (spacesService === undefined) { + throw new Error( + `Can't check saved object privileges for multiple namespaces if Spaces is disabled` + ); + } else if (!namespaceOrNamespaces.length) { + throw new Error(`Can't check saved object privileges for 0 namespaces`); + } + const spaceIds = namespaceOrNamespaces.map(x => spacesService.namespaceToSpaceId(x)); + return await checkPrivilegesWithRequest(request).atSpaces(spaceIds, actions); + } else if (spacesService) { + const spaceId = spacesService.namespaceToSpaceId(namespaceOrNamespaces); + return await checkPrivilegesWithRequest(request).atSpace(spaceId, actions); + } + return await checkPrivilegesWithRequest(request).globally(actions); }; }; }; diff --git a/x-pack/plugins/security/server/authorization/disable_ui_capabilities.test.ts b/x-pack/plugins/security/server/authorization/disable_ui_capabilities.test.ts index 912ae60e12065..ea97a1b3b590c 100644 --- a/x-pack/plugins/security/server/authorization/disable_ui_capabilities.test.ts +++ b/x-pack/plugins/security/server/authorization/disable_ui_capabilities.test.ts @@ -11,7 +11,9 @@ import { httpServerMock, loggingServiceMock } from '../../../../../src/core/serv import { authorizationMock } from './index.mock'; import { Feature } from '../../../features/server'; -type MockAuthzOptions = { rejectCheckPrivileges: any } | { resolveCheckPrivileges: any }; +type MockAuthzOptions = + | { rejectCheckPrivileges: any } + | { resolveCheckPrivileges: { privileges: Array<{ privilege: string; authorized: boolean }> } }; const actions = new Actions('1.0.0-zeta1'); const mockRequest = httpServerMock.createKibanaRequest(); @@ -26,7 +28,8 @@ const createMockAuthz = (options: MockAuthzOptions) => { throw options.rejectCheckPrivileges; } - expect(checkActions).toEqual(Object.keys(options.resolveCheckPrivileges.privileges)); + const expected = options.resolveCheckPrivileges.privileges.map(x => x.privilege); + expect(checkActions).toEqual(expected); return options.resolveCheckPrivileges; }); }); @@ -226,17 +229,17 @@ describe('usingPrivileges', () => { test(`disables ui capabilities when they don't have privileges`, async () => { const mockAuthz = createMockAuthz({ resolveCheckPrivileges: { - privileges: { - [actions.ui.get('navLinks', 'foo')]: true, - [actions.ui.get('navLinks', 'bar')]: false, - [actions.ui.get('navLinks', 'quz')]: false, - [actions.ui.get('management', 'kibana', 'indices')]: true, - [actions.ui.get('management', 'kibana', 'settings')]: false, - [actions.ui.get('fooFeature', 'foo')]: true, - [actions.ui.get('fooFeature', 'bar')]: false, - [actions.ui.get('barFeature', 'foo')]: true, - [actions.ui.get('barFeature', 'bar')]: false, - }, + privileges: [ + { privilege: actions.ui.get('navLinks', 'foo'), authorized: true }, + { privilege: actions.ui.get('navLinks', 'bar'), authorized: false }, + { privilege: actions.ui.get('navLinks', 'quz'), authorized: false }, + { privilege: actions.ui.get('management', 'kibana', 'indices'), authorized: true }, + { privilege: actions.ui.get('management', 'kibana', 'settings'), authorized: false }, + { privilege: actions.ui.get('fooFeature', 'foo'), authorized: true }, + { privilege: actions.ui.get('fooFeature', 'bar'), authorized: false }, + { privilege: actions.ui.get('barFeature', 'foo'), authorized: true }, + { privilege: actions.ui.get('barFeature', 'bar'), authorized: false }, + ], }, }); @@ -314,15 +317,15 @@ describe('usingPrivileges', () => { test(`doesn't re-enable disabled uiCapabilities`, async () => { const mockAuthz = createMockAuthz({ resolveCheckPrivileges: { - privileges: { - [actions.ui.get('navLinks', 'foo')]: true, - [actions.ui.get('navLinks', 'bar')]: true, - [actions.ui.get('management', 'kibana', 'indices')]: true, - [actions.ui.get('fooFeature', 'foo')]: true, - [actions.ui.get('fooFeature', 'bar')]: true, - [actions.ui.get('barFeature', 'foo')]: true, - [actions.ui.get('barFeature', 'bar')]: true, - }, + privileges: [ + { privilege: actions.ui.get('navLinks', 'foo'), authorized: true }, + { privilege: actions.ui.get('navLinks', 'bar'), authorized: true }, + { privilege: actions.ui.get('management', 'kibana', 'indices'), authorized: true }, + { privilege: actions.ui.get('fooFeature', 'foo'), authorized: true }, + { privilege: actions.ui.get('fooFeature', 'bar'), authorized: true }, + { privilege: actions.ui.get('barFeature', 'foo'), authorized: true }, + { privilege: actions.ui.get('barFeature', 'bar'), authorized: true }, + ], }, }); diff --git a/x-pack/plugins/security/server/authorization/disable_ui_capabilities.ts b/x-pack/plugins/security/server/authorization/disable_ui_capabilities.ts index be26f52fbf756..f0f1a42ad0bd5 100644 --- a/x-pack/plugins/security/server/authorization/disable_ui_capabilities.ts +++ b/x-pack/plugins/security/server/authorization/disable_ui_capabilities.ts @@ -9,7 +9,7 @@ import { UICapabilities } from 'ui/capabilities'; import { KibanaRequest, Logger } from '../../../../../src/core/server'; import { Feature } from '../../../features/server'; -import { CheckPrivilegesAtResourceResponse } from './check_privileges'; +import { CheckPrivilegesResponse } from './check_privileges'; import { Authorization } from './index'; export function disableUICapabilitiesFactory( @@ -77,7 +77,7 @@ export function disableUICapabilitiesFactory( [] ); - let checkPrivilegesResponse: CheckPrivilegesAtResourceResponse; + let checkPrivilegesResponse: CheckPrivilegesResponse; try { const checkPrivilegesDynamically = authz.checkPrivilegesDynamicallyWithRequest(request); checkPrivilegesResponse = await checkPrivilegesDynamically(uiActions); @@ -105,7 +105,9 @@ export function disableUICapabilitiesFactory( } const action = authz.actions.ui.get(featureId, ...uiCapabilityParts); - return checkPrivilegesResponse.privileges[action] === true; + return checkPrivilegesResponse.privileges.some( + x => x.privilege === action && x.authorized === true + ); }; return mapValues(uiCapabilities, (featureUICapabilities, featureId) => { diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index 032d231fe798f..68acf68f46109 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -149,6 +149,7 @@ export class Plugin { auditLogger: new SecurityAuditLogger(() => this.getLegacyAPI().auditLogger), authz, savedObjects: core.savedObjects, + getSpacesService: this.getSpacesService, }); core.capabilities.registerSwitcher(authz.disableUnauthorizedCapabilities); diff --git a/x-pack/plugins/security/server/saved_objects/index.ts b/x-pack/plugins/security/server/saved_objects/index.ts index 5954729562847..7dac745fcf84b 100644 --- a/x-pack/plugins/security/server/saved_objects/index.ts +++ b/x-pack/plugins/security/server/saved_objects/index.ts @@ -13,14 +13,21 @@ import { import { SecureSavedObjectsClientWrapper } from './secure_saved_objects_client_wrapper'; import { Authorization } from '../authorization'; import { SecurityAuditLogger } from '../audit'; +import { SpacesService } from '../plugin'; interface SetupSavedObjectsParams { auditLogger: SecurityAuditLogger; authz: Pick; savedObjects: CoreSetup['savedObjects']; + getSpacesService(): SpacesService | undefined; } -export function setupSavedObjects({ auditLogger, authz, savedObjects }: SetupSavedObjectsParams) { +export function setupSavedObjects({ + auditLogger, + authz, + savedObjects, + getSpacesService, +}: SetupSavedObjectsParams) { const getKibanaRequest = (request: KibanaRequest | LegacyRequest) => request instanceof KibanaRequest ? request : KibanaRequest.from(request); @@ -44,6 +51,7 @@ export function setupSavedObjects({ auditLogger, authz, savedObjects }: SetupSav kibanaRequest ), errors: SavedObjectsClient.errors, + getSpacesService, }) : client; }); diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts index 3c04508e3a74a..3c4034e07f995 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.test.ts @@ -9,6 +9,11 @@ import { Actions } from '../authorization'; import { securityAuditLoggerMock } from '../audit/index.mock'; import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; import { SavedObjectsClientContract } from 'kibana/server'; +import { SavedObjectActions } from '../authorization/actions/saved_object'; + +let clientOpts: ReturnType; +let client: SecureSavedObjectsClientWrapper; +const USERNAME = Symbol(); const createSecureSavedObjectsClientWrapperOptions = () => { const actions = new Actions('some-version'); @@ -22,810 +27,677 @@ const createSecureSavedObjectsClientWrapperOptions = () => { const errors = ({ decorateForbiddenError: jest.fn().mockReturnValue(forbiddenError), decorateGeneralError: jest.fn().mockReturnValue(generalError), + isNotFoundError: jest.fn().mockReturnValue(false), } as unknown) as jest.Mocked; + const getSpacesService = jest.fn().mockReturnValue(true); return { actions, baseClient: savedObjectsClientMock.create(), checkSavedObjectsPrivilegesAsCurrentUser: jest.fn(), errors, + getSpacesService, auditLogger: securityAuditLoggerMock.create(), forbiddenError, generalError, }; }; -describe('#errors', () => { - test(`assigns errors from constructor to .errors`, () => { - const options = createSecureSavedObjectsClientWrapperOptions(); - const client = new SecureSavedObjectsClientWrapper(options); +const expectGeneralError = async (fn: Function, args: Record) => { + // mock the checkPrivileges.globally rejection + const rejection = new Error('An actual error would happen here'); + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue(rejection); + + await expect(fn.bind(client)(...Object.values(args))).rejects.toThrowError( + clientOpts.generalError + ); + expect(clientOpts.errors.decorateGeneralError).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); +}; + +/** + * Fails the first authorization check, passes any others + * Requires that function args are passed in as key/value pairs + * The argument properties must be in the correct order to be spread properly + */ +const expectForbiddenError = async (fn: Function, args: Record) => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure + ); + + await expect(fn.bind(client)(...Object.values(args))).rejects.toThrowError( + clientOpts.forbiddenError + ); + const getCalls = (clientOpts.actions.savedObject.get as jest.MockedFunction< + SavedObjectActions['get'] + >).mock.calls; + const actions = clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mock.calls[0][0]; + const spaceId = args.options?.namespace || 'default'; + + const ACTION = getCalls[0][1]; + const types = getCalls.map(x => x[0]); + const missing = [{ spaceId, privilege: actions[0] }]; // if there was more than one type, only the first type was unauthorized + const spaceIds = [spaceId]; + + expect(clientOpts.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( + USERNAME, + ACTION, + types, + spaceIds, + missing, + args + ); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); +}; + +const expectSuccess = async (fn: Function, args: Record) => { + const result = await fn.bind(client)(...Object.values(args)); + const getCalls = (clientOpts.actions.savedObject.get as jest.MockedFunction< + SavedObjectActions['get'] + >).mock.calls; + const ACTION = getCalls[0][1]; + const types = getCalls.map(x => x[0]); + const spaceIds = [args.options?.namespace || 'default']; + + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( + USERNAME, + ACTION, + types, + spaceIds, + args + ); + return result; +}; + +const expectPrivilegeCheck = async (fn: Function, args: Record) => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure + ); + + await expect(fn.bind(client)(...Object.values(args))).rejects.toThrow(); // test is simpler with error case + const getResults = (clientOpts.actions.savedObject.get as jest.MockedFunction< + SavedObjectActions['get'] + >).mock.results; + const actions = getResults.map(x => x.value); + + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledTimes(1); + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( + actions, + args.options?.namespace + ); +}; + +const expectObjectNamespaceFiltering = async (fn: Function, args: Record) => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementationOnce( + getMockCheckPrivilegesSuccess // privilege check for authorization + ); + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure // privilege check for namespace filtering + ); + + const authorizedNamespace = args.options.namespace || 'default'; + const namespaces = ['some-other-namespace', authorizedNamespace]; + const returnValue = { namespaces, foo: 'bar' }; + // we don't know which base client method will be called; mock them all + clientOpts.baseClient.create.mockReturnValue(returnValue as any); + clientOpts.baseClient.get.mockReturnValue(returnValue as any); + clientOpts.baseClient.update.mockReturnValue(returnValue as any); + + const result = await fn.bind(client)(...Object.values(args)); + expect(result).toEqual(expect.objectContaining({ namespaces: [authorizedNamespace, '?'] })); + + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledTimes(2); + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenLastCalledWith( + 'login:', + namespaces + ); +}; + +const expectObjectsNamespaceFiltering = async (fn: Function, args: Record) => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementationOnce( + getMockCheckPrivilegesSuccess // privilege check for authorization + ); + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure // privilege check for namespace filtering + ); + + const authorizedNamespace = args.options.namespace || 'default'; + const returnValue = { + saved_objects: [ + { namespaces: ['foo'] }, + { namespaces: [authorizedNamespace] }, + { namespaces: ['foo', authorizedNamespace] }, + ], + }; + + // we don't know which base client method will be called; mock them all + clientOpts.baseClient.bulkCreate.mockReturnValue(returnValue as any); + clientOpts.baseClient.bulkGet.mockReturnValue(returnValue as any); + clientOpts.baseClient.bulkUpdate.mockReturnValue(returnValue as any); + clientOpts.baseClient.find.mockReturnValue(returnValue as any); + + const result = await fn.bind(client)(...Object.values(args)); + expect(result).toEqual( + expect.objectContaining({ + saved_objects: [ + { namespaces: ['?'] }, + { namespaces: [authorizedNamespace] }, + { namespaces: [authorizedNamespace, '?'] }, + ], + }) + ); + + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledTimes(2); + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenLastCalledWith('login:', [ + 'foo', + authorizedNamespace, + ]); +}; + +function getMockCheckPrivilegesSuccess(actions: string | string[], namespaces?: string | string[]) { + const _namespaces = Array.isArray(namespaces) ? namespaces : [namespaces || 'default']; + const _actions = Array.isArray(actions) ? actions : [actions]; + return { + hasAllRequested: true, + username: USERNAME, + privileges: _namespaces + .map(resource => + _actions.map(action => ({ + resource, + privilege: action, + authorized: true, + })) + ) + .flat(), + }; +} + +/** + * Fails the authorization check for the first privilege, and passes any others + * This check may be for an action for two different types in the same namespace + * Or, it may be for an action for the same type in two different namespaces + * Either way, the first privilege check returned is false, and any others return true + */ +function getMockCheckPrivilegesFailure(actions: string | string[], namespaces?: string | string[]) { + const _namespaces = Array.isArray(namespaces) ? namespaces : [namespaces || 'default']; + const _actions = Array.isArray(actions) ? actions : [actions]; + return { + hasAllRequested: false, + username: USERNAME, + privileges: _namespaces + .map((resource, idxa) => + _actions.map((action, idxb) => ({ + resource, + privilege: action, + authorized: idxa > 0 || idxb > 0, + })) + ) + .flat(), + }; +} + +/** + * Before each test, create the Client with its Options + */ +beforeEach(() => { + clientOpts = createSecureSavedObjectsClientWrapperOptions(); + client = new SecureSavedObjectsClientWrapper(clientOpts); + + // succeed privilege checks by default + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesSuccess + ); +}); + +describe('#addToNamespaces', () => { + const type = 'foo'; + const id = `${type}-id`; + const newNs1 = 'foo-namespace'; + const newNs2 = 'bar-namespace'; + const namespaces = [newNs1, newNs2]; + const currentNs = 'default'; + const privilege1 = `mock-saved_object:${type}/create`; + const privilege2 = `mock-saved_object:${type}/update`; + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + await expectGeneralError(client.addToNamespaces, { type, id, namespaces }); + }); + + test(`throws decorated ForbiddenError when unauthorized to create in new space`, async () => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure + ); + + await expect(client.addToNamespaces(type, id, namespaces)).rejects.toThrowError( + clientOpts.forbiddenError + ); + + expect(clientOpts.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( + USERNAME, + 'addToNamespacesCreate', + [type], + namespaces.sort(), + [{ privilege: privilege1, spaceId: newNs1 }], + { id, type, namespaces, options: {} } + ); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); + }); + + test(`throws decorated ForbiddenError when unauthorized to update in current space`, async () => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementationOnce( + getMockCheckPrivilegesSuccess // create + ); + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure // update + ); + + await expect(client.addToNamespaces(type, id, namespaces)).rejects.toThrowError( + clientOpts.forbiddenError + ); + + expect(clientOpts.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledTimes(1); + expect( + clientOpts.auditLogger.savedObjectsAuthorizationFailure + ).toHaveBeenLastCalledWith( + USERNAME, + 'addToNamespacesUpdate', + [type], + [currentNs], + [{ privilege: privilege2, spaceId: currentNs }], + { id, type, namespaces, options: {} } + ); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledTimes(1); + }); + + test(`returns result of baseClient.addToNamespaces when authorized`, async () => { + const apiCallReturnValue = Symbol(); + clientOpts.baseClient.addToNamespaces.mockReturnValue(apiCallReturnValue as any); + + const result = await client.addToNamespaces(type, id, namespaces); + expect(result).toBe(apiCallReturnValue); + + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledTimes(2); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenNthCalledWith( + 1, + USERNAME, + 'addToNamespacesCreate', // action for privilege check is 'create', but auditAction is 'addToNamespacesCreate' + [type], + namespaces.sort(), + { type, id, namespaces, options: {} } + ); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenNthCalledWith( + 2, + USERNAME, + 'addToNamespacesUpdate', // action for privilege check is 'update', but auditAction is 'addToNamespacesUpdate' + [type], + [currentNs], + { type, id, namespaces, options: {} } + ); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementationOnce( + getMockCheckPrivilegesSuccess // create + ); + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure // update + ); + + await expect(client.addToNamespaces(type, id, namespaces)).rejects.toThrow(); // test is simpler with error case + + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledTimes(2); + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenNthCalledWith( + 1, + [privilege1], + namespaces + ); + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenNthCalledWith( + 2, + [privilege2], + undefined // default namespace + ); + }); +}); + +describe('#bulkCreate', () => { + const attributes = { some: 'attr' }; + const obj1 = Object.freeze({ type: 'foo', otherThing: 'sup', attributes }); + const obj2 = Object.freeze({ type: 'bar', otherThing: 'everyone', attributes }); + const options = Object.freeze({ namespace: 'some-ns' }); + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + const objects = [obj1]; + await expectGeneralError(client.bulkCreate, { objects }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + const objects = [obj1, obj2]; + await expectForbiddenError(client.bulkCreate, { objects, options }); + }); + + test(`returns result of baseClient.bulkCreate when authorized`, async () => { + const apiCallReturnValue = { saved_objects: [], foo: 'bar' }; + clientOpts.baseClient.bulkCreate.mockReturnValue(apiCallReturnValue as any); + + const objects = [obj1, obj2]; + const result = await expectSuccess(client.bulkCreate, { objects, options }); + expect(result).toEqual(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + const objects = [obj1, obj2]; + await expectPrivilegeCheck(client.bulkCreate, { objects, options }); + }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + const objects = [obj1, obj2]; + await expectObjectsNamespaceFiltering(client.bulkCreate, { objects, options }); + }); +}); + +describe('#bulkGet', () => { + const obj1 = Object.freeze({ type: 'foo', id: 'foo-id' }); + const obj2 = Object.freeze({ type: 'bar', id: 'bar-id' }); + const options = Object.freeze({ namespace: 'some-ns' }); + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + const objects = [obj1]; + await expectGeneralError(client.bulkGet, { objects }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + const objects = [obj1, obj2]; + await expectForbiddenError(client.bulkGet, { objects, options }); + }); + + test(`returns result of baseClient.bulkGet when authorized`, async () => { + const apiCallReturnValue = { saved_objects: [], foo: 'bar' }; + clientOpts.baseClient.bulkGet.mockReturnValue(apiCallReturnValue as any); + + const objects = [obj1, obj2]; + const result = await expectSuccess(client.bulkGet, { objects, options }); + expect(result).toEqual(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + const objects = [obj1, obj2]; + await expectPrivilegeCheck(client.bulkGet, { objects, options }); + }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + const objects = [obj1, obj2]; + await expectObjectsNamespaceFiltering(client.bulkGet, { objects, options }); + }); +}); + +describe('#bulkUpdate', () => { + const obj1 = Object.freeze({ type: 'foo', id: 'foo-id', attributes: { some: 'attr' } }); + const obj2 = Object.freeze({ type: 'bar', id: 'bar-id', attributes: { other: 'attr' } }); + const options = Object.freeze({ namespace: 'some-ns' }); + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + const objects = [obj1]; + await expectGeneralError(client.bulkUpdate, { objects }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + const objects = [obj1, obj2]; + await expectForbiddenError(client.bulkUpdate, { objects, options }); + }); + + test(`returns result of baseClient.bulkUpdate when authorized`, async () => { + const apiCallReturnValue = { saved_objects: [], foo: 'bar' }; + clientOpts.baseClient.bulkUpdate.mockReturnValue(apiCallReturnValue as any); + + const objects = [obj1, obj2]; + const result = await expectSuccess(client.bulkUpdate, { objects, options }); + expect(result).toEqual(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + const objects = [obj1, obj2]; + await expectPrivilegeCheck(client.bulkUpdate, { objects, options }); + }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + const objects = [obj1, obj2]; + await expectObjectsNamespaceFiltering(client.bulkUpdate, { objects, options }); + }); +}); + +describe('#create', () => { + const type = 'foo'; + const attributes = { some_attr: 's' }; + const options = Object.freeze({ namespace: 'some-ns' }); + + test(`throws decorated GeneralError when checkPrivileges.globally rejects promise`, async () => { + await expectGeneralError(client.create, { type }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + await expectForbiddenError(client.create, { type, attributes, options }); + }); + + test(`returns result of baseClient.create when authorized`, async () => { + const apiCallReturnValue = Symbol(); + clientOpts.baseClient.create.mockResolvedValue(apiCallReturnValue as any); + + const result = await expectSuccess(client.create, { type, attributes, options }); + expect(result).toBe(apiCallReturnValue); + }); - expect(client.errors).toBe(options.errors); + test(`checks privileges for user, actions, and namespace`, async () => { + await expectPrivilegeCheck(client.create, { type, attributes, options }); + }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + await expectObjectNamespaceFiltering(client.create, { type, attributes, options }); }); }); -describe(`spaces disabled`, () => { - describe('#create', () => { - test(`throws decorated GeneralError when checkPrivileges.globally rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - await expect(client.create(type)).rejects.toThrowError(options.generalError); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'create')], - undefined - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when unauthorized`, async () => { - const type = 'foo'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { [options.actions.savedObject.get(type, 'create')]: false }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const attributes = { some_attr: 's' }; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.create(type, attributes, apiCallOptions)).rejects.toThrowError( - options.forbiddenError - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'create')], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'create', - [type], - [options.actions.savedObject.get(type, 'create')], - { type, attributes, options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of baseClient.create when authorized`, async () => { - const type = 'foo'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { [options.actions.savedObject.get(type, 'create')]: true }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.create.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const attributes = { some_attr: 's' }; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.create(type, attributes, apiCallOptions)).resolves.toBe( - apiCallReturnValue - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'create')], - apiCallOptions.namespace - ); - expect(options.baseClient.create).toHaveBeenCalledWith(type, attributes, apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'create', - [type], - { type, attributes, options: apiCallOptions } - ); - }); - }); - - describe('#bulkCreate', () => { - test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect( - client.bulkCreate([{ type, attributes: {} }], apiCallOptions) - ).rejects.toThrowError(options.generalError); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'bulk_create')], - apiCallOptions.namespace - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when unauthorized`, async () => { - const type1 = 'foo'; - const type2 = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { - [options.actions.savedObject.get(type1, 'bulk_create')]: false, - [options.actions.savedObject.get(type2, 'bulk_create')]: true, - }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const objects = [ - { type: type1, attributes: {} }, - { type: type2, attributes: {} }, - ]; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.bulkCreate(objects, apiCallOptions)).rejects.toThrowError( - options.forbiddenError - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [ - options.actions.savedObject.get(type1, 'bulk_create'), - options.actions.savedObject.get(type2, 'bulk_create'), - ], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'bulk_create', - [type1, type2], - [options.actions.savedObject.get(type1, 'bulk_create')], - { objects, options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of baseClient.bulkCreate when authorized`, async () => { - const type1 = 'foo'; - const type2 = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { - [options.actions.savedObject.get(type1, 'bulk_create')]: true, - [options.actions.savedObject.get(type2, 'bulk_create')]: true, - }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.bulkCreate.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const objects = [ - { type: type1, otherThing: 'sup', attributes: {} }, - { type: type2, otherThing: 'everyone', attributes: {} }, - ]; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.bulkCreate(objects, apiCallOptions)).resolves.toBe(apiCallReturnValue); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [ - options.actions.savedObject.get(type1, 'bulk_create'), - options.actions.savedObject.get(type2, 'bulk_create'), - ], - apiCallOptions.namespace - ); - expect(options.baseClient.bulkCreate).toHaveBeenCalledWith(objects, apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'bulk_create', - [type1, type2], - { objects, options: apiCallOptions } - ); - }); - }); - - describe('#delete', () => { - test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - await expect(client.delete(type, 'bar')).rejects.toThrowError(options.generalError); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'delete')], - undefined - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when unauthorized`, async () => { - const type = 'foo'; - const id = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { - [options.actions.savedObject.get(type, 'delete')]: false, - }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.delete(type, id, apiCallOptions)).rejects.toThrowError( - options.forbiddenError - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'delete')], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'delete', - [type], - [options.actions.savedObject.get(type, 'delete')], - { type, id, options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of internalRepository.delete when authorized`, async () => { - const type = 'foo'; - const id = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { [options.actions.savedObject.get(type, 'delete')]: true }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.delete.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.delete(type, id, apiCallOptions)).resolves.toBe(apiCallReturnValue); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'delete')], - apiCallOptions.namespace - ); - expect(options.baseClient.delete).toHaveBeenCalledWith(type, id, apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'delete', - [type], - { type, id, options: apiCallOptions } - ); - }); - }); - - describe('#find', () => { - test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - await expect(client.find({ type })).rejects.toThrowError(options.generalError); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'find')], - undefined - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when type's singular and unauthorized`, async () => { - const type = 'foo'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { [options.actions.savedObject.get(type, 'find')]: false }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ type, namespace: 'some-ns' }); - await expect(client.find(apiCallOptions)).rejects.toThrowError(options.forbiddenError); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'find')], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'find', - [type], - [options.actions.savedObject.get(type, 'find')], - { options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when type's an array and unauthorized`, async () => { - const type1 = 'foo'; - const type2 = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { - [options.actions.savedObject.get(type1, 'find')]: false, - [options.actions.savedObject.get(type2, 'find')]: true, - }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ type: [type1, type2], namespace: 'some-ns' }); - await expect(client.find(apiCallOptions)).rejects.toThrowError(options.forbiddenError); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [ - options.actions.savedObject.get(type1, 'find'), - options.actions.savedObject.get(type2, 'find'), - ], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'find', - [type1, type2], - [options.actions.savedObject.get(type1, 'find')], - { options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of baseClient.find when authorized`, async () => { - const type = 'foo'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { [options.actions.savedObject.get(type, 'find')]: true }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.find.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ type, namespace: 'some-ns' }); - await expect(client.find(apiCallOptions)).resolves.toBe(apiCallReturnValue); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'find')], - apiCallOptions.namespace - ); - expect(options.baseClient.find).toHaveBeenCalledWith(apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'find', - [type], - { options: apiCallOptions } - ); - }); - }); - - describe('#bulkGet', () => { - test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - await expect(client.bulkGet([{ id: 'bar', type }])).rejects.toThrowError( - options.generalError - ); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'bulk_get')], - undefined - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when unauthorized`, async () => { - const type1 = 'foo'; - const type2 = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { - [options.actions.savedObject.get(type1, 'bulk_get')]: false, - [options.actions.savedObject.get(type2, 'bulk_get')]: true, - }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const objects = [ - { type: type1, id: `bar-${type1}` }, - { type: type2, id: `bar-${type2}` }, - ]; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.bulkGet(objects, apiCallOptions)).rejects.toThrowError( - options.forbiddenError - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [ - options.actions.savedObject.get(type1, 'bulk_get'), - options.actions.savedObject.get(type2, 'bulk_get'), - ], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'bulk_get', - [type1, type2], - [options.actions.savedObject.get(type1, 'bulk_get')], - { objects, options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of baseClient.bulkGet when authorized`, async () => { - const type1 = 'foo'; - const type2 = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { - [options.actions.savedObject.get(type1, 'bulk_get')]: true, - [options.actions.savedObject.get(type2, 'bulk_get')]: true, - }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.bulkGet.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const objects = [ - { type: type1, id: `id-${type1}` }, - { type: type2, id: `id-${type2}` }, - ]; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.bulkGet(objects, apiCallOptions)).resolves.toBe(apiCallReturnValue); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [ - options.actions.savedObject.get(type1, 'bulk_get'), - options.actions.savedObject.get(type2, 'bulk_get'), - ], - apiCallOptions.namespace - ); - expect(options.baseClient.bulkGet).toHaveBeenCalledWith(objects, apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'bulk_get', - [type1, type2], - { objects, options: apiCallOptions } - ); - }); - }); - - describe('#get', () => { - test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - await expect(client.get(type, 'bar')).rejects.toThrowError(options.generalError); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'get')], - undefined - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when unauthorized`, async () => { - const type = 'foo'; - const id = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { - [options.actions.savedObject.get(type, 'get')]: false, - }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.get(type, id, apiCallOptions)).rejects.toThrowError( - options.forbiddenError - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'get')], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'get', - [type], - [options.actions.savedObject.get(type, 'get')], - { type, id, options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of baseClient.get when authorized`, async () => { - const type = 'foo'; - const id = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { [options.actions.savedObject.get(type, 'get')]: true }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.get.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.get(type, id, apiCallOptions)).resolves.toBe(apiCallReturnValue); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'get')], - apiCallOptions.namespace - ); - expect(options.baseClient.get).toHaveBeenCalledWith(type, id, apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'get', - [type], - { type, id, options: apiCallOptions } - ); - }); - }); - - describe('#update', () => { - test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - await expect(client.update(type, 'bar', {})).rejects.toThrowError(options.generalError); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'update')], - undefined - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when unauthorized`, async () => { - const type = 'foo'; - const id = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { - [options.actions.savedObject.get(type, 'update')]: false, - }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const attributes = { some: 'attr' }; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.update(type, id, attributes, apiCallOptions)).rejects.toThrowError( - options.forbiddenError - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'update')], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'update', - [type], - [options.actions.savedObject.get(type, 'update')], - { type, id, attributes, options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of baseClient.update when authorized`, async () => { - const type = 'foo'; - const id = 'bar'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { [options.actions.savedObject.get(type, 'update')]: true }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.update.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const attributes = { some: 'attr' }; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.update(type, id, attributes, apiCallOptions)).resolves.toBe( - apiCallReturnValue - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'update')], - apiCallOptions.namespace - ); - expect(options.baseClient.update).toHaveBeenCalledWith(type, id, attributes, apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'update', - [type], - { type, id, attributes, options: apiCallOptions } - ); - }); - }); - - describe('#bulkUpdate', () => { - test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { - const type = 'foo'; - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockRejectedValue( - new Error('An actual error would happen here') - ); - const client = new SecureSavedObjectsClientWrapper(options); - - await expect(client.bulkUpdate([{ id: 'bar', type, attributes: {} }])).rejects.toThrowError( - options.generalError - ); - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'bulk_update')], - undefined - ); - expect(options.errors.decorateGeneralError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`throws decorated ForbiddenError when unauthorized`, async () => { - const type = 'foo'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: false, - username, - privileges: { - [options.actions.savedObject.get(type, 'bulk_update')]: false, - }, - }); - - const client = new SecureSavedObjectsClientWrapper(options); - - const objects = [{ type, id: `bar-${type}`, attributes: {} }]; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.bulkUpdate(objects, apiCallOptions)).rejects.toThrowError( - options.forbiddenError - ); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'bulk_update')], - apiCallOptions.namespace - ); - expect(options.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); - expect(options.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( - username, - 'bulk_update', - [type], - [options.actions.savedObject.get(type, 'bulk_update')], - { objects, options: apiCallOptions } - ); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); - }); - - test(`returns result of baseClient.bulkUpdate when authorized`, async () => { - const type = 'foo'; - const username = Symbol(); - const options = createSecureSavedObjectsClientWrapperOptions(); - options.checkSavedObjectsPrivilegesAsCurrentUser.mockResolvedValue({ - hasAllRequested: true, - username, - privileges: { - [options.actions.savedObject.get(type, 'bulk_update')]: true, - }, - }); - - const apiCallReturnValue = Symbol(); - options.baseClient.bulkUpdate.mockReturnValue(apiCallReturnValue as any); - - const client = new SecureSavedObjectsClientWrapper(options); - - const objects = [{ type, id: `id-${type}`, attributes: {} }]; - const apiCallOptions = Object.freeze({ namespace: 'some-ns' }); - await expect(client.bulkUpdate(objects, apiCallOptions)).resolves.toBe(apiCallReturnValue); - - expect(options.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( - [options.actions.savedObject.get(type, 'bulk_update')], - apiCallOptions.namespace - ); - expect(options.baseClient.bulkUpdate).toHaveBeenCalledWith(objects, apiCallOptions); - expect(options.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); - expect(options.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( - username, - 'bulk_update', - [type], - { objects, options: apiCallOptions } - ); - }); +describe('#delete', () => { + const type = 'foo'; + const id = `${type}-id`; + const options = Object.freeze({ namespace: 'some-ns' }); + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + await expectGeneralError(client.delete, { type, id }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + await expectForbiddenError(client.delete, { type, id, options }); + }); + + test(`returns result of internalRepository.delete when authorized`, async () => { + const apiCallReturnValue = Symbol(); + clientOpts.baseClient.delete.mockReturnValue(apiCallReturnValue as any); + + const result = await expectSuccess(client.delete, { type, id, options }); + expect(result).toBe(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + await expectPrivilegeCheck(client.delete, { type, id, options }); + }); +}); + +describe('#find', () => { + const type1 = 'foo'; + const type2 = 'bar'; + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + await expectGeneralError(client.find, { type: type1 }); + }); + + test(`throws decorated ForbiddenError when type's singular and unauthorized`, async () => { + const options = Object.freeze({ type: type1, namespace: 'some-ns' }); + await expectForbiddenError(client.find, { options }); + }); + + test(`throws decorated ForbiddenError when type's an array and unauthorized`, async () => { + const options = Object.freeze({ type: [type1, type2], namespace: 'some-ns' }); + await expectForbiddenError(client.find, { options }); + }); + + test(`returns result of baseClient.find when authorized`, async () => { + const apiCallReturnValue = { saved_objects: [], foo: 'bar' }; + clientOpts.baseClient.find.mockReturnValue(apiCallReturnValue as any); + + const options = Object.freeze({ type: type1, namespace: 'some-ns' }); + const result = await expectSuccess(client.find, { options }); + expect(result).toEqual(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + const options = Object.freeze({ type: [type1, type2], namespace: 'some-ns' }); + await expectPrivilegeCheck(client.find, { options }); + }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + const options = Object.freeze({ type: [type1, type2], namespace: 'some-ns' }); + await expectObjectsNamespaceFiltering(client.find, { options }); + }); +}); + +describe('#get', () => { + const type = 'foo'; + const id = `${type}-id`; + const options = Object.freeze({ namespace: 'some-ns' }); + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + await expectGeneralError(client.get, { type, id }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + await expectForbiddenError(client.get, { type, id, options }); + }); + + test(`returns result of baseClient.get when authorized`, async () => { + const apiCallReturnValue = Symbol(); + clientOpts.baseClient.get.mockReturnValue(apiCallReturnValue as any); + + const result = await expectSuccess(client.get, { type, id, options }); + expect(result).toBe(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + await expectPrivilegeCheck(client.get, { type, id, options }); + }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + await expectObjectNamespaceFiltering(client.get, { type, id, options }); + }); +}); + +describe('#deleteFromNamespaces', () => { + const type = 'foo'; + const id = `${type}-id`; + const namespace1 = 'foo-namespace'; + const namespace2 = 'bar-namespace'; + const namespaces = [namespace1, namespace2]; + const privilege = `mock-saved_object:${type}/delete`; + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + await expectGeneralError(client.deleteFromNamespaces, { type, id, namespaces }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure + ); + + await expect(client.deleteFromNamespaces(type, id, namespaces)).rejects.toThrowError( + clientOpts.forbiddenError + ); + + expect(clientOpts.errors.decorateForbiddenError).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).toHaveBeenCalledWith( + USERNAME, + 'deleteFromNamespaces', // action for privilege check is 'delete', but auditAction is 'deleteFromNamespaces' + [type], + namespaces.sort(), + [{ privilege, spaceId: namespace1 }], + { type, id, namespaces, options: {} } + ); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).not.toHaveBeenCalled(); + }); + + test(`returns result of baseClient.deleteFromNamespaces when authorized`, async () => { + const apiCallReturnValue = Symbol(); + clientOpts.baseClient.deleteFromNamespaces.mockReturnValue(apiCallReturnValue as any); + + const result = await client.deleteFromNamespaces(type, id, namespaces); + expect(result).toBe(apiCallReturnValue); + + expect(clientOpts.auditLogger.savedObjectsAuthorizationFailure).not.toHaveBeenCalled(); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledTimes(1); + expect(clientOpts.auditLogger.savedObjectsAuthorizationSuccess).toHaveBeenCalledWith( + USERNAME, + 'deleteFromNamespaces', // action for privilege check is 'delete', but auditAction is 'deleteFromNamespaces' + [type], + namespaces.sort(), + { type, id, namespaces, options: {} } + ); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + clientOpts.checkSavedObjectsPrivilegesAsCurrentUser.mockImplementation( + getMockCheckPrivilegesFailure + ); + + await expect(client.deleteFromNamespaces(type, id, namespaces)).rejects.toThrow(); // test is simpler with error case + + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledTimes(1); + expect(clientOpts.checkSavedObjectsPrivilegesAsCurrentUser).toHaveBeenCalledWith( + [privilege], + namespaces + ); + }); +}); + +describe('#update', () => { + const type = 'foo'; + const id = `${type}-id`; + const attributes = { some: 'attr' }; + const options = Object.freeze({ namespace: 'some-ns' }); + + test(`throws decorated GeneralError when hasPrivileges rejects promise`, async () => { + await expectGeneralError(client.update, { type, id, attributes }); + }); + + test(`throws decorated ForbiddenError when unauthorized`, async () => { + await expectForbiddenError(client.update, { type, id, attributes, options }); + }); + + test(`returns result of baseClient.update when authorized`, async () => { + const apiCallReturnValue = Symbol(); + clientOpts.baseClient.update.mockReturnValue(apiCallReturnValue as any); + + const result = await expectSuccess(client.update, { type, id, attributes, options }); + expect(result).toBe(apiCallReturnValue); + }); + + test(`checks privileges for user, actions, and namespace`, async () => { + await expectPrivilegeCheck(client.update, { type, id, attributes, options }); + }); + + test(`filters namespaces that the user doesn't have access to`, async () => { + await expectObjectNamespaceFiltering(client.update, { type, id, attributes, options }); + }); +}); + +describe('other', () => { + test(`assigns errors from constructor to .errors`, () => { + expect(client.errors).toBe(clientOpts.errors); }); }); diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts index 2209e7fb66fcb..29503d475be73 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts @@ -13,9 +13,13 @@ import { SavedObjectsCreateOptions, SavedObjectsFindOptions, SavedObjectsUpdateOptions, + SavedObjectsAddToNamespacesOptions, + SavedObjectsDeleteFromNamespacesOptions, } from '../../../../../src/core/server'; import { SecurityAuditLogger } from '../audit'; import { Actions, CheckSavedObjectsPrivileges } from '../authorization'; +import { CheckPrivilegesResponse } from '../authorization/check_privileges'; +import { SpacesService } from '../plugin'; interface SecureSavedObjectsClientWrapperOptions { actions: Actions; @@ -23,6 +27,19 @@ interface SecureSavedObjectsClientWrapperOptions { baseClient: SavedObjectsClientContract; errors: SavedObjectsClientContract['errors']; checkSavedObjectsPrivilegesAsCurrentUser: CheckSavedObjectsPrivileges; + getSpacesService(): SpacesService | undefined; +} + +interface SavedObjectNamespaces { + namespaces?: string[]; +} + +interface SavedObjectsNamespaces { + saved_objects: SavedObjectNamespaces[]; +} + +function uniq(arr: T[]): T[] { + return Array.from(new Set(arr)); } export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContract { @@ -30,19 +47,23 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra private readonly auditLogger: PublicMethodsOf; private readonly baseClient: SavedObjectsClientContract; private readonly checkSavedObjectsPrivilegesAsCurrentUser: CheckSavedObjectsPrivileges; + private getSpacesService: () => SpacesService | undefined; public readonly errors: SavedObjectsClientContract['errors']; + constructor({ actions, auditLogger, baseClient, checkSavedObjectsPrivilegesAsCurrentUser, errors, + getSpacesService, }: SecureSavedObjectsClientWrapperOptions) { this.errors = errors; this.actions = actions; this.auditLogger = auditLogger; this.baseClient = baseClient; this.checkSavedObjectsPrivilegesAsCurrentUser = checkSavedObjectsPrivilegesAsCurrentUser; + this.getSpacesService = getSpacesService; } public async create( @@ -52,7 +73,8 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra ) { await this.ensureAuthorized(type, 'create', options.namespace, { type, attributes, options }); - return await this.baseClient.create(type, attributes, options); + const savedObject = await this.baseClient.create(type, attributes, options); + return await this.redactSavedObjectNamespaces(savedObject); } public async bulkCreate( @@ -66,7 +88,8 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra { objects, options } ); - return await this.baseClient.bulkCreate(objects, options); + const response = await this.baseClient.bulkCreate(objects, options); + return await this.redactSavedObjectsNamespaces(response); } public async delete(type: string, id: string, options: SavedObjectsBaseOptions = {}) { @@ -78,7 +101,8 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra public async find(options: SavedObjectsFindOptions) { await this.ensureAuthorized(options.type, 'find', options.namespace, { options }); - return this.baseClient.find(options); + const response = await this.baseClient.find(options); + return await this.redactSavedObjectsNamespaces(response); } public async bulkGet( @@ -90,13 +114,15 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra options, }); - return await this.baseClient.bulkGet(objects, options); + const response = await this.baseClient.bulkGet(objects, options); + return await this.redactSavedObjectsNamespaces(response); } public async get(type: string, id: string, options: SavedObjectsBaseOptions = {}) { await this.ensureAuthorized(type, 'get', options.namespace, { type, id, options }); - return await this.baseClient.get(type, id, options); + const savedObject = await this.baseClient.get(type, id, options); + return await this.redactSavedObjectNamespaces(savedObject); } public async update( @@ -105,14 +131,44 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra attributes: Partial, options: SavedObjectsUpdateOptions = {} ) { - await this.ensureAuthorized(type, 'update', options.namespace, { - type, - id, - attributes, - options, - }); + const args = { type, id, attributes, options }; + await this.ensureAuthorized(type, 'update', options.namespace, args); - return await this.baseClient.update(type, id, attributes, options); + const savedObject = await this.baseClient.update(type, id, attributes, options); + return await this.redactSavedObjectNamespaces(savedObject); + } + + public async addToNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsAddToNamespacesOptions = {} + ) { + const args = { type, id, namespaces, options }; + const { namespace } = options; + // To share an object, the user must have the "create" permission in each of the destination namespaces. + await this.ensureAuthorized(type, 'create', namespaces, args, 'addToNamespacesCreate'); + + // To share an object, the user must also have the "update" permission in one or more of the source namespaces. Because the + // `addToNamespaces` operation is scoped to the current namespace, we can just check if the user has the "update" permission in the + // current namespace. If the user has permission, but the saved object doesn't exist in this namespace, the base client operation will + // result in a 404 error. + await this.ensureAuthorized(type, 'update', namespace, args, 'addToNamespacesUpdate'); + + return await this.baseClient.addToNamespaces(type, id, namespaces, options); + } + + public async deleteFromNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsDeleteFromNamespacesOptions = {} + ) { + const args = { type, id, namespaces, options }; + // To un-share an object, the user must have the "delete" permission in each of the target namespaces. + await this.ensureAuthorized(type, 'delete', namespaces, args, 'deleteFromNamespaces'); + + return await this.baseClient.deleteFromNamespaces(type, id, namespaces, options); } public async bulkUpdate( @@ -126,12 +182,16 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra { objects, options } ); - return await this.baseClient.bulkUpdate(objects, options); + const response = await this.baseClient.bulkUpdate(objects, options); + return await this.redactSavedObjectsNamespaces(response); } - private async checkPrivileges(actions: string | string[], namespace?: string) { + private async checkPrivileges( + actions: string | string[], + namespaceOrNamespaces?: string | string[] + ) { try { - return await this.checkSavedObjectsPrivilegesAsCurrentUser(actions, namespace); + return await this.checkSavedObjectsPrivilegesAsCurrentUser(actions, namespaceOrNamespaces); } catch (error) { throw this.errors.decorateGeneralError(error, error.body && error.body.reason); } @@ -140,43 +200,133 @@ export class SecureSavedObjectsClientWrapper implements SavedObjectsClientContra private async ensureAuthorized( typeOrTypes: string | string[], action: string, - namespace?: string, - args?: Record + namespaceOrNamespaces?: string | string[], + args?: Record, + auditAction: string = action, + requiresAll = true ) { const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; const actionsToTypesMap = new Map( types.map(type => [this.actions.savedObject.get(type, action), type]) ); const actions = Array.from(actionsToTypesMap.keys()); - const { hasAllRequested, username, privileges } = await this.checkPrivileges( - actions, - namespace - ); + const result = await this.checkPrivileges(actions, namespaceOrNamespaces); + + const { hasAllRequested, username, privileges } = result; + const spaceIds = uniq( + privileges.map(({ resource }) => resource).filter(x => x !== undefined) + ).sort() as string[]; - if (hasAllRequested) { - this.auditLogger.savedObjectsAuthorizationSuccess(username, action, types, args); + const isAuthorized = + (requiresAll && hasAllRequested) || + (!requiresAll && privileges.some(({ authorized }) => authorized)); + if (isAuthorized) { + this.auditLogger.savedObjectsAuthorizationSuccess( + username, + auditAction, + types, + spaceIds, + args + ); } else { const missingPrivileges = this.getMissingPrivileges(privileges); this.auditLogger.savedObjectsAuthorizationFailure( username, - action, + auditAction, types, + spaceIds, missingPrivileges, args ); - const msg = `Unable to ${action} ${missingPrivileges - .map(privilege => actionsToTypesMap.get(privilege)) - .sort() - .join(',')}`; + const targetTypes = uniq( + missingPrivileges.map(({ privilege }) => actionsToTypesMap.get(privilege)).sort() + ).join(','); + const msg = `Unable to ${action} ${targetTypes}`; throw this.errors.decorateForbiddenError(new Error(msg)); } } - private getMissingPrivileges(privileges: Record) { - return Object.keys(privileges).filter(privilege => !privileges[privilege]); + private getMissingPrivileges(privileges: CheckPrivilegesResponse['privileges']) { + return privileges + .filter(({ authorized }) => !authorized) + .map(({ resource, privilege }) => ({ spaceId: resource, privilege })); } private getUniqueObjectTypes(objects: Array<{ type: string }>) { - return [...new Set(objects.map(o => o.type))]; + return uniq(objects.map(o => o.type)); + } + + private async getNamespacesPrivilegeMap(namespaces: string[]) { + const action = this.actions.login; + const checkPrivilegesResult = await this.checkPrivileges(action, namespaces); + // check if the user can log into each namespace + const map = checkPrivilegesResult.privileges.reduce( + (acc: Record, { resource, authorized }) => { + // there should never be a case where more than one privilege is returned for a given space + // if there is, fail-safe (authorized + unauthorized = unauthorized) + if (resource && (!authorized || !acc.hasOwnProperty(resource))) { + acc[resource] = authorized; + } + return acc; + }, + {} + ); + return map; + } + + private redactAndSortNamespaces(spaceIds: string[], privilegeMap: Record) { + const comparator = (a: string, b: string) => { + const _a = a.toLowerCase(); + const _b = b.toLowerCase(); + if (_a === '?') { + return 1; + } else if (_a < _b) { + return -1; + } else if (_a > _b) { + return 1; + } + return 0; + }; + return spaceIds.map(spaceId => (privilegeMap[spaceId] ? spaceId : '?')).sort(comparator); + } + + private async redactSavedObjectNamespaces( + savedObject: T + ): Promise { + if (this.getSpacesService() === undefined || savedObject.namespaces == null) { + return savedObject; + } + + const privilegeMap = await this.getNamespacesPrivilegeMap(savedObject.namespaces); + + return { + ...savedObject, + namespaces: this.redactAndSortNamespaces(savedObject.namespaces, privilegeMap), + }; + } + + private async redactSavedObjectsNamespaces( + response: T + ): Promise { + if (this.getSpacesService() === undefined) { + return response; + } + const { saved_objects: savedObjects } = response; + const namespaces = uniq(savedObjects.flatMap(savedObject => savedObject.namespaces || [])); + if (namespaces.length === 0) { + return response; + } + + const privilegeMap = await this.getNamespacesPrivilegeMap(namespaces); + + return { + ...response, + saved_objects: savedObjects.map(savedObject => ({ + ...savedObject, + namespaces: + savedObject.namespaces && + this.redactAndSortNamespaces(savedObject.namespaces, privilegeMap), + })), + }; } } diff --git a/x-pack/plugins/spaces/public/management/edit_space/delete_spaces_button.tsx b/x-pack/plugins/spaces/public/management/edit_space/delete_spaces_button.tsx index 28e45bc8cfd2a..ea63905e27b26 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/delete_spaces_button.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/delete_spaces_button.tsx @@ -99,10 +99,14 @@ export class DeleteSpacesButton extends Component { public deleteSpaces = async () => { const { spacesManager, space } = this.props; + this.setState({ + showConfirmDeleteModal: false, + }); + try { await spacesManager.deleteSpace(space); } catch (error) { - const { message: errorMessage = '' } = error.data || {}; + const { message: errorMessage = '' } = error.data || error.body || {}; this.props.notifications.toasts.addDanger( i18n.translate('xpack.spaces.management.deleteSpacesButton.deleteSpaceErrorTitle', { @@ -110,12 +114,9 @@ export class DeleteSpacesButton extends Component { values: { errorMessage }, }) ); + return; } - this.setState({ - showConfirmDeleteModal: false, - }); - const message = i18n.translate( 'xpack.spaces.management.deleteSpacesButton.spaceSuccessfullyDeletedNotificationMessage', { diff --git a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx index ff4be84207832..df5e6a2ca34af 100644 --- a/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_grid/spaces_grid_page.tsx @@ -176,10 +176,14 @@ export class SpacesGridPage extends Component { return; } + this.setState({ + showConfirmDeleteModal: false, + }); + try { await spacesManager.deleteSpace(space); } catch (error) { - const { message: errorMessage = '' } = error.data || {}; + const { message: errorMessage = '' } = error.data || error.body || {}; this.props.notifications.toasts.addDanger( i18n.translate('xpack.spaces.management.spacesGridPage.errorDeletingSpaceErrorMessage', { @@ -189,12 +193,9 @@ export class SpacesGridPage extends Component { }, }) ); + return; } - this.setState({ - showConfirmDeleteModal: false, - }); - this.loadGrid(); const message = i18n.translate( diff --git a/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts b/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts index 59e157c3fc2db..72faab0d2c892 100644 --- a/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts +++ b/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts @@ -188,11 +188,13 @@ describe('copySavedObjectsToSpaces', () => { }, ], "savedObjectsClient": Object { + "addToNamespaces": [MockFunction], "bulkCreate": [MockFunction], "bulkGet": [MockFunction], "bulkUpdate": [MockFunction], "create": [MockFunction], "delete": [MockFunction], + "deleteFromNamespaces": [MockFunction], "errors": [Function], "find": [MockFunction], "get": [MockFunction], @@ -252,11 +254,13 @@ describe('copySavedObjectsToSpaces', () => { "readable": false, }, "savedObjectsClient": Object { + "addToNamespaces": [MockFunction], "bulkCreate": [MockFunction], "bulkGet": [MockFunction], "bulkUpdate": [MockFunction], "create": [MockFunction], "delete": [MockFunction], + "deleteFromNamespaces": [MockFunction], "errors": [Function], "find": [MockFunction], "get": [MockFunction], @@ -315,11 +319,13 @@ describe('copySavedObjectsToSpaces', () => { "readable": false, }, "savedObjectsClient": Object { + "addToNamespaces": [MockFunction], "bulkCreate": [MockFunction], "bulkGet": [MockFunction], "bulkUpdate": [MockFunction], "create": [MockFunction], "delete": [MockFunction], + "deleteFromNamespaces": [MockFunction], "errors": [Function], "find": [MockFunction], "get": [MockFunction], diff --git a/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.test.ts b/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.test.ts index 7809f1f8be66f..aa1d5e9a47832 100644 --- a/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.test.ts +++ b/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.test.ts @@ -204,11 +204,13 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { }, ], "savedObjectsClient": Object { + "addToNamespaces": [MockFunction], "bulkCreate": [MockFunction], "bulkGet": [MockFunction], "bulkUpdate": [MockFunction], "create": [MockFunction], "delete": [MockFunction], + "deleteFromNamespaces": [MockFunction], "errors": [Function], "find": [MockFunction], "get": [MockFunction], @@ -275,11 +277,13 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { }, ], "savedObjectsClient": Object { + "addToNamespaces": [MockFunction], "bulkCreate": [MockFunction], "bulkGet": [MockFunction], "bulkUpdate": [MockFunction], "create": [MockFunction], "delete": [MockFunction], + "deleteFromNamespaces": [MockFunction], "errors": [Function], "find": [MockFunction], "get": [MockFunction], @@ -345,11 +349,13 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { }, ], "savedObjectsClient": Object { + "addToNamespaces": [MockFunction], "bulkCreate": [MockFunction], "bulkGet": [MockFunction], "bulkUpdate": [MockFunction], "create": [MockFunction], "delete": [MockFunction], + "deleteFromNamespaces": [MockFunction], "errors": [Function], "find": [MockFunction], "get": [MockFunction], diff --git a/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.test.ts b/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.test.ts index 74e75fb8f12c7..c83830f6feace 100644 --- a/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.test.ts +++ b/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.test.ts @@ -250,14 +250,10 @@ describe('#getAll', () => { mockAuthorization.mode.useRbacForRequest.mockReturnValue(true); mockCheckPrivilegesAtSpaces.mockReturnValue({ username, - spacePrivileges: { - [savedObjects[0].id]: { - [privilege]: false, - }, - [savedObjects[1].id]: { - [privilege]: false, - }, - }, + privileges: [ + { resource: savedObjects[0].id, privilege, authorized: false }, + { resource: savedObjects[1].id, privilege, authorized: false }, + ], }); const maxSpaces = 1234; const mockConfig = createMockConfig({ @@ -314,14 +310,10 @@ describe('#getAll', () => { mockAuthorization.mode.useRbacForRequest.mockReturnValue(true); mockCheckPrivilegesAtSpaces.mockReturnValue({ username, - spacePrivileges: { - [savedObjects[0].id]: { - [privilege]: true, - }, - [savedObjects[1].id]: { - [privilege]: false, - }, - }, + privileges: [ + { resource: savedObjects[0].id, privilege, authorized: true }, + { resource: savedObjects[1].id, privilege, authorized: false }, + ], }); const mockInternalRepository = { find: jest.fn().mockReturnValue({ diff --git a/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.ts b/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.ts index 22c34c03368e3..0c066fb76994f 100644 --- a/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.ts +++ b/x-pack/plugins/spaces/server/lib/spaces_client/spaces_client.ts @@ -74,16 +74,14 @@ export class SpacesClient { const privilege = privilegeFactory(this.authorization!); - const { username, spacePrivileges } = await checkPrivileges.atSpaces(spaceIds, privilege); + const { username, privileges } = await checkPrivileges.atSpaces(spaceIds, privilege); - const authorized = Object.keys(spacePrivileges).filter(spaceId => { - return spacePrivileges[spaceId][privilege]; - }); + const authorized = privileges.filter(x => x.authorized).map(x => x.resource); this.debugLogger( `SpacesClient.getAll(), authorized for ${ authorized.length - } spaces, derived from ES privilege check: ${JSON.stringify(spacePrivileges)}` + } spaces, derived from ES privilege check: ${JSON.stringify(privileges)}` ); if (authorized.length === 0) { @@ -94,7 +92,7 @@ export class SpacesClient { throw Boom.forbidden(); } - this.auditLogger.spacesAuthorizationSuccess(username, 'getAll', authorized); + this.auditLogger.spacesAuthorizationSuccess(username, 'getAll', authorized as string[]); const filteredSpaces: Space[] = spaces.filter((space: any) => authorized.includes(space.id)); this.debugLogger( `SpacesClient.getAll(), using RBAC. returning spaces: ${filteredSpaces @@ -211,9 +209,9 @@ export class SpacesClient { throw Boom.badRequest('This Space cannot be deleted because it is reserved.'); } - await repository.delete('space', id); - await repository.deleteByNamespace(id); + + await repository.delete('space', id); } private useRbac(): boolean { diff --git a/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts b/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts index f2ba8785f5a3f..511e9676940d2 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts @@ -11,7 +11,13 @@ import { mockRouteContext, mockRouteContextWithInvalidLicense, } from '../__fixtures__'; -import { CoreSetup, IRouter, kibanaResponseFactory, RouteValidatorConfig } from 'src/core/server'; +import { + CoreSetup, + IRouter, + kibanaResponseFactory, + RouteValidatorConfig, + SavedObjectsErrorHelpers, +} from 'src/core/server'; import { loggingServiceMock, httpServiceMock, @@ -75,6 +81,7 @@ describe('Spaces Public API', () => { return { routeValidation: routeDefinition.validate as RouteValidatorConfig<{}, {}, {}>, routeHandler, + savedObjectsRepositoryMock, }; }; @@ -143,6 +150,27 @@ describe('Spaces Public API', () => { expect(status).toEqual(404); }); + it(`returns http/400 when scripts cannot be executed in Elasticsearch`, async () => { + const { routeHandler, savedObjectsRepositoryMock } = await setup(); + + const request = httpServerMock.createKibanaRequest({ + params: { + id: 'a-space', + }, + method: 'delete', + }); + // @ts-ignore + savedObjectsRepositoryMock.deleteByNamespace.mockRejectedValue( + SavedObjectsErrorHelpers.decorateEsCannotExecuteScriptError(new Error()) + ); + const response = await routeHandler(mockRouteContext, request, kibanaResponseFactory); + + const { status, payload } = response; + + expect(status).toEqual(400); + expect(payload.message).toEqual('Cannot execute script in Elasticsearch query'); + }); + it(`DELETE spaces/{id}' cannot delete reserved spaces`, async () => { const { routeHandler } = await setup(); diff --git a/x-pack/plugins/spaces/server/routes/api/external/delete.ts b/x-pack/plugins/spaces/server/routes/api/external/delete.ts index 4b7e6b00182ac..150f1d198cdf6 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/delete.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/delete.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import Boom from 'boom'; import { schema } from '@kbn/config-schema'; import { SavedObjectsErrorHelpers } from '../../../../../../../src/core/server'; import { wrapError } from '../../../lib/errors'; @@ -12,7 +13,7 @@ import { ExternalRouteDeps } from '.'; import { createLicensedRouteHandler } from '../../lib'; export function initDeleteSpacesApi(deps: ExternalRouteDeps) { - const { externalRouter, spacesService } = deps; + const { externalRouter, log, spacesService } = deps; externalRouter.delete( { @@ -33,6 +34,13 @@ export function initDeleteSpacesApi(deps: ExternalRouteDeps) { } catch (error) { if (SavedObjectsErrorHelpers.isNotFoundError(error)) { return response.notFound(); + } else if (SavedObjectsErrorHelpers.isEsCannotExecuteScriptError(error)) { + log.error( + `Failed to delete space '${id}', cannot execute script in Elasticsearch query: ${error.message}` + ); + return response.customError( + wrapError(Boom.badRequest('Cannot execute script in Elasticsearch query')) + ); } return response.customError(wrapError(error)); } diff --git a/x-pack/plugins/spaces/server/routes/api/external/index.ts b/x-pack/plugins/spaces/server/routes/api/external/index.ts index 1bdb7ceb8a3f7..079f690bfe546 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/index.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/index.ts @@ -12,6 +12,8 @@ import { initPostSpacesApi } from './post'; import { initPutSpacesApi } from './put'; import { SpacesServiceSetup } from '../../../spaces_service/spaces_service'; import { initCopyToSpacesApi } from './copy_to_space'; +import { initShareAddSpacesApi } from './share_add_spaces'; +import { initShareRemoveSpacesApi } from './share_remove_spaces'; export interface ExternalRouteDeps { externalRouter: IRouter; @@ -28,4 +30,6 @@ export function initExternalSpacesApi(deps: ExternalRouteDeps) { initPostSpacesApi(deps); initPutSpacesApi(deps); initCopyToSpacesApi(deps); + initShareAddSpacesApi(deps); + initShareRemoveSpacesApi(deps); } diff --git a/x-pack/plugins/spaces/server/routes/api/external/share_add_spaces.ts b/x-pack/plugins/spaces/server/routes/api/external/share_add_spaces.ts new file mode 100644 index 0000000000000..f40cc5cc50572 --- /dev/null +++ b/x-pack/plugins/spaces/server/routes/api/external/share_add_spaces.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { wrapError } from '../../../lib/errors'; +import { ExternalRouteDeps } from '.'; +import { SPACE_ID_REGEX } from '../../../lib/space_schema'; +import { createLicensedRouteHandler } from '../../lib'; + +const uniq = (arr: T[]): T[] => Array.from(new Set(arr)); +export function initShareAddSpacesApi(deps: ExternalRouteDeps) { + const { externalRouter, getStartServices } = deps; + + externalRouter.post( + { + path: '/api/spaces/_share_saved_object_add', + validate: { + body: schema.object({ + spaces: schema.arrayOf( + schema.string({ + validate: value => { + if (!SPACE_ID_REGEX.test(value)) { + return `lower case, a-z, 0-9, "_", and "-" are allowed`; + } + }, + }), + { + validate: spaceIds => { + if (!spaceIds.length) { + return 'must specify one or more space ids'; + } else if (uniq(spaceIds).length !== spaceIds.length) { + return 'duplicate space ids are not allowed'; + } + }, + } + ), + object: schema.object({ + type: schema.string(), + id: schema.string(), + }), + }), + }, + }, + createLicensedRouteHandler(async (_context, request, response) => { + const [startServices] = await getStartServices(); + const scopedClient = startServices.savedObjects.getScopedClient(request); + + const spaces = request.body.spaces; + const { type, id } = request.body.object; + + try { + await scopedClient.addToNamespaces(type, id, spaces); + } catch (error) { + return response.customError(wrapError(error)); + } + return response.noContent(); + }) + ); +} diff --git a/x-pack/plugins/spaces/server/routes/api/external/share_remove_spaces.ts b/x-pack/plugins/spaces/server/routes/api/external/share_remove_spaces.ts new file mode 100644 index 0000000000000..5f58a5dfd5e5f --- /dev/null +++ b/x-pack/plugins/spaces/server/routes/api/external/share_remove_spaces.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { wrapError } from '../../../lib/errors'; +import { ExternalRouteDeps } from '.'; +import { SPACE_ID_REGEX } from '../../../lib/space_schema'; +import { createLicensedRouteHandler } from '../../lib'; + +const uniq = (arr: T[]): T[] => Array.from(new Set(arr)); +export function initShareRemoveSpacesApi(deps: ExternalRouteDeps) { + const { externalRouter, getStartServices } = deps; + + externalRouter.post( + { + path: '/api/spaces/_share_saved_object_remove', + validate: { + body: schema.object({ + spaces: schema.arrayOf( + schema.string({ + validate: value => { + if (!SPACE_ID_REGEX.test(value)) { + return `lower case, a-z, 0-9, "_", and "-" are allowed`; + } + }, + }), + { + validate: spaceIds => { + if (!spaceIds.length) { + return 'must specify one or more space ids'; + } else if (uniq(spaceIds).length !== spaceIds.length) { + return 'duplicate space ids are not allowed'; + } + }, + } + ), + object: schema.object({ + type: schema.string(), + id: schema.string(), + }), + }), + }, + }, + createLicensedRouteHandler(async (_context, request, response) => { + const [startServices] = await getStartServices(); + const scopedClient = startServices.savedObjects.getScopedClient(request); + + const spaces = request.body.spaces; + const { type, id } = request.body.object; + + try { + await scopedClient.deleteFromNamespaces(type, id, spaces); + } catch (error) { + return response.customError(wrapError(error)); + } + return response.noContent(); + }) + ); +} diff --git a/x-pack/plugins/spaces/server/saved_objects/__snapshots__/spaces_saved_objects_client.test.ts.snap b/x-pack/plugins/spaces/server/saved_objects/__snapshots__/spaces_saved_objects_client.test.ts.snap deleted file mode 100644 index 8b1a258138355..0000000000000 --- a/x-pack/plugins/spaces/server/saved_objects/__snapshots__/spaces_saved_objects_client.test.ts.snap +++ /dev/null @@ -1,29 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`default space #bulkCreate throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`default space #bulkGet throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`default space #create throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`default space #delete throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`default space #find throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`default space #get throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`default space #update throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`space_1 space #bulkCreate throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`space_1 space #bulkGet throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`space_1 space #create throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`space_1 space #delete throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`space_1 space #find throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`space_1 space #get throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; - -exports[`space_1 space #update throws error if options.namespace is specified 1`] = `"Spaces currently determines the namespaces"`; diff --git a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts index 2d6fe36792c40..f9961329c088b 100644 --- a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts +++ b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts @@ -50,42 +50,41 @@ const createMockResponse = () => ({ references: [], }); +const ERROR_NAMESPACE_SPECIFIED = 'Spaces currently determines the namespaces'; + [ { id: DEFAULT_SPACE_ID, expectedNamespace: undefined }, { id: 'space_1', expectedNamespace: 'space_1' }, ].forEach(currentSpace => { describe(`${currentSpace.id} space`, () => { + const createSpacesSavedObjectsClient = async () => { + const request = createMockRequest(); + const baseClient = createMockClient(); + const spacesService = await createSpacesService(currentSpace.id); + + const client = new SpacesSavedObjectsClient({ + request, + baseClient, + spacesService, + typeRegistry, + }); + return { client, baseClient }; + }; + describe('#get', () => { test(`throws error if options.namespace is specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + const { client } = await createSpacesSavedObjectsClient(); - await expect( - client.get('foo', '', { namespace: 'bar' }) - ).rejects.toThrowErrorMatchingSnapshot(); + await expect(client.get('foo', '', { namespace: 'bar' })).rejects.toThrow( + ERROR_NAMESPACE_SPECIFIED + ); }); - test(`supplements options with undefined namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); const expectedReturnValue = createMockResponse(); baseClient.get.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const type = Symbol(); const id = Symbol(); const options = Object.freeze({ foo: 'bar' }); @@ -102,37 +101,17 @@ const createMockResponse = () => ({ describe('#bulkGet', () => { test(`throws error if options.namespace is specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + const { client } = await createSpacesSavedObjectsClient(); await expect( client.bulkGet([{ id: '', type: 'foo' }], { namespace: 'bar' }) - ).rejects.toThrowErrorMatchingSnapshot(); + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); }); - test(`supplements options with undefined namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const expectedReturnValue = { - saved_objects: [createMockResponse()], - }; + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); + const expectedReturnValue = { saved_objects: [createMockResponse()] }; baseClient.bulkGet.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const objects = [{ type: 'foo' }]; const options = Object.freeze({ foo: 'bar' }); @@ -149,25 +128,15 @@ const createMockResponse = () => ({ describe('#find', () => { test(`throws error if options.namespace is specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + const { client } = await createSpacesSavedObjectsClient(); - await expect( - client.find({ type: 'foo', namespace: 'bar' }) - ).rejects.toThrowErrorMatchingSnapshot(); + await expect(client.find({ type: 'foo', namespace: 'bar' })).rejects.toThrow( + ERROR_NAMESPACE_SPECIFIED + ); }); test(`passes options.type to baseClient if valid singular type specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); + const { client, baseClient } = await createSpacesSavedObjectsClient(); const expectedReturnValue = { saved_objects: [createMockResponse()], total: 1, @@ -175,16 +144,8 @@ const createMockResponse = () => ({ page: 0, }; baseClient.find.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const options = Object.freeze({ type: 'foo' }); - const actualReturnValue = await client.find(options); expect(actualReturnValue).toBe(expectedReturnValue); @@ -194,9 +155,8 @@ const createMockResponse = () => ({ }); }); - test(`supplements options with undefined namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); const expectedReturnValue = { saved_objects: [createMockResponse()], total: 1, @@ -204,14 +164,6 @@ const createMockResponse = () => ({ page: 0, }; baseClient.find.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const options = Object.freeze({ type: ['foo', 'bar'] }); const actualReturnValue = await client.find(options); @@ -226,35 +178,17 @@ const createMockResponse = () => ({ describe('#create', () => { test(`throws error if options.namespace is specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + const { client } = await createSpacesSavedObjectsClient(); - await expect( - client.create('foo', {}, { namespace: 'bar' }) - ).rejects.toThrowErrorMatchingSnapshot(); + await expect(client.create('foo', {}, { namespace: 'bar' })).rejects.toThrow( + ERROR_NAMESPACE_SPECIFIED + ); }); - test(`supplements options with undefined namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); const expectedReturnValue = createMockResponse(); baseClient.create.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const type = Symbol(); const attributes = Symbol(); @@ -272,37 +206,17 @@ const createMockResponse = () => ({ describe('#bulkCreate', () => { test(`throws error if options.namespace is specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + const { client } = await createSpacesSavedObjectsClient(); await expect( client.bulkCreate([{ id: '', type: 'foo', attributes: {} }], { namespace: 'bar' }) - ).rejects.toThrowErrorMatchingSnapshot(); + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); }); - test(`supplements options with undefined namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const expectedReturnValue = { - saved_objects: [createMockResponse()], - }; + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); + const expectedReturnValue = { saved_objects: [createMockResponse()] }; baseClient.bulkCreate.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const objects = [{ type: 'foo' }]; const options = Object.freeze({ foo: 'bar' }); @@ -319,36 +233,18 @@ const createMockResponse = () => ({ describe('#update', () => { test(`throws error if options.namespace is specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + const { client } = await createSpacesSavedObjectsClient(); await expect( // @ts-ignore client.update(null, null, null, { namespace: 'bar' }) - ).rejects.toThrowErrorMatchingSnapshot(); + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); }); - test(`supplements options with undefined namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); const expectedReturnValue = createMockResponse(); baseClient.update.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const type = Symbol(); const id = Symbol(); @@ -366,21 +262,19 @@ const createMockResponse = () => ({ }); describe('#bulkUpdate', () => { - test(`supplements options with the spaces namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const expectedReturnValue = { - saved_objects: [createMockResponse()], - }; - baseClient.bulkUpdate.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); + test(`throws error if options.namespace is specified`, async () => { + const { client } = await createSpacesSavedObjectsClient(); - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + await expect( + // @ts-ignore + client.bulkUpdate(null, { namespace: 'bar' }) + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); + }); + + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); + const expectedReturnValue = { saved_objects: [createMockResponse()] }; + baseClient.bulkUpdate.mockReturnValue(Promise.resolve(expectedReturnValue)); const actualReturnValue = await client.bulkUpdate([ { id: 'id', type: 'foo', attributes: {}, references: [] }, @@ -403,36 +297,18 @@ const createMockResponse = () => ({ describe('#delete', () => { test(`throws error if options.namespace is specified`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); + const { client } = await createSpacesSavedObjectsClient(); await expect( // @ts-ignore client.delete(null, null, { namespace: 'bar' }) - ).rejects.toThrowErrorMatchingSnapshot(); + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); }); - test(`supplements options with undefined namespace`, async () => { - const request = createMockRequest(); - const baseClient = createMockClient(); + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); const expectedReturnValue = createMockResponse(); baseClient.delete.mockReturnValue(Promise.resolve(expectedReturnValue)); - const spacesService = await createSpacesService(currentSpace.id); - - const client = new SpacesSavedObjectsClient({ - request, - baseClient, - spacesService, - typeRegistry, - }); const type = Symbol(); const id = Symbol(); @@ -447,5 +323,65 @@ const createMockResponse = () => ({ }); }); }); + + describe('#addToNamespaces', () => { + test(`throws error if options.namespace is specified`, async () => { + const { client } = await createSpacesSavedObjectsClient(); + + await expect( + // @ts-ignore + client.addToNamespaces(null, null, null, { namespace: 'bar' }) + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); + }); + + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); + const expectedReturnValue = createMockResponse(); + baseClient.addToNamespaces.mockReturnValue(Promise.resolve(expectedReturnValue)); + + const type = Symbol(); + const id = Symbol(); + const namespaces = Symbol(); + const options = Object.freeze({ foo: 'bar' }); + // @ts-ignore + const actualReturnValue = await client.addToNamespaces(type, id, namespaces, options); + + expect(actualReturnValue).toBe(expectedReturnValue); + expect(baseClient.addToNamespaces).toHaveBeenCalledWith(type, id, namespaces, { + foo: 'bar', + namespace: currentSpace.expectedNamespace, + }); + }); + }); + + describe('#deleteFromNamespaces', () => { + test(`throws error if options.namespace is specified`, async () => { + const { client } = await createSpacesSavedObjectsClient(); + + await expect( + // @ts-ignore + client.deleteFromNamespaces(null, null, null, { namespace: 'bar' }) + ).rejects.toThrow(ERROR_NAMESPACE_SPECIFIED); + }); + + test(`supplements options with the current namespace`, async () => { + const { client, baseClient } = await createSpacesSavedObjectsClient(); + const expectedReturnValue = createMockResponse(); + baseClient.deleteFromNamespaces.mockReturnValue(Promise.resolve(expectedReturnValue)); + + const type = Symbol(); + const id = Symbol(); + const namespaces = Symbol(); + const options = Object.freeze({ foo: 'bar' }); + // @ts-ignore + const actualReturnValue = await client.deleteFromNamespaces(type, id, namespaces, options); + + expect(actualReturnValue).toBe(expectedReturnValue); + expect(baseClient.deleteFromNamespaces).toHaveBeenCalledWith(type, id, namespaces, { + foo: 'bar', + namespace: currentSpace.expectedNamespace, + }); + }); + }); }); }); diff --git a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts index f216d5743cf89..e31bc7cef6900 100644 --- a/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts +++ b/x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.ts @@ -13,6 +13,8 @@ import { SavedObjectsCreateOptions, SavedObjectsFindOptions, SavedObjectsUpdateOptions, + SavedObjectsAddToNamespacesOptions, + SavedObjectsDeleteFromNamespacesOptions, ISavedObjectTypeRegistry, } from 'src/core/server'; import { SpacesServiceSetup } from '../spaces_service/spaces_service'; @@ -213,6 +215,50 @@ export class SpacesSavedObjectsClient implements SavedObjectsClientContract { }); } + /** + * Adds namespaces to a SavedObject + * + * @param type + * @param id + * @param namespaces + * @param options + */ + public async addToNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsAddToNamespacesOptions = {} + ) { + throwErrorIfNamespaceSpecified(options); + + return await this.client.addToNamespaces(type, id, namespaces, { + ...options, + namespace: spaceIdToNamespace(this.spaceId), + }); + } + + /** + * Removes namespaces from a SavedObject + * + * @param type + * @param id + * @param namespaces + * @param options + */ + public async deleteFromNamespaces( + type: string, + id: string, + namespaces: string[], + options: SavedObjectsDeleteFromNamespacesOptions = {} + ) { + throwErrorIfNamespaceSpecified(options); + + return await this.client.deleteFromNamespaces(type, id, namespaces, { + ...options, + namespace: spaceIdToNamespace(this.spaceId), + }); + } + /** * Updates an array of objects by id * diff --git a/x-pack/plugins/uptime/server/rest_api/types.ts b/x-pack/plugins/uptime/server/rest_api/types.ts index aecb099b7bed5..e05e7a4d7faf1 100644 --- a/x-pack/plugins/uptime/server/rest_api/types.ts +++ b/x-pack/plugins/uptime/server/rest_api/types.ts @@ -10,7 +10,7 @@ import { RouteConfig, RouteMethod, CallAPIOptions, - SavedObjectsClient, + SavedObjectsClientContract, RequestHandlerContext, KibanaRequest, KibanaResponseFactory, @@ -69,18 +69,7 @@ export interface UMRouteParams { options?: CallAPIOptions | undefined ) => Promise; dynamicSettings: DynamicSettings; - savedObjectsClient: Pick< - SavedObjectsClient, - | 'errors' - | 'create' - | 'bulkCreate' - | 'delete' - | 'find' - | 'bulkGet' - | 'get' - | 'update' - | 'bulkUpdate' - >; + savedObjectsClient: SavedObjectsClientContract; } /** diff --git a/x-pack/test/api_integration/apis/spaces/saved_objects.ts b/x-pack/test/api_integration/apis/spaces/saved_objects.ts index 05f14a50f2170..7584be7fd8498 100644 --- a/x-pack/test/api_integration/apis/spaces/saved_objects.ts +++ b/x-pack/test/api_integration/apis/spaces/saved_objects.ts @@ -89,7 +89,7 @@ export default function({ getService }: FtrProviderContext) { .expect(404) .then((response: Record) => { expect(response.body).to.eql({ - message: 'Not Found', + message: 'Saved object [space/default] not found', statusCode: 404, error: 'Not Found', }); diff --git a/x-pack/test/saved_object_api_integration/common/config.ts b/x-pack/test/saved_object_api_integration/common/config.ts index dda7934ce875a..eaf7230a832a8 100644 --- a/x-pack/test/saved_object_api_integration/common/config.ts +++ b/x-pack/test/saved_object_api_integration/common/config.ts @@ -56,8 +56,10 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ...config.xpack.api.get('kbnTestServer.serverArgs'), '--optimize.enabled=false', '--server.xsrf.disableProtection=true', + `--plugin-path=${path.join(__dirname, 'fixtures', 'isolated_type_plugin')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'namespace_agnostic_type_plugin')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'hidden_type_plugin')}`, + `--plugin-path=${path.join(__dirname, 'fixtures', 'shared_type_plugin')}`, ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), ], }, diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json b/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json index 34361ad9df542..d2c14189e2529 100644 --- a/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json +++ b/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json @@ -53,7 +53,7 @@ { "type": "doc", "value": { - "id": "index-pattern:91200a00-9efd-11e7-acb3-3dab96693fab", + "id": "index-pattern:defaultspace-index-pattern-id", "index": ".kibana", "source": { "index-pattern": { @@ -76,7 +76,7 @@ "source": { "config": { "buildNum": 8467, - "defaultIndex": "91200a00-9efd-11e7-acb3-3dab96693fab" + "defaultIndex": "defaultspace-index-pattern-id" }, "type": "config", "updated_at": "2017-09-21T18:49:16.302Z" @@ -88,15 +88,15 @@ { "type": "doc", "value": { - "id": "visualization:dd7caf20-9efd-11e7-acb3-3dab96693fab", + "id": "isolatedtype:defaultspace-isolatedtype-id", "index": ".kibana", "source": { - "type": "visualization", + "type": "isolatedtype", "updated_at": "2017-09-21T18:51:23.794Z", - "visualization": { + "isolatedtype": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"91200a00-9efd-11e7-acb3-3dab96693fab\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + "searchSourceJSON": "{\"index\":\"defaultspace-index-pattern-id\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" }, "title": "Count of requests", "uiStateJSON": "{\"spy\":{\"mode\":{\"name\":null,\"fill\":false}}}", @@ -111,7 +111,7 @@ { "type": "doc", "value": { - "id": "dashboard:be3733a0-9efe-11e7-acb3-3dab96693fab", + "id": "dashboard:defaultspace-dashboard-id", "index": ".kibana", "source": { "dashboard": { @@ -121,7 +121,7 @@ "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{}", - "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"dd7caf20-9efd-11e7-acb3-3dab96693fab\",\"col\":1,\"row\":1}]", + "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"isolatedtype\",\"id\":\"defaultspace-isolatedtype-id\",\"col\":1,\"row\":1}]", "refreshInterval": { "display": "Off", "pause": false, @@ -144,7 +144,7 @@ { "type": "doc", "value": { - "id": "space_1:index-pattern:space_1-91200a00-9efd-11e7-acb3-3dab96693fab", + "id": "space_1:index-pattern:space1-index-pattern-id", "index": ".kibana", "source": { "index-pattern": { @@ -168,7 +168,7 @@ "source": { "config": { "buildNum": 8467, - "defaultIndex": "91200a00-9efd-11e7-acb3-3dab96693fab" + "defaultIndex": "defaultspace-index-pattern-id" }, "namespace": "space_1", "type": "config", @@ -181,16 +181,16 @@ { "type": "doc", "value": { - "id": "space_1:visualization:space_1-dd7caf20-9efd-11e7-acb3-3dab96693fab", + "id": "space_1:isolatedtype:space1-isolatedtype-id", "index": ".kibana", "source": { "namespace": "space_1", - "type": "visualization", + "type": "isolatedtype", "updated_at": "2017-09-21T18:51:23.794Z", - "visualization": { + "isolatedtype": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"space_1-91200a00-9efd-11e7-acb3-3dab96693fab\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + "searchSourceJSON": "{\"index\":\"space1-index-pattern-id\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" }, "title": "Count of requests", "uiStateJSON": "{\"spy\":{\"mode\":{\"name\":null,\"fill\":false}}}", @@ -205,7 +205,7 @@ { "type": "doc", "value": { - "id": "space_1:dashboard:space_1-be3733a0-9efe-11e7-acb3-3dab96693fab", + "id": "space_1:dashboard:space1-dashboard-id", "index": ".kibana", "source": { "dashboard": { @@ -215,7 +215,7 @@ "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{}", - "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"space_1-dd7caf20-9efd-11e7-acb3-3dab96693fab\",\"col\":1,\"row\":1}]", + "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"isolatedtype\",\"id\":\"space1-isolatedtype-id\",\"col\":1,\"row\":1}]", "refreshInterval": { "display": "Off", "pause": false, @@ -239,7 +239,7 @@ { "type": "doc", "value": { - "id": "space_2:index-pattern:space_2-91200a00-9efd-11e7-acb3-3dab96693fab", + "id": "space_2:index-pattern:space2-index-pattern-id", "index": ".kibana", "source": { "index-pattern": { @@ -263,7 +263,7 @@ "source": { "config": { "buildNum": 8467, - "defaultIndex": "91200a00-9efd-11e7-acb3-3dab96693fab" + "defaultIndex": "defaultspace-index-pattern-id" }, "namespace": "space_2", "type": "config", @@ -276,16 +276,16 @@ { "type": "doc", "value": { - "id": "space_2:visualization:space_2-dd7caf20-9efd-11e7-acb3-3dab96693fab", + "id": "space_2:isolatedtype:space2-isolatedtype-id", "index": ".kibana", "source": { "namespace": "space_2", - "type": "visualization", + "type": "isolatedtype", "updated_at": "2017-09-21T18:51:23.794Z", - "visualization": { + "isolatedtype": { "description": "", "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"space_2-91200a00-9efd-11e7-acb3-3dab96693fab\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" + "searchSourceJSON": "{\"index\":\"space2-index-pattern-id\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}" }, "title": "Count of requests", "uiStateJSON": "{\"spy\":{\"mode\":{\"name\":null,\"fill\":false}}}", @@ -300,7 +300,7 @@ { "type": "doc", "value": { - "id": "space_2:dashboard:space_2-be3733a0-9efe-11e7-acb3-3dab96693fab", + "id": "space_2:dashboard:space2-dashboard-id", "index": ".kibana", "source": { "dashboard": { @@ -310,7 +310,7 @@ "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"highlightAll\":true,\"version\":true}" }, "optionsJSON": "{}", - "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"visualization\",\"id\":\"space_2-dd7caf20-9efd-11e7-acb3-3dab96693fab\",\"col\":1,\"row\":1}]", + "panelsJSON": "[{\"size_x\":6,\"size_y\":3,\"panelIndex\":1,\"type\":\"isolatedtype\",\"id\":\"space2-isolatedtype-id\",\"col\":1,\"row\":1}]", "refreshInterval": { "display": "Off", "pause": false, @@ -334,11 +334,11 @@ { "type": "doc", "value": { - "id": "globaltype:8121a00-8efd-21e7-1cb3-34ab966434445", + "id": "globaltype:globaltype-id", "index": ".kibana", "source": { "globaltype": { - "name": "My favorite global object" + "title": "My favorite global object" }, "type": "globaltype", "updated_at": "2017-09-21T18:59:16.270Z" @@ -346,3 +346,54 @@ "type": "doc" } } + +{ + "type": "doc", + "value": { + "id": "sharedtype:default_and_space_1", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the default and space_1 spaces" + }, + "type": "sharedtype", + "namespaces": ["default", "space_1"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:only_space_1", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object only in space_1" + }, + "type": "sharedtype", + "namespaces": ["space_1"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:only_space_2", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object only in space_2" + }, + "type": "sharedtype", + "namespaces": ["space_2"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json b/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json index c2489f2a906c8..7b5b1d86f6bcc 100644 --- a/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json +++ b/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json @@ -82,7 +82,7 @@ }, "globaltype": { "properties": { - "name": { + "title": { "fields": { "keyword": { "ignore_above": 2048, @@ -147,9 +147,41 @@ } } }, + "isolatedtype": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + }, "namespace": { "type": "keyword" }, + "namespaces": { + "type": "keyword" + }, "search": { "properties": { "columns": { @@ -186,6 +218,19 @@ } } }, + "sharedtype": { + "properties": { + "title": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + }, "space": { "properties": { "_reserved": { @@ -282,35 +327,6 @@ "type": "text" } } - }, - "visualization": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "savedSearchId": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "type": "text" - } - } } } }, @@ -322,4 +338,4 @@ } } } -} \ No newline at end of file +} diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/index.js b/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/index.js index ea32811794c47..5989db84e2290 100644 --- a/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/index.js +++ b/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/index.js @@ -21,5 +21,7 @@ export default function(kibana) { }, config() {}, + + init() {}, // need empty init for plugin to load }); } diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/mappings.json b/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/mappings.json index e4815273964a1..45f898e10e2ba 100644 --- a/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/mappings.json +++ b/x-pack/test/saved_object_api_integration/common/fixtures/hidden_type_plugin/mappings.json @@ -1,7 +1,7 @@ { "hiddentype": { "properties": { - "name": { + "title": { "type": "text", "fields": { "keyword": { diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/index.js b/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/index.js new file mode 100644 index 0000000000000..a406c6737da5f --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/index.js @@ -0,0 +1,26 @@ +/* + * 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 mappings from './mappings.json'; + +export default function(kibana) { + return new kibana.Plugin({ + require: ['kibana', 'elasticsearch', 'xpack_main'], + name: 'isolated_type_plugin', + uiExports: { + savedObjectsManagement: { + isolatedtype: { + isImportableAndExportable: true, + }, + }, + mappings, + }, + + config() {}, + + init() {}, // need empty init for plugin to load + }); +} diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/mappings.json b/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/mappings.json new file mode 100644 index 0000000000000..141ebbc93c290 --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/mappings.json @@ -0,0 +1,31 @@ +{ + "isolatedtype": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + } +} diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/package.json b/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/package.json new file mode 100644 index 0000000000000..665ecb1b31d7e --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/fixtures/isolated_type_plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "isolated_type_plugin", + "version": "0.0.0", + "kibana": { + "version": "kibana" + } +} diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/namespace_agnostic_type_plugin/mappings.json b/x-pack/test/saved_object_api_integration/common/fixtures/namespace_agnostic_type_plugin/mappings.json index b30a2c3877b88..64d309b4209a2 100644 --- a/x-pack/test/saved_object_api_integration/common/fixtures/namespace_agnostic_type_plugin/mappings.json +++ b/x-pack/test/saved_object_api_integration/common/fixtures/namespace_agnostic_type_plugin/mappings.json @@ -1,7 +1,7 @@ { "globaltype": { "properties": { - "name": { + "title": { "type": "text", "fields": { "keyword": { diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/index.js b/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/index.js new file mode 100644 index 0000000000000..91a24fb9f4f56 --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/index.js @@ -0,0 +1,27 @@ +/* + * 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 mappings from './mappings.json'; + +export default function(kibana) { + return new kibana.Plugin({ + require: ['kibana', 'elasticsearch', 'xpack_main'], + name: 'shared_type_plugin', + uiExports: { + savedObjectsManagement: {}, + savedObjectSchemas: { + sharedtype: { + multiNamespace: true, + }, + }, + mappings, + }, + + config() {}, + + init() {}, // need empty init for plugin to load + }); +} diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/mappings.json b/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/mappings.json new file mode 100644 index 0000000000000..918958aec0d6d --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/mappings.json @@ -0,0 +1,15 @@ +{ + "sharedtype": { + "properties": { + "title": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + } +} diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/package.json b/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/package.json new file mode 100644 index 0000000000000..c52f4256c5c06 --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/fixtures/shared_type_plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "shared_type_plugin", + "version": "0.0.0", + "kibana": { + "version": "kibana" + } +} diff --git a/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_cases.ts b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_cases.ts new file mode 100644 index 0000000000000..b32950538f8e5 --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_cases.ts @@ -0,0 +1,40 @@ +/* + * 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 SAVED_OBJECT_TEST_CASES = Object.freeze({ + SINGLE_NAMESPACE_DEFAULT_SPACE: Object.freeze({ + type: 'isolatedtype', + id: 'defaultspace-isolatedtype-id', + }), + SINGLE_NAMESPACE_SPACE_1: Object.freeze({ + type: 'isolatedtype', + id: 'space1-isolatedtype-id', + }), + SINGLE_NAMESPACE_SPACE_2: Object.freeze({ + type: 'isolatedtype', + id: 'space2-isolatedtype-id', + }), + MULTI_NAMESPACE_DEFAULT_AND_SPACE_1: Object.freeze({ + type: 'sharedtype', + id: 'default_and_space_1', + }), + MULTI_NAMESPACE_ONLY_SPACE_1: Object.freeze({ + type: 'sharedtype', + id: 'only_space_1', + }), + MULTI_NAMESPACE_ONLY_SPACE_2: Object.freeze({ + type: 'sharedtype', + id: 'only_space_2', + }), + NAMESPACE_AGNOSTIC: Object.freeze({ + type: 'globaltype', + id: 'globaltype-id', + }), + HIDDEN: Object.freeze({ + type: 'hiddentype', + id: 'any', + }), +}); diff --git a/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts new file mode 100644 index 0000000000000..5640dfefa4f8d --- /dev/null +++ b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts @@ -0,0 +1,302 @@ +/* + * 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 { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; +import { SAVED_OBJECT_TEST_CASES as CASES } from './saved_object_test_cases'; +import { SPACES } from './spaces'; +import { AUTHENTICATION } from './authentication'; +import { TestCase, TestUser, ExpectResponseBody } from './types'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { + NOT_A_KIBANA_USER, + SUPERUSER, + KIBANA_LEGACY_USER, + KIBANA_DUAL_PRIVILEGES_USER, + KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, + KIBANA_RBAC_USER, + KIBANA_RBAC_DASHBOARD_ONLY_USER, + KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, + KIBANA_RBAC_DEFAULT_SPACE_READ_USER, + KIBANA_RBAC_SPACE_1_ALL_USER, + KIBANA_RBAC_SPACE_1_READ_USER, +} = AUTHENTICATION; + +export function getUrlPrefix(spaceId: string) { + return spaceId && spaceId !== DEFAULT_SPACE_ID ? `/s/${spaceId}` : ``; +} + +export function getExpectedSpaceIdProperty(spaceId: string) { + if (spaceId === DEFAULT_SPACE_ID) { + return {}; + } + return { + spaceId, + }; +} + +export const getTestTitle = ( + testCaseOrCases: TestCase | TestCase[], + bulkStatusCode?: 200 | 403 // only used for bulk test suites; other suites specify forbidden/permitted in each test case +) => { + const testCases = Array.isArray(testCaseOrCases) ? testCaseOrCases : [testCaseOrCases]; + const stringify = (array: TestCase[]) => array.map(x => `${x.type}/${x.id}`).join(); + if (bulkStatusCode === 403 || (testCases.length === 1 && testCases[0].failure === 403)) { + return `forbidden [${stringify(testCases)}]`; + } + if (testCases.find(x => x.failure === 403)) { + throw new Error( + 'Cannot create test title for multiple forbidden test cases; specify individual tests for each of these test cases' + ); + } + // permitted + const list: string[] = []; + Object.entries({ + success: undefined, + 'bad request': 400, + 'not found': 404, + conflict: 409, + }).forEach(([descriptor, failure]) => { + const filtered = testCases.filter(x => x.failure === failure); + if (filtered.length) { + list.push(`${descriptor} [${stringify(filtered)}]`); + } + }); + return `${list.join(' and ')}`; +}; + +export const testCaseFailures = { + // test suites need explicit return types for number primitives + fail400: (condition?: boolean): { failure?: 400 } => + condition !== false ? { failure: 400 } : {}, + fail404: (condition?: boolean): { failure?: 404 } => + condition !== false ? { failure: 404 } : {}, + fail409: (condition?: boolean): { failure?: 409 } => + condition !== false ? { failure: 409 } : {}, +}; + +/** + * Test cases have additional properties that we don't want to send in HTTP Requests + */ +export const createRequest = ({ type, id }: TestCase) => ({ type, id }); + +const uniq = (arr: T[]): T[] => Array.from(new Set(arr)); +const isNamespaceAgnostic = (type: string) => type === 'globaltype'; +const isMultiNamespace = (type: string) => type === 'sharedtype'; +export const expectResponses = { + forbidden: (action: string) => (typeOrTypes: string | string[]): ExpectResponseBody => async ( + response: Record + ) => { + const types = Array.isArray(typeOrTypes) ? typeOrTypes : [typeOrTypes]; + const uniqueSorted = uniq(types).sort(); + expect(response.body).to.eql({ + statusCode: 403, + error: 'Forbidden', + message: `Unable to ${action} ${uniqueSorted.join()}`, + }); + }, + permitted: async (object: Record, testCase: TestCase) => { + const { type, id, failure } = testCase; + if (failure) { + let error: ReturnType; + if (failure === 400) { + error = SavedObjectsErrorHelpers.createUnsupportedTypeError(type); + } else if (failure === 404) { + error = SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); + } else if (failure === 409) { + error = SavedObjectsErrorHelpers.createConflictError(type, id); + } else { + throw new Error(`Encountered unexpected error code ${failure}`); + } + // should not call permitted with a 403 failure case + if (object.type && object.id) { + // bulk request error + expect(object.type).to.eql(type); + expect(object.id).to.eql(id); + expect(object.error).to.eql(error.output.payload); + } else { + // non-bulk request error + expect(object.error).to.eql(error.output.payload.error); + expect(object.statusCode).to.eql(error.output.payload.statusCode); + // ignore the error.message, because it can vary for decorated non-bulk errors (e.g., conflict) + } + } else { + // fall back to default behavior of testing the success outcome + expect(object.type).to.eql(type); + if (id) { + expect(object.id).to.eql(id); + } else { + // created an object without specifying the ID, so it was auto-generated + expect(object.id).to.match(/^[0-9a-f-]{36}$/); + } + expect(object).not.to.have.property('error'); + expect(object.updated_at).to.match(/^[\d-]{10}T[\d:\.]{12}Z$/); + // don't test attributes, version, or references + } + }, + /** + * Additional assertions that we use in `bulk_create` and `create` to ensure that + * newly-created (or overwritten) objects don't have unexpected properties + */ + successCreated: async (es: any, spaceId: string, type: string, id: string) => { + const isNamespaceUndefined = + spaceId === SPACES.DEFAULT.spaceId || isNamespaceAgnostic(type) || isMultiNamespace(type); + const expectedSpacePrefix = isNamespaceUndefined ? '' : `${spaceId}:`; + const savedObject = await es.get({ + id: `${expectedSpacePrefix}${type}:${id}`, + index: '.kibana', + }); + const { namespace: actualNamespace, namespaces: actualNamespaces } = savedObject._source; + if (isNamespaceUndefined) { + expect(actualNamespace).to.eql(undefined); + } else { + expect(actualNamespace).to.eql(spaceId); + } + if (isMultiNamespace(type)) { + if (id === CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1.id) { + expect(actualNamespaces).to.eql([DEFAULT_SPACE_ID, SPACE_1_ID]); + } else if (id === CASES.MULTI_NAMESPACE_ONLY_SPACE_1.id) { + expect(actualNamespaces).to.eql([SPACE_1_ID]); + } else if (id === CASES.MULTI_NAMESPACE_ONLY_SPACE_2.id) { + expect(actualNamespaces).to.eql([SPACE_2_ID]); + } else { + // newly created in this space + expect(actualNamespaces).to.eql([spaceId]); + } + } + return savedObject; + }, +}; + +/** + * Get test scenarios for each type of suite. + * @param modifier Use this to generate additional permutations of test scenarios. + * For instance, a modifier of ['foo', 'bar'] would return + * a `securityAndSpaces` of: [ + * { spaceId: DEFAULT_SPACE_ID, users: {...}, modifier: 'foo' }, + * { spaceId: DEFAULT_SPACE_ID, users: {...}, modifier: 'bar' }, + * { spaceId: SPACE_1_ID, users: {...}, modifier: 'foo' }, + * { spaceId: SPACE_1_ID, users: {...}, modifier: 'bar' }, + * ] + */ +export const getTestScenarios = (modifiers?: T[]) => { + const commonUsers = { + noAccess: { ...NOT_A_KIBANA_USER, description: 'user with no access' }, + superuser: { ...SUPERUSER, description: 'superuser' }, + legacyAll: { ...KIBANA_LEGACY_USER, description: 'legacy user' }, + allGlobally: { ...KIBANA_RBAC_USER, description: 'rbac user with all globally' }, + readGlobally: { + ...KIBANA_RBAC_DASHBOARD_ONLY_USER, + description: 'rbac user with read globally', + }, + dualAll: { ...KIBANA_DUAL_PRIVILEGES_USER, description: 'dual-privileges user' }, + dualRead: { + ...KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, + description: 'dual-privileges readonly user', + }, + }; + + interface Security { + modifier?: T; + users: Record< + | keyof typeof commonUsers + | 'allAtDefaultSpace' + | 'readAtDefaultSpace' + | 'allAtSpace1' + | 'readAtSpace1', + TestUser + >; + } + interface SecurityAndSpaces { + modifier?: T; + users: Record< + keyof typeof commonUsers | 'allAtSpace' | 'readAtSpace' | 'allAtOtherSpace', + TestUser + >; + spaceId: string; + } + interface Spaces { + modifier?: T; + spaceId: string; + } + + let spaces: Spaces[] = [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID].map(x => ({ spaceId: x })); + let security: Security[] = [ + { + users: { + ...commonUsers, + allAtDefaultSpace: { + ...KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, + description: 'rbac user with all at default space', + }, + readAtDefaultSpace: { + ...KIBANA_RBAC_DEFAULT_SPACE_READ_USER, + description: 'rbac user with read at default space', + }, + allAtSpace1: { + ...KIBANA_RBAC_SPACE_1_ALL_USER, + description: 'rbac user with all at space_1', + }, + readAtSpace1: { + ...KIBANA_RBAC_SPACE_1_READ_USER, + description: 'rbac user with read at space_1', + }, + }, + }, + ]; + let securityAndSpaces: SecurityAndSpaces[] = [ + { + spaceId: DEFAULT_SPACE_ID, + users: { + ...commonUsers, + allAtSpace: { + ...KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, + description: 'user with all at the space', + }, + readAtSpace: { + ...KIBANA_RBAC_DEFAULT_SPACE_READ_USER, + description: 'user with read at the space', + }, + allAtOtherSpace: { + ...KIBANA_RBAC_SPACE_1_ALL_USER, + description: 'user with all at other space', + }, + }, + }, + { + spaceId: SPACE_1_ID, + users: { + ...commonUsers, + allAtSpace: { ...KIBANA_RBAC_SPACE_1_ALL_USER, description: 'user with all at the space' }, + readAtSpace: { + ...KIBANA_RBAC_SPACE_1_READ_USER, + description: 'user with read at the space', + }, + allAtOtherSpace: { + ...KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, + description: 'user with all at other space', + }, + }, + }, + ]; + if (modifiers) { + const addModifier = (list: T[]) => + list.map(x => modifiers.map(modifier => ({ ...x, modifier }))).flat(); + spaces = addModifier(spaces); + security = addModifier(security); + securityAndSpaces = addModifier(securityAndSpaces); + } + return { + spaces, + security, + securityAndSpaces, + }; +}; diff --git a/x-pack/test/saved_object_api_integration/common/lib/space_test_utils.ts b/x-pack/test/saved_object_api_integration/common/lib/space_test_utils.ts deleted file mode 100644 index 1619d77761c84..0000000000000 --- a/x-pack/test/saved_object_api_integration/common/lib/space_test_utils.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; - -export function getUrlPrefix(spaceId: string) { - return spaceId && spaceId !== DEFAULT_SPACE_ID ? `/s/${spaceId}` : ``; -} - -export function getIdPrefix(spaceId: string) { - return spaceId === DEFAULT_SPACE_ID ? '' : `${spaceId}-`; -} - -export function getExpectedSpaceIdProperty(spaceId: string) { - if (spaceId === DEFAULT_SPACE_ID) { - return {}; - } - return { - spaceId, - }; -} diff --git a/x-pack/test/saved_object_api_integration/common/lib/types.ts b/x-pack/test/saved_object_api_integration/common/lib/types.ts index 487afff1494c0..f6e6d391ae905 100644 --- a/x-pack/test/saved_object_api_integration/common/lib/types.ts +++ b/x-pack/test/saved_object_api_integration/common/lib/types.ts @@ -4,9 +4,28 @@ * you may not use this file except in compliance with the Elastic License. */ -export type DescribeFn = (text: string, fn: () => void) => void; +export type ExpectResponseBody = (response: Record) => Promise; -export interface TestDefinitionAuthentication { - username?: string; - password?: string; +export interface TestDefinition { + title: string; + responseStatusCode: number; + responseBody: ExpectResponseBody; +} + +export interface TestSuite { + user?: TestUser; + spaceId?: string; + tests: T[]; +} + +export interface TestCase { + type: string; + id: string; + failure?: 400 | 403 | 404 | 409; +} + +export interface TestUser { + username: string; + password: string; + description: string; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts index b6f1bb956d72d..0dafe6b7b386d 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts @@ -6,224 +6,137 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface BulkCreateTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; -} - -interface BulkCreateCustomTest extends BulkCreateTest { - description: string; - requestBody: { - [key: string]: any; - }; -} - -interface BulkCreateTests { - default: BulkCreateTest; - includingSpace: BulkCreateTest; - custom?: BulkCreateCustomTest; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +export interface BulkCreateTestDefinition extends TestDefinition { + request: Array<{ type: string; id: string }>; + overwrite: boolean; } - -interface BulkCreateTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - tests: BulkCreateTests; +export type BulkCreateTestSuite = TestSuite; +export interface BulkCreateTestCase extends TestCase { + failure?: 400 | 409; // only used for permitted response case } -const createBulkRequests = (spaceId: string) => [ - { - type: 'visualization', - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - attributes: { - title: 'An existing visualization', - }, - }, - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, - attributes: { - title: 'A great new dashboard', - }, - }, - { - type: 'globaltype', - id: '05976c65-1145-4858-bbf0-d225cc78a06e', - attributes: { - name: 'A new globaltype object', - }, - }, - { - type: 'globaltype', - id: '8121a00-8efd-21e7-1cb3-34ab966434445', - attributes: { - name: 'An existing globaltype', - }, - }, -]; +const NEW_ATTRIBUTE_KEY = 'title'; // all type mappings include this attribute, for simplicity's sake +const NEW_ATTRIBUTE_VAL = `New attribute value ${Date.now()}`; -const isGlobalType = (type: string) => type === 'globaltype'; +const NEW_SINGLE_NAMESPACE_OBJ = Object.freeze({ type: 'dashboard', id: 'new-dashboard-id' }); +const NEW_MULTI_NAMESPACE_OBJ = Object.freeze({ type: 'sharedtype', id: 'new-sharedtype-id' }); +const NEW_NAMESPACE_AGNOSTIC_OBJ = Object.freeze({ type: 'globaltype', id: 'new-globaltype-id' }); +export const TEST_CASES = Object.freeze({ + ...CASES, + NEW_SINGLE_NAMESPACE_OBJ, + NEW_MULTI_NAMESPACE_OBJ, + NEW_NAMESPACE_AGNOSTIC_OBJ, +}); export function bulkCreateTestSuiteFactory(es: any, esArchiver: any, supertest: SuperTest) { - const createExpectResults = (spaceId = DEFAULT_SPACE_ID) => async (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - saved_objects: [ - { - type: 'visualization', - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - error: { - message: 'version conflict, document already exists', - statusCode: 409, - }, - }, - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, - updated_at: resp.body.saved_objects[1].updated_at, - version: resp.body.saved_objects[1].version, - attributes: { - title: 'A great new dashboard', - }, - references: [], - }, - { - type: 'globaltype', - id: `05976c65-1145-4858-bbf0-d225cc78a06e`, - updated_at: resp.body.saved_objects[2].updated_at, - version: resp.body.saved_objects[2].version, - attributes: { - name: 'A new globaltype object', - }, - references: [], - }, - { - type: 'globaltype', - id: '8121a00-8efd-21e7-1cb3-34ab966434445', - error: { - message: 'version conflict, document already exists', - statusCode: 409, - }, - }, - ], - }); - - for (const savedObject of createBulkRequests(spaceId)) { - const expectedSpacePrefix = - spaceId === DEFAULT_SPACE_ID || isGlobalType(savedObject.type) ? '' : `${spaceId}:`; - - // query ES directory to ensure namespace was or wasn't specified - const { _source } = await es.get({ - id: `${expectedSpacePrefix}${savedObject.type}:${savedObject.id}`, - index: '.kibana', - }); - - const { namespace: actualNamespace } = _source; - - if (spaceId === DEFAULT_SPACE_ID || isGlobalType(savedObject.type)) { - expect(actualNamespace).to.eql(undefined); - } else { - expect(actualNamespace).to.eql(spaceId); + const expectForbidden = expectResponses.forbidden('bulk_create'); + const expectResponseBody = ( + testCases: BulkCreateTestCase | BulkCreateTestCase[], + statusCode: 200 | 403, + spaceId = SPACES.DEFAULT.spaceId + ): ExpectResponseBody => async (response: Record) => { + const testCaseArray = Array.isArray(testCases) ? testCases : [testCases]; + if (statusCode === 403) { + const types = testCaseArray.map(x => x.type); + await expectForbidden(types)(response); + } else { + // permitted + const savedObjects = response.body.saved_objects; + expect(savedObjects).length(testCaseArray.length); + for (let i = 0; i < savedObjects.length; i++) { + const object = savedObjects[i]; + const testCase = testCaseArray[i]; + await expectResponses.permitted(object, testCase); + if (!testCase.failure) { + expect(object.attributes[NEW_ATTRIBUTE_KEY]).to.eql(NEW_ATTRIBUTE_VAL); + await expectResponses.successCreated(es, spaceId, object.type, object.id); + } } } }; - - const expectBadRequestForHiddenType = (resp: { [key: string]: any }) => { - const spaceEntry = resp.body.saved_objects.find( - (entry: any) => entry.id === 'my-hiddentype' && entry.type === 'hiddentype' - ); - expect(spaceEntry).to.eql({ - id: 'my-hiddentype', - type: 'hiddentype', - error: { - message: "Unsupported saved object type: 'hiddentype': Bad Request", - statusCode: 400, - error: 'Bad Request', + const createTestDefinitions = ( + testCases: BulkCreateTestCase | BulkCreateTestCase[], + forbidden: boolean, + overwrite: boolean, + options?: { + spaceId?: string; + singleRequest?: boolean; + responseBodyOverride?: ExpectResponseBody; + } + ): BulkCreateTestDefinition[] => { + const cases = Array.isArray(testCases) ? testCases : [testCases]; + const responseStatusCode = forbidden ? 403 : 200; + if (!options?.singleRequest) { + // if we are testing cases that should result in a forbidden response, we can do each case individually + // this ensures that multiple test cases of a single type will each result in a forbidden error + return cases.map(x => ({ + title: getTestTitle(x, responseStatusCode), + request: [createRequest(x)], + responseStatusCode, + responseBody: + options?.responseBodyOverride || + expectResponseBody(x, responseStatusCode, options?.spaceId), + overwrite, + })); + } + // batch into a single request to save time during test execution + return [ + { + title: getTestTitle(cases, responseStatusCode), + request: cases.map(x => createRequest(x)), + responseStatusCode, + responseBody: + options?.responseBodyOverride || + expectResponseBody(cases, responseStatusCode, options?.spaceId), + overwrite, }, - }); + ]; }; - const expectedForbiddenTypes = ['dashboard', 'globaltype', 'visualization']; - const expectedForbiddenTypesWithHiddenType = [ - 'dashboard', - 'globaltype', - 'hiddentype', - 'visualization', - ]; - const createExpectRbacForbidden = (types: string[] = expectedForbiddenTypes) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to bulk_create ${types.join(',')}`, - }); - }; - - const makeBulkCreateTest = (describeFn: DescribeFn) => ( + const makeBulkCreateTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: BulkCreateTestDefinition + definition: BulkCreateTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.default.statusCode}`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_create`) - .auth(user.username, user.password) - .send(createBulkRequests(spaceId)) - .expect(tests.default.statusCode) - .then(tests.default.response); - }); - - it(`including a hiddentype saved object should return ${tests.includingSpace.statusCode}`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_create`) - .auth(user.username, user.password) - .send( - createBulkRequests(spaceId).concat([ - { - type: 'hiddentype', - id: `my-hiddentype`, - attributes: { - name: 'My awesome hiddentype', - }, - }, - ]) - ) - .expect(tests.includingSpace.statusCode) - .then(tests.includingSpace.response); - }); + const attrs = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; - if (tests.custom) { - it(tests.custom!.description, async () => { + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const requestBody = test.request.map(x => ({ ...x, ...attrs })); + const query = test.overwrite ? '?overwrite=true' : ''; await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_create`) - .auth(user.username, user.password) - .send(tests.custom!.requestBody) - .expect(tests.custom!.statusCode) - .then(tests.custom!.response); + .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_create${query}`) + .auth(user?.username, user?.password) + .send(requestBody) + .expect(test.responseStatusCode) + .then(test.responseBody); }); } }); }; - const bulkCreateTest = makeBulkCreateTest(describe); + const addTests = makeBulkCreateTest(describe); // @ts-ignore - bulkCreateTest.only = makeBulkCreateTest(describe.only); + addTests.only = makeBulkCreateTest(describe.only); return { - bulkCreateTest, - createExpectResults, - createExpectRbacForbidden, - expectBadRequestForHiddenType, - expectedForbiddenTypesWithHiddenType, + addTests, + createTestDefinitions, + expectForbidden, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts index 9c5cc375502d1..f03dac597294c 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts @@ -6,203 +6,110 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; -interface BulkGetTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; +export interface BulkGetTestDefinition extends TestDefinition { + request: Array<{ type: string; id: string }>; } - -interface BulkGetTests { - default: BulkGetTest; - includingHiddenType: BulkGetTest; -} - -interface BulkGetTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - otherSpaceId?: string; - tests: BulkGetTests; +export type BulkGetTestSuite = TestSuite; +export interface BulkGetTestCase extends TestCase { + failure?: 400 | 404; // only used for permitted response case } -const createBulkRequests = (spaceId: string) => [ - { - type: 'visualization', - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - }, - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}does not exist`, - }, - { - type: 'globaltype', - id: '8121a00-8efd-21e7-1cb3-34ab966434445', - }, -]; +const DOES_NOT_EXIST = Object.freeze({ type: 'dashboard', id: 'does-not-exist' }); +export const TEST_CASES = Object.freeze({ ...CASES, DOES_NOT_EXIST }); export function bulkGetTestSuiteFactory(esArchiver: any, supertest: SuperTest) { - const createExpectNotFoundResults = (spaceId: string) => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - saved_objects: [ - { - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - type: 'visualization', - error: { - statusCode: 404, - message: 'Not found', - }, - }, - { - id: `${getIdPrefix(spaceId)}does not exist`, - type: 'dashboard', - error: { - statusCode: 404, - message: 'Not found', - }, - }, - { - id: `8121a00-8efd-21e7-1cb3-34ab966434445`, - type: 'globaltype', - updated_at: '2017-09-21T18:59:16.270Z', - version: resp.body.saved_objects[2].version, - attributes: { - name: 'My favorite global object', - }, - references: [], - }, - ], - }); + const expectForbidden = expectResponses.forbidden('bulk_get'); + const expectResponseBody = ( + testCases: BulkGetTestCase | BulkGetTestCase[], + statusCode: 200 | 403 + ): ExpectResponseBody => async (response: Record) => { + const testCaseArray = Array.isArray(testCases) ? testCases : [testCases]; + if (statusCode === 403) { + const types = testCaseArray.map(x => x.type); + await expectForbidden(types)(response); + } else { + // permitted + const savedObjects = response.body.saved_objects; + expect(savedObjects).length(testCaseArray.length); + for (let i = 0; i < savedObjects.length; i++) { + const object = savedObjects[i]; + const testCase = testCaseArray[i]; + await expectResponses.permitted(object, testCase); + } + } }; - - const expectBadRequestForHiddenType = (resp: { [key: string]: any }) => { - const spaceEntry = resp.body.saved_objects.find( - (entry: any) => entry.id === 'my-hiddentype' && entry.type === 'hiddentype' - ); - expect(spaceEntry).to.eql({ - id: 'my-hiddentype', - type: 'hiddentype', - error: { - message: "Unsupported saved object type: 'hiddentype': Bad Request", - statusCode: 400, - error: 'Bad Request', + const createTestDefinitions = ( + testCases: BulkGetTestCase | BulkGetTestCase[], + forbidden: boolean, + options?: { + singleRequest?: boolean; + responseBodyOverride?: ExpectResponseBody; + } + ): BulkGetTestDefinition[] => { + const cases = Array.isArray(testCases) ? testCases : [testCases]; + const responseStatusCode = forbidden ? 403 : 200; + if (!options?.singleRequest) { + // if we are testing cases that should result in a forbidden response, we can do each case individually + // this ensures that multiple test cases of a single type will each result in a forbidden error + return cases.map(x => ({ + title: getTestTitle(x, responseStatusCode), + request: [createRequest(x)], + responseStatusCode, + responseBody: options?.responseBodyOverride || expectResponseBody(x, responseStatusCode), + })); + } + // batch into a single request to save time during test execution + return [ + { + title: getTestTitle(cases, responseStatusCode), + request: cases.map(x => createRequest(x)), + responseStatusCode, + responseBody: + options?.responseBodyOverride || expectResponseBody(cases, responseStatusCode), }, - }); + ]; }; - const expectedForbiddenTypes = ['dashboard', 'globaltype', 'visualization']; - const expectedForbiddenTypesWithHiddenType = [ - 'dashboard', - 'globaltype', - 'hiddentype', - 'visualization', - ]; - const createExpectRbacForbidden = (types: string[] = expectedForbiddenTypes) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to bulk_get ${types.join(',')}`, - }); - }; - - const createExpectResults = (spaceId = DEFAULT_SPACE_ID) => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - saved_objects: [ - { - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - type: 'visualization', - migrationVersion: resp.body.saved_objects[0].migrationVersion, - updated_at: '2017-09-21T18:51:23.794Z', - version: resp.body.saved_objects[0].version, - attributes: { - title: 'Count of requests', - description: '', - version: 1, - // cheat for some of the more complex attributes - visState: resp.body.saved_objects[0].attributes.visState, - uiStateJSON: resp.body.saved_objects[0].attributes.uiStateJSON, - kibanaSavedObjectMeta: resp.body.saved_objects[0].attributes.kibanaSavedObjectMeta, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`, - }, - ], - }, - { - id: `${getIdPrefix(spaceId)}does not exist`, - type: 'dashboard', - error: { - statusCode: 404, - message: 'Not found', - }, - }, - { - id: `8121a00-8efd-21e7-1cb3-34ab966434445`, - type: 'globaltype', - updated_at: '2017-09-21T18:59:16.270Z', - version: resp.body.saved_objects[2].version, - attributes: { - name: 'My favorite global object', - }, - references: [], - }, - ], - }); - }; - - const makeBulkGetTest = (describeFn: DescribeFn) => ( + const makeBulkGetTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: BulkGetTestDefinition + definition: BulkGetTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, otherSpaceId, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.default.statusCode}`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_get`) - .auth(user.username, user.password) - .send(createBulkRequests(otherSpaceId || spaceId)) - .expect(tests.default.statusCode) - .then(tests.default.response); - }); - - it(`with a hiddentype saved object included should return ${tests.includingHiddenType.statusCode}`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_get`) - .auth(user.username, user.password) - .send( - createBulkRequests(otherSpaceId || spaceId).concat([ - { - type: 'hiddentype', - id: `my-hiddentype`, - }, - ]) - ) - .expect(tests.includingHiddenType.statusCode) - .then(tests.includingHiddenType.response); - }); + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + await supertest + .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_get`) + .auth(user?.username, user?.password) + .send(test.request) + .expect(test.responseStatusCode) + .then(test.responseBody); + }); + } }); }; - const bulkGetTest = makeBulkGetTest(describe); + const addTests = makeBulkGetTest(describe); // @ts-ignore - bulkGetTest.only = makeBulkGetTest(describe.only); + addTests.only = makeBulkGetTest(describe.only); return { - bulkGetTest, - createExpectNotFoundResults, - createExpectResults, - createExpectRbacForbidden, - expectBadRequestForHiddenType, - expectedForbiddenTypesWithHiddenType, + addTests, + createTestDefinitions, + expectForbidden, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts index d14c5ccbd1d0e..e0e2118300ef4 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts @@ -6,234 +6,119 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface BulkUpdateTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; -} - -interface BulkUpdateTests { - spaceAware: BulkUpdateTest; - notSpaceAware: BulkUpdateTest; - hiddenType: BulkUpdateTest; - doesntExist: BulkUpdateTest; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +export interface BulkUpdateTestDefinition extends TestDefinition { + request: Array<{ type: string; id: string }>; } - -interface BulkUpdateTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - otherSpaceId?: string; - tests: BulkUpdateTests; +export type BulkUpdateTestSuite = TestSuite; +export interface BulkUpdateTestCase extends TestCase { + failure?: 404; // only used for permitted response case } -export function bulkUpdateTestSuiteFactory(esArchiver: any, supertest: SuperTest) { - const createExpectNotFound = (type: string, id: string, spaceId = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - const [, savedObject] = resp.body.saved_objects; - expect(savedObject.error).eql({ - statusCode: 404, - error: 'Not Found', - message: `Saved object [${type}/${getIdPrefix(spaceId)}${id}] not found`, - }); - }; - - const createExpectDoesntExistNotFound = (spaceId?: string) => { - return createExpectNotFound('visualization', 'not an id', spaceId); - }; - - const createExpectSpaceAwareNotFound = (spaceId?: string) => { - return createExpectNotFound('visualization', 'dd7caf20-9efd-11e7-acb3-3dab96693fab', spaceId); - }; - - const expectHiddenTypeNotFound = createExpectNotFound( - 'hiddentype', - 'hiddentype_1', - DEFAULT_SPACE_ID - ); - - const createExpectRbacForbidden = (types: string[]) => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to bulk_update ${types.join()}`, - }); - }; - - const expectDoesntExistRbacForbidden = createExpectRbacForbidden(['globaltype', 'visualization']); +const NEW_ATTRIBUTE_KEY = 'title'; // all type mappings include this attribute, for simplicity's sake +const NEW_ATTRIBUTE_VAL = `Updated attribute value ${Date.now()}`; - const expectNotSpaceAwareRbacForbidden = createExpectRbacForbidden(['globaltype']); +const DOES_NOT_EXIST = Object.freeze({ type: 'dashboard', id: 'does-not-exist' }); +export const TEST_CASES = Object.freeze({ ...CASES, DOES_NOT_EXIST }); - const expectHiddenTypeRbacForbidden = createExpectRbacForbidden(['globaltype', 'hiddentype']); - const expectHiddenTypeRbacForbiddenWithGlobalAllowed = createExpectRbacForbidden(['hiddentype']); - - const expectSpaceAwareRbacForbidden = createExpectRbacForbidden(['globaltype', 'visualization']); - - const expectNotSpaceAwareResults = (resp: { [key: string]: any }) => { - const [, savedObject] = resp.body.saved_objects; - // loose uuid validation - expect(savedObject) - .to.have.property('id') - .match(/^[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(savedObject) - .to.have.property('updated_at') - .match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(savedObject).to.eql({ - id: savedObject.id, - type: 'globaltype', - updated_at: savedObject.updated_at, - version: savedObject.version, - attributes: { - name: 'My second favorite', - }, - }); +export function bulkUpdateTestSuiteFactory(esArchiver: any, supertest: SuperTest) { + const expectForbidden = expectResponses.forbidden('bulk_update'); + const expectResponseBody = ( + testCases: BulkUpdateTestCase | BulkUpdateTestCase[], + statusCode: 200 | 403 + ): ExpectResponseBody => async (response: Record) => { + const testCaseArray = Array.isArray(testCases) ? testCases : [testCases]; + if (statusCode === 403) { + const types = testCaseArray.map(x => x.type); + await expectForbidden(types)(response); + } else { + // permitted + const savedObjects = response.body.saved_objects; + expect(savedObjects).length(testCaseArray.length); + for (let i = 0; i < savedObjects.length; i++) { + const object = savedObjects[i]; + const testCase = testCaseArray[i]; + await expectResponses.permitted(object, testCase); + if (!testCase.failure) { + expect(object.attributes[NEW_ATTRIBUTE_KEY]).to.eql(NEW_ATTRIBUTE_VAL); + } + } + } }; - - const expectSpaceAwareResults = (resp: { [key: string]: any }) => { - const [, savedObject] = resp.body.saved_objects; - // loose uuid validation ignoring prefix - expect(savedObject) - .to.have.property('id') - .match(/[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(savedObject) - .to.have.property('updated_at') - .match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(savedObject).to.eql({ - id: savedObject.id, - type: 'visualization', - updated_at: savedObject.updated_at, - version: savedObject.version, - attributes: { - title: 'My second favorite vis', + const createTestDefinitions = ( + testCases: BulkUpdateTestCase | BulkUpdateTestCase[], + forbidden: boolean, + options?: { + singleRequest?: boolean; + responseBodyOverride?: ExpectResponseBody; + } + ): BulkUpdateTestDefinition[] => { + const cases = Array.isArray(testCases) ? testCases : [testCases]; + const responseStatusCode = forbidden ? 403 : 200; + if (!options?.singleRequest) { + // if we are testing cases that should result in a forbidden response, we can do each case individually + // this ensures that multiple test cases of a single type will each result in a forbidden error + return cases.map(x => ({ + title: getTestTitle(x, responseStatusCode), + request: [createRequest(x)], + responseStatusCode, + responseBody: options?.responseBodyOverride || expectResponseBody(x, responseStatusCode), + })); + } + // batch into a single request to save time during test execution + return [ + { + title: getTestTitle(cases, responseStatusCode), + request: cases.map(x => createRequest(x)), + responseStatusCode, + responseBody: + options?.responseBodyOverride || expectResponseBody(cases, responseStatusCode), }, - }); + ]; }; - const makeBulkUpdateTest = (describeFn: DescribeFn) => ( + const makeBulkUpdateTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: BulkUpdateTestDefinition + definition: BulkUpdateTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, otherSpaceId, tests } = definition; - - // We add this type into all bulk updates - // to ensure that having additional items in the bulk - // update doesn't change the expected outcome overall - let updateCount = 0; - const generateNonSpaceAwareGlobalSavedObject = () => ({ - type: 'globaltype', - id: `8121a00-8efd-21e7-1cb3-34ab966434445`, - attributes: { - name: `Update #${++updateCount}`, - }, - }); + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.spaceAware.statusCode} for a space-aware doc`, async () => { - await supertest - .put(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_update`) - .auth(user.username, user.password) - .send([ - generateNonSpaceAwareGlobalSavedObject(), - { - type: 'visualization', - id: `${getIdPrefix(otherSpaceId || spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - attributes: { - title: 'My second favorite vis', - }, - }, - generateNonSpaceAwareGlobalSavedObject(), - ]) - .expect(tests.spaceAware.statusCode) - .then(tests.spaceAware.response); - }); - - it(`should return ${tests.notSpaceAware.statusCode} for a non space-aware doc`, async () => { - await supertest - .put(`${getUrlPrefix(otherSpaceId || spaceId)}/api/saved_objects/_bulk_update`) - .auth(user.username, user.password) - .send([ - generateNonSpaceAwareGlobalSavedObject(), - { - type: 'globaltype', - id: `8121a00-8efd-21e7-1cb3-34ab966434445`, - attributes: { - name: 'My second favorite', - }, - }, - generateNonSpaceAwareGlobalSavedObject(), - ]) - .expect(tests.notSpaceAware.statusCode) - .then(tests.notSpaceAware.response); - }); - it(`should return ${tests.hiddenType.statusCode} for hiddentype doc`, async () => { - await supertest - .put(`${getUrlPrefix(otherSpaceId || spaceId)}/api/saved_objects/_bulk_update`) - .auth(user.username, user.password) - .send([ - generateNonSpaceAwareGlobalSavedObject(), - { - type: 'hiddentype', - id: 'hiddentype_1', - attributes: { - name: 'My favorite hidden type', - }, - }, - generateNonSpaceAwareGlobalSavedObject(), - ]) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response); - }); + const attrs = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; - describe('unknown id', () => { - it(`should return ${tests.doesntExist.statusCode}`, async () => { + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const requestBody = test.request.map(x => ({ ...x, ...attrs })); await supertest .put(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_update`) - .auth(user.username, user.password) - .send([ - generateNonSpaceAwareGlobalSavedObject(), - { - type: 'visualization', - id: `${getIdPrefix(spaceId)}not an id`, - attributes: { - title: 'My second favorite vis', - }, - }, - generateNonSpaceAwareGlobalSavedObject(), - ]) - .expect(tests.doesntExist.statusCode) - .then(tests.doesntExist.response); + .auth(user?.username, user?.password) + .send(requestBody) + .expect(test.responseStatusCode) + .then(test.responseBody); }); - }); + } }); }; - const bulkUpdateTest = makeBulkUpdateTest(describe); + const addTests = makeBulkUpdateTest(describe); // @ts-ignore - bulkUpdateTest.only = makeBulkUpdateTest(describe.only); + addTests.only = makeBulkUpdateTest(describe.only); return { - createExpectDoesntExistNotFound, - createExpectSpaceAwareNotFound, - expectSpaceNotFound: expectHiddenTypeNotFound, - expectDoesntExistRbacForbidden, - expectNotSpaceAwareRbacForbidden, - expectNotSpaceAwareResults, - expectSpaceAwareRbacForbidden, - expectSpaceAwareResults, - expectHiddenTypeRbacForbidden, - expectHiddenTypeRbacForbiddenWithGlobalAllowed, - bulkUpdateTest, + addTests, + createTestDefinitions, + expectForbidden, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/create.ts b/x-pack/test/saved_object_api_integration/common/suites/create.ts index 29960c513d40f..f657756be92cd 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/create.ts @@ -3,206 +3,117 @@ * 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 { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface CreateTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; -} - -interface CreateCustomTest extends CreateTest { - type: string; - description: string; - requestBody: any; -} - -interface CreateTests { - spaceAware: CreateTest; - notSpaceAware: CreateTest; - hiddenType: CreateTest; - custom?: CreateCustomTest; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +export interface CreateTestDefinition extends TestDefinition { + request: { type: string; id: string }; + overwrite: boolean; } - -interface CreateTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - tests: CreateTests; +export type CreateTestSuite = TestSuite; +export interface CreateTestCase extends TestCase { + failure?: 400 | 403 | 409; } -const spaceAwareType = 'visualization'; -const notSpaceAwareType = 'globaltype'; +const NEW_ATTRIBUTE_KEY = 'title'; // all type mappings include this attribute, for simplicity's sake +const NEW_ATTRIBUTE_VAL = `New attribute value ${Date.now()}`; + +// ID intentionally left blank on NEW_SINGLE_NAMESPACE_OBJ to ensure we can create saved objects without specifying the ID +// we could create six separate test cases to test every permutation, but there's no real value in doing so +const NEW_SINGLE_NAMESPACE_OBJ = Object.freeze({ type: 'dashboard', id: '' }); +const NEW_MULTI_NAMESPACE_OBJ = Object.freeze({ type: 'sharedtype', id: 'new-sharedtype-id' }); +const NEW_NAMESPACE_AGNOSTIC_OBJ = Object.freeze({ type: 'globaltype', id: 'new-globaltype-id' }); +export const TEST_CASES = Object.freeze({ + ...CASES, + NEW_SINGLE_NAMESPACE_OBJ, + NEW_MULTI_NAMESPACE_OBJ, + NEW_NAMESPACE_AGNOSTIC_OBJ, +}); export function createTestSuiteFactory(es: any, esArchiver: any, supertest: SuperTest) { - const createExpectRbacForbidden = (type: string) => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to create ${type}`, - }); - }; - - const expectBadRequestForHiddenType = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - message: "Unsupported saved object type: 'hiddentype': Bad Request", - statusCode: 400, - error: 'Bad Request', - }); - }; - - const createExpectSpaceAwareResults = (spaceId = DEFAULT_SPACE_ID) => async (resp: { - [key: string]: any; - }) => { - expect(resp.body) - .to.have.property('id') - .match(/^[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(resp.body) - .to.have.property('updated_at') - .match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(resp.body).to.eql({ - id: resp.body.id, - migrationVersion: resp.body.migrationVersion, - type: spaceAwareType, - updated_at: resp.body.updated_at, - version: resp.body.version, - attributes: { - title: 'My favorite vis', - }, - references: [], - }); - - const expectedSpacePrefix = spaceId === DEFAULT_SPACE_ID ? '' : `${spaceId}:`; - - // query ES directory to ensure namespace was or wasn't specified - const { _source } = await es.get({ - id: `${expectedSpacePrefix}${spaceAwareType}:${resp.body.id}`, - index: '.kibana', - }); - - const { namespace: actualNamespace } = _source; - - if (spaceId === DEFAULT_SPACE_ID) { - expect(actualNamespace).to.eql(undefined); + const expectForbidden = expectResponses.forbidden('create'); + const expectResponseBody = ( + testCase: CreateTestCase, + spaceId = SPACES.DEFAULT.spaceId + ): ExpectResponseBody => async (response: Record) => { + if (testCase.failure === 403) { + await expectForbidden(testCase.type)(response); } else { - expect(actualNamespace).to.eql(spaceId); + // permitted + const object = response.body; + await expectResponses.permitted(object, testCase); + if (!testCase.failure) { + expect(object.attributes[NEW_ATTRIBUTE_KEY]).to.eql(NEW_ATTRIBUTE_VAL); + await expectResponses.successCreated(es, spaceId, object.type, object.id); + } } }; - - const expectNotSpaceAwareRbacForbidden = createExpectRbacForbidden(notSpaceAwareType); - - const expectNotSpaceAwareResults = async (resp: { [key: string]: any }) => { - expect(resp.body) - .to.have.property('id') - .match(/^[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(resp.body) - .to.have.property('updated_at') - .match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(resp.body).to.eql({ - id: resp.body.id, - type: notSpaceAwareType, - updated_at: resp.body.updated_at, - version: resp.body.version, - attributes: { - name: `Can't be contained to a space`, - }, - references: [], - }); - - // query ES directory to ensure namespace wasn't specified - const { _source } = await es.get({ - id: `${notSpaceAwareType}:${resp.body.id}`, - index: '.kibana', - }); - - const { namespace: actualNamespace } = _source; - - expect(actualNamespace).to.eql(undefined); + const createTestDefinitions = ( + testCases: CreateTestCase | CreateTestCase[], + forbidden: boolean, + overwrite: boolean, + options?: { + spaceId?: string; + responseBodyOverride?: ExpectResponseBody; + } + ): CreateTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403 })); + } + return cases.map(x => ({ + title: getTestTitle(x), + responseStatusCode: x.failure ?? 200, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x, options?.spaceId), + overwrite, + })); }; - const expectSpaceAwareRbacForbidden = createExpectRbacForbidden(spaceAwareType); - - const expectHiddenTypeRbacForbidden = createExpectRbacForbidden('hiddentype'); - - const makeCreateTest = (describeFn: DescribeFn) => ( + const makeCreateTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: CreateTestDefinition + definition: CreateTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; + describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.spaceAware.statusCode} for a space-aware type`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/${spaceAwareType}`) - .auth(user.username, user.password) - .send({ - attributes: { - title: 'My favorite vis', - }, - }) - .expect(tests.spaceAware.statusCode) - .then(tests.spaceAware.response); - }); - - it(`should return ${tests.notSpaceAware.statusCode} for a non space-aware type`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/${notSpaceAwareType}`) - .auth(user.username, user.password) - .send({ - attributes: { - name: `Can't be contained to a space`, - }, - }) - .expect(tests.notSpaceAware.statusCode) - .then(tests.notSpaceAware.response); - }); - - it(`should return ${tests.hiddenType.statusCode} for the hiddentype`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/hiddentype`) - .auth(user.username, user.password) - .send({ - attributes: { - name: `Can't be created via the Saved Objects API`, - }, - }) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response); - }); - if (tests.custom) { - it(tests.custom.description, async () => { + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const { type, id } = test.request; + const path = `${type}${id ? `/${id}` : ''}`; + const requestBody = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; + const query = test.overwrite ? '?overwrite=true' : ''; await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/${tests.custom!.type}`) - .auth(user.username, user.password) - .send(tests.custom!.requestBody) - .expect(tests.custom!.statusCode) - .then(tests.custom!.response); + .post(`${getUrlPrefix(spaceId)}/api/saved_objects/${path}${query}`) + .auth(user?.username, user?.password) + .send(requestBody) + .expect(test.responseStatusCode) + .then(test.responseBody); }); } }); }; - const createTest = makeCreateTest(describe); + const addTests = makeCreateTest(describe); // @ts-ignore - createTest.only = makeCreateTest(describe.only); + addTests.only = makeCreateTest(describe.only); return { - createExpectSpaceAwareResults, - createTest, - expectNotSpaceAwareRbacForbidden, - expectNotSpaceAwareResults, - expectSpaceAwareRbacForbidden, - expectBadRequestForHiddenType, - expectHiddenTypeRbacForbidden, + addTests, + createTestDefinitions, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/delete.ts b/x-pack/test/saved_object_api_integration/common/suites/delete.ts index d96ae5446d732..2222aa0c97267 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/delete.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/delete.ts @@ -4,147 +4,97 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface DeleteTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; +import expect from '@kbn/expect/expect.js'; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +export interface DeleteTestDefinition extends TestDefinition { + request: { type: string; id: string }; } - -interface DeleteTests { - spaceAware: DeleteTest; - notSpaceAware: DeleteTest; - hiddenType: DeleteTest; - invalidId: DeleteTest; +export type DeleteTestSuite = TestSuite; +export interface DeleteTestCase extends TestCase { + failure?: 403 | 404; } -interface DeleteTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - otherSpaceId?: string; - tests: DeleteTests; -} +const DOES_NOT_EXIST = Object.freeze({ type: 'dashboard', id: 'does-not-exist' }); +export const TEST_CASES = Object.freeze({ ...CASES, DOES_NOT_EXIST }); export function deleteTestSuiteFactory(esArchiver: any, supertest: SuperTest) { - const createExpectNotFound = (spaceId: string, type: string, id: string) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - statusCode: 404, - error: 'Not Found', - message: `Saved object [${type}/${getIdPrefix(spaceId)}${id}] not found`, - }); - }; - - const createExpectRbacForbidden = (type: string) => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to delete ${type}`, - }); - }; - - const expectGenericNotFound = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 404, - error: 'Not Found', - message: `Not Found`, - }); - }; - - const createExpectSpaceAwareNotFound = (spaceId: string = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - createExpectNotFound(spaceId, 'dashboard', 'be3733a0-9efe-11e7-acb3-3dab96693fab')(resp); - }; - - const createExpectUnknownDocNotFound = (spaceId: string = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - createExpectNotFound(spaceId, 'dashboard', `not-a-real-id`)(resp); + const expectForbidden = expectResponses.forbidden('delete'); + const expectResponseBody = (testCase: DeleteTestCase): ExpectResponseBody => async ( + response: Record + ) => { + if (testCase.failure === 403) { + await expectForbidden(testCase.type)(response); + } else { + // permitted + const object = response.body; + if (testCase.failure) { + await expectResponses.permitted(object, testCase); + } else { + // the success response for `delete` is an empty object + expect(object).to.eql({}); + } + } }; - - const expectEmpty = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({}); + const createTestDefinitions = ( + testCases: DeleteTestCase | DeleteTestCase[], + forbidden: boolean, + options?: { + spaceId?: string; + responseBodyOverride?: ExpectResponseBody; + } + ): DeleteTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403 })); + } + return cases.map(x => ({ + title: getTestTitle(x), + responseStatusCode: x.failure ?? 200, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x), + })); }; - const expectRbacInvalidIdForbidden = createExpectRbacForbidden('dashboard'); - - const expectRbacNotSpaceAwareForbidden = createExpectRbacForbidden('globaltype'); - - const expectRbacSpaceAwareForbidden = createExpectRbacForbidden('dashboard'); - - const expectRbacHiddenTypeForbidden = createExpectRbacForbidden('hiddentype'); - - const makeDeleteTest = (describeFn: DescribeFn) => ( + const makeDeleteTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: DeleteTestDefinition + definition: DeleteTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, otherSpaceId, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.spaceAware.statusCode} when deleting a space-aware doc`, async () => - await supertest - .delete( - `${getUrlPrefix(spaceId)}/api/saved_objects/dashboard/${getIdPrefix( - otherSpaceId || spaceId - )}be3733a0-9efe-11e7-acb3-3dab96693fab` - ) - .auth(user.username, user.password) - .expect(tests.spaceAware.statusCode) - .then(tests.spaceAware.response)); - - it(`should return ${tests.notSpaceAware.statusCode} when deleting a non-space-aware doc`, async () => - await supertest - .delete( - `${getUrlPrefix( - spaceId - )}/api/saved_objects/globaltype/8121a00-8efd-21e7-1cb3-34ab966434445` - ) - .auth(user.username, user.password) - .expect(tests.notSpaceAware.statusCode) - .then(tests.notSpaceAware.response)); - - it(`should return ${tests.hiddenType.statusCode} when deleting a hiddentype doc`, async () => - await supertest - .delete(`${getUrlPrefix(spaceId)}/api/saved_objects/hiddentype/hiddentype_1`) - .auth(user.username, user.password) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response)); - - it(`should return ${tests.invalidId.statusCode} when deleting an unknown doc`, async () => - await supertest - .delete( - `${getUrlPrefix(spaceId)}/api/saved_objects/dashboard/${getIdPrefix( - otherSpaceId || spaceId - )}not-a-real-id` - ) - .auth(user.username, user.password) - .expect(tests.invalidId.statusCode) - .then(tests.invalidId.response)); + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const { type, id } = test.request; + await supertest + .delete(`${getUrlPrefix(spaceId)}/api/saved_objects/${type}/${id}`) + .auth(user?.username, user?.password) + .expect(test.responseStatusCode) + .then(test.responseBody); + }); + } }); }; - const deleteTest = makeDeleteTest(describe); + const addTests = makeDeleteTest(describe); // @ts-ignore - deleteTest.only = makeDeleteTest(describe.only); + addTests.only = makeDeleteTest(describe.only); return { - expectGenericNotFound, - createExpectSpaceAwareNotFound, - createExpectUnknownDocNotFound, - deleteTest, - expectEmpty, - expectRbacInvalidIdForbidden, - expectRbacNotSpaceAwareForbidden, - expectRbacSpaceAwareForbidden, - expectRbacHiddenTypeForbidden, + addTests, + createTestDefinitions, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/export.ts b/x-pack/test/saved_object_api_integration/common/suites/export.ts index e6853096962ec..ddd43d42410ae 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/export.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/export.ts @@ -5,164 +5,191 @@ */ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { expectResponses, getUrlPrefix } from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; -interface ExportTest { - statusCode: number; - description: string; - response: (resp: { [key: string]: any }) => void; -} +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; -interface ExportTests { - spaceAwareType: ExportTest; - hiddenType: ExportTest; - noTypeOrObjects: ExportTest; +export interface ExportTestDefinition extends TestDefinition { + request: ReturnType; } - -interface ExportTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - tests: ExportTests; +export type ExportTestSuite = TestSuite; +export interface ExportTestCase { + title: string; + type: string; + id?: string; + successResult?: TestCase | TestCase[]; + failure?: 400 | 403; } +export const getTestCases = (spaceId?: string) => ({ + singleNamespaceObject: { + title: 'single-namespace object', + ...(spaceId === SPACE_1_ID + ? CASES.SINGLE_NAMESPACE_SPACE_1 + : spaceId === SPACE_2_ID + ? CASES.SINGLE_NAMESPACE_SPACE_2 + : CASES.SINGLE_NAMESPACE_DEFAULT_SPACE), + } as ExportTestCase, + singleNamespaceType: { + // this test explicitly ensures that single-namespace objects from other spaces are not returned + title: 'single-namespace type', + type: 'isolatedtype', + successResult: + spaceId === SPACE_1_ID + ? CASES.SINGLE_NAMESPACE_SPACE_1 + : spaceId === SPACE_2_ID + ? CASES.SINGLE_NAMESPACE_SPACE_2 + : CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + } as ExportTestCase, + multiNamespaceObject: { + title: 'multi-namespace object', + ...(spaceId === SPACE_1_ID + ? CASES.MULTI_NAMESPACE_ONLY_SPACE_1 + : spaceId === SPACE_2_ID + ? CASES.MULTI_NAMESPACE_ONLY_SPACE_2 + : CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1), + failure: 400, // multi-namespace types cannot be exported yet + } as ExportTestCase, + multiNamespaceType: { + title: 'multi-namespace type', + type: 'sharedtype', + // successResult: + // spaceId === SPACE_1_ID + // ? [CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, CASES.MULTI_NAMESPACE_ONLY_SPACE_1] + // : spaceId === SPACE_2_ID + // ? CASES.MULTI_NAMESPACE_ONLY_SPACE_2 + // : CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + failure: 400, // multi-namespace types cannot be exported yet + } as ExportTestCase, + namespaceAgnosticObject: { + title: 'namespace-agnostic object', + ...CASES.NAMESPACE_AGNOSTIC, + } as ExportTestCase, + namespaceAgnosticType: { + title: 'namespace-agnostic type', + type: 'globaltype', + successResult: CASES.NAMESPACE_AGNOSTIC, + } as ExportTestCase, + hiddenObject: { title: 'hidden object', ...CASES.HIDDEN, failure: 400 } as ExportTestCase, + hiddenType: { title: 'hidden type', type: 'hiddentype', failure: 400 } as ExportTestCase, +}); +export const createRequest = ({ type, id }: ExportTestCase) => + id ? { objects: [{ type, id }] } : { type }; +const getTestTitle = ({ failure, title }: ExportTestCase) => { + let description = 'success'; + if (failure === 400) { + description = 'bad request'; + } else if (failure === 403) { + description = 'forbidden'; + } + return `${description} ["${title}"]`; +}; + export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest) { - const createExpectRbacForbidden = (type: string) => (resp: { [key: string]: any }) => { - // In export only, the API uses "bulk_get" or "find" depending on the parameters it receives. - // The best that could be done here is to have an if statement to ensure at least one of the - // two errors has been thrown. - if (resp.body.message.indexOf(`bulk_get`) !== -1) { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to bulk_get ${type}`, + const expectForbiddenBulkGet = expectResponses.forbidden('bulk_get'); + const expectForbiddenFind = expectResponses.forbidden('find'); + const expectResponseBody = (testCase: ExportTestCase): ExpectResponseBody => async ( + response: Record + ) => { + const { type, id, successResult = { type, id }, failure } = testCase; + if (failure === 403) { + // In export only, the API uses "bulk_get" or "find" depending on the parameters it receives. + // The best that could be done here is to have an if statement to ensure at least one of the + // two errors has been thrown. + if (id) { + await expectForbiddenBulkGet(type)(response); + } else { + await expectForbiddenFind(type)(response); + } + } else if (failure === 400) { + // 400 + expect(response.body.error).to.eql('Bad Request'); + expect(response.body.statusCode).to.eql(failure); + if (id) { + expect(response.body.message).to.eql( + `Trying to export object(s) with non-exportable types: ${type}:${id}` + ); + } else { + expect(response.body.message).to.eql(`Trying to export non-exportable type(s): ${type}`); + } + } else { + // 2xx + expect(response.body).not.to.have.property('error'); + const ndjson = response.text.split('\n'); + const savedObjectsArray = Array.isArray(successResult) ? successResult : [successResult]; + expect(ndjson.length).to.eql(savedObjectsArray.length + 1); + for (let i = 0; i < savedObjectsArray.length; i++) { + const object = JSON.parse(ndjson[i]); + const { type: expectedType, id: expectedId } = savedObjectsArray[i]; + expect(object.type).to.eql(expectedType); + expect(object.id).to.eql(expectedId); + expect(object.updated_at).to.match(/^[\d-]{10}T[\d:\.]{12}Z$/); + // don't test attributes, version, or references + } + const exportDetails = JSON.parse(ndjson[ndjson.length - 1]); + expect(exportDetails).to.eql({ + exportedCount: ndjson.length - 1, + missingRefCount: 0, + missingReferences: [], }); - return; } - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to find ${type}`, - }); }; - - const expectTypeOrObjectsRequired = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 400, - error: 'Bad Request', - message: '[request body]: expected a plain object value, but found [null] instead.', - }); - }; - - const expectInvalidTypeSpecified = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 400, - error: 'Bad Request', - message: `Trying to export object(s) with non-exportable types: hiddentype:hiddentype_1`, - }); - }; - - const createExpectVisualizationResults = (spaceId = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - const response = JSON.parse(resp.text); - expect(response).to.eql({ - type: 'visualization', - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - version: response.version, - attributes: response.attributes, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`, - }, - ], - migrationVersion: response.migrationVersion, - updated_at: '2017-09-21T18:51:23.794Z', - }); + const createTestDefinitions = ( + testCases: ExportTestCase | ExportTestCase[], + forbidden: boolean, + options?: { + responseBodyOverride?: ExpectResponseBody; + } + ): ExportTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403 })); + } + return cases.map(x => ({ + title: getTestTitle(x), + responseStatusCode: x.failure ?? 200, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x), + })); }; - const makeExportTest = (describeFn: DescribeFn) => ( + const makeExportTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: ExportTestDefinition + definition: ExportTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, tests } = definition; + const { user, spaceId = DEFAULT_SPACE_ID, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`space aware type should return ${tests.spaceAwareType.statusCode} with ${tests.spaceAwareType.description} when querying by type`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_export`) - .send({ - type: 'visualization', - excludeExportDetails: true, - }) - .auth(user.username, user.password) - .expect(tests.spaceAwareType.statusCode) - .then(tests.spaceAwareType.response); - }); - - it(`space aware type should return ${tests.spaceAwareType.statusCode} with ${tests.spaceAwareType.description} when querying by objects`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_export`) - .send({ - objects: [ - { - type: 'visualization', - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - }, - ], - excludeExportDetails: true, - }) - .auth(user.username, user.password) - .expect(tests.spaceAwareType.statusCode) - .then(tests.spaceAwareType.response); - }); - - describe('hidden type', () => { - it(`should return ${tests.hiddenType.statusCode} with ${tests.hiddenType.description}`, async () => { + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_export`) - .send({ - objects: [ - { - type: 'hiddentype', - id: `hiddentype_1`, - }, - ], - excludeExportDetails: true, - }) - .auth(user.username, user.password) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response); + .auth(user?.username, user?.password) + .send(test.request) + .expect(test.responseStatusCode) + .then(test.responseBody); }); - }); - - describe('no type or objects', () => { - it(`should return ${tests.noTypeOrObjects.statusCode} with ${tests.noTypeOrObjects.description}`, async () => { - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_export`) - .auth(user.username, user.password) - .expect(tests.noTypeOrObjects.statusCode) - .then(tests.noTypeOrObjects.response); - }); - }); + } }); }; - const exportTest = makeExportTest(describe); + const addTests = makeExportTest(describe); // @ts-ignore - exportTest.only = makeExportTest(describe.only); + addTests.only = makeExportTest(describe.only); return { - createExpectRbacForbidden, - expectTypeOrObjectsRequired, - expectInvalidTypeSpecified, - createExpectVisualizationResults, - exportTest, + addTests, + createTestDefinitions, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/find.ts b/x-pack/test/saved_object_api_integration/common/suites/find.ts index 5479960634ccb..75d6653365fdf 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/find.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/find.ts @@ -3,271 +3,190 @@ * 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 { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface FindTest { - statusCode: number; - description: string; - response: (resp: { [key: string]: any }) => void; +import querystring from 'querystring'; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { expectResponses, getUrlPrefix } from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; + +export interface FindTestDefinition extends TestDefinition { + request: { query: string }; } - -interface FindTests { - spaceAwareType: FindTest; - notSpaceAwareType: FindTest; - unknownType: FindTest; - pageBeyondTotal: FindTest; - unknownSearchField: FindTest; - hiddenType: FindTest; - noType: FindTest; - filterWithNotSpaceAwareType: FindTest; - filterWithHiddenType: FindTest; - filterWithUnknownType: FindTest; - filterWithNoType: FindTest; - filterWithUnAllowedType: FindTest; +export type FindTestSuite = TestSuite; +export interface FindTestCase { + title: string; + query: string; + successResult?: { + savedObjects?: TestCase | TestCase[]; + page?: number; + perPage?: number; + total?: number; + }; + failure?: 400 | 403; } -interface FindTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - tests: FindTests; -} +export const getTestCases = (spaceId?: string) => ({ + singleNamespaceType: { + title: 'find single-namespace type', + query: 'type=isolatedtype&fields=title', + successResult: { + savedObjects: + spaceId === SPACE_1_ID + ? CASES.SINGLE_NAMESPACE_SPACE_1 + : spaceId === SPACE_2_ID + ? CASES.SINGLE_NAMESPACE_SPACE_2 + : CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + }, + } as FindTestCase, + multiNamespaceType: { + title: 'find multi-namespace type', + query: 'type=sharedtype&fields=title', + successResult: { + savedObjects: + spaceId === SPACE_1_ID + ? [CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, CASES.MULTI_NAMESPACE_ONLY_SPACE_1] + : spaceId === SPACE_2_ID + ? CASES.MULTI_NAMESPACE_ONLY_SPACE_2 + : CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + }, + } as FindTestCase, + namespaceAgnosticType: { + title: 'find namespace-agnostic type', + query: 'type=globaltype&fields=title', + successResult: { savedObjects: CASES.NAMESPACE_AGNOSTIC }, + } as FindTestCase, + hiddenType: { title: 'find hidden type', query: 'type=hiddentype&fields=name' } as FindTestCase, + unknownType: { title: 'find unknown type', query: 'type=wigwags' } as FindTestCase, + pageBeyondTotal: { + title: 'find page beyond total', + query: 'type=isolatedtype&page=100&per_page=100', + successResult: { page: 100, perPage: 100, total: 1, savedObjects: [] }, + } as FindTestCase, + unknownSearchField: { + title: 'find unknown search field', + query: 'type=url&search_fields=a', + } as FindTestCase, + filterWithNamespaceAgnosticType: { + title: 'filter with namespace-agnostic type', + query: 'type=globaltype&filter=globaltype.attributes.title:*global*', + successResult: { savedObjects: CASES.NAMESPACE_AGNOSTIC }, + } as FindTestCase, + filterWithHiddenType: { + title: 'filter with hidden type', + query: `type=hiddentype&fields=name&filter=hiddentype.attributes.title:'hello'`, + } as FindTestCase, + filterWithUnknownType: { + title: 'filter with unknown type', + query: `type=wigwags&filter=wigwags.attributes.title:'unknown'`, + } as FindTestCase, + filterWithDisallowedType: { + title: 'filter with disallowed type', + query: `type=globaltype&filter=dashboard.title:'Requests'`, + failure: 400, + } as FindTestCase, +}); +export const createRequest = ({ query }: FindTestCase) => ({ query }); +const getTestTitle = ({ failure, title }: FindTestCase) => { + let description = 'success'; + if (failure === 400) { + description = 'bad request'; + } else if (failure === 403) { + description = 'forbidden'; + } + return `${description} ["${title}"]`; +}; export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) { - const createExpectEmpty = (page: number, perPage: number, total: number) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - page, - per_page: perPage, - total, - saved_objects: [], - }); - }; - - const createExpectRbacForbidden = (type?: string) => (resp: { [key: string]: any }) => { - const message = type ? `Unable to find ${type}` : `Not authorized to find saved_object`; - - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message, - }); - }; - - const expectNotSpaceAwareResults = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 1, - saved_objects: [ - { - type: 'globaltype', - id: `8121a00-8efd-21e7-1cb3-34ab966434445`, - version: resp.body.saved_objects[0].version, - attributes: { - name: 'My favorite global object', - }, - references: [], - updated_at: '2017-09-21T18:59:16.270Z', - }, - ], - }); - }; - - const expectFilterWrongTypeError = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - error: 'Bad Request', - message: 'This type dashboard is not allowed: Bad Request', - statusCode: 400, - }); - }; - - const expectTypeRequired = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - error: 'Bad Request', - message: '[request query.type]: expected at least one defined value but got [undefined]', - statusCode: 400, - }); + const expectForbidden = expectResponses.forbidden('find'); + const expectResponseBody = (testCase: FindTestCase): ExpectResponseBody => async ( + response: Record + ) => { + const { failure, successResult = {}, query } = testCase; + const parsedQuery = querystring.parse(query); + if (failure === 403) { + const type = parsedQuery.type; + await expectForbidden(type)(response); + } else if (failure === 400) { + const type = (parsedQuery.filter as string).split('.')[0]; + expect(response.body.error).to.eql('Bad Request'); + expect(response.body.statusCode).to.eql(failure); + expect(response.body.message).to.eql(`This type ${type} is not allowed: Bad Request`); + } else { + // 2xx + expect(response.body).not.to.have.property('error'); + const { page = 1, perPage = 20, total, savedObjects = [] } = successResult; + const savedObjectsArray = Array.isArray(savedObjects) ? savedObjects : [savedObjects]; + expect(response.body.page).to.eql(page); + expect(response.body.per_page).to.eql(perPage); + expect(response.body.total).to.eql(total || savedObjectsArray.length); + for (let i = 0; i < savedObjectsArray.length; i++) { + const object = response.body.saved_objects[i]; + const { type: expectedType, id: expectedId } = savedObjectsArray[i]; + expect(object.type).to.eql(expectedType); + expect(object.id).to.eql(expectedId); + expect(object.updated_at).to.match(/^[\d-]{10}T[\d:\.]{12}Z$/); + // don't test attributes, version, or references + } + } }; - - const createExpectVisualizationResults = (spaceId = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - page: 1, - per_page: 20, - total: 1, - saved_objects: [ - { - type: 'visualization', - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - version: resp.body.saved_objects[0].version, - attributes: { - title: 'Count of requests', - }, - migrationVersion: resp.body.saved_objects[0].migrationVersion, - references: [ - { - id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`, - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - }, - ], - updated_at: '2017-09-21T18:51:23.794Z', - }, - ], - }); + const createTestDefinitions = ( + testCases: FindTestCase | FindTestCase[], + forbidden: boolean, + options?: { + responseBodyOverride?: ExpectResponseBody; + } + ): FindTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403 })); + } + return cases.map(x => ({ + title: getTestTitle(x), + responseStatusCode: x.failure ?? 200, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x), + })); }; - const makeFindTest = (describeFn: DescribeFn) => ( + const makeFindTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: FindTestDefinition + definition: FindTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, tests } = definition; + const { user, spaceId = DEFAULT_SPACE_ID, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`space aware type should return ${tests.spaceAwareType.statusCode} with ${tests.spaceAwareType.description}`, async () => - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=visualization&fields=title`) - .auth(user.username, user.password) - .expect(tests.spaceAwareType.statusCode) - .then(tests.spaceAwareType.response)); - - it(`not space aware type should return ${tests.notSpaceAwareType.statusCode} with ${tests.notSpaceAwareType.description}`, async () => - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=globaltype&fields=name`) - .auth(user.username, user.password) - .expect(tests.notSpaceAwareType.statusCode) - .then(tests.notSpaceAwareType.response)); - - it(`finding a hiddentype should return ${tests.hiddenType.statusCode} with ${tests.hiddenType.description}`, async () => - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=hiddentype&fields=name`) - .auth(user.username, user.password) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response)); - - describe('unknown type', () => { - it(`should return ${tests.unknownType.statusCode} with ${tests.unknownType.description}`, async () => - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=wigwags`) - .auth(user.username, user.password) - .expect(tests.unknownType.statusCode) - .then(tests.unknownType.response)); - }); - - describe('page beyond total', () => { - it(`should return ${tests.pageBeyondTotal.statusCode} with ${tests.pageBeyondTotal.description}`, async () => - await supertest - .get( - `${getUrlPrefix( - spaceId - )}/api/saved_objects/_find?type=visualization&page=100&per_page=100` - ) - .auth(user.username, user.password) - .expect(tests.pageBeyondTotal.statusCode) - .then(tests.pageBeyondTotal.response)); - }); - - describe('unknown search field', () => { - it(`should return ${tests.unknownSearchField.statusCode} with ${tests.unknownSearchField.description}`, async () => - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find?type=url&search_fields=a`) - .auth(user.username, user.password) - .expect(tests.unknownSearchField.statusCode) - .then(tests.unknownSearchField.response)); - }); - - describe('no type', () => { - it(`should return ${tests.noType.statusCode} with ${tests.noType.description}`, async () => - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find`) - .auth(user.username, user.password) - .expect(tests.noType.statusCode) - .then(tests.noType.response)); - }); - - describe('filter', () => { - it(`by wrong type should return ${tests.filterWithUnAllowedType.statusCode} with ${tests.filterWithUnAllowedType.description}`, async () => - await supertest - .get( - `${getUrlPrefix( - spaceId - )}/api/saved_objects/_find?type=globaltype&filter=dashboard.title:'Requests'` - ) - .auth(user.username, user.password) - .expect(tests.filterWithUnAllowedType.statusCode) - .then(tests.filterWithUnAllowedType.response)); - - it(`not space aware type should return ${tests.filterWithNotSpaceAwareType.statusCode} with ${tests.filterWithNotSpaceAwareType.description}`, async () => + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const query = test.request.query ? `?${test.request.query}` : ''; await supertest - .get( - `${getUrlPrefix( - spaceId - )}/api/saved_objects/_find?type=globaltype&filter=globaltype.attributes.name:*global*` - ) - .auth(user.username, user.password) - .expect(tests.filterWithNotSpaceAwareType.statusCode) - .then(tests.filterWithNotSpaceAwareType.response)); - - it(`finding a hiddentype should return ${tests.filterWithHiddenType.statusCode} with ${tests.filterWithHiddenType.description}`, async () => - await supertest - .get( - `${getUrlPrefix( - spaceId - )}/api/saved_objects/_find?type=hiddentype&fields=name&filter=hiddentype.attributes.name:'hello'` - ) - .auth(user.username, user.password) - .expect(tests.filterWithHiddenType.statusCode) - .then(tests.filterWithHiddenType.response)); - - describe('unknown type', () => { - it(`should return ${tests.filterWithUnknownType.statusCode} with ${tests.filterWithUnknownType.description}`, async () => - await supertest - .get( - `${getUrlPrefix( - spaceId - )}/api/saved_objects/_find?type=wigwags&filter=wigwags.attributes.title:'unknown'` - ) - .auth(user.username, user.password) - .expect(tests.filterWithUnknownType.statusCode) - .then(tests.filterWithUnknownType.response)); - }); - - describe('no type', () => { - it(`should return ${tests.filterWithNoType.statusCode} with ${tests.filterWithNoType.description}`, async () => - await supertest - .get( - `${getUrlPrefix( - spaceId - )}/api/saved_objects/_find?filter=global.attributes.name:*global*` - ) - .auth(user.username, user.password) - .expect(tests.filterWithNoType.statusCode) - .then(tests.filterWithNoType.response)); + .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find${query}`) + .auth(user?.username, user?.password) + .expect(test.responseStatusCode) + .then(test.responseBody); }); - }); + } }); }; - const findTest = makeFindTest(describe); + const addTests = makeFindTest(describe); // @ts-ignore - findTest.only = makeFindTest(describe.only); + addTests.only = makeFindTest(describe.only); return { - createExpectEmpty, - createExpectRbacForbidden, - createExpectVisualizationResults, - expectFilterWrongTypeError, - expectNotSpaceAwareResults, - expectTypeRequired, - findTest, + addTests, + createTestDefinitions, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/get.ts b/x-pack/test/saved_object_api_integration/common/suites/get.ts index c98209ca1e105..d8fa4d91276d7 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/get.ts @@ -3,193 +3,89 @@ * 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 { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface GetTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; -} - -interface GetTests { - spaceAware: GetTest; - notSpaceAware: GetTest; - hiddenType: GetTest; - doesntExist: GetTest; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +export interface GetTestDefinition extends TestDefinition { + request: { type: string; id: string }; } +export type GetTestSuite = TestSuite; +export type GetTestCase = TestCase; -interface GetTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - otherSpaceId?: string; - tests: GetTests; -} - -const spaceAwareId = 'dd7caf20-9efd-11e7-acb3-3dab96693fab'; -const notSpaceAwareId = '8121a00-8efd-21e7-1cb3-34ab966434445'; -const doesntExistId = 'foobar'; +const DOES_NOT_EXIST = Object.freeze({ type: 'dashboard', id: 'does-not-exist' }); +export const TEST_CASES = Object.freeze({ ...CASES, DOES_NOT_EXIST }); export function getTestSuiteFactory(esArchiver: any, supertest: SuperTest) { - const createExpectDoesntExistNotFound = (spaceId = DEFAULT_SPACE_ID) => { - return createExpectNotFound('visualization', doesntExistId, spaceId); - }; - - const createExpectNotFound = (type: string, id: string, spaceId = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - error: 'Not Found', - message: `Saved object [${type}/${getIdPrefix(spaceId)}${id}] not found`, - statusCode: 404, - }); - }; - - const expectHiddenTypeNotFound = createExpectNotFound( - 'hiddentype', - 'hiddentype_1', - DEFAULT_SPACE_ID - ); - - const createExpectNotSpaceAwareRbacForbidden = () => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - error: 'Forbidden', - message: `Unable to get globaltype`, - statusCode: 403, - }); - }; - - const createExpectNotSpaceAwareResults = (spaceId = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - id: `${notSpaceAwareId}`, - type: 'globaltype', - updated_at: '2017-09-21T18:59:16.270Z', - version: resp.body.version, - attributes: { - name: 'My favorite global object', - }, - references: [], - }); - }; - - const createExpectRbacForbidden = (type: string) => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - error: 'Forbidden', - message: `Unable to get ${type}`, - statusCode: 403, - }); + const expectForbidden = expectResponses.forbidden('get'); + const expectResponseBody = (testCase: GetTestCase): ExpectResponseBody => async ( + response: Record + ) => { + if (testCase.failure === 403) { + await expectForbidden(testCase.type)(response); + } else { + // permitted + const object = response.body; + await expectResponses.permitted(object, testCase); + } }; - - const createExpectSpaceAwareNotFound = (spaceId = DEFAULT_SPACE_ID) => { - return createExpectNotFound('visualization', spaceAwareId, spaceId); + const createTestDefinitions = ( + testCases: GetTestCase | GetTestCase[], + forbidden: boolean, + options?: { + spaceId?: string; + responseBodyOverride?: ExpectResponseBody; + } + ): GetTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403 })); + } + return cases.map(x => ({ + title: getTestTitle(x), + responseStatusCode: x.failure ?? 200, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x), + })); }; - const expectSpaceAwareRbacForbidden = createExpectRbacForbidden('visualization'); - const expectNotSpaceAwareRbacForbidden = createExpectRbacForbidden('globaltype'); - const expectHiddenTypeRbacForbidden = createExpectRbacForbidden('hiddentype'); - const expectDoesntExistRbacForbidden = createExpectRbacForbidden('visualization'); - - const createExpectSpaceAwareResults = (spaceId = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - type: 'visualization', - migrationVersion: resp.body.migrationVersion, - updated_at: '2017-09-21T18:51:23.794Z', - version: resp.body.version, - attributes: { - title: 'Count of requests', - description: '', - version: 1, - // cheat for some of the more complex attributes - visState: resp.body.attributes.visState, - uiStateJSON: resp.body.attributes.uiStateJSON, - kibanaSavedObjectMeta: resp.body.attributes.kibanaSavedObjectMeta, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: `${getIdPrefix(spaceId)}91200a00-9efd-11e7-acb3-3dab96693fab`, - }, - ], - }); - }; - - const makeGetTest = (describeFn: DescribeFn) => ( + const makeGetTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: GetTestDefinition + definition: GetTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, otherSpaceId, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.spaceAware.statusCode} when getting a space aware doc`, async () => { - await supertest - .get( - `${getUrlPrefix(spaceId)}/api/saved_objects/visualization/${getIdPrefix( - otherSpaceId || spaceId - )}${spaceAwareId}` - ) - .auth(user.username, user.password) - .expect(tests.spaceAware.statusCode) - .then(tests.spaceAware.response); - }); - - it(`should return ${tests.notSpaceAware.statusCode} when getting a non-space-aware doc`, async () => { - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/globaltype/${notSpaceAwareId}`) - .auth(user.username, user.password) - .expect(tests.notSpaceAware.statusCode) - .then(tests.notSpaceAware.response); - }); - - it(`should return ${tests.hiddenType.statusCode} when getting a hiddentype doc`, async () => { - await supertest - .get(`${getUrlPrefix(spaceId)}/api/saved_objects/hiddentype/hiddentype_1`) - .auth(user.username, user.password) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response); - }); - - describe('document does not exist', () => { - it(`should return ${tests.doesntExist.statusCode}`, async () => { + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const { type, id } = test.request; await supertest - .get( - `${getUrlPrefix(spaceId)}/api/saved_objects/visualization/${getIdPrefix( - otherSpaceId || spaceId - )}${doesntExistId}` - ) - .auth(user.username, user.password) - .expect(tests.doesntExist.statusCode) - .then(tests.doesntExist.response); + .get(`${getUrlPrefix(spaceId)}/api/saved_objects/${type}/${id}`) + .auth(user?.username, user?.password) + .expect(test.responseStatusCode) + .then(test.responseBody); }); - }); + } }); }; - const getTest = makeGetTest(describe); + const addTests = makeGetTest(describe); // @ts-ignore - getTest.only = makeGetTest(describe.only); + addTests.only = makeGetTest(describe.only); return { - createExpectDoesntExistNotFound, - createExpectNotSpaceAwareRbacForbidden, - createExpectNotSpaceAwareResults, - createExpectSpaceAwareNotFound, - createExpectSpaceAwareResults, - expectHiddenTypeNotFound, - expectSpaceAwareRbacForbidden, - expectNotSpaceAwareRbacForbidden, - expectDoesntExistRbacForbidden, - expectHiddenTypeRbacForbidden, - getTest, + addTests, + createTestDefinitions, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/import.ts b/x-pack/test/saved_object_api_integration/common/suites/import.ts index f6723c912f82e..2f631221c6955 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/import.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/import.ts @@ -6,195 +6,152 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface ImportTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +export interface ImportTestDefinition extends TestDefinition { + request: Array<{ type: string; id: string }>; } - -interface ImportTests { - default: ImportTest; - hiddenType: ImportTest; - unknownType: ImportTest; +export type ImportTestSuite = TestSuite; +export interface ImportTestCase extends TestCase { + failure?: 400 | 409; // only used for permitted response case } -interface ImportTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - tests: ImportTests; -} +const NEW_ATTRIBUTE_KEY = 'title'; // all type mappings include this attribute, for simplicity's sake +const NEW_ATTRIBUTE_VAL = `New attribute value ${Date.now()}`; -const createImportData = (spaceId: string) => [ - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, - attributes: { - title: 'A great new dashboard', - }, - }, - { - type: 'globaltype', - id: '05976c65-1145-4858-bbf0-d225cc78a06e', - attributes: { - name: 'A new globaltype object', - }, - }, -]; +const NEW_SINGLE_NAMESPACE_OBJ = Object.freeze({ type: 'dashboard', id: 'new-dashboard-id' }); +const NEW_MULTI_NAMESPACE_OBJ = Object.freeze({ type: 'sharedtype', id: 'new-sharedtype-id' }); +const NEW_NAMESPACE_AGNOSTIC_OBJ = Object.freeze({ type: 'globaltype', id: 'new-globaltype-id' }); +export const TEST_CASES = Object.freeze({ + ...CASES, + NEW_SINGLE_NAMESPACE_OBJ, + NEW_MULTI_NAMESPACE_OBJ, + NEW_NAMESPACE_AGNOSTIC_OBJ, +}); export function importTestSuiteFactory(es: any, esArchiver: any, supertest: SuperTest) { - const createExpectResults = (spaceId = DEFAULT_SPACE_ID) => async (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - success: true, - successCount: 2, - }); - }; - - const expectResultsWithUnsupportedHiddenType = async (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - success: false, - successCount: 2, - errors: [ - { - error: { - type: 'unsupported_type', - }, - id: '1', - type: 'hiddentype', - }, - ], - }); + const expectForbidden = expectResponses.forbidden('bulk_create'); + const expectResponseBody = ( + testCases: ImportTestCase | ImportTestCase[], + statusCode: 200 | 403, + spaceId = SPACES.DEFAULT.spaceId + ): ExpectResponseBody => async (response: Record) => { + const testCaseArray = Array.isArray(testCases) ? testCases : [testCases]; + if (statusCode === 403) { + const types = testCaseArray.map(x => x.type); + await expectForbidden(types)(response); + } else { + // permitted + const { success, successCount, errors } = response.body; + const expectedSuccesses = testCaseArray.filter(x => !x.failure); + const expectedFailures = testCaseArray.filter(x => x.failure); + expect(success).to.eql(expectedFailures.length === 0); + expect(successCount).to.eql(expectedSuccesses.length); + if (expectedFailures.length) { + expect(errors).to.have.length(expectedFailures.length); + } else { + expect(response.body).not.to.have.property('errors'); + } + for (let i = 0; i < expectedSuccesses.length; i++) { + const { type, id } = expectedSuccesses[i]; + const { _source } = await expectResponses.successCreated(es, spaceId, type, id); + expect(_source[type][NEW_ATTRIBUTE_KEY]).to.eql(NEW_ATTRIBUTE_VAL); + } + for (let i = 0; i < expectedFailures.length; i++) { + const { type, id, failure } = expectedFailures[i]; + // we don't know the order of the returned errors; search for each one + const object = (errors as Array>).find( + x => x.type === type && x.id === id + ); + expect(object).not.to.be(undefined); + if (failure === 400) { + expect(object!.error).to.eql({ type: 'unsupported_type' }); + } else { + // 409 + expect(object!.error).to.eql({ type: 'conflict' }); + } + } + } }; - - const expectUnknownTypeUnsupported = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - success: false, - successCount: 2, - errors: [ - { - id: '1', - type: 'wigwags', - title: 'Wigwags title', - error: { - type: 'unsupported_type', - }, - }, - ], - }); + const createTestDefinitions = ( + testCases: ImportTestCase | ImportTestCase[], + forbidden: boolean, + options?: { + spaceId?: string; + singleRequest?: boolean; + responseBodyOverride?: ExpectResponseBody; + } + ): ImportTestDefinition[] => { + const cases = Array.isArray(testCases) ? testCases : [testCases]; + const responseStatusCode = forbidden ? 403 : 200; + if (!options?.singleRequest) { + // if we are testing cases that should result in a forbidden response, we can do each case individually + // this ensures that multiple test cases of a single type will each result in a forbidden error + return cases.map(x => ({ + title: getTestTitle(x, responseStatusCode), + request: [createRequest(x)], + responseStatusCode, + responseBody: + options?.responseBodyOverride || + expectResponseBody(x, responseStatusCode, options?.spaceId), + })); + } + // batch into a single request to save time during test execution + return [ + { + title: getTestTitle(cases, responseStatusCode), + request: cases.map(x => createRequest(x)), + responseStatusCode, + responseBody: + options?.responseBodyOverride || + expectResponseBody(cases, responseStatusCode, options?.spaceId), + }, + ]; }; - const expectHiddenTypeUnsupported = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - success: false, - successCount: 2, - errors: [ - { - id: '1', - type: 'hiddentype', - error: { - type: 'unsupported_type', - }, - }, - ], - }); - }; - - const expectRbacForbidden = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to bulk_create dashboard,globaltype`, - }); - }; - - const makeImportTest = (describeFn: DescribeFn) => ( + const makeImportTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: ImportTestDefinition + definition: ImportTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.default.statusCode}`, async () => { - const data = createImportData(spaceId); - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_import`) - .auth(user.username, user.password) - .attach( - 'file', - Buffer.from(data.map(obj => JSON.stringify(obj)).join('\n'), 'utf8'), - 'export.ndjson' - ) - .expect(tests.default.statusCode) - .then(tests.default.response); - }); - - describe('hiddentype', () => { - it(`should return ${tests.hiddenType.statusCode}`, async () => { - const data = createImportData(spaceId); - data.push({ - type: 'hiddentype', - id: '1', - attributes: { - name: 'My Hidden Type', - }, - }); - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_import`) - .query({ overwrite: true }) - .auth(user.username, user.password) - .attach( - 'file', - Buffer.from(data.map(obj => JSON.stringify(obj)).join('\n'), 'utf8'), - 'export.ndjson' - ) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response); - }); - }); + const attrs = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; - describe('unknown type', () => { - it(`should return ${tests.unknownType.statusCode}`, async () => { - const data = createImportData(spaceId); - data.push({ - type: 'wigwags', - id: '1', - attributes: { - title: 'Wigwags title', - }, - }); + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const requestBody = test.request + .map(obj => JSON.stringify({ ...obj, ...attrs })) + .join('\n'); await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_import`) - .query({ overwrite: true }) - .auth(user.username, user.password) - .attach( - 'file', - Buffer.from(data.map(obj => JSON.stringify(obj)).join('\n'), 'utf8'), - 'export.ndjson' - ) - .expect(tests.unknownType.statusCode) - .then(tests.unknownType.response); + .auth(user?.username, user?.password) + .attach('file', Buffer.from(requestBody, 'utf8'), 'export.ndjson') + .expect(test.responseStatusCode) + .then(test.responseBody); }); - }); + } }); }; - const importTest = makeImportTest(describe); + const addTests = makeImportTest(describe); // @ts-ignore - importTest.only = makeImportTest(describe.only); + addTests.only = makeImportTest(describe.only); return { - importTest, - createExpectResults, - expectResultsWithUnsupportedHiddenType, - expectRbacForbidden, - expectUnknownTypeUnsupported, - expectHiddenTypeUnsupported, + addTests, + createTestDefinitions, + expectForbidden, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts index 1b538b9b1b65d..47c4babc5fcf9 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts @@ -6,219 +6,165 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; -interface ResolveImportErrorsTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; +export interface ResolveImportErrorsTestDefinition extends TestDefinition { + request: Array<{ type: string; id: string }>; + overwrite: boolean; } - -interface ResolveImportErrorsTests { - default: ResolveImportErrorsTest; - hiddenType: ResolveImportErrorsTest; - unknownType: ResolveImportErrorsTest; +export type ResolveImportErrorsTestSuite = TestSuite; +export interface ResolveImportErrorsTestCase extends TestCase { + failure?: 400 | 409; // only used for permitted response case } -interface ResolveImportErrorsTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - tests: ResolveImportErrorsTests; -} +const NEW_ATTRIBUTE_KEY = 'title'; // all type mappings include this attribute, for simplicity's sake +const NEW_ATTRIBUTE_VAL = `New attribute value ${Date.now()}`; -const createImportData = (spaceId: string) => [ - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, - attributes: { - title: 'A great new dashboard', - }, - }, - { - type: 'globaltype', - id: '05976c65-1145-4858-bbf0-d225cc78a06e', - attributes: { - name: 'A new globaltype object', - }, - }, -]; +const NEW_SINGLE_NAMESPACE_OBJ = Object.freeze({ type: 'dashboard', id: 'new-dashboard-id' }); +const NEW_MULTI_NAMESPACE_OBJ = Object.freeze({ type: 'sharedtype', id: 'new-sharedtype-id' }); +const NEW_NAMESPACE_AGNOSTIC_OBJ = Object.freeze({ type: 'globaltype', id: 'new-globaltype-id' }); +export const TEST_CASES = Object.freeze({ + ...CASES, + NEW_SINGLE_NAMESPACE_OBJ, + NEW_MULTI_NAMESPACE_OBJ, + NEW_NAMESPACE_AGNOSTIC_OBJ, +}); export function resolveImportErrorsTestSuiteFactory( es: any, esArchiver: any, supertest: SuperTest ) { - const createExpectResults = (spaceId = DEFAULT_SPACE_ID) => async (resp: { - [key: string]: any; - }) => { - expect(resp.body).to.eql({ - success: true, - successCount: 1, - }); - }; - - const expectUnknownTypeUnsupported = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - success: false, - successCount: 1, - errors: [ - { - id: '1', - type: 'wigwags', - title: 'Wigwags title', - error: { - type: 'unsupported_type', - }, - }, - ], - }); - }; - - const expectHiddenTypeUnsupported = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - success: false, - successCount: 1, - errors: [ - { - id: '1', - type: 'hiddentype', - error: { - type: 'unsupported_type', - }, - }, - ], - }); + const expectForbidden = expectResponses.forbidden('bulk_create'); + const expectResponseBody = ( + testCases: ResolveImportErrorsTestCase | ResolveImportErrorsTestCase[], + statusCode: 200 | 403, + spaceId = SPACES.DEFAULT.spaceId + ): ExpectResponseBody => async (response: Record) => { + const testCaseArray = Array.isArray(testCases) ? testCases : [testCases]; + if (statusCode === 403) { + const types = testCaseArray.map(x => x.type); + await expectForbidden(types)(response); + } else { + // permitted + const { success, successCount, errors } = response.body; + const expectedSuccesses = testCaseArray.filter(x => !x.failure); + const expectedFailures = testCaseArray.filter(x => x.failure); + expect(success).to.eql(expectedFailures.length === 0); + expect(successCount).to.eql(expectedSuccesses.length); + if (expectedFailures.length) { + expect(errors).to.have.length(expectedFailures.length); + } else { + expect(response.body).not.to.have.property('errors'); + } + for (let i = 0; i < expectedSuccesses.length; i++) { + const { type, id } = expectedSuccesses[i]; + const { _source } = await expectResponses.successCreated(es, spaceId, type, id); + expect(_source[type][NEW_ATTRIBUTE_KEY]).to.eql(NEW_ATTRIBUTE_VAL); + } + for (let i = 0; i < expectedFailures.length; i++) { + const { type, id, failure } = expectedFailures[i]; + // we don't know the order of the returned errors; search for each one + const object = (errors as Array>).find( + x => x.type === type && x.id === id + ); + expect(object).not.to.be(undefined); + if (failure === 400) { + expect(object!.error).to.eql({ type: 'unsupported_type' }); + } else { + // 409 + expect(object!.error).to.eql({ type: 'conflict' }); + } + } + } }; - - const expectRbacForbidden = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to bulk_create dashboard`, - }); + const createTestDefinitions = ( + testCases: ResolveImportErrorsTestCase | ResolveImportErrorsTestCase[], + forbidden: boolean, + overwrite: boolean, + options?: { + spaceId?: string; + singleRequest?: boolean; + responseBodyOverride?: ExpectResponseBody; + } + ): ResolveImportErrorsTestDefinition[] => { + const cases = Array.isArray(testCases) ? testCases : [testCases]; + const responseStatusCode = forbidden ? 403 : 200; + if (!options?.singleRequest) { + // if we are testing cases that should result in a forbidden response, we can do each case individually + // this ensures that multiple test cases of a single type will each result in a forbidden error + return cases.map(x => ({ + title: getTestTitle(x, responseStatusCode), + request: [createRequest(x)], + responseStatusCode, + responseBody: + options?.responseBodyOverride || + expectResponseBody(x, responseStatusCode, options?.spaceId), + overwrite, + })); + } + // batch into a single request to save time during test execution + return [ + { + title: getTestTitle(cases, responseStatusCode), + request: cases.map(x => createRequest(x)), + responseStatusCode, + responseBody: + options?.responseBodyOverride || + expectResponseBody(cases, responseStatusCode, options?.spaceId), + overwrite, + }, + ]; }; - const makeResolveImportErrorsTest = (describeFn: DescribeFn) => ( + const makeResolveImportErrorsTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: ResolveImportErrorsTestDefinition + definition: ResolveImportErrorsTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.default.statusCode}`, async () => { - const data = createImportData(spaceId); - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_resolve_import_errors`) - .auth(user.username, user.password) - .field( - 'retries', - JSON.stringify([ - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, - overwrite: true, - }, - ]) - ) - .attach( - 'file', - Buffer.from(data.map(obj => JSON.stringify(obj)).join('\n'), 'utf8'), - 'export.ndjson' - ) - .expect(tests.default.statusCode) - .then(tests.default.response); - }); + const attrs = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; - describe('unknown type', () => { - it(`should return ${tests.unknownType.statusCode}`, async () => { - const data = createImportData(spaceId); - data.push({ - type: 'wigwags', - id: '1', - attributes: { - title: 'Wigwags title', - }, - }); - await supertest - .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_resolve_import_errors`) - .auth(user.username, user.password) - .field( - 'retries', - JSON.stringify([ - { - type: 'wigwags', - id: '1', - overwrite: true, - }, - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, - overwrite: true, - }, - ]) - ) - .attach( - 'file', - Buffer.from(data.map(obj => JSON.stringify(obj)).join('\n'), 'utf8'), - 'export.ndjson' - ) - .expect(tests.unknownType.statusCode) - .then(tests.unknownType.response); - }); - }); - describe('hidden type', () => { - it(`should return ${tests.hiddenType.statusCode}`, async () => { - const data = createImportData(spaceId); - data.push({ - type: 'hiddentype', - id: '1', - attributes: { - name: 'My Hidden Type', - }, - }); + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const retryAttrs = test.overwrite ? { overwrite: true } : {}; + const retries = JSON.stringify( + test.request.map(({ type, id }) => ({ type, id, ...retryAttrs })) + ); + const requestBody = test.request + .map(obj => JSON.stringify({ ...obj, ...attrs })) + .join('\n'); await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_resolve_import_errors`) - .auth(user.username, user.password) - .field( - 'retries', - JSON.stringify([ - { - type: 'hiddentype', - id: '1', - overwrite: true, - }, - { - type: 'dashboard', - id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, - overwrite: true, - }, - ]) - ) - .attach( - 'file', - Buffer.from(data.map(obj => JSON.stringify(obj)).join('\n'), 'utf8'), - 'export.ndjson' - ) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response); + .auth(user?.username, user?.password) + .field('retries', retries) + .attach('file', Buffer.from(requestBody, 'utf8'), 'export.ndjson') + .expect(test.responseStatusCode) + .then(test.responseBody); }); - }); + } }); }; - const resolveImportErrorsTest = makeResolveImportErrorsTest(describe); + const addTests = makeResolveImportErrorsTest(describe); // @ts-ignore - resolveImportErrorsTest.only = makeResolveImportErrorsTest(describe.only); + addTests.only = makeResolveImportErrorsTest(describe.only); return { - resolveImportErrorsTest, - createExpectResults, - expectRbacForbidden, - expectUnknownTypeUnsupported, - expectHiddenTypeUnsupported, + addTests, + createTestDefinitions, + expectForbidden, }; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/update.ts b/x-pack/test/saved_object_api_integration/common/suites/update.ts index d6b7602c0114a..587e8cf320a4f 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/update.ts @@ -6,205 +6,97 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; -import { getIdPrefix, getUrlPrefix } from '../lib/space_test_utils'; -import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; - -interface UpdateTest { - statusCode: number; - response: (resp: { [key: string]: any }) => void; -} - -interface UpdateTests { - spaceAware: UpdateTest; - notSpaceAware: UpdateTest; - hiddenType: UpdateTest; - doesntExist: UpdateTest; +import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; +import { SPACES } from '../lib/spaces'; +import { + createRequest, + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../lib/saved_object_test_utils'; +import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; + +export interface UpdateTestDefinition extends TestDefinition { + request: { type: string; id: string }; } - -interface UpdateTestDefinition { - user?: TestDefinitionAuthentication; - spaceId?: string; - otherSpaceId?: string; - tests: UpdateTests; +export type UpdateTestSuite = TestSuite; +export interface UpdateTestCase extends TestCase { + failure?: 403 | 404; } -export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest) { - const createExpectNotFound = (type: string, id: string, spaceId = DEFAULT_SPACE_ID) => (resp: { - [key: string]: any; - }) => { - expect(resp.body).eql({ - statusCode: 404, - error: 'Not Found', - message: `Saved object [${type}/${getIdPrefix(spaceId)}${id}] not found`, - }); - }; - - const createExpectDoesntExistNotFound = (spaceId?: string) => { - return createExpectNotFound('visualization', 'not an id', spaceId); - }; - - const createExpectSpaceAwareNotFound = (spaceId?: string) => { - return createExpectNotFound('visualization', 'dd7caf20-9efd-11e7-acb3-3dab96693fab', spaceId); - }; - - const expectHiddenTypeNotFound = createExpectNotFound( - 'hiddentype', - 'hiddentype_1', - DEFAULT_SPACE_ID - ); - - const createExpectRbacForbidden = (type: string) => (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - statusCode: 403, - error: 'Forbidden', - message: `Unable to update ${type}`, - }); - }; +const NEW_ATTRIBUTE_KEY = 'title'; // all type mappings include this attribute, for simplicity's sake +const NEW_ATTRIBUTE_VAL = `Updated attribute value ${Date.now()}`; - const expectDoesntExistRbacForbidden = createExpectRbacForbidden('visualization'); +const DOES_NOT_EXIST = Object.freeze({ type: 'dashboard', id: 'does-not-exist' }); +export const TEST_CASES = Object.freeze({ ...CASES, DOES_NOT_EXIST }); - const expectNotSpaceAwareRbacForbidden = createExpectRbacForbidden('globaltype'); - - const expectHiddenTypeRbacForbidden = createExpectRbacForbidden('hiddentype'); - - const expectNotSpaceAwareResults = (resp: { [key: string]: any }) => { - // loose uuid validation - expect(resp.body) - .to.have.property('id') - .match(/^[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(resp.body) - .to.have.property('updated_at') - .match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(resp.body).to.eql({ - id: resp.body.id, - type: 'globaltype', - updated_at: resp.body.updated_at, - version: resp.body.version, - attributes: { - name: 'My second favorite', - }, - }); +export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest) { + const expectForbidden = expectResponses.forbidden('update'); + const expectResponseBody = (testCase: UpdateTestCase): ExpectResponseBody => async ( + response: Record + ) => { + if (testCase.failure === 403) { + await expectForbidden(testCase.type)(response); + } else { + // permitted + const object = response.body; + await expectResponses.permitted(object, testCase); + if (!testCase.failure) { + expect(object.attributes[NEW_ATTRIBUTE_KEY]).to.eql(NEW_ATTRIBUTE_VAL); + } + } }; - - const expectSpaceAwareRbacForbidden = createExpectRbacForbidden('visualization'); - - const expectSpaceAwareResults = (resp: { [key: string]: any }) => { - // loose uuid validation ignoring prefix - expect(resp.body) - .to.have.property('id') - .match(/[0-9a-f-]{36}$/); - - // loose ISO8601 UTC time with milliseconds validation - expect(resp.body) - .to.have.property('updated_at') - .match(/^[\d-]{10}T[\d:\.]{12}Z$/); - - expect(resp.body).to.eql({ - id: resp.body.id, - type: 'visualization', - updated_at: resp.body.updated_at, - version: resp.body.version, - attributes: { - title: 'My second favorite vis', - }, - }); + const createTestDefinitions = ( + testCases: UpdateTestCase | UpdateTestCase[], + forbidden: boolean, + options?: { + responseBodyOverride?: ExpectResponseBody; + } + ): UpdateTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403 })); + } + return cases.map(x => ({ + title: getTestTitle(x), + responseStatusCode: x.failure ?? 200, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x), + })); }; - const makeUpdateTest = (describeFn: DescribeFn) => ( + const makeUpdateTest = (describeFn: Mocha.SuiteFunction) => ( description: string, - definition: UpdateTestDefinition + definition: UpdateTestSuite ) => { - const { user = {}, spaceId = DEFAULT_SPACE_ID, otherSpaceId, tests } = definition; + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; describeFn(description, () => { before(() => esArchiver.load('saved_objects/spaces')); after(() => esArchiver.unload('saved_objects/spaces')); - it(`should return ${tests.spaceAware.statusCode} for a space-aware doc`, async () => { - await supertest - .put( - `${getUrlPrefix(spaceId)}/api/saved_objects/visualization/${getIdPrefix( - otherSpaceId || spaceId - )}dd7caf20-9efd-11e7-acb3-3dab96693fab` - ) - .auth(user.username, user.password) - .send({ - attributes: { - title: 'My second favorite vis', - }, - }) - .expect(tests.spaceAware.statusCode) - .then(tests.spaceAware.response); - }); - - it(`should return ${tests.notSpaceAware.statusCode} for a non space-aware doc`, async () => { - await supertest - .put( - `${getUrlPrefix( - otherSpaceId || spaceId - )}/api/saved_objects/globaltype/8121a00-8efd-21e7-1cb3-34ab966434445` - ) - .auth(user.username, user.password) - .send({ - attributes: { - name: 'My second favorite', - }, - }) - .expect(tests.notSpaceAware.statusCode) - .then(tests.notSpaceAware.response); - }); - - it(`should return ${tests.hiddenType.statusCode} for hiddentype doc`, async () => { - await supertest - .put(`${getUrlPrefix(otherSpaceId || spaceId)}/api/saved_objects/hiddentype/hiddentype_1`) - .auth(user.username, user.password) - .send({ - attributes: { - name: 'My favorite hidden type', - }, - }) - .expect(tests.hiddenType.statusCode) - .then(tests.hiddenType.response); - }); - describe('unknown id', () => { - it(`should return ${tests.doesntExist.statusCode}`, async () => { + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const { type, id } = test.request; + const requestBody = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; await supertest - .put( - `${getUrlPrefix(spaceId)}/api/saved_objects/visualization/${getIdPrefix( - spaceId - )}not an id` - ) - .auth(user.username, user.password) - .send({ - attributes: { - title: 'My second favorite vis', - }, - }) - .expect(tests.doesntExist.statusCode) - .then(tests.doesntExist.response); + .put(`${getUrlPrefix(spaceId)}/api/saved_objects/${type}/${id}`) + .auth(user?.username, user?.password) + .send(requestBody) + .expect(test.responseStatusCode) + .then(test.responseBody); }); - }); + } }); }; - const updateTest = makeUpdateTest(describe); + const addTests = makeUpdateTest(describe); // @ts-ignore - updateTest.only = makeUpdateTest(describe.only); + addTests.only = makeUpdateTest(describe.only); return { - createExpectDoesntExistNotFound, - createExpectSpaceAwareNotFound, - expectSpaceNotFound: expectHiddenTypeNotFound, - expectDoesntExistRbacForbidden, - expectNotSpaceAwareRbacForbidden, - expectNotSpaceAwareResults, - expectSpaceAwareRbacForbidden, - expectSpaceAwareResults, - expectHiddenTypeRbacForbidden, - updateTest, + addTests, + createTestDefinitions, }; } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts index 7768665f3b941..70d3afbfc9af3 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts @@ -4,206 +4,104 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; +import { + bulkCreateTestSuiteFactory, + TEST_CASES as CASES, + BulkCreateTestDefinition, +} from '../../common/suites/bulk_create'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (overwrite: boolean, spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { + ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + ...fail409(!overwrite && spaceId === DEFAULT_SPACE_ID), + }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(!overwrite && spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(!overwrite && spaceId === SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail409(!overwrite || (spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID)), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail409(!overwrite || spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail409(!overwrite || spaceId !== SPACE_2_ID) }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_MULTI_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail400() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - bulkCreateTest, - createExpectResults, - createExpectRbacForbidden, - expectBadRequestForHiddenType, - expectedForbiddenTypesWithHiddenType, - } = bulkCreateTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = bulkCreateTestSuiteFactory( + es, + esArchiver, + supertest + ); + const createTests = (overwrite: boolean, spaceId: string) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(overwrite, spaceId); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: createTestDefinitions(allTypes, true, overwrite, { spaceId }), + authorized: [ + createTestDefinitions(normalTypes, false, overwrite, { spaceId, singleRequest: true }), + createTestDefinitions(hiddenType, true, overwrite, { spaceId }), + createTestDefinitions(allTypes, true, overwrite, { + spaceId, + singleRequest: true, + responseBodyOverride: expectForbidden(['hiddentype']), + }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, overwrite, { + spaceId, + singleRequest: true, + }), + }; + }; describe('_bulk_create', () => { - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - bulkCreateTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingSpace: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - }, - }); - - bulkCreateTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkCreateTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkCreateTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkCreateTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); + getTestScenarios([false, true]).securityAndSpaces.forEach( + ({ spaceId, users, modifier: overwrite }) => { + const suffix = ` within the ${spaceId} space${overwrite ? ' with overwrite enabled' : ''}`; + const { unauthorized, authorized, superuser } = createTests(overwrite!, spaceId); + const _addTests = (user: TestUser, tests: BulkCreateTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - bulkCreateTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - }); + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally, users.allAtSpace].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); + } + ); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_get.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_get.ts index ec5bce1707569..09ea867bff371 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_get.ts @@ -4,205 +4,91 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkGetTestSuiteFactory } from '../../common/suites/bulk_get'; +import { + bulkGetTestSuiteFactory, + TEST_CASES as CASES, + BulkGetTestDefinition, +} from '../../common/suites/bulk_get'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail400() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const { - bulkGetTest, - createExpectResults, - createExpectRbacForbidden, - expectBadRequestForHiddenType, - expectedForbiddenTypesWithHiddenType, - } = bulkGetTestSuiteFactory(esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = bulkGetTestSuiteFactory( + esArchiver, + supertest + ); + const createTests = (spaceId: string) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(spaceId); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false, { singleRequest: true }), + createTestDefinitions(hiddenType, true), + createTestDefinitions(allTypes, true, { + singleRequest: true, + responseBodyOverride: expectForbidden(['hiddentype']), + }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, { singleRequest: true }), + }; + }; describe('_bulk_get', () => { - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - bulkGetTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkGetTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingHiddenType: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - }, - }); - - bulkGetTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkGetTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized, superuser } = createTests(spaceId); + const _addTests = (user: TestUser, tests: BulkGetTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - bulkGetTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, + [users.noAccess, users.legacyAll, users.allAtOtherSpace].forEach(user => { + _addTests(user, unauthorized); }); - - bulkGetTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, + [ + users.dualAll, + users.dualRead, + users.allGlobally, + users.readGlobally, + users.allAtSpace, + users.readAtSpace, + ].forEach(user => { + _addTests(user, authorized); }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_update.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_update.ts index 06240647b37a8..987209653b347 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_update.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_update.ts @@ -4,290 +4,91 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkUpdateTestSuiteFactory } from '../../common/suites/bulk_update'; +import { + bulkUpdateTestSuiteFactory, + TEST_CASES as CASES, + BulkUpdateTestDefinition, +} from '../../common/suites/bulk_update'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('bulkUpdate', () => { - const { - createExpectDoesntExistNotFound, - expectDoesntExistRbacForbidden, - expectNotSpaceAwareResults, - expectNotSpaceAwareRbacForbidden, - expectSpaceAwareRbacForbidden, - expectSpaceAwareResults, - expectSpaceNotFound, - expectHiddenTypeRbacForbidden, - expectHiddenTypeRbacForbiddenWithGlobalAllowed, - bulkUpdateTest, - } = bulkUpdateTestSuiteFactory(esArchiver, supertest); - - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - bulkUpdateTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 200, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - bulkUpdateTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbiddenWithGlobalAllowed, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions, expectForbidden } = bulkUpdateTestSuiteFactory( + esArchiver, + supertest + ); + const createTests = (spaceId: string) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(spaceId); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false, { singleRequest: true }), + createTestDefinitions(hiddenType, true), + createTestDefinitions(allTypes, true, { + singleRequest: true, + responseBodyOverride: expectForbidden(['hiddentype']), + }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, { singleRequest: true }), + }; + }; - bulkUpdateTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); + describe('_bulk_update', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized, superuser } = createTests(spaceId); + const _addTests = (user: TestUser, tests: BulkUpdateTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - bulkUpdateTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbiddenWithGlobalAllowed, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); }); - - bulkUpdateTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbiddenWithGlobalAllowed, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - bulkUpdateTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, + [users.dualAll, users.allGlobally, users.allAtSpace].forEach(user => { + _addTests(user, authorized); }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts index e4adaa580c1db..7278504b8f0e8 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts @@ -4,248 +4,91 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { createTestSuiteFactory } from '../../common/suites/create'; +import { + createTestSuiteFactory, + TEST_CASES as CASES, + CreateTestDefinition, +} from '../../common/suites/create'; -export default function({ getService }: FtrProviderContext) { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('legacyEs'); - const esArchiver = getService('esArchiver'); - - const { - createTest, - createExpectSpaceAwareResults, - expectNotSpaceAwareResults, - expectNotSpaceAwareRbacForbidden, - expectSpaceAwareRbacForbidden, - expectBadRequestForHiddenType, - expectHiddenTypeRbacForbidden, - } = createTestSuiteFactory(es, esArchiver, supertestWithoutAuth); - - describe('create', () => { - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - createTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 400, - response: expectBadRequestForHiddenType, - }, - }, - }); +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; - createTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); +const createTestCases = (overwrite: boolean, spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { + ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + ...fail409(!overwrite && spaceId === DEFAULT_SPACE_ID), + }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(!overwrite && spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(!overwrite && spaceId === SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail409(!overwrite || (spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID)), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail409(!overwrite || spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail409(!overwrite || spaceId !== SPACE_2_ID) }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_MULTI_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail400() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; - createTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertestWithoutAuth'); + const esArchiver = getService('esArchiver'); + const es = getService('legacyEs'); - createTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); + const { addTests, createTestDefinitions } = createTestSuiteFactory(es, esArchiver, supertest); + const createTests = (overwrite: boolean, spaceId: string) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(overwrite, spaceId); + return { + unauthorized: createTestDefinitions(allTypes, true, overwrite, { spaceId }), + authorized: [ + createTestDefinitions(normalTypes, false, overwrite, { spaceId }), + createTestDefinitions(hiddenType, true, overwrite, { spaceId }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, overwrite, { spaceId }), + }; + }; - createTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); + describe('_create', () => { + getTestScenarios([false, true]).securityAndSpaces.forEach( + ({ spaceId, users, modifier: overwrite }) => { + const suffix = ` within the ${spaceId} space${overwrite ? ' with overwrite enabled' : ''}`; + const { unauthorized, authorized, superuser } = createTests(overwrite!, spaceId); + const _addTests = (user: TestUser, tests: CreateTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - createTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - }); + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally, users.allAtSpace].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); + } + ); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/delete.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/delete.ts index bfd2112428db4..995b8fc2422d9 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/delete.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/delete.ts @@ -4,288 +4,83 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { deleteTestSuiteFactory } from '../../common/suites/delete'; +import { + deleteTestSuiteFactory, + TEST_CASES as CASES, + DeleteTestDefinition, +} from '../../common/suites/delete'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('delete', () => { - const { - createExpectUnknownDocNotFound, - deleteTest, - expectEmpty, - expectRbacSpaceAwareForbidden, - expectRbacNotSpaceAwareForbidden, - expectRbacInvalidIdForbidden, - expectGenericNotFound, - expectRbacHiddenTypeForbidden, - } = deleteTestSuiteFactory(esArchiver, supertest); - - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - deleteTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 404, - response: expectGenericNotFound, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(scenario.spaceId), - }, - }, - }); - - deleteTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(scenario.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions } = deleteTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(spaceId); + return { + unauthorized: createTestDefinitions(allTypes, true, { spaceId }), + authorized: [ + createTestDefinitions(normalTypes, false, { spaceId }), + createTestDefinitions(hiddenType, true, { spaceId }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, { spaceId }), + }; + }; - deleteTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); + describe('_delete', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized, superuser } = createTests(spaceId); + const _addTests = (user: TestUser, tests: DeleteTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - deleteTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(scenario.spaceId), - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); }); - - deleteTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(scenario.spaceId), - }, - }, - }); - - deleteTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacHiddenTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, + [users.dualAll, users.allGlobally, users.allAtSpace].forEach(user => { + _addTests(user, authorized); }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/export.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/export.ts index b64c3ed87c35d..6f2426e55c6a6 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/export.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/export.ts @@ -4,274 +4,70 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; -import { SPACES } from '../../common/lib/spaces'; +import { getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { exportTestSuiteFactory } from '../../common/suites/export'; +import { + exportTestSuiteFactory, + getTestCases, + ExportTestDefinition, +} from '../../common/suites/export'; + +const createTestCases = (spaceId: string) => { + const cases = getTestCases(spaceId); + const exportableTypes = [ + cases.singleNamespaceObject, + cases.singleNamespaceType, + cases.namespaceAgnosticObject, + cases.namespaceAgnosticType, + ]; + const nonExportableTypes = [ + cases.multiNamespaceObject, + cases.multiNamespaceType, + cases.hiddenObject, + cases.hiddenType, + ]; + const allTypes = exportableTypes.concat(nonExportableTypes); + return { exportableTypes, nonExportableTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('export', () => { - const { - createExpectRbacForbidden, - expectTypeOrObjectsRequired, - createExpectVisualizationResults, - expectInvalidTypeSpecified, - exportTest, - } = exportTestSuiteFactory(esArchiver, supertest); + const { addTests, createTestDefinitions } = exportTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const { exportableTypes, nonExportableTypes, allTypes } = createTestCases(spaceId); + return { + unauthorized: [ + createTestDefinitions(exportableTypes, true), + createTestDefinitions(nonExportableTypes, false), + ].flat(), + authorized: createTestDefinitions(allTypes, false), + }; + }; - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - exportTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); + describe('_export', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized } = createTests(spaceId); + const _addTests = (user: TestUser, tests: ExportTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - exportTest(`superuser with the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, + [users.noAccess, users.legacyAll, users.allAtOtherSpace].forEach(user => { + _addTests(user, unauthorized); }); - - exportTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest(`rbac user with all at the other space within ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, + [ + users.dualAll, + users.dualRead, + users.allGlobally, + users.readGlobally, + users.allAtSpace, + users.readAtSpace, + users.superuser, + ].forEach(user => { + _addTests(user, authorized); }); }); }); diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/find.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/find.ts index 366b8b44585cd..7c16c01d203c0 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/find.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/find.ts @@ -4,727 +4,71 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; -import { SPACES } from '../../common/lib/spaces'; +import { getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { findTestSuiteFactory } from '../../common/suites/find'; +import { findTestSuiteFactory, getTestCases, FindTestDefinition } from '../../common/suites/find'; + +const createTestCases = (spaceId: string) => { + const cases = getTestCases(spaceId); + const normalTypes = [ + cases.singleNamespaceType, + cases.multiNamespaceType, + cases.namespaceAgnosticType, + cases.pageBeyondTotal, + cases.unknownSearchField, + cases.filterWithNamespaceAgnosticType, + cases.filterWithDisallowedType, + ]; + const hiddenAndUnknownTypes = [ + cases.hiddenType, + cases.unknownType, + cases.filterWithHiddenType, + cases.filterWithUnknownType, + ]; + const allTypes = normalTypes.concat(hiddenAndUnknownTypes); + return { normalTypes, hiddenAndUnknownTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('find', () => { - const { - createExpectEmpty, - createExpectRbacForbidden, - createExpectVisualizationResults, - expectFilterWrongTypeError, - expectNotSpaceAwareResults, - expectTypeRequired, - findTest, - } = findTestSuiteFactory(esArchiver, supertest); + const { addTests, createTestDefinitions } = findTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const { normalTypes, hiddenAndUnknownTypes, allTypes } = createTestCases(spaceId); + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false), + createTestDefinitions(hiddenAndUnknownTypes, true), + ].flat(), + superuser: createTestDefinitions(allTypes, false), + }; + }; - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - findTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and find url message', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, - }); + describe('_find', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized, superuser } = createTests(spaceId); + const _addTests = (user: TestUser, tests: FindTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - findTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - unknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithUnknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, + [users.noAccess, users.legacyAll, users.allAtOtherSpace].forEach(user => { + _addTests(user, unauthorized); }); - - findTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and find url message', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, - }); - - findTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(scenario.spaceId), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and find url message', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, + [ + users.dualAll, + users.dualRead, + users.allGlobally, + users.readGlobally, + users.allAtSpace, + users.readAtSpace, + ].forEach(user => { + _addTests(user, authorized); }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/get.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/get.ts index 9667abcc5e57a..9e3203e147493 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/get.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/get.ts @@ -4,289 +4,84 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { getTestSuiteFactory } from '../../common/suites/get'; +import { + getTestSuiteFactory, + TEST_CASES as CASES, + GetTestDefinition, +} from '../../common/suites/get'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const { - createExpectDoesntExistNotFound, - createExpectSpaceAwareResults, - createExpectNotSpaceAwareResults, - expectSpaceAwareRbacForbidden, - expectNotSpaceAwareRbacForbidden, - expectDoesntExistRbacForbidden, - expectHiddenTypeRbacForbidden, - expectHiddenTypeNotFound, - getTest, - } = getTestSuiteFactory(esArchiver, supertest); - - describe('get', () => { - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - getTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - getTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 404, - response: expectHiddenTypeNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - getTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - getTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions } = getTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(spaceId); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false), + createTestDefinitions(hiddenType, true), + ].flat(), + superuser: createTestDefinitions(allTypes, false), + }; + }; - getTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); + describe('_get', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized, superuser } = createTests(spaceId); + const _addTests = (user: TestUser, tests: GetTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - getTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, + [users.noAccess, users.legacyAll, users.allAtOtherSpace].forEach(user => { + _addTests(user, unauthorized); }); - - getTest(`rbac user with read globall within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - getTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - getTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(scenario.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - getTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, + [ + users.dualAll, + users.dualRead, + users.allGlobally, + users.readGlobally, + users.allAtSpace, + users.readAtSpace, + ].forEach(user => { + _addTests(user, authorized); }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts index 58859c292ce35..10c7f61dce5cc 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/import.ts @@ -4,245 +4,92 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { importTestSuiteFactory } from '../../common/suites/import'; +import { + importTestSuiteFactory, + TEST_CASES as CASES, + ImportTestDefinition, +} from '../../common/suites/import'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const importableTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail409(spaceId === DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(spaceId === SPACE_2_ID) }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409() }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const nonImportableTypes = [ + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail400() }, + { ...CASES.HIDDEN, ...fail400() }, + { ...CASES.NEW_MULTI_NAMESPACE_OBJ, ...fail400() }, + ]; + const allTypes = importableTypes.concat(nonImportableTypes); + return { importableTypes, nonImportableTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - importTest, - createExpectResults, - expectRbacForbidden, - expectUnknownTypeUnsupported: expectUnknownTypeUnsupported, - expectHiddenTypeUnsupported, - } = importTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = importTestSuiteFactory( + es, + esArchiver, + supertest + ); + const createTests = (spaceId: string) => { + const { importableTypes, nonImportableTypes, allTypes } = createTestCases(spaceId); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: [ + createTestDefinitions(importableTypes, true, { spaceId }), + createTestDefinitions(nonImportableTypes, false, { spaceId, singleRequest: true }), + createTestDefinitions(allTypes, true, { + spaceId, + singleRequest: true, + responseBodyOverride: expectForbidden(['dashboard', 'globaltype', 'isolatedtype']), + }), + ].flat(), + authorized: createTestDefinitions(allTypes, false, { spaceId, singleRequest: true }), + }; + }; describe('_import', () => { - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - importTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - importTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized } = createTests(spaceId); + const _addTests = (user: TestUser, tests: ImportTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - importTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); }); - - importTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - importTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - importTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, + [users.dualAll, users.allGlobally, users.allAtSpace, users.superuser].forEach(user => { + _addTests(user, authorized); }); }); }); diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts index bb42c5422ece5..46d7ab6425989 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts @@ -20,6 +20,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./bulk_create')); loadTestFile(require.resolve('./bulk_get')); + loadTestFile(require.resolve('./bulk_update')); loadTestFile(require.resolve('./create')); loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./export')); @@ -28,6 +29,5 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./import')); loadTestFile(require.resolve('./resolve_import_errors')); loadTestFile(require.resolve('./update')); - loadTestFile(require.resolve('./bulk_update')); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts index 6c91fe6310170..8e8fe874b4317 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/resolve_import_errors.ts @@ -4,258 +4,99 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve_import_errors'; +import { + resolveImportErrorsTestSuiteFactory, + TEST_CASES as CASES, + ResolveImportErrorsTestDefinition, +} from '../../common/suites/resolve_import_errors'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (overwrite: boolean, spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const importableTypes = [ + { + ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + ...fail409(!overwrite && spaceId === DEFAULT_SPACE_ID), + }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(!overwrite && spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(!overwrite && spaceId === SPACE_2_ID) }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const nonImportableTypes = [ + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail400() }, + { ...CASES.HIDDEN, ...fail400() }, + { ...CASES.NEW_MULTI_NAMESPACE_OBJ, ...fail400() }, + ]; + const allTypes = importableTypes.concat(nonImportableTypes); + return { importableTypes, nonImportableTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - resolveImportErrorsTest, - createExpectResults, - expectRbacForbidden, - expectUnknownTypeUnsupported, - expectHiddenTypeUnsupported, - } = resolveImportErrorsTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = resolveImportErrorsTestSuiteFactory( + es, + esArchiver, + supertest + ); + const createTests = (overwrite: boolean, spaceId: string) => { + const { importableTypes, nonImportableTypes, allTypes } = createTestCases(overwrite, spaceId); + const singleRequest = true; + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: [ + createTestDefinitions(importableTypes, true, overwrite, { spaceId }), + createTestDefinitions(nonImportableTypes, false, overwrite, { spaceId, singleRequest }), + createTestDefinitions(allTypes, true, overwrite, { + spaceId, + singleRequest, + responseBodyOverride: expectForbidden(['dashboard', 'globaltype', 'isolatedtype']), + }), + ].flat(), + authorized: createTestDefinitions(allTypes, false, overwrite, { spaceId, singleRequest }), + }; + }; describe('_resolve_import_errors', () => { - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - resolveImportErrorsTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - resolveImportErrorsTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - resolveImportErrorsTest( - `dual-privileges readonly user within the ${scenario.spaceId} space`, - { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - } - ); - - resolveImportErrorsTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - resolveImportErrorsTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest( - `rbac user with all at the space within the ${scenario.spaceId} space`, - { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectResults(scenario.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - } - ); - - resolveImportErrorsTest( - `rbac user with read at the space within the ${scenario.spaceId} space`, - { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - } - ); + getTestScenarios([false, true]).securityAndSpaces.forEach( + ({ spaceId, users, modifier: overwrite }) => { + const suffix = ` within the ${spaceId} space${overwrite ? ' with overwrite enabled' : ''}`; + const { unauthorized, authorized } = createTests(overwrite!, spaceId); + const _addTests = (user: TestUser, tests: ResolveImportErrorsTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - resolveImportErrorsTest( - `rbac user with all at other space within the ${scenario.spaceId} space`, - { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - } - ); - }); + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally, users.allAtSpace, users.superuser].forEach(user => { + _addTests(user, authorized); + }); + } + ); }); } diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts index 8eb06e41e2a41..21f354d2a8e76 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts @@ -4,289 +4,83 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { updateTestSuiteFactory } from '../../common/suites/update'; +import { + updateTestSuiteFactory, + TEST_CASES as CASES, + UpdateTestDefinition, +} from '../../common/suites/update'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('update', () => { - const { - createExpectDoesntExistNotFound, - expectDoesntExistRbacForbidden, - expectNotSpaceAwareResults, - expectNotSpaceAwareRbacForbidden, - expectSpaceAwareRbacForbidden, - expectSpaceAwareResults, - expectSpaceNotFound, - expectHiddenTypeRbacForbidden, - updateTest, - } = updateTestSuiteFactory(esArchiver, supertest); - - [ - { - spaceId: SPACES.DEFAULT.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - }, - }, - { - spaceId: SPACES.SPACE_1.spaceId, - users: { - noAccess: AUTHENTICATION.NOT_A_KIBANA_USER, - superuser: AUTHENTICATION.SUPERUSER, - legacyAll: AUTHENTICATION.KIBANA_LEGACY_USER, - allGlobally: AUTHENTICATION.KIBANA_RBAC_USER, - readGlobally: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - dualAll: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - dualRead: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - allAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - readAtSpace: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - allAtOtherSpace: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - }, - }, - ].forEach(scenario => { - updateTest(`user with no access within the ${scenario.spaceId} space`, { - user: scenario.users.noAccess, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`superuser within the ${scenario.spaceId} space`, { - user: scenario.users.superuser, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 404, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - updateTest(`legacy user within the ${scenario.spaceId} space`, { - user: scenario.users.legacyAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`dual-privileges user within the ${scenario.spaceId} space`, { - user: scenario.users.dualAll, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions } = updateTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(spaceId); + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false), + createTestDefinitions(hiddenType, true), + ].flat(), + superuser: createTestDefinitions(allTypes, false), + }; + }; - updateTest(`dual-privileges readonly user within the ${scenario.spaceId} space`, { - user: scenario.users.dualRead, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); + describe('_update', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` within the ${spaceId} space`; + const { unauthorized, authorized, superuser } = createTests(spaceId); + const _addTests = (user: TestUser, tests: UpdateTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; - updateTest(`rbac user with all globally within the ${scenario.spaceId} space`, { - user: scenario.users.allGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); }); - - updateTest(`rbac user with read globally within the ${scenario.spaceId} space`, { - user: scenario.users.readGlobally, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`rbac user with all at the space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(scenario.spaceId), - }, - }, - }); - - updateTest(`rbac user with read at the space within the ${scenario.spaceId} space`, { - user: scenario.users.readAtSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`rbac user with all at other space within the ${scenario.spaceId} space`, { - user: scenario.users.allAtOtherSpace, - spaceId: scenario.spaceId, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, + [users.dualAll, users.allGlobally, users.allAtSpace].forEach(user => { + _addTests(user, authorized); }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts index 943a22c4399c7..5b3397c7909ae 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_create.ts @@ -4,176 +4,88 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; +import { + bulkCreateTestSuiteFactory, + TEST_CASES as CASES, + BulkCreateTestDefinition, +} from '../../common/suites/bulk_create'; + +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (overwrite: boolean) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail409(!overwrite) }, + CASES.SINGLE_NAMESPACE_SPACE_1, + CASES.SINGLE_NAMESPACE_SPACE_2, + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail409(!overwrite) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail409() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail409() }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_MULTI_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail400() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - bulkCreateTest, - createExpectResults, - createExpectRbacForbidden, - expectBadRequestForHiddenType, - expectedForbiddenTypesWithHiddenType: expectedForbiddenTypesWithHiddenType, - } = bulkCreateTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = bulkCreateTestSuiteFactory( + es, + esArchiver, + supertest + ); + const createTests = (overwrite: boolean) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(overwrite); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: createTestDefinitions(allTypes, true, overwrite), + authorized: [ + createTestDefinitions(normalTypes, false, overwrite, { singleRequest: true }), + createTestDefinitions(hiddenType, true, overwrite), + createTestDefinitions(allTypes, true, overwrite, { + singleRequest: true, + responseBodyOverride: expectForbidden(['hiddentype']), + }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, overwrite, { singleRequest: true }), + }; + }; describe('_bulk_create', () => { - bulkCreateTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingSpace: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - }, - }); - - bulkCreateTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkCreateTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkCreateTest(`rbac readonly user`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkCreateTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); + getTestScenarios([false, true]).security.forEach(({ users, modifier: overwrite }) => { + const suffix = overwrite ? ' with overwrite enabled' : ''; + const { unauthorized, authorized, superuser } = createTests(overwrite!); + const _addTests = (user: TestUser, tests: BulkCreateTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, tests }); + }; - bulkCreateTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingSpace: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_get.ts b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_get.ts index fde98694fe575..69494ed254669 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_get.ts @@ -4,175 +4,81 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkGetTestSuiteFactory } from '../../common/suites/bulk_get'; +import { + bulkGetTestSuiteFactory, + TEST_CASES as CASES, + BulkGetTestDefinition, +} from '../../common/suites/bulk_get'; + +const { fail400, fail404 } = testCaseFailures; + +const createTestCases = () => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404() }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404() }, + CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404() }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail400() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const { - bulkGetTest, - createExpectResults, - createExpectRbacForbidden, - expectedForbiddenTypesWithHiddenType, - expectBadRequestForHiddenType, - } = bulkGetTestSuiteFactory(esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = bulkGetTestSuiteFactory( + esArchiver, + supertest + ); + const createTests = () => { + const { normalTypes, hiddenType, allTypes } = createTestCases(); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false, { singleRequest: true }), + createTestDefinitions(hiddenType, true), + createTestDefinitions(allTypes, true, { + singleRequest: true, + responseBodyOverride: expectForbidden(['hiddentype']), + }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, { singleRequest: true }), + }; + }; describe('_bulk_get', () => { - bulkGetTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkGetTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingHiddenType: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - }, - }); - - bulkGetTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkGetTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`rbac user with read globally`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(['hiddentype']), - }, - }, - }); - - bulkGetTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkGetTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); - - bulkGetTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, - }); + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized, superuser } = createTests(); + const _addTests = (user: TestUser, tests: BulkGetTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - bulkGetTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - default: { - statusCode: 403, - response: createExpectRbacForbidden(), - }, - includingHiddenType: { - statusCode: 403, - response: createExpectRbacForbidden(expectedForbiddenTypesWithHiddenType), - }, - }, + [ + users.noAccess, + users.legacyAll, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.dualRead, users.allGlobally, users.readGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_update.ts b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_update.ts index 6f4635f17cf8c..fb169f4c6fb86 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/bulk_update.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/bulk_update.ts @@ -4,268 +4,83 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkUpdateTestSuiteFactory } from '../../common/suites/bulk_update'; +import { + bulkUpdateTestSuiteFactory, + TEST_CASES as CASES, + BulkUpdateTestDefinition, +} from '../../common/suites/bulk_update'; + +const { fail404 } = testCaseFailures; + +const createTestCases = () => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404() }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404() }, + CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404() }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('bulkUpdate', () => { - const { - createExpectDoesntExistNotFound, - expectDoesntExistRbacForbidden, - expectNotSpaceAwareResults, - expectNotSpaceAwareRbacForbidden, - expectSpaceAwareRbacForbidden, - expectSpaceAwareResults, - expectSpaceNotFound, - expectHiddenTypeRbacForbidden, - expectHiddenTypeRbacForbiddenWithGlobalAllowed, - bulkUpdateTest, - } = bulkUpdateTestSuiteFactory(esArchiver, supertest); - - bulkUpdateTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 200, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(), - }, - }, - }); + const { addTests, createTestDefinitions, expectForbidden } = bulkUpdateTestSuiteFactory( + esArchiver, + supertest + ); + const createTests = () => { + const { normalTypes, hiddenType, allTypes } = createTestCases(); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false, { singleRequest: true }), + createTestDefinitions(hiddenType, true), + createTestDefinitions(allTypes, true, { + singleRequest: true, + responseBodyOverride: expectForbidden(['hiddentype']), + }), + ].flat(), + superuser: createTestDefinitions(allTypes, false, { singleRequest: true }), + }; + }; - bulkUpdateTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbiddenWithGlobalAllowed, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - bulkUpdateTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbiddenWithGlobalAllowed, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - bulkUpdateTest(`rbac user with read globally`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - bulkUpdateTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); + describe('_bulk_update', () => { + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized, superuser } = createTests(); + const _addTests = (user: TestUser, tests: BulkUpdateTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - bulkUpdateTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/create.ts b/x-pack/test/saved_object_api_integration/security_only/apis/create.ts index 60a9fa0a86aa6..dc8e564e42477 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/create.ts @@ -4,222 +4,79 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { createTestSuiteFactory } from '../../common/suites/create'; +import { + createTestSuiteFactory, + TEST_CASES as CASES, + CreateTestDefinition, +} from '../../common/suites/create'; -export default function({ getService }: FtrProviderContext) { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('legacyEs'); - const esArchiver = getService('esArchiver'); - - const { - createTest, - createExpectSpaceAwareResults, - expectNotSpaceAwareResults, - expectNotSpaceAwareRbacForbidden, - expectSpaceAwareRbacForbidden, - expectBadRequestForHiddenType, - expectHiddenTypeRbacForbidden, - } = createTestSuiteFactory(es, esArchiver, supertestWithoutAuth); - - describe('create', () => { - createTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); +const { fail400, fail409 } = testCaseFailures; - createTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 400, - response: expectBadRequestForHiddenType, - }, - }, - }); - - createTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); +const createTestCases = (overwrite: boolean) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail409(!overwrite) }, + CASES.SINGLE_NAMESPACE_SPACE_1, + CASES.SINGLE_NAMESPACE_SPACE_2, + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail409(!overwrite) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail409() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail409() }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_MULTI_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail400() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; - createTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`rbac user with read globally`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); - - createTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertestWithoutAuth'); + const esArchiver = getService('esArchiver'); + const es = getService('legacyEs'); - createTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); + const { addTests, createTestDefinitions } = createTestSuiteFactory(es, esArchiver, supertest); + const createTests = (overwrite: boolean) => { + const { normalTypes, hiddenType, allTypes } = createTestCases(overwrite); + return { + unauthorized: createTestDefinitions(allTypes, true, overwrite), + authorized: [ + createTestDefinitions(normalTypes, false, overwrite), + createTestDefinitions(hiddenType, true, overwrite), + ].flat(), + superuser: createTestDefinitions(allTypes, false, overwrite), + }; + }; - createTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, - }); + describe('_create', () => { + getTestScenarios([false, true]).security.forEach(({ users, modifier: overwrite }) => { + const suffix = overwrite ? ' with overwrite enabled' : ''; + const { unauthorized, authorized, superuser } = createTests(overwrite!); + const _addTests = (user: TestUser, tests: CreateTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, tests }); + }; - createTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/delete.ts b/x-pack/test/saved_object_api_integration/security_only/apis/delete.ts index f775b5a365d6b..05939197be352 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/delete.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/delete.ts @@ -4,266 +4,75 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { deleteTestSuiteFactory } from '../../common/suites/delete'; +import { + deleteTestSuiteFactory, + TEST_CASES as CASES, + DeleteTestDefinition, +} from '../../common/suites/delete'; + +const { fail404 } = testCaseFailures; + +const createTestCases = () => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404() }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404() }, + CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404() }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('delete', () => { - const { - createExpectUnknownDocNotFound, - deleteTest, - expectEmpty, - expectRbacSpaceAwareForbidden, - expectRbacNotSpaceAwareForbidden, - expectRbacInvalidIdForbidden, - expectRbacHiddenTypeForbidden: expectRbacSpaceTypeForbidden, - expectGenericNotFound, - } = deleteTestSuiteFactory(esArchiver, supertest); - - deleteTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 404, - response: expectGenericNotFound, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(), - }, - }, - }); + const { addTests, createTestDefinitions } = deleteTestSuiteFactory(esArchiver, supertest); + const createTests = () => { + const { normalTypes, hiddenType, allTypes } = createTestCases(); + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false), + createTestDefinitions(hiddenType, true), + ].flat(), + superuser: createTestDefinitions(allTypes, false), + }; + }; - deleteTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(), - }, - }, - }); - - deleteTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(), - }, - }, - }); - - deleteTest(`rbac user with read globally`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); - - deleteTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, - }); + describe('_delete', () => { + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized, superuser } = createTests(); + const _addTests = (user: TestUser, tests: DeleteTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - deleteTest(`rbac user with readonly at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectRbacSpaceAwareForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectRbacNotSpaceAwareForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacSpaceTypeForbidden, - }, - invalidId: { - statusCode: 403, - response: expectRbacInvalidIdForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/export.ts b/x-pack/test/saved_object_api_integration/security_only/apis/export.ts index 2a2c3a9b90b08..0fae45a1897a7 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/export.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/export.ts @@ -4,252 +4,75 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { exportTestSuiteFactory } from '../../common/suites/export'; +import { + exportTestSuiteFactory, + getTestCases, + ExportTestDefinition, +} from '../../common/suites/export'; + +const createTestCases = () => { + const cases = getTestCases(); + const exportableTypes = [ + cases.singleNamespaceObject, + cases.singleNamespaceType, + cases.namespaceAgnosticObject, + cases.namespaceAgnosticType, + ]; + const nonExportableTypes = [ + cases.multiNamespaceObject, + cases.multiNamespaceType, + cases.hiddenObject, + cases.hiddenType, + ]; + const allTypes = exportableTypes.concat(nonExportableTypes); + return { exportableTypes, nonExportableTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('export', () => { - const { - createExpectRbacForbidden, - expectTypeOrObjectsRequired, - createExpectVisualizationResults, - expectInvalidTypeSpecified, - exportTest, - } = exportTestSuiteFactory(esArchiver, supertest); - - exportTest('user with no access', { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('superuser', { - user: AUTHENTICATION.SUPERUSER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('legacy user', { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('dual-privileges user', { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('dual-privileges readonly user', { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('rbac user with all globally', { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('rbac user with read globally', { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); + const { addTests, createTestDefinitions } = exportTestSuiteFactory(esArchiver, supertest); + const createTests = () => { + const { exportableTypes, nonExportableTypes, allTypes } = createTestCases(); + return { + unauthorized: [ + createTestDefinitions(exportableTypes, true), + createTestDefinitions(nonExportableTypes, false), + ].flat(), + authorized: createTestDefinitions(allTypes, false), + }; + }; - exportTest('rbac user with all at default space', { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('rbac user with read at default space', { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); - - exportTest('rbac user with all at space_1', { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); + describe('_export', () => { + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized } = createTests(); + const _addTests = (user: TestUser, tests: ExportTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - exportTest('rbac user with read at space_1', { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [ + users.dualAll, + users.dualRead, + users.allGlobally, + users.readGlobally, + users.superuser, + ].forEach(user => { + _addTests(user, authorized); + }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/find.ts b/x-pack/test/saved_object_api_integration/security_only/apis/find.ts index 64d85a199e7bc..97513783b94b9 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/find.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/find.ts @@ -4,749 +4,70 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { findTestSuiteFactory } from '../../common/suites/find'; +import { findTestSuiteFactory, getTestCases, FindTestDefinition } from '../../common/suites/find'; + +const createTestCases = () => { + const cases = getTestCases(); + const normalTypes = [ + cases.singleNamespaceType, + cases.multiNamespaceType, + cases.namespaceAgnosticType, + cases.pageBeyondTotal, + cases.unknownSearchField, + cases.filterWithNamespaceAgnosticType, + cases.filterWithDisallowedType, + ]; + const hiddenAndUnknownTypes = [ + cases.hiddenType, + cases.unknownType, + cases.filterWithHiddenType, + cases.filterWithUnknownType, + ]; + const allTypes = normalTypes.concat(hiddenAndUnknownTypes); + return { normalTypes, hiddenAndUnknownTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('find', () => { - const { - createExpectEmpty, - createExpectRbacForbidden, - createExpectVisualizationResults, - expectFilterWrongTypeError, - expectNotSpaceAwareResults, - expectTypeRequired, - findTest, - } = findTestSuiteFactory(esArchiver, supertest); - - findTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden login and find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and unknown search field', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden login and find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, - }); - - findTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - unknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithUnknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - spaceAwareType: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden login and find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'forbidden login and find visualization message', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and unknown search field', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'forbidden login and find globaltype message', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden login and find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, - }); - - findTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); - - findTest(`rbac user with read globally`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); + const { addTests, createTestDefinitions } = findTestSuiteFactory(esArchiver, supertest); + const createTests = () => { + const { normalTypes, hiddenAndUnknownTypes, allTypes } = createTestCases(); + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false), + createTestDefinitions(hiddenAndUnknownTypes, true), + ].flat(), + superuser: createTestDefinitions(allTypes, false), + }; + }; - findTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and unknown search field', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, - }); - - findTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and unknown search field', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, - }); - - findTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and unknown search field', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, - }); + describe('_find', () => { + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized, superuser } = createTests(); + const _addTests = (user: TestUser, tests: FindTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - findTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - notSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - hiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - unknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 403, - response: createExpectRbacForbidden('visualization'), - }, - unknownSearchField: { - description: 'forbidden login and unknown search field', - statusCode: 403, - response: createExpectRbacForbidden('url'), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the globaltype', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - filterWithHiddenType: { - description: 'forbidden find hiddentype message', - statusCode: 403, - response: createExpectRbacForbidden('hiddentype'), - }, - filterWithUnknownType: { - description: 'forbidden find wigwags message', - statusCode: 403, - response: createExpectRbacForbidden('wigwags'), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'forbidden', - statusCode: 403, - response: createExpectRbacForbidden('globaltype'), - }, - }, + [ + users.noAccess, + users.legacyAll, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.dualRead, users.allGlobally, users.readGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/get.ts b/x-pack/test/saved_object_api_integration/security_only/apis/get.ts index 2a31463fce8b2..7cd50fe4cea61 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/get.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/get.ts @@ -4,267 +4,73 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { getTestSuiteFactory } from '../../common/suites/get'; +import { + getTestSuiteFactory, + TEST_CASES as CASES, + GetTestDefinition, +} from '../../common/suites/get'; + +const { fail404 } = testCaseFailures; + +const createTestCases = () => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404() }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404() }, + CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404() }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - const { - createExpectDoesntExistNotFound, - createExpectSpaceAwareResults, - createExpectNotSpaceAwareResults, - expectSpaceAwareRbacForbidden, - expectNotSpaceAwareRbacForbidden, - expectDoesntExistRbacForbidden, - expectHiddenTypeRbacForbidden, - expectHiddenTypeNotFound, - getTest, - } = getTestSuiteFactory(esArchiver, supertest); - - describe('get', () => { - getTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - getTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(), - }, - hiddenType: { - statusCode: 404, - response: expectHiddenTypeNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); + const { addTests, createTestDefinitions } = getTestSuiteFactory(esArchiver, supertest); + const createTests = () => { + const { normalTypes, hiddenType, allTypes } = createTestCases(); + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false), + createTestDefinitions(hiddenType, true), + ].flat(), + superuser: createTestDefinitions(allTypes, false), + }; + }; - getTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - getTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - getTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - getTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - getTest(`rbac user with read globally`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(), - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - getTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - getTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - getTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); + describe('_get', () => { + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized, superuser } = createTests(); + const _addTests = (user: TestUser, tests: GetTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - getTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.dualRead, users.allGlobally, users.readGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/import.ts b/x-pack/test/saved_object_api_integration/security_only/apis/import.ts index 770410dcfed81..5a6e530b02939 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/import.ts @@ -4,223 +4,87 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { importTestSuiteFactory } from '../../common/suites/import'; +import { + importTestSuiteFactory, + TEST_CASES as CASES, + ImportTestDefinition, +} from '../../common/suites/import'; + +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = () => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const importableTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail409() }, + CASES.SINGLE_NAMESPACE_SPACE_1, + CASES.SINGLE_NAMESPACE_SPACE_2, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409() }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const nonImportableTypes = [ + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail400() }, + { ...CASES.HIDDEN, ...fail400() }, + { ...CASES.NEW_MULTI_NAMESPACE_OBJ, ...fail400() }, + ]; + const allTypes = importableTypes.concat(nonImportableTypes); + return { importableTypes, nonImportableTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - importTest, - createExpectResults, - expectRbacForbidden, - expectUnknownTypeUnsupported, - expectResultsWithUnsupportedHiddenType, - } = importTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = importTestSuiteFactory( + es, + esArchiver, + supertest + ); + const createTests = () => { + const { importableTypes, nonImportableTypes, allTypes } = createTestCases(); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: [ + createTestDefinitions(importableTypes, true), + createTestDefinitions(nonImportableTypes, false, { singleRequest: true }), + createTestDefinitions(allTypes, true, { + singleRequest: true, + responseBodyOverride: expectForbidden(['dashboard', 'globaltype', 'isolatedtype']), + }), + ].flat(), + authorized: createTestDefinitions(allTypes, false, { singleRequest: true }), + }; + }; describe('_import', () => { - importTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - hiddenType: { - // import filters out the space type, so the remaining objects will import successfully - statusCode: 200, - response: expectResultsWithUnsupportedHiddenType, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - importTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - hiddenType: { - // import filters out the space type, so the remaining objects will import successfully - statusCode: 200, - response: expectResultsWithUnsupportedHiddenType, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - importTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - hiddenType: { - // import filters out the space type, so the remaining objects will import successfully - statusCode: 200, - response: expectResultsWithUnsupportedHiddenType, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - importTest(`rbac readonly user`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - importTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized } = createTests(); + const _addTests = (user: TestUser, tests: ImportTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - importTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally, users.superuser].forEach(user => { + _addTests(user, authorized); + }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/index.ts b/x-pack/test/saved_object_api_integration/security_only/apis/index.ts index bb637a9bc4c90..f581e18ff17af 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/index.ts @@ -20,6 +20,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./bulk_create')); loadTestFile(require.resolve('./bulk_get')); + loadTestFile(require.resolve('./bulk_update')); loadTestFile(require.resolve('./create')); loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./export')); @@ -28,6 +29,5 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./import')); loadTestFile(require.resolve('./resolve_import_errors')); loadTestFile(require.resolve('./update')); - loadTestFile(require.resolve('./bulk_update')); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts index 59d50c16c259a..f945d2b64c432 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/resolve_import_errors.ts @@ -4,221 +4,88 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve_import_errors'; +import { + resolveImportErrorsTestSuiteFactory, + TEST_CASES as CASES, + ResolveImportErrorsTestDefinition, +} from '../../common/suites/resolve_import_errors'; + +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (overwrite: boolean) => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const importableTypes = [ + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail409(!overwrite) }, + CASES.SINGLE_NAMESPACE_SPACE_1, + CASES.SINGLE_NAMESPACE_SPACE_2, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + ]; + const nonImportableTypes = [ + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail400() }, + { ...CASES.HIDDEN, ...fail400() }, + { ...CASES.NEW_MULTI_NAMESPACE_OBJ, ...fail400() }, + ]; + const allTypes = importableTypes.concat(nonImportableTypes); + return { importableTypes, nonImportableTypes, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - resolveImportErrorsTest, - createExpectResults, - - expectRbacForbidden, - expectUnknownTypeUnsupported, - expectHiddenTypeUnsupported, - } = resolveImportErrorsTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions, expectForbidden } = resolveImportErrorsTestSuiteFactory( + es, + esArchiver, + supertest + ); + const createTests = (overwrite: boolean) => { + const { importableTypes, nonImportableTypes, allTypes } = createTestCases(overwrite); + // use singleRequest to reduce execution time and/or test combined cases + return { + unauthorized: [ + createTestDefinitions(importableTypes, true, overwrite), + createTestDefinitions(nonImportableTypes, false, overwrite, { singleRequest: true }), + createTestDefinitions(allTypes, true, overwrite, { + singleRequest: true, + responseBodyOverride: expectForbidden(['dashboard', 'globaltype', 'isolatedtype']), + }), + ].flat(), + authorized: createTestDefinitions(allTypes, false, overwrite, { singleRequest: true }), + }; + }; describe('_resolve_import_errors', () => { - resolveImportErrorsTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - resolveImportErrorsTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - resolveImportErrorsTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - default: { - statusCode: 200, - response: createExpectResults(), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - resolveImportErrorsTest(`rbac readonly user`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); - - resolveImportErrorsTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, - }); + getTestScenarios([false, true]).security.forEach(({ users, modifier: overwrite }) => { + const suffix = overwrite ? ' with overwrite enabled' : ''; + const { unauthorized, authorized } = createTests(overwrite!); + const _addTests = (user: TestUser, tests: ResolveImportErrorsTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, tests }); + }; - resolveImportErrorsTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - default: { - statusCode: 403, - response: expectRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectRbacForbidden, - }, - unknownType: { - statusCode: 403, - response: expectRbacForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally, users.superuser].forEach(user => { + _addTests(user, authorized); + }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/security_only/apis/update.ts b/x-pack/test/saved_object_api_integration/security_only/apis/update.ts index 8564296bdf558..e1e3a5f8a7dc7 100644 --- a/x-pack/test/saved_object_api_integration/security_only/apis/update.ts +++ b/x-pack/test/saved_object_api_integration/security_only/apis/update.ts @@ -4,267 +4,75 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AUTHENTICATION } from '../../common/lib/authentication'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; +import { TestUser } from '../../common/lib/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { updateTestSuiteFactory } from '../../common/suites/update'; +import { + updateTestSuiteFactory, + TEST_CASES as CASES, + UpdateTestDefinition, +} from '../../common/suites/update'; + +const { fail404 } = testCaseFailures; + +const createTestCases = () => { + // for each permitted (non-403) outcome, if failure !== undefined then we expect + // to receive an error; otherwise, we expect to receive a success result + const normalTypes = [ + CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404() }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404() }, + CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404() }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, + ]; + const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; + const allTypes = normalTypes.concat(hiddenType); + return { normalTypes, hiddenType, allTypes }; +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); - describe('update', () => { - const { - createExpectDoesntExistNotFound, - expectDoesntExistRbacForbidden, - expectNotSpaceAwareResults, - expectNotSpaceAwareRbacForbidden, - expectSpaceAwareRbacForbidden, - expectSpaceAwareResults, - expectSpaceNotFound, - expectHiddenTypeRbacForbidden, - updateTest, - } = updateTestSuiteFactory(esArchiver, supertest); - - updateTest(`user with no access`, { - user: AUTHENTICATION.NOT_A_KIBANA_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`superuser`, { - user: AUTHENTICATION.SUPERUSER, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 404, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); + const { addTests, createTestDefinitions } = updateTestSuiteFactory(esArchiver, supertest); + const createTests = () => { + const { normalTypes, hiddenType, allTypes } = createTestCases(); + return { + unauthorized: createTestDefinitions(allTypes, true), + authorized: [ + createTestDefinitions(normalTypes, false), + createTestDefinitions(hiddenType, true), + ].flat(), + superuser: createTestDefinitions(allTypes, false), + }; + }; - updateTest(`legacy user`, { - user: AUTHENTICATION.KIBANA_LEGACY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`dual-privileges user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_USER, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - updateTest(`dual-privileges readonly user`, { - user: AUTHENTICATION.KIBANA_DUAL_PRIVILEGES_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`rbac user with all globally`, { - user: AUTHENTICATION.KIBANA_RBAC_USER, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, - }); - - updateTest(`rbac user with read globally`, { - user: AUTHENTICATION.KIBANA_RBAC_DASHBOARD_ONLY_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`rbac user with all at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`rbac user with read at default space`, { - user: AUTHENTICATION.KIBANA_RBAC_DEFAULT_SPACE_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); - - updateTest(`rbac user with all at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_ALL_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, - }); + describe('_update', () => { + getTestScenarios().security.forEach(({ users }) => { + const { unauthorized, authorized, superuser } = createTests(); + const _addTests = (user: TestUser, tests: UpdateTestDefinition[]) => { + addTests(user.description, { user, tests }); + }; - updateTest(`rbac user with read at space_1`, { - user: AUTHENTICATION.KIBANA_RBAC_SPACE_1_READ_USER, - tests: { - spaceAware: { - statusCode: 403, - response: expectSpaceAwareRbacForbidden, - }, - notSpaceAware: { - statusCode: 403, - response: expectNotSpaceAwareRbacForbidden, - }, - hiddenType: { - statusCode: 403, - response: expectHiddenTypeRbacForbidden, - }, - doesntExist: { - statusCode: 403, - response: expectDoesntExistRbacForbidden, - }, - }, + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.allAtDefaultSpace, + users.readAtDefaultSpace, + users.allAtSpace1, + users.readAtSpace1, + ].forEach(user => { + _addTests(user, unauthorized); + }); + [users.dualAll, users.allGlobally].forEach(user => { + _addTests(user, authorized); + }); + _addTests(users.superuser, superuser); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts index 690e358b744d5..70d74822a8b0f 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts @@ -6,83 +6,72 @@ import expect from '@kbn/expect'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkCreateTestSuiteFactory } from '../../common/suites/bulk_create'; +import { bulkCreateTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/bulk_create'; -const expectNamespaceSpecifiedBadRequest = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - error: 'Bad Request', - message: '[request body.0.namespace]: definition for this key is missing', - statusCode: 400, - }); -}; +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (overwrite: boolean, spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { + ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + ...fail409(!overwrite && spaceId === DEFAULT_SPACE_ID), + }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(!overwrite && spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(!overwrite && spaceId === SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail409(!overwrite || (spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID)), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail409(!overwrite || spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail409(!overwrite || spaceId !== SPACE_2_ID) }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + { ...CASES.HIDDEN, ...fail400() }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_MULTI_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - bulkCreateTest, - createExpectResults, - expectBadRequestForHiddenType, - } = bulkCreateTestSuiteFactory(es, esArchiver, supertest); - - describe('_bulk_create', () => { - bulkCreateTest('in the current space (space_1)', { - ...SPACES.SPACE_1, - tests: { - default: { - statusCode: 200, - response: createExpectResults(SPACES.SPACE_1.spaceId), - }, - includingSpace: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - custom: { - description: 'when a namespace is specified on the saved object', - requestBody: [ - { - type: 'visualization', - namespace: 'space_1', - attributes: { - title: 'something', - }, - }, - ], - statusCode: 400, - response: expectNamespaceSpecifiedBadRequest, + const { addTests, createTestDefinitions } = bulkCreateTestSuiteFactory(es, esArchiver, supertest); + const createTests = (overwrite: boolean, spaceId: string) => { + const testCases = createTestCases(overwrite, spaceId); + return createTestDefinitions(testCases, false, overwrite, { + spaceId, + singleRequest: true, + }).concat( + ['namespace', 'namespaces'].map(key => ({ + title: `(bad request) when ${key} is specified on the saved object`, + request: [{ type: 'isolatedtype', id: 'some-id', [key]: 'any-value' }] as any, + responseStatusCode: 400, + responseBody: async (response: Record) => { + expect(response.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: `[request body.0.${key}]: definition for this key is missing`, + }); }, - }, - }); + overwrite, + })) + ); + }; - bulkCreateTest('in the default space', { - ...SPACES.DEFAULT, - tests: { - default: { - statusCode: 200, - response: createExpectResults(SPACES.DEFAULT.spaceId), - }, - includingSpace: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - custom: { - description: 'when a namespace is specified on the saved object', - requestBody: [ - { - type: 'visualization', - namespace: 'space_1', - attributes: { - title: 'something', - }, - }, - ], - statusCode: 400, - response: expectNamespaceSpecifiedBadRequest, - }, - }, + describe('_bulk_create', () => { + getTestScenarios([false, true]).spaces.forEach(({ spaceId, modifier: overwrite }) => { + const suffix = overwrite ? ' with overwrite enabled' : ''; + const tests = createTests(overwrite!, spaceId); + addTests(`within the ${spaceId} space${suffix}`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_get.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_get.ts index bed29f8eb39a1..ad10719750585 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_get.ts @@ -5,48 +5,48 @@ */ import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkGetTestSuiteFactory } from '../../common/suites/bulk_get'; +import { bulkGetTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/bulk_get'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.HIDDEN, ...fail400() }, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const { - bulkGetTest, - createExpectResults, - createExpectNotFoundResults, - expectBadRequestForHiddenType, - } = bulkGetTestSuiteFactory(esArchiver, supertest); + const { addTests, createTestDefinitions } = bulkGetTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false, { singleRequest: true }); + }; describe('_bulk_get', () => { - bulkGetTest(`objects within the current space (space_1)`, { - ...SPACES.SPACE_1, - tests: { - default: { - statusCode: 200, - response: createExpectResults(SPACES.SPACE_1.spaceId), - }, - includingHiddenType: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - }, - }); - - bulkGetTest(`objects within another space`, { - ...SPACES.SPACE_1, - otherSpaceId: SPACES.SPACE_2.spaceId, - tests: { - default: { - statusCode: 200, - response: createExpectNotFoundResults(SPACES.SPACE_2.spaceId), - }, - includingHiddenType: { - statusCode: 200, - response: expectBadRequestForHiddenType, - }, - }, + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_update.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_update.ts index 0681908a765ce..be6ce9e30c56e 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_update.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_update.ts @@ -5,88 +5,48 @@ */ import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { bulkUpdateTestSuiteFactory } from '../../common/suites/bulk_update'; +import { bulkUpdateTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/bulk_update'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.HIDDEN, ...fail404() }, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - describe('bulkUpdate', () => { - const { - createExpectSpaceAwareNotFound, - expectSpaceAwareResults, - createExpectDoesntExistNotFound, - expectNotSpaceAwareResults, - expectSpaceNotFound, - bulkUpdateTest, - } = bulkUpdateTestSuiteFactory(esArchiver, supertest); - - bulkUpdateTest(`in the default space`, { - spaceId: SPACES.DEFAULT.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 200, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(SPACES.DEFAULT.spaceId), - }, - }, - }); - - bulkUpdateTest('in the current space (space_1)', { - spaceId: SPACES.SPACE_1.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 200, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(SPACES.SPACE_1.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions } = bulkUpdateTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false, { singleRequest: true }); + }; - bulkUpdateTest('objects that exist in another space (space_1)', { - spaceId: SPACES.DEFAULT.spaceId, - otherSpaceId: SPACES.SPACE_1.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareNotFound(SPACES.SPACE_1.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 200, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 200, - response: createExpectDoesntExistNotFound(), - }, - }, + describe('_bulk_update', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts index 3bd4019649363..d0c6a21e73971 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts @@ -4,90 +4,56 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { createTestSuiteFactory } from '../../common/suites/create'; +import { createTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/create'; -const expectNamespaceSpecifiedBadRequest = (resp: { [key: string]: any }) => { - expect(resp.body).to.eql({ - error: 'Bad Request', - message: '[request body.namespace]: definition for this key is missing', - statusCode: 400, - }); -}; +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (overwrite: boolean, spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { + ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + ...fail409(!overwrite && spaceId === DEFAULT_SPACE_ID), + }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(!overwrite && spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(!overwrite && spaceId === SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail409(!overwrite || (spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID)), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail409(!overwrite || spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail409(!overwrite || spaceId !== SPACE_2_ID) }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + { ...CASES.HIDDEN, ...fail400() }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + CASES.NEW_MULTI_NAMESPACE_OBJ, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, +]; export default function({ getService }: FtrProviderContext) { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('legacyEs'); + const supertest = getService('supertestWithoutAuth'); const esArchiver = getService('esArchiver'); + const es = getService('legacyEs'); - const { - createTest, - createExpectSpaceAwareResults, - expectNotSpaceAwareResults, - expectBadRequestForHiddenType, - } = createTestSuiteFactory(es, esArchiver, supertestWithoutAuth); - - describe('create', () => { - createTest('in the current space (space_1)', { - ...SPACES.SPACE_1, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(SPACES.SPACE_1.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 400, - response: expectBadRequestForHiddenType, - }, - custom: { - description: 'when a namespace is specified on the saved object', - type: 'visualization', - requestBody: { - namespace: 'space_1', - attributes: { - title: 'something', - }, - }, - statusCode: 400, - response: expectNamespaceSpecifiedBadRequest, - }, - }, - }); + const { addTests, createTestDefinitions } = createTestSuiteFactory(es, esArchiver, supertest); + const createTests = (overwrite: boolean, spaceId: string) => { + const testCases = createTestCases(overwrite, spaceId); + return createTestDefinitions(testCases, false, overwrite, { spaceId }); + }; - createTest('in the default space', { - ...SPACES.DEFAULT, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(SPACES.DEFAULT.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 400, - response: expectBadRequestForHiddenType, - }, - custom: { - description: 'when a namespace is specified on the saved object', - type: 'visualization', - requestBody: { - namespace: 'space_1', - attributes: { - title: 'something', - }, - }, - statusCode: 400, - response: expectNamespaceSpecifiedBadRequest, - }, - }, + describe('_create', () => { + getTestScenarios([false, true]).spaces.forEach(({ spaceId, modifier: overwrite }) => { + const suffix = overwrite ? ' with overwrite enabled' : ''; + const tests = createTests(overwrite!, spaceId); + addTests(`within the ${spaceId} space${suffix}`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/delete.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/delete.ts index 437b3f95024c6..bb48e06d93a09 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/delete.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/delete.ts @@ -5,87 +5,48 @@ */ import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { deleteTestSuiteFactory } from '../../common/suites/delete'; +import { deleteTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/delete'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.HIDDEN, ...fail404() }, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - describe('delete', () => { - const { - createExpectSpaceAwareNotFound, - createExpectUnknownDocNotFound, - deleteTest, - expectEmpty, - expectGenericNotFound, - } = deleteTestSuiteFactory(esArchiver, supertest); - - deleteTest(`in the default space`, { - ...SPACES.DEFAULT, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 404, - response: expectGenericNotFound, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(SPACES.DEFAULT.spaceId), - }, - }, - }); - - deleteTest(`in the current space (space_1)`, { - ...SPACES.SPACE_1, - tests: { - spaceAware: { - statusCode: 200, - response: expectEmpty, - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 404, - response: expectGenericNotFound, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(SPACES.SPACE_1.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions } = deleteTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false, { spaceId }); + }; - deleteTest(`in another space (space_2)`, { - spaceId: SPACES.SPACE_1.spaceId, - otherSpaceId: SPACES.SPACE_2.spaceId, - tests: { - spaceAware: { - statusCode: 404, - response: createExpectSpaceAwareNotFound(SPACES.SPACE_2.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectEmpty, - }, - hiddenType: { - statusCode: 404, - response: expectGenericNotFound, - }, - invalidId: { - statusCode: 404, - response: createExpectUnknownDocNotFound(SPACES.SPACE_2.spaceId), - }, - }, + describe('_delete', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/export.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/export.ts index f4be02c05ac88..25d4fbfae990b 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/export.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/export.ts @@ -4,62 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SPACES } from '../../common/lib/spaces'; +import { getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { exportTestSuiteFactory } from '../../common/suites/export'; +import { exportTestSuiteFactory, getTestCases } from '../../common/suites/export'; + +const createTestCases = (spaceId: string) => { + const cases = getTestCases(spaceId); + return Object.values(cases); +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const { - expectTypeOrObjectsRequired, - createExpectVisualizationResults, - expectInvalidTypeSpecified, - exportTest, - } = exportTestSuiteFactory(esArchiver, supertest); - - describe('export', () => { - exportTest('objects only within the current space (space_1)', { - ...SPACES.SPACE_1, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(SPACES.SPACE_1.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, - }); + const { addTests, createTestDefinitions } = exportTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false); + }; - exportTest('objects only within the current space (default)', { - ...SPACES.DEFAULT, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(SPACES.DEFAULT.spaceId), - }, - hiddenType: { - description: 'exporting space not allowed', - statusCode: 400, - response: expectInvalidTypeSpecified, - }, - noTypeOrObjects: { - description: 'bad request, type or object is required', - statusCode: 400, - response: expectTypeOrObjectsRequired, - }, - }, + describe('_export', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/find.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/find.ts index a07d3edf834e9..a15f7de404db8 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/find.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/find.ts @@ -4,154 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SPACES } from '../../common/lib/spaces'; +import { getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { findTestSuiteFactory } from '../../common/suites/find'; +import { findTestSuiteFactory, getTestCases } from '../../common/suites/find'; + +const createTestCases = (spaceId: string) => { + const cases = getTestCases(spaceId); + return Object.values(cases); +}; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const { - createExpectEmpty, - createExpectVisualizationResults, - expectFilterWrongTypeError, - expectNotSpaceAwareResults, - expectTypeRequired, - findTest, - } = findTestSuiteFactory(esArchiver, supertest); - - describe('find', () => { - findTest(`objects only within the current space (space_1)`, { - ...SPACES.SPACE_1, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(SPACES.SPACE_1.spaceId), - }, - notSpaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - unknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithUnknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, - }); + const { addTests, createTestDefinitions } = findTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false); + }; - findTest(`objects only within the current space (default)`, { - ...SPACES.DEFAULT, - tests: { - spaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: createExpectVisualizationResults(SPACES.DEFAULT.spaceId), - }, - notSpaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - unknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - pageBeyondTotal: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(100, 100, 1), - }, - unknownSearchField: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - noType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithNotSpaceAwareType: { - description: 'only the visualization', - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - filterWithHiddenType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithUnknownType: { - description: 'empty result', - statusCode: 200, - response: createExpectEmpty(1, 20, 0), - }, - filterWithNoType: { - description: 'bad request, type is required', - statusCode: 400, - response: expectTypeRequired, - }, - filterWithUnAllowedType: { - description: 'Bad Request', - statusCode: 400, - response: expectFilterWrongTypeError, - }, - }, + describe('_find', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/get.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/get.ts index 592bedd92b4d7..512ae968dd0dd 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/get.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/get.ts @@ -5,88 +5,48 @@ */ import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { getTestSuiteFactory } from '../../common/suites/get'; +import { getTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/get'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.HIDDEN, ...fail404() }, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - const { - createExpectDoesntExistNotFound, - createExpectSpaceAwareNotFound, - createExpectSpaceAwareResults, - createExpectNotSpaceAwareResults, - expectHiddenTypeNotFound: expectHiddenTypeNotFound, - getTest, - } = getTestSuiteFactory(esArchiver, supertest); - - describe('get', () => { - getTest(`can access objects belonging to the current space (default)`, { - ...SPACES.DEFAULT, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(SPACES.DEFAULT.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(SPACES.DEFAULT.spaceId), - }, - hiddenType: { - statusCode: 404, - response: expectHiddenTypeNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(SPACES.DEFAULT.spaceId), - }, - }, - }); - - getTest(`can access objects belonging to the current space (space_1)`, { - ...SPACES.SPACE_1, - tests: { - spaceAware: { - statusCode: 200, - response: createExpectSpaceAwareResults(SPACES.SPACE_1.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(SPACES.SPACE_1.spaceId), - }, - hiddenType: { - statusCode: 404, - response: expectHiddenTypeNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(SPACES.SPACE_1.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions } = getTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false, { spaceId }); + }; - getTest(`can't access space aware objects belonging to another space (space_1)`, { - spaceId: SPACES.DEFAULT.spaceId, - otherSpaceId: SPACES.SPACE_1.spaceId, - tests: { - spaceAware: { - statusCode: 404, - response: createExpectSpaceAwareNotFound(SPACES.SPACE_1.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: createExpectNotSpaceAwareResults(SPACES.SPACE_1.spaceId), - }, - hiddenType: { - statusCode: 404, - response: expectHiddenTypeNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(SPACES.SPACE_1.spaceId), - }, - }, + describe('_get', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts index c78a0e1cc2cce..5fe4b08d91b54 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/import.ts @@ -5,56 +5,48 @@ */ import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { importTestSuiteFactory } from '../../common/suites/import'; +import { importTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/import'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail409(spaceId === DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(spaceId === SPACE_2_ID) }, + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail400() }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409() }, + { ...CASES.HIDDEN, ...fail400() }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + { ...CASES.NEW_MULTI_NAMESPACE_OBJ, ...fail400() }, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - importTest, - createExpectResults, - expectUnknownTypeUnsupported, - expectHiddenTypeUnsupported, - } = importTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions } = importTestSuiteFactory(es, esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false, { spaceId, singleRequest: true }); + }; describe('_import', () => { - importTest('in the current space (space_1)', { - ...SPACES.SPACE_1, - tests: { - default: { - statusCode: 200, - response: createExpectResults(SPACES.SPACE_1.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - importTest('in the default space', { - ...SPACES.DEFAULT, - tests: { - default: { - statusCode: 200, - response: createExpectResults(SPACES.DEFAULT.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts index bb481e0c98bc1..c2f8339d38c97 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts @@ -12,6 +12,7 @@ export default function({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./bulk_create')); loadTestFile(require.resolve('./bulk_get')); + loadTestFile(require.resolve('./bulk_update')); loadTestFile(require.resolve('./create')); loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./export')); @@ -20,6 +21,5 @@ export default function({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./import')); loadTestFile(require.resolve('./resolve_import_errors')); loadTestFile(require.resolve('./update')); - loadTestFile(require.resolve('./bulk_update')); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts index 22a7ab81e5530..04f9ac8414afd 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/resolve_import_errors.ts @@ -5,56 +5,59 @@ */ import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { resolveImportErrorsTestSuiteFactory } from '../../common/suites/resolve_import_errors'; +import { + resolveImportErrorsTestSuiteFactory, + TEST_CASES as CASES, +} from '../../common/suites/resolve_import_errors'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail400, fail409 } = testCaseFailures; + +const createTestCases = (overwrite: boolean, spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { + ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, + ...fail409(!overwrite && spaceId === DEFAULT_SPACE_ID), + }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail409(!overwrite && spaceId === SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail409(!overwrite && spaceId === SPACE_2_ID) }, + { ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail400() }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail400() }, + { ...CASES.NAMESPACE_AGNOSTIC, ...fail409(!overwrite) }, + { ...CASES.HIDDEN, ...fail400() }, + CASES.NEW_SINGLE_NAMESPACE_OBJ, + { ...CASES.NEW_MULTI_NAMESPACE_OBJ, ...fail400() }, + CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('legacyEs'); - const { - resolveImportErrorsTest, - createExpectResults, - expectUnknownTypeUnsupported, - expectHiddenTypeUnsupported, - } = resolveImportErrorsTestSuiteFactory(es, esArchiver, supertest); + const { addTests, createTestDefinitions } = resolveImportErrorsTestSuiteFactory( + es, + esArchiver, + supertest + ); + const createTests = (overwrite: boolean, spaceId: string) => { + const testCases = createTestCases(overwrite, spaceId); + return createTestDefinitions(testCases, false, overwrite, { spaceId, singleRequest: true }); + }; describe('_resolve_import_errors', () => { - resolveImportErrorsTest('in the current space (space_1)', { - ...SPACES.SPACE_1, - tests: { - default: { - statusCode: 200, - response: createExpectResults(SPACES.SPACE_1.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, - }); - - resolveImportErrorsTest('in the default space', { - ...SPACES.DEFAULT, - tests: { - default: { - statusCode: 200, - response: createExpectResults(SPACES.DEFAULT.spaceId), - }, - hiddenType: { - statusCode: 200, - response: expectHiddenTypeUnsupported, - }, - unknownType: { - statusCode: 200, - response: expectUnknownTypeUnsupported, - }, - }, + getTestScenarios([false, true]).spaces.forEach(({ spaceId, modifier: overwrite }) => { + const suffix = overwrite ? ' with overwrite enabled' : ''; + const tests = createTests(overwrite!, spaceId); + addTests(`within the ${spaceId} space${suffix}`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts index 6ffbda511d871..381861e33b68d 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts @@ -5,88 +5,48 @@ */ import { SPACES } from '../../common/lib/spaces'; +import { testCaseFailures, getTestScenarios } from '../../common/lib/saved_object_test_utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { updateTestSuiteFactory } from '../../common/suites/update'; +import { updateTestSuiteFactory, TEST_CASES as CASES } from '../../common/suites/update'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => [ + // for each outcome, if failure !== undefined then we expect to receive + // an error; otherwise, we expect to receive a success result + { ...CASES.SINGLE_NAMESPACE_DEFAULT_SPACE, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SINGLE_NAMESPACE_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + { + ...CASES.MULTI_NAMESPACE_DEFAULT_AND_SPACE_1, + ...fail404(spaceId !== DEFAULT_SPACE_ID && spaceId !== SPACE_1_ID), + }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.MULTI_NAMESPACE_ONLY_SPACE_2, ...fail404(spaceId !== SPACE_2_ID) }, + CASES.NAMESPACE_AGNOSTIC, + { ...CASES.HIDDEN, ...fail404() }, + { ...CASES.DOES_NOT_EXIST, ...fail404() }, +]; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); - describe('update', () => { - const { - createExpectSpaceAwareNotFound, - expectSpaceAwareResults, - createExpectDoesntExistNotFound, - expectNotSpaceAwareResults, - expectSpaceNotFound, - updateTest, - } = updateTestSuiteFactory(esArchiver, supertest); - - updateTest(`in the default space`, { - spaceId: SPACES.DEFAULT.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 404, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(SPACES.DEFAULT.spaceId), - }, - }, - }); - - updateTest('in the current space (space_1)', { - spaceId: SPACES.SPACE_1.spaceId, - tests: { - spaceAware: { - statusCode: 200, - response: expectSpaceAwareResults, - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 404, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(SPACES.SPACE_1.spaceId), - }, - }, - }); + const { addTests, createTestDefinitions } = updateTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + return createTestDefinitions(testCases, false); + }; - updateTest('objects that exist in another space (space_1)', { - spaceId: SPACES.DEFAULT.spaceId, - otherSpaceId: SPACES.SPACE_1.spaceId, - tests: { - spaceAware: { - statusCode: 404, - response: createExpectSpaceAwareNotFound(SPACES.SPACE_1.spaceId), - }, - notSpaceAware: { - statusCode: 200, - response: expectNotSpaceAwareResults, - }, - hiddenType: { - statusCode: 404, - response: expectSpaceNotFound, - }, - doesntExist: { - statusCode: 404, - response: createExpectDoesntExistNotFound(), - }, - }, + describe('_update', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createTests(spaceId); + addTests(`within the ${spaceId} space`, { spaceId, tests }); }); }); } diff --git a/x-pack/test/spaces_api_integration/common/config.ts b/x-pack/test/spaces_api_integration/common/config.ts index dffc6c524cc6e..19743e09f9420 100644 --- a/x-pack/test/spaces_api_integration/common/config.ts +++ b/x-pack/test/spaces_api_integration/common/config.ts @@ -67,6 +67,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) // disable anonymouse access so that we're testing both on and off in different suites '--status.allowAnonymous=false', '--server.xsrf.disableProtection=true', + `--plugin-path=${path.join(__dirname, 'fixtures', 'shared_type_plugin')}`, ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), ], }, diff --git a/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json b/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json index 64c1be0b90071..9a8a0a1fdda14 100644 --- a/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json +++ b/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json @@ -376,3 +376,123 @@ "type": "_doc" } } + +{ + "type": "doc", + "value": { + "id": "sharedtype:default_space_only", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the default space" + }, + "type": "sharedtype", + "namespaces": ["default"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:space_1_only", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the space_1 space" + }, + "type": "sharedtype", + "namespaces": ["space_1"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:space_2_only", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the space_2 space" + }, + "type": "sharedtype", + "namespaces": ["space_2"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:default_and_space_1", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the default and space_1 spaces" + }, + "type": "sharedtype", + "namespaces": ["default", "space_1"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:default_and_space_2", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the default and space_2 spaces" + }, + "type": "sharedtype", + "namespaces": ["default", "space_2"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:space_1_and_space_2", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the space_1 and space_2 spaces" + }, + "type": "sharedtype", + "namespaces": ["space_1", "space_2"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + +{ + "type": "doc", + "value": { + "id": "sharedtype:all_spaces", + "index": ".kibana", + "source": { + "sharedtype": { + "title": "A shared saved-object in the default, space_1, and space_2 spaces" + }, + "type": "sharedtype", + "namespaces": ["default", "space_1", "space_2"], + "updated_at": "2017-09-21T18:59:16.270Z" + }, + "type": "doc" + } +} + diff --git a/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json b/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json index 1440585b625b9..508de68c32f70 100644 --- a/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json +++ b/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/mappings.json @@ -159,6 +159,9 @@ "namespace": { "type": "keyword" }, + "namespaces": { + "type": "keyword" + }, "search": { "properties": { "columns": { @@ -320,6 +323,19 @@ "type": "text" } } + }, + "sharedtype": { + "properties": { + "title": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } } } }, diff --git a/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/index.js b/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/index.js new file mode 100644 index 0000000000000..91a24fb9f4f56 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/index.js @@ -0,0 +1,27 @@ +/* + * 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 mappings from './mappings.json'; + +export default function(kibana) { + return new kibana.Plugin({ + require: ['kibana', 'elasticsearch', 'xpack_main'], + name: 'shared_type_plugin', + uiExports: { + savedObjectsManagement: {}, + savedObjectSchemas: { + sharedtype: { + multiNamespace: true, + }, + }, + mappings, + }, + + config() {}, + + init() {}, // need empty init for plugin to load + }); +} diff --git a/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/mappings.json b/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/mappings.json new file mode 100644 index 0000000000000..918958aec0d6d --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/mappings.json @@ -0,0 +1,15 @@ +{ + "sharedtype": { + "properties": { + "title": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 2048 + } + } + } + } + } +} diff --git a/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/package.json b/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/package.json new file mode 100644 index 0000000000000..c52f4256c5c06 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/fixtures/shared_type_plugin/package.json @@ -0,0 +1,7 @@ +{ + "name": "shared_type_plugin", + "version": "0.0.0", + "kibana": { + "version": "kibana" + } +} diff --git a/x-pack/test/spaces_api_integration/common/lib/saved_object_test_cases.ts b/x-pack/test/spaces_api_integration/common/lib/saved_object_test_cases.ts new file mode 100644 index 0000000000000..67f5d737ba010 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/lib/saved_object_test_cases.ts @@ -0,0 +1,40 @@ +/* + * 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 MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES = Object.freeze({ + DEFAULT_SPACE_ONLY: Object.freeze({ + id: 'default_space_only', + existingNamespaces: ['default'], + }), + SPACE_1_ONLY: Object.freeze({ + id: 'space_1_only', + existingNamespaces: ['space_1'], + }), + SPACE_2_ONLY: Object.freeze({ + id: 'space_2_only', + existingNamespaces: ['space_2'], + }), + DEFAULT_AND_SPACE_1: Object.freeze({ + id: 'default_and_space_1', + existingNamespaces: ['default', 'space_1'], + }), + DEFAULT_AND_SPACE_2: Object.freeze({ + id: 'default_and_space_2', + existingNamespaces: ['default', 'space_2'], + }), + SPACE_1_AND_SPACE_2: Object.freeze({ + id: 'space_1_and_space_2', + existingNamespaces: ['space_1', 'space_2'], + }), + ALL_SPACES: Object.freeze({ + id: 'all_spaces', + existingNamespaces: ['default', 'space_1', 'space_2'], + }), + DOES_NOT_EXIST: Object.freeze({ + id: 'does_not_exist', + existingNamespaces: [] as string[], + }), +}); diff --git a/x-pack/test/spaces_api_integration/common/suites/delete.ts b/x-pack/test/spaces_api_integration/common/suites/delete.ts index 9036fcbf7a8dd..0d8728fdf622e 100644 --- a/x-pack/test/spaces_api_integration/common/suites/delete.ts +++ b/x-pack/test/spaces_api_integration/common/suites/delete.ts @@ -6,6 +6,7 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { getUrlPrefix } from '../lib/space_test_utils'; +import { MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; interface DeleteTest { @@ -128,6 +129,25 @@ export function deleteTestSuiteFactory(es: any, esArchiver: any, supertest: Supe ]; expect(buckets).to.eql(expectedBuckets); + + // There were seven multi-namespace objects. + // Since Space 2 was deleted, any multi-namespace objects that existed in that space + // are updated to remove it, and of those, any that don't exist in any space are deleted. + const multiNamespaceResponse = await es.search({ + index: '.kibana', + body: { query: { terms: { type: ['sharedtype'] } } }, + }); + const docs: [Record] = multiNamespaceResponse.hits.hits; + expect(docs).length(6); // just six results, since spaces_2_only got deleted + Object.values(CASES).forEach(({ id, existingNamespaces }) => { + const remainingNamespaces = existingNamespaces.filter(x => x !== 'space_2'); + const doc = docs.find(x => x._id === `sharedtype:${id}`); + if (remainingNamespaces.length > 0) { + expect(doc?._source?.namespaces).to.eql(remainingNamespaces); + } else { + expect(doc).to.be(undefined); + } + }); }; const expectNotFound = (resp: { [key: string]: any }) => { diff --git a/x-pack/test/spaces_api_integration/common/suites/share_add.ts b/x-pack/test/spaces_api_integration/common/suites/share_add.ts new file mode 100644 index 0000000000000..b9a012b606da3 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/suites/share_add.ts @@ -0,0 +1,118 @@ +/* + * 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 { SuperTest } from 'supertest'; +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; +import { SPACES } from '../lib/spaces'; +import { + expectResponses, + getUrlPrefix, +} from '../../../saved_object_api_integration/common/lib/saved_object_test_utils'; +import { + ExpectResponseBody, + TestDefinition, + TestSuite, +} from '../../../saved_object_api_integration/common/lib/types'; + +export interface ShareAddTestDefinition extends TestDefinition { + request: { spaces: string[]; object: { type: string; id: string } }; +} +export type ShareAddTestSuite = TestSuite; +export interface ShareAddTestCase { + id: string; + namespaces: string[]; + failure?: 400 | 403 | 404; + fail400Param?: string; + fail403Param?: string; +} + +const TYPE = 'sharedtype'; +const createRequest = ({ id, namespaces }: ShareAddTestCase) => ({ + spaces: namespaces, + object: { type: TYPE, id }, +}); +const getTestTitle = ({ id, namespaces }: ShareAddTestCase) => + `{id: ${id}, namespaces: [${namespaces.join(',')}]}`; + +export function shareAddTestSuiteFactory(esArchiver: any, supertest: SuperTest) { + const expectResponseBody = (testCase: ShareAddTestCase): ExpectResponseBody => async ( + response: Record + ) => { + const { id, failure, fail400Param, fail403Param } = testCase; + const object = response.body; + if (failure === 403) { + await expectResponses.forbidden(fail403Param!)(TYPE)(response); + } else if (failure) { + let error: any; + if (failure === 400) { + error = SavedObjectsErrorHelpers.createBadRequestError( + `${id} already exists in the following namespace(s): ${fail400Param}` + ); + } else if (failure === 404) { + error = SavedObjectsErrorHelpers.createGenericNotFoundError(TYPE, id); + } + expect(object.error).to.eql(error.output.payload.error); + expect(object.statusCode).to.eql(error.output.payload.statusCode); + } else { + // success + expect(object).to.eql({}); + } + }; + const createTestDefinitions = ( + testCases: ShareAddTestCase | ShareAddTestCase[], + forbidden: boolean, + options?: { + responseBodyOverride?: ExpectResponseBody; + fail403Param?: string; + } + ): ShareAddTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403, fail403Param: options?.fail403Param })); + } + return cases.map(x => ({ + title: getTestTitle(x), + responseStatusCode: x.failure ?? 204, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x), + })); + }; + + const makeShareAddTest = (describeFn: Mocha.SuiteFunction) => ( + description: string, + definition: ShareAddTestSuite + ) => { + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; + + describeFn(description, () => { + before(() => esArchiver.load('saved_objects/spaces')); + after(() => esArchiver.unload('saved_objects/spaces')); + + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const requestBody = test.request; + await supertest + .post(`${getUrlPrefix(spaceId)}/api/spaces/_share_saved_object_add`) + .auth(user?.username, user?.password) + .send(requestBody) + .expect(test.responseStatusCode) + .then(test.responseBody); + }); + } + }); + }; + + const addTests = makeShareAddTest(describe); + // @ts-ignore + addTests.only = makeShareAddTest(describe.only); + + return { + addTests, + createTestDefinitions, + }; +} diff --git a/x-pack/test/spaces_api_integration/common/suites/share_remove.ts b/x-pack/test/spaces_api_integration/common/suites/share_remove.ts new file mode 100644 index 0000000000000..b5fcbe5a1cf2c --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/suites/share_remove.ts @@ -0,0 +1,116 @@ +/* + * 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 { SuperTest } from 'supertest'; +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; +import { SPACES } from '../lib/spaces'; +import { + expectResponses, + getUrlPrefix, + getTestTitle, +} from '../../../saved_object_api_integration/common/lib/saved_object_test_utils'; +import { + ExpectResponseBody, + TestDefinition, + TestSuite, +} from '../../../saved_object_api_integration/common/lib/types'; + +export interface ShareRemoveTestDefinition extends TestDefinition { + request: { spaces: string[]; object: { type: string; id: string } }; +} +export type ShareRemoveTestSuite = TestSuite; +export interface ShareRemoveTestCase { + id: string; + namespaces: string[]; + failure?: 400 | 403 | 404; + fail400Param?: string; +} + +const TYPE = 'sharedtype'; +const createRequest = ({ id, namespaces }: ShareRemoveTestCase) => ({ + spaces: namespaces, + object: { type: TYPE, id }, +}); + +export function shareRemoveTestSuiteFactory(esArchiver: any, supertest: SuperTest) { + const expectForbidden = expectResponses.forbidden('delete'); + const expectResponseBody = (testCase: ShareRemoveTestCase): ExpectResponseBody => async ( + response: Record + ) => { + const { id, failure, fail400Param } = testCase; + const object = response.body; + if (failure === 403) { + await expectForbidden(TYPE)(response); + } else if (failure) { + let error: any; + if (failure === 400) { + error = SavedObjectsErrorHelpers.createBadRequestError( + `${id} doesn't exist in the following namespace(s): ${fail400Param}` + ); + } else if (failure === 404) { + error = SavedObjectsErrorHelpers.createGenericNotFoundError(TYPE, id); + } + expect(object.error).to.eql(error.output.payload.error); + expect(object.statusCode).to.eql(error.output.payload.statusCode); + } else { + // success + expect(object).to.eql({}); + } + }; + const createTestDefinitions = ( + testCases: ShareRemoveTestCase | ShareRemoveTestCase[], + forbidden: boolean, + options?: { + responseBodyOverride?: ExpectResponseBody; + } + ): ShareRemoveTestDefinition[] => { + let cases = Array.isArray(testCases) ? testCases : [testCases]; + if (forbidden) { + // override the expected result in each test case + cases = cases.map(x => ({ ...x, failure: 403 })); + } + return cases.map(x => ({ + title: getTestTitle({ ...x, type: TYPE }), + responseStatusCode: x.failure ?? 204, + request: createRequest(x), + responseBody: options?.responseBodyOverride || expectResponseBody(x), + })); + }; + + const makeShareRemoveTest = (describeFn: Mocha.SuiteFunction) => ( + description: string, + definition: ShareRemoveTestSuite + ) => { + const { user, spaceId = SPACES.DEFAULT.spaceId, tests } = definition; + + describeFn(description, () => { + before(() => esArchiver.load('saved_objects/spaces')); + after(() => esArchiver.unload('saved_objects/spaces')); + + for (const test of tests) { + it(`should return ${test.responseStatusCode} ${test.title}`, async () => { + const requestBody = test.request; + await supertest + .post(`${getUrlPrefix(spaceId)}/api/spaces/_share_saved_object_remove`) + .auth(user?.username, user?.password) + .send(requestBody) + .expect(test.responseStatusCode) + .then(test.responseBody); + }); + } + }); + }; + + const addTests = makeShareRemoveTest(describe); + // @ts-ignore + addTests.only = makeShareRemoveTest(describe.only); + + return { + addTests, + createTestDefinitions, + }; +} diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts index e918ab0b53841..8d85d95e6812f 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts @@ -25,6 +25,8 @@ export default function({ loadTestFile, getService }: TestInvoker) { loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./get_all')); loadTestFile(require.resolve('./get')); + loadTestFile(require.resolve('./share_add')); + loadTestFile(require.resolve('./share_remove')); loadTestFile(require.resolve('./update')); }); } diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/share_add.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/share_add.ts new file mode 100644 index 0000000000000..c7e65ac424776 --- /dev/null +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/share_add.ts @@ -0,0 +1,124 @@ +/* + * 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 { SPACES } from '../../common/lib/spaces'; +import { + testCaseFailures, + getTestScenarios, +} from '../../../saved_object_api_integration/common/lib/saved_object_test_utils'; +import { TestUser } from '../../../saved_object_api_integration/common/lib/types'; +import { MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES as CASES } from '../../common/lib/saved_object_test_cases'; +import { TestInvoker } from '../../common/lib/types'; +import { shareAddTestSuiteFactory, ShareAddTestDefinition } from '../../common/suites/share_add'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + const namespaces = [spaceId]; + return [ + // Test cases to check adding the target namespace to different saved objects + { ...CASES.DEFAULT_SPACE_ONLY, namespaces, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SPACE_1_ONLY, namespaces, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SPACE_2_ONLY, namespaces, ...fail404(spaceId !== SPACE_2_ID) }, + { ...CASES.DEFAULT_AND_SPACE_1, namespaces, ...fail404(spaceId === SPACE_2_ID) }, + { ...CASES.DEFAULT_AND_SPACE_2, namespaces, ...fail404(spaceId === SPACE_1_ID) }, + { ...CASES.SPACE_1_AND_SPACE_2, namespaces, ...fail404(spaceId === DEFAULT_SPACE_ID) }, + { ...CASES.ALL_SPACES, namespaces }, + { ...CASES.DOES_NOT_EXIST, namespaces, ...fail404() }, + // Test cases to check adding multiple namespaces to different saved objects that exist in one space + // These are non-exhaustive, they only check cases for adding two additional namespaces to a saved object + // More permutations are covered in the corresponding spaces_only test suite + { + ...CASES.DEFAULT_SPACE_ONLY, + namespaces: [SPACE_1_ID, SPACE_2_ID], + ...fail404(spaceId !== DEFAULT_SPACE_ID), + }, + { + ...CASES.SPACE_1_ONLY, + namespaces: [DEFAULT_SPACE_ID, SPACE_2_ID], + ...fail404(spaceId !== SPACE_1_ID), + }, + { + ...CASES.SPACE_2_ONLY, + namespaces: [DEFAULT_SPACE_ID, SPACE_1_ID], + ...fail404(spaceId !== SPACE_2_ID), + }, + ]; +}; +const calculateSingleSpaceAuthZ = ( + testCases: ReturnType, + spaceId: string +) => { + const targetsOtherSpace = testCases.filter( + x => !x.namespaces.includes(spaceId) || x.namespaces.length > 1 + ); + const tmp = testCases.filter(x => !targetsOtherSpace.includes(x)); // doesn't target other space + const doesntExistInThisSpace = tmp.filter(x => !x.existingNamespaces.includes(spaceId)); + const existsInThisSpace = tmp.filter(x => x.existingNamespaces.includes(spaceId)); + return { targetsOtherSpace, doesntExistInThisSpace, existsInThisSpace }; +}; +// eslint-disable-next-line import/no-default-export +export default function({ getService }: TestInvoker) { + const supertest = getService('supertestWithoutAuth'); + const esArchiver = getService('esArchiver'); + + const { addTests, createTestDefinitions } = shareAddTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const testCases = createTestCases(spaceId); + const thisSpace = calculateSingleSpaceAuthZ(testCases, spaceId); + const otherSpaceId = spaceId === DEFAULT_SPACE_ID ? SPACE_1_ID : DEFAULT_SPACE_ID; + const otherSpace = calculateSingleSpaceAuthZ(testCases, otherSpaceId); + return { + unauthorized: createTestDefinitions(testCases, true, { fail403Param: 'create' }), + authorizedInSpace: [ + createTestDefinitions(thisSpace.targetsOtherSpace, true, { fail403Param: 'create' }), + createTestDefinitions(thisSpace.doesntExistInThisSpace, false), + createTestDefinitions(thisSpace.existsInThisSpace, false), + ].flat(), + authorizedInOtherSpace: [ + createTestDefinitions(otherSpace.targetsOtherSpace, true, { fail403Param: 'create' }), + // If the preflight GET request fails, it will return a 404 error; users who are authorized to create saved objects in the target + // space(s) but are not authorized to update saved objects in this space will see a 403 error instead of 404. This is a safeguard to + // prevent potential information disclosure of the spaces that a given saved object may exist in. + createTestDefinitions(otherSpace.doesntExistInThisSpace, true, { fail403Param: 'update' }), + createTestDefinitions(otherSpace.existsInThisSpace, false), + ].flat(), + authorized: createTestDefinitions(testCases, false), + }; + }; + + describe('_share_saved_object_add', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` targeting the ${spaceId} space`; + const { unauthorized, authorizedInSpace, authorizedInOtherSpace, authorized } = createTests( + spaceId + ); + const _addTests = (user: TestUser, tests: ShareAddTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; + + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + ].forEach(user => { + _addTests(user, unauthorized); + }); + _addTests(users.allAtSpace, authorizedInSpace); + _addTests(users.allAtOtherSpace, authorizedInOtherSpace); + [users.dualAll, users.allGlobally, users.superuser].forEach(user => { + _addTests(user, authorized); + }); + }); + }); +} diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/share_remove.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/share_remove.ts new file mode 100644 index 0000000000000..3a8d42f620a3e --- /dev/null +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/share_remove.ts @@ -0,0 +1,99 @@ +/* + * 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 { SPACES } from '../../common/lib/spaces'; +import { + testCaseFailures, + getTestScenarios, +} from '../../../saved_object_api_integration/common/lib/saved_object_test_utils'; +import { TestUser } from '../../../saved_object_api_integration/common/lib/types'; +import { MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES as CASES } from '../../common/lib/saved_object_test_cases'; +import { TestInvoker } from '../../common/lib/types'; +import { + shareRemoveTestSuiteFactory, + ShareRemoveTestCase, + ShareRemoveTestDefinition, +} from '../../common/suites/share_remove'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +const createTestCases = (spaceId: string) => { + // Test cases to check removing the target namespace from different saved objects + let namespaces = [spaceId]; + const singleSpace = [ + { id: CASES.DEFAULT_SPACE_ONLY.id, namespaces, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { id: CASES.SPACE_1_ONLY.id, namespaces, ...fail404(spaceId !== SPACE_1_ID) }, + { id: CASES.SPACE_2_ONLY.id, namespaces, ...fail404(spaceId !== SPACE_2_ID) }, + { id: CASES.DEFAULT_AND_SPACE_1.id, namespaces, ...fail404(spaceId === SPACE_2_ID) }, + { id: CASES.DEFAULT_AND_SPACE_2.id, namespaces, ...fail404(spaceId === SPACE_1_ID) }, + { id: CASES.SPACE_1_AND_SPACE_2.id, namespaces, ...fail404(spaceId === DEFAULT_SPACE_ID) }, + { id: CASES.ALL_SPACES.id, namespaces }, + { id: CASES.DOES_NOT_EXIST.id, namespaces, ...fail404() }, + ] as ShareRemoveTestCase[]; + + // Test cases to check removing all three namespaces from different saved objects that exist in two spaces + // These are non-exhaustive, they only check some cases -- each object will result in a 404, either because + // it never existed in the target namespace, or it was removed in one of the test cases above + // More permutations are covered in the corresponding spaces_only test suite + namespaces = [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID]; + const multipleSpaces = [ + { id: CASES.DEFAULT_AND_SPACE_1.id, namespaces, ...fail404() }, + { id: CASES.DEFAULT_AND_SPACE_2.id, namespaces, ...fail404() }, + { id: CASES.SPACE_1_AND_SPACE_2.id, namespaces, ...fail404() }, + ] as ShareRemoveTestCase[]; + + const allCases = singleSpace.concat(multipleSpaces); + return { singleSpace, multipleSpaces, allCases }; +}; + +// eslint-disable-next-line import/no-default-export +export default function({ getService }: TestInvoker) { + const supertest = getService('supertestWithoutAuth'); + const esArchiver = getService('esArchiver'); + + const { addTests, createTestDefinitions } = shareRemoveTestSuiteFactory(esArchiver, supertest); + const createTests = (spaceId: string) => { + const { singleSpace, multipleSpaces, allCases } = createTestCases(spaceId); + return { + unauthorized: createTestDefinitions(allCases, true), + authorizedThisSpace: [ + createTestDefinitions(singleSpace, false), + createTestDefinitions(multipleSpaces, true), + ].flat(), + authorizedGlobally: createTestDefinitions(allCases, false), + }; + }; + + describe('_share_saved_object_remove', () => { + getTestScenarios().securityAndSpaces.forEach(({ spaceId, users }) => { + const suffix = ` targeting the ${spaceId} space`; + const { unauthorized, authorizedThisSpace, authorizedGlobally } = createTests(spaceId); + const _addTests = (user: TestUser, tests: ShareRemoveTestDefinition[]) => { + addTests(`${user.description}${suffix}`, { user, spaceId, tests }); + }; + + [ + users.noAccess, + users.legacyAll, + users.dualRead, + users.readGlobally, + users.readAtSpace, + users.allAtOtherSpace, + ].forEach(user => { + _addTests(user, unauthorized); + }); + _addTests(users.allAtSpace, authorizedThisSpace); + [users.dualAll, users.allGlobally, users.superuser].forEach(user => { + _addTests(user, authorizedGlobally); + }); + }); + }); +} diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts index 1182f6bdabcff..b02dc35b58b56 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts @@ -17,6 +17,8 @@ export default function spacesOnlyTestSuite({ loadTestFile }: TestInvoker) { loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./get_all')); loadTestFile(require.resolve('./get')); + loadTestFile(require.resolve('./share_add')); + loadTestFile(require.resolve('./share_remove')); loadTestFile(require.resolve('./update')); }); } diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/share_add.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/share_add.ts new file mode 100644 index 0000000000000..f1e603836fa21 --- /dev/null +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/share_add.ts @@ -0,0 +1,84 @@ +/* + * 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 { SPACES } from '../../common/lib/spaces'; +import { + testCaseFailures, + getTestScenarios, +} from '../../../saved_object_api_integration/common/lib/saved_object_test_utils'; +import { TestInvoker } from '../../common/lib/types'; +import { MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES as CASES } from '../../common/lib/saved_object_test_cases'; +import { shareAddTestSuiteFactory } from '../../common/suites/share_add'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +/** + * Single-namespace test cases + * @param spaceId the namespace to add to each saved object + */ +const createSingleTestCases = (spaceId: string) => { + const namespaces = ['some-space-id']; + return [ + { ...CASES.DEFAULT_SPACE_ONLY, namespaces, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SPACE_1_ONLY, namespaces, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SPACE_2_ONLY, namespaces, ...fail404(spaceId !== SPACE_2_ID) }, + { ...CASES.DEFAULT_AND_SPACE_1, namespaces, ...fail404(spaceId === SPACE_2_ID) }, + { ...CASES.DEFAULT_AND_SPACE_2, namespaces, ...fail404(spaceId === SPACE_1_ID) }, + { ...CASES.SPACE_1_AND_SPACE_2, namespaces, ...fail404(spaceId === DEFAULT_SPACE_ID) }, + { ...CASES.ALL_SPACES, namespaces }, + { ...CASES.DOES_NOT_EXIST, namespaces, ...fail404() }, + ]; +}; +/** + * Multi-namespace test cases + * These are non-exhaustive, but they check different permutations of saved objects and spaces to add + */ +const createMultiTestCases = () => { + const allSpaces = [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID]; + let id = CASES.DEFAULT_SPACE_ONLY.id; + const one = [{ id, namespaces: allSpaces }]; + id = CASES.DEFAULT_AND_SPACE_1.id; + const two = [{ id, namespaces: allSpaces }]; + id = CASES.ALL_SPACES.id; + const three = [{ id, namespaces: allSpaces }]; + return { one, two, three }; +}; + +// eslint-disable-next-line import/no-default-export +export default function({ getService }: TestInvoker) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + const { addTests, createTestDefinitions } = shareAddTestSuiteFactory(esArchiver, supertest); + const createSingleTests = (spaceId: string) => { + const testCases = createSingleTestCases(spaceId); + return createTestDefinitions(testCases, false); + }; + const createMultiTests = () => { + const testCases = createMultiTestCases(); + return { + one: createTestDefinitions(testCases.one, false), + two: createTestDefinitions(testCases.two, false), + three: createTestDefinitions(testCases.three, false), + }; + }; + + describe('_share_saved_object_add', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createSingleTests(spaceId); + addTests(`targeting the ${spaceId} space`, { spaceId, tests }); + }); + const { one, two, three } = createMultiTests(); + addTests('for a saved object in the default space', { tests: one }); + addTests('for a saved object in the default and space_1 spaces', { tests: two }); + addTests('for a saved object in the default, space_1, and space_2 spaces', { tests: three }); + }); +} diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/share_remove.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/share_remove.ts new file mode 100644 index 0000000000000..15be72c9f09ac --- /dev/null +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/share_remove.ts @@ -0,0 +1,99 @@ +/* + * 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 { SPACES } from '../../common/lib/spaces'; +import { + testCaseFailures, + getTestScenarios, +} from '../../../saved_object_api_integration/common/lib/saved_object_test_utils'; +import { TestInvoker } from '../../common/lib/types'; +import { MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES as CASES } from '../../common/lib/saved_object_test_cases'; +import { shareRemoveTestSuiteFactory } from '../../common/suites/share_remove'; + +const { + DEFAULT: { spaceId: DEFAULT_SPACE_ID }, + SPACE_1: { spaceId: SPACE_1_ID }, + SPACE_2: { spaceId: SPACE_2_ID }, +} = SPACES; +const { fail404 } = testCaseFailures; + +/** + * Single-namespace test cases + * @param spaceId the namespace to remove from each saved object + */ +const createSingleTestCases = (spaceId: string) => { + const namespaces = [spaceId]; + return [ + { ...CASES.DEFAULT_SPACE_ONLY, namespaces, ...fail404(spaceId !== DEFAULT_SPACE_ID) }, + { ...CASES.SPACE_1_ONLY, namespaces, ...fail404(spaceId !== SPACE_1_ID) }, + { ...CASES.SPACE_2_ONLY, namespaces, ...fail404(spaceId !== SPACE_2_ID) }, + { ...CASES.DEFAULT_AND_SPACE_1, namespaces, ...fail404(spaceId === SPACE_2_ID) }, + { ...CASES.DEFAULT_AND_SPACE_2, namespaces, ...fail404(spaceId === SPACE_1_ID) }, + { ...CASES.SPACE_1_AND_SPACE_2, namespaces, ...fail404(spaceId === DEFAULT_SPACE_ID) }, + { ...CASES.ALL_SPACES, namespaces }, + { ...CASES.DOES_NOT_EXIST, namespaces, ...fail404() }, + ]; +}; +/** + * Multi-namespace test cases + * These are non-exhaustive, but they check different permutations of saved objects and spaces to remove + */ +const createMultiTestCases = () => { + const nonExistentSpaceId = 'does_not_exist'; // space that doesn't exist + let id = CASES.DEFAULT_SPACE_ONLY.id; + const one = [ + { id, namespaces: [nonExistentSpaceId] }, + { id, namespaces: [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID] }, + { id, namespaces: [DEFAULT_SPACE_ID], ...fail404() }, // this saved object no longer exists + ]; + id = CASES.DEFAULT_AND_SPACE_1.id; + const two = [ + { id, namespaces: [DEFAULT_SPACE_ID, nonExistentSpaceId] }, + // this saved object will not be found in the context of the current namespace ('default') + { id, namespaces: [DEFAULT_SPACE_ID], ...fail404() }, // this object's namespaces no longer contains DEFAULT_SPACE_ID + { id, namespaces: [SPACE_1_ID], ...fail404() }, // this object's namespaces does contain SPACE_1_ID + ]; + id = CASES.ALL_SPACES.id; + const three = [ + { id, namespaces: [DEFAULT_SPACE_ID, SPACE_1_ID, nonExistentSpaceId] }, + // this saved object will not be found in the context of the current namespace ('default') + { id, namespaces: [DEFAULT_SPACE_ID], ...fail404() }, // this object's namespaces no longer contains DEFAULT_SPACE_ID + { id, namespaces: [SPACE_1_ID], ...fail404() }, // this object's namespaces no longer contains SPACE_1_ID + { id, namespaces: [SPACE_2_ID], ...fail404() }, // this object's namespaces does contain SPACE_2_ID + ]; + return { one, two, three }; +}; + +// eslint-disable-next-line import/no-default-export +export default function({ getService }: TestInvoker) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + const { addTests, createTestDefinitions } = shareRemoveTestSuiteFactory(esArchiver, supertest); + const createSingleTests = (spaceId: string) => { + const testCases = createSingleTestCases(spaceId); + return createTestDefinitions(testCases, false); + }; + const createMultiTests = () => { + const testCases = createMultiTestCases(); + return { + one: createTestDefinitions(testCases.one, false), + two: createTestDefinitions(testCases.two, false), + three: createTestDefinitions(testCases.three, false), + }; + }; + + describe('_share_saved_object_remove', () => { + getTestScenarios().spaces.forEach(({ spaceId }) => { + const tests = createSingleTests(spaceId); + addTests(`targeting the ${spaceId} space`, { spaceId, tests }); + }); + const { one, two, three } = createMultiTests(); + addTests('for a saved object in the default space', { tests: one }); + addTests('for a saved object in the default and space_1 spaces', { tests: two }); + addTests('for a saved object in the default, space_1, and space_2 spaces', { tests: three }); + }); +} From 83b9417d4534f7c8d2c6daa9009bd20e1937cf16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 10 Apr 2020 08:28:06 +0100 Subject: [PATCH 030/121] [APM] Custom links submit button is off screen in IE11 (#63122) --- .../CustomLinkFlyout/DeleteButton.tsx | 2 + .../CustomLinkFlyout/FlyoutFooter.tsx | 38 ++++++++----------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/DeleteButton.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/DeleteButton.tsx index 2b3a5cbe87992..87cb171518ea4 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/DeleteButton.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/DeleteButton.tsx @@ -8,6 +8,7 @@ import { EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { NotificationsStart } from 'kibana/public'; import React, { useState } from 'react'; +import { px, unit } from '../../../../../../style/variables'; import { callApmApi } from '../../../../../../services/rest/createCallApmApi'; import { useApmPluginContext } from '../../../../../../hooks/useApmPluginContext'; @@ -31,6 +32,7 @@ export function DeleteButton({ onDelete, customLinkId }: Props) { setIsDeleting(false); onDelete(); }} + style={{ marginRight: px(unit) }} > {i18n.translate('xpack.apm.settings.customizeUI.customLink.delete', { defaultMessage: 'Delete' diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FlyoutFooter.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FlyoutFooter.tsx index cb27221309812..96505d639bcdd 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FlyoutFooter.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/FlyoutFooter.tsx @@ -40,29 +40,23 @@ export const FlyoutFooter = ({ )} - - - {customLinkId && ( - - - + + {customLinkId && ( + + )} + + {i18n.translate( + 'xpack.apm.settings.customizeUI.customLink.flyout.save', + { + defaultMessage: 'Save' + } )} - - - {i18n.translate( - 'xpack.apm.settings.customizeUI.customLink.flyout.save', - { - defaultMessage: 'Save' - } - )} - - - + From 34b1d0a10d529da48f35106d6b82cf96498e6677 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Fri, 10 Apr 2020 11:28:59 +0200 Subject: [PATCH 031/121] [SIEM] Updates cypress readme with documentation about the test data. (#62747) * updates test data section * Update x-pack/legacy/plugins/siem/cypress/README.md Co-Authored-By: Ryland Herrick Co-authored-by: Ryland Herrick --- x-pack/legacy/plugins/siem/cypress/README.md | 132 +++++++++++++++---- 1 file changed, 107 insertions(+), 25 deletions(-) diff --git a/x-pack/legacy/plugins/siem/cypress/README.md b/x-pack/legacy/plugins/siem/cypress/README.md index 41137ce6d8a9d..a031fea172be5 100644 --- a/x-pack/legacy/plugins/siem/cypress/README.md +++ b/x-pack/legacy/plugins/siem/cypress/README.md @@ -111,6 +111,112 @@ elasticsearch: hosts: ['https://:9200'] ``` +## Running (Headless) Tests on the Command Line as a Jenkins execution (The preferred way) + +To run (headless) tests as a Jenkins execution. + +1. First bootstrap kibana changes from the Kibana root directory: + +```sh +yarn kbn bootstrap +``` + +2. Launch Cypress command line test runner: + +```sh +cd x-pack/legacy/plugins/siem +yarn cypress:run-as-ci +``` + +Note that with this type of execution you don't need to have running a kibana and elasticsearch instance. This is because + the command, as it would happen in the CI, will launch the instances. The elasticsearch instance will be fed with the data + placed in: `x-pack/test/siem_cypress/es_archives` + +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. + +### Test data + +As said before when running the tests as Jenkins the tests are fed with the data placed in: `x-pack/test/siem_cypress/es_archives`. + +Currently there are two different ways of feeding data: +1. By default +2. Specifying a specific set of data for a specific test + +#### By default + +When a execution of the test is going to be done an empty kibana and a set of audibteat data are loaded (empty_kibana and auditbeat). With this data usually is enough to cover most of the scenarios that we are testing. + +#### Running tests with custom data + +Sometimes the default data is not enough and we need a specific set of data in order to being able to test the desired behaviour. + +In that case in the hooks of the test use the function `esArchiverLoad` to load the set of data neeed and `esArchiverUnload` to remove the changes done in the data. + +Example: + +```typescript +import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; + +describe('This are going to be a set of tests', () => { + before(() => { + esArchiverLoad('name_of_the_data_set_you_want_to_load'); + }); + + after(() => { + esArchiverUnload('name_of_the_data_set_you_want_to_unload'); + }); + + it('Going to test something awesome', () => { + hereGoesYourAwesomeTestcode + }); +}); + +``` + +Note that loading and unloading data takes a signifcant amount of time so try to minimize the use of it when possible. + +### Current sets of data + +The current sets of data can be found in: `x-pack/test/siem_cypress/es_archives` folder. + +- auditbeat + - Auditbeat data generated in Sep, 2019 with the following hosts present: + - suricata-iowa + - siem-kibana + - siem-es + - jessie +- closed_signals + - Set of data with 108 closed signals linked to "Signals test" custom rule. +- custome_rules + - Set if data with just 4 custom activated rules. +- empty_kibana + - Empty kibana board. +- prebuilt_rules_loaded + - Elastic prebuilt loaded rules and deactivated. +- signals + - Set of data with 108 opened signals linked to "Signals test" custom rule. + +### How to generate new test data + +We are using es_archiver in order to generate the data that our Cypress tests needs. + +1. Setup if possible a clean instance of kibana and elasticsearch (if not, possible please try to clean the data that you are going to generate). +2. With the kibana and elasticsearch instance up and running, create the data that you need for your test. +3. When you are sure that you have all the data you need run the following command from: `x-pack/legacy/plugins/siem` + +```sh +node ../../../../scripts/es_archiver save --dir ../../../test/siem_cypress/es_archives --config ../../../../test/functional/config.js --es-url http://:@: +``` + +Example: +```sh +node ../../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../../test/siem_cypress/es_archives --config ../../../../test/functional/config.js --es-url http://elastic:changeme@localhost:9220 +``` + +Note that the command is going to create the folder if does not exist in the directory with the imported data. + + ## Running Tests Interactively Use the Cypress interactive test runner to develop and debug specific tests @@ -210,30 +316,6 @@ cd x-pack/legacy/plugins/siem CYPRESS_baseUrl=http://localhost:5601 CYPRESS_ELASTICSEARCH_USERNAME=elastic CYPRESS_ELASTICSEARCH_PASSWORD= yarn cypress:run ``` -## Running (Headless) Tests on the Command Line as a Jenkins execution - -To run (headless) tests as a Jenkins execution. - -1. First bootstrap kibana changes from the Kibana root directory: - -```sh -yarn kbn bootstrap -``` - -2. Launch Cypress command line test runner: - -```sh -cd x-pack/legacy/plugins/siem -yarn cypress:run-as-ci -``` - -Note that with this type of execution you don't need to have running a kibana and elasticsearch instance. This is because - the command, as it would happen in the CI, will launch the instances. The elasticsearch instance will be fed with the data - placed in: `x-pack/test/siem_cypress/es_archives`. - -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. - ## Reporting When Cypress tests are run on the command line via `yarn cypress:run`, @@ -280,4 +362,4 @@ target/kibana-siem/cypress/videos ## Linting -Optional linting rules for Cypress and linting setup can be found [here](https://github.com/cypress-io/eslint-plugin-cypress#usage) \ No newline at end of file +Optional linting rules for Cypress and linting setup can be found [here](https://github.com/cypress-io/eslint-plugin-cypress#usage) From 93971dbfab74b39335115e8236741329486c4b79 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 10 Apr 2020 12:28:55 +0200 Subject: [PATCH 032/121] [Watcher] Preserve the watch active status after updates (#61999) * Preserve the watch active status after updates * Use route validation params to set isActive * Fix Jest test * Implement PR feedback - Make the isActive flag required on the save watch endpoint - Move the isActive state to base_watch and serialize from there. * Fix Jest tests Co-authored-by: Elastic Machine --- .../watch_create_json.test.ts | 3 ++ .../watch_create_threshold.test.tsx | 8 +++++ .../client_integration/watch_edit.test.ts | 2 ++ .../application/models/watch/base_watch.js | 2 ++ .../server/lib/elasticsearch_js_plugin.ts | 4 +++ .../routes/api/watch/register_save_route.ts | 29 ++++++++----------- 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts index 2096c0dd61bd8..47de4548898cf 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts @@ -108,6 +108,7 @@ describe(' create route', () => { name: watch.name, type: watch.type, isNew: true, + isActive: true, actions: [ { id: DEFAULT_LOGGING_ACTION_ID, @@ -185,6 +186,7 @@ describe(' create route', () => { id, type, isNew: true, + isActive: true, actions: [], watch: defaultWatchJson, }; @@ -246,6 +248,7 @@ describe(' create route', () => { id, type, isNew: true, + isActive: true, actions: [], watch: defaultWatchJson, }; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx index 943233d3c14ed..e5bdcbbfb82cf 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx @@ -244,6 +244,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [ { id: 'logging_1', @@ -314,6 +315,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [ { id: 'index_1', @@ -376,6 +378,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [ { id: 'slack_1', @@ -448,6 +451,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [ { id: 'email_1', @@ -540,6 +544,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [ { id: 'webhook_1', @@ -629,6 +634,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [ { id: 'jira_1', @@ -709,6 +715,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [ { id: 'pagerduty_1', @@ -772,6 +779,7 @@ describe(' create route', () => { name: WATCH_NAME, type: WATCH_TYPES.THRESHOLD, isNew: true, + isActive: true, actions: [], index: MATCH_INDICES, timeField: WATCH_TIME_FIELD, diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts index 51285a5786b00..ced06562b1d20 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts @@ -98,6 +98,7 @@ describe('', () => { name: EDITED_WATCH_NAME, type: watch.type, isNew: false, + isActive: true, actions: [ { id: DEFAULT_LOGGING_ACTION_ID, @@ -191,6 +192,7 @@ describe('', () => { name: EDITED_WATCH_NAME, type, isNew: false, + isActive: true, actions: [], timeField, triggerIntervalSize, diff --git a/x-pack/plugins/watcher/public/application/models/watch/base_watch.js b/x-pack/plugins/watcher/public/application/models/watch/base_watch.js index 3fe4fb006d241..af2e45b35501e 100644 --- a/x-pack/plugins/watcher/public/application/models/watch/base_watch.js +++ b/x-pack/plugins/watcher/public/application/models/watch/base_watch.js @@ -32,6 +32,7 @@ export class BaseWatch { this.isSystemWatch = Boolean(get(props, 'isSystemWatch')); this.watchStatus = WatchStatus.fromUpstreamJson(get(props, 'watchStatus')); this.watchErrors = WatchErrors.fromUpstreamJson(get(props, 'watchErrors')); + this.isActive = this.watchStatus.isActive ?? true; const actions = get(props, 'actions', []); this.actions = actions.map(Action.fromUpstreamJson); @@ -115,6 +116,7 @@ export class BaseWatch { name: this.name, type: this.type, isNew: this.isNew, + isActive: this.isActive, actions: map(this.actions, action => action.upstreamJson), }; } diff --git a/x-pack/plugins/watcher/server/lib/elasticsearch_js_plugin.ts b/x-pack/plugins/watcher/server/lib/elasticsearch_js_plugin.ts index 240e93e160fe0..3cb8dfb623fac 100644 --- a/x-pack/plugins/watcher/server/lib/elasticsearch_js_plugin.ts +++ b/x-pack/plugins/watcher/server/lib/elasticsearch_js_plugin.ts @@ -174,6 +174,10 @@ export const elasticsearchJsPlugin = (Client: any, config: any, components: any) name: 'master_timeout', type: 'duration', }, + active: { + name: 'active', + type: 'boolean', + }, }, url: { fmt: '/_watcher/watch/<%=id%>', diff --git a/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.ts b/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.ts index 61d167bb9bbcd..10ee0c4857862 100644 --- a/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watch/register_save_route.ts @@ -5,7 +5,6 @@ */ import { schema } from '@kbn/config-schema'; -import { IScopedClusterClient } from 'kibana/server'; import { i18n } from '@kbn/i18n'; import { WATCH_TYPES } from '../../../../common/constants'; import { serializeJsonWatch, serializeThresholdWatch } from '../../../../common/lib/serialization'; @@ -21,23 +20,11 @@ const bodySchema = schema.object( { type: schema.string(), isNew: schema.boolean(), + isActive: schema.boolean(), }, { unknowns: 'allow' } ); -function fetchWatch(dataClient: IScopedClusterClient, watchId: string) { - return dataClient.callAsCurrentUser('watcher.getWatch', { - id: watchId, - }); -} - -function saveWatch(dataClient: IScopedClusterClient, id: string, body: any) { - return dataClient.callAsCurrentUser('watcher.putWatch', { - id, - body, - }); -} - export function registerSaveRoute(deps: RouteDependencies) { deps.router.put( { @@ -49,12 +36,16 @@ export function registerSaveRoute(deps: RouteDependencies) { }, licensePreRoutingFactory(deps, async (ctx, request, response) => { const { id } = request.params; - const { type, isNew, ...watchConfig } = request.body; + const { type, isNew, isActive, ...watchConfig } = request.body; + + const dataClient = ctx.watcher!.client; // For new watches, verify watch with the same ID doesn't already exist if (isNew) { try { - const existingWatch = await fetchWatch(ctx.watcher!.client, id); + const existingWatch = await dataClient.callAsCurrentUser('watcher.getWatch', { + id, + }); if (existingWatch.found) { return response.conflict({ body: { @@ -92,7 +83,11 @@ export function registerSaveRoute(deps: RouteDependencies) { try { // Create new watch return response.ok({ - body: await saveWatch(ctx.watcher!.client, id, serializedWatch), + body: await dataClient.callAsCurrentUser('watcher.putWatch', { + id, + active: isActive, + body: serializedWatch, + }), }); } catch (e) { // Case: Error from Elasticsearch JS client From d662cb5f4525e3a808900403f54f3c4f2c2c7097 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 10 Apr 2020 12:58:18 +0200 Subject: [PATCH 033/121] [ESUI] Move XJson Mode to src/plugins/es_ui_shared (#62758) * Move XJson to x-pack/es_ui_shared Also convert files to TS and clean up use of @ts-ignore * Move console_lang to public * Proper use of mocks * Globally mock out .ace.worker.js modules Having worker code exported in `public` of es_ui_shared poisoned a lot of Jest tests with the need to mock out the ace worker. Instead of adding mocks everywhere we handle the importing in Jest by adding an entry to module mapper. * Remove manual imports of mocks * Delete es_ui_shared/public/mocks for now * Put useXJson code in single place * Import and instantiate xJsonMode * Remove language mocks imports Besides the fact that these paths are wrong these are no longer needed because we mock at use Jest module mapper Co-authored-by: Elastic Machine --- src/dev/jest/config.js | 1 + .../jest/mocks/ace_worker_module_mock.js} | 2 +- .../legacy/console_editor/editor_output.tsx | 2 +- .../send_request_to_es.ts | 2 +- .../__tests__/output_tokenization.test.js | 1 + .../mode/input_highlight_rules.js | 2 +- .../mode/output_highlight_rules.js | 2 +- .../models/legacy_core_editor/mode/script.js | 2 +- .../__tests__/sense_editor.test.js | 2 +- .../models/sense_editor/sense_editor.ts | 2 +- src/plugins/console/public/lib/utils/index.ts | 5 +-- .../console_lang/ace/modes/index.ts} | 2 +- .../elasticsearch_sql_highlight_rules.ts | 0 .../ace/modes/lexer_rules/index.ts} | 0 .../lexer_rules/script_highlight_rules.ts} | 4 +-- .../lexer_rules/x_json_highlight_rules.ts} | 12 +++---- .../console_lang/ace/modes/x_json/index.ts | 19 ++++++++++ .../ace/modes/x_json/worker/index.ts | 26 ++++++++++++++ .../ace/modes/x_json/worker/worker.d.ts | 25 +++++++++++++ .../modes/x_json/worker/x_json.ace.worker.js | 0 .../console_lang/ace/modes/x_json/x_json.ts} | 35 ++++++++++++++++--- .../{ => public}/console_lang/index.ts | 3 ++ .../{ => public}/console_lang/lib/index.ts | 0 .../json_xjson_translation_tools.test.ts | 0 .../__tests__/utils_string_collapsing.txt | 0 .../__tests__/utils_string_expanding.txt | 0 .../lib/json_xjson_translation_tools/index.ts | 0 src/plugins/es_ui_shared/public/index.ts | 11 ++++++ .../static/ace_x_json/hooks/index.ts | 20 +++++++++++ .../ace_x_json/hooks/use_x_json.ts} | 26 ++++++++------ x-pack/dev-tools/jest/create_jest_config.js | 1 + .../console_lang/ace/modes/index.ts | 7 ---- .../console_lang/ace/modes/x_json/index.ts | 7 ---- .../ace/modes/x_json/worker/index.ts | 13 ------- .../ace/modes/x_json/worker/worker.d.ts | 12 ------- .../console_lang/ace/modes/x_json/x_json.ts | 34 ------------------ .../es_ui_shared/console_lang/index.ts | 7 ---- .../es_ui_shared/console_lang/mocks.ts | 9 ----- .../components/custom_hooks/index.ts | 1 - .../custom_hooks/use_x_json_mode.ts | 26 -------------- .../create_analytics_advanced_editor.tsx | 5 ++- .../use_create_analytics_form/reducer.ts | 2 +- .../ml_job_editor/ml_job_editor.tsx | 5 ++- x-pack/plugins/ml/shared_imports.ts | 5 ++- .../public/application/editor/editor.test.tsx | 2 -- .../public/application/editor/init_editor.ts | 2 +- .../utils/check_for_json_errors.ts | 2 +- .../public/app/hooks/use_x_json_mode.ts | 20 ----------- .../step_define/step_define_form.tsx | 4 ++- .../transform/public/shared_imports.ts | 4 +-- .../builtin_action_types/es_index.tsx | 2 +- .../public/application/lib/use_x_json_mode.ts | 25 ------------- .../watch_create_json.test.ts | 2 -- .../watch_create_threshold.test.tsx | 2 -- .../client_integration/watch_edit.test.ts | 1 - .../client_integration/watch_list.test.ts | 1 - .../client_integration/watch_status.test.ts | 1 - .../json_watch_edit/json_watch_edit_form.tsx | 3 +- .../json_watch_edit_simulate.tsx | 2 +- .../json_watch_edit/use_x_json_mode.ts | 24 ------------- .../public/application/shared_imports.ts | 2 ++ 61 files changed, 193 insertions(+), 246 deletions(-) rename src/{plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts => dev/jest/mocks/ace_worker_module_mock.js} (94%) rename src/plugins/es_ui_shared/{console_lang/ace/modes/index.js => public/console_lang/ace/modes/index.ts} (94%) rename src/plugins/es_ui_shared/{ => public}/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts (100%) rename src/plugins/es_ui_shared/{console_lang/ace/modes/lexer_rules/index.js => public/console_lang/ace/modes/lexer_rules/index.ts} (100%) rename src/plugins/es_ui_shared/{console_lang/ace/modes/lexer_rules/script_highlight_rules.js => public/console_lang/ace/modes/lexer_rules/script_highlight_rules.ts} (97%) rename src/plugins/es_ui_shared/{console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js => public/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.ts} (94%) create mode 100644 src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/index.ts create mode 100644 src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/index.ts create mode 100644 src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/worker.d.ts rename x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.js => src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/x_json.ace.worker.js (100%) rename src/plugins/es_ui_shared/{console_lang/ace/modes/x_json/x_json_mode.ts => public/console_lang/ace/modes/x_json/x_json.ts} (61%) rename src/plugins/es_ui_shared/{ => public}/console_lang/index.ts (92%) rename src/plugins/es_ui_shared/{ => public}/console_lang/lib/index.ts (100%) rename src/plugins/es_ui_shared/{ => public}/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts (100%) rename src/plugins/es_ui_shared/{ => public}/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt (100%) rename src/plugins/es_ui_shared/{ => public}/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt (100%) rename src/plugins/es_ui_shared/{ => public}/console_lang/lib/json_xjson_translation_tools/index.ts (100%) create mode 100644 src/plugins/es_ui_shared/static/ace_x_json/hooks/index.ts rename src/plugins/es_ui_shared/{console_lang/ace/modes/index.d.ts => static/ace_x_json/hooks/use_x_json.ts} (60%) delete mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts delete mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts delete mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/index.ts delete mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts delete mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts delete mode 100644 x-pack/plugins/es_ui_shared/console_lang/index.ts delete mode 100644 x-pack/plugins/es_ui_shared/console_lang/mocks.ts delete mode 100644 x-pack/plugins/ml/public/application/components/custom_hooks/use_x_json_mode.ts delete mode 100644 x-pack/plugins/transform/public/app/hooks/use_x_json_mode.ts delete mode 100644 x-pack/plugins/triggers_actions_ui/public/application/lib/use_x_json_mode.ts delete mode 100644 x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index a941735c7840e..7da14e0dfe51b 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -62,6 +62,7 @@ export default { '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '/src/dev/jest/mocks/file_mock.js', '\\.(css|less|scss)$': '/src/dev/jest/mocks/style_mock.js', + '\\.ace\\.worker.js$': '/src/dev/jest/mocks/ace_worker_module_mock.js', }, setupFiles: [ '/src/dev/jest/setup/babel_polyfill.js', diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts b/src/dev/jest/mocks/ace_worker_module_mock.js similarity index 94% rename from src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts rename to src/dev/jest/mocks/ace_worker_module_mock.js index caa7b518b8b66..9d267f494f8bf 100644 --- a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts +++ b/src/dev/jest/mocks/ace_worker_module_mock.js @@ -17,4 +17,4 @@ * under the License. */ -export { XJsonMode } from './x_json_mode'; +module.exports = ''; diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx index 36d90bb6bff1a..8510aaebfaa1e 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx @@ -20,7 +20,7 @@ import { EuiScreenReaderOnly } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect, useRef } from 'react'; -import { expandLiteralStrings } from '../../../../../../../es_ui_shared/console_lang/lib'; +import { expandLiteralStrings } from '../../../../../../../es_ui_shared/public'; import { useEditorReadContext, useRequestReadContext, diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts index 102f90a9feb6f..cfbd5691bc22b 100644 --- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts +++ b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts @@ -18,7 +18,7 @@ */ import { extractDeprecationMessages } from '../../../lib/utils'; -import { collapseLiteralStrings } from '../../../../../es_ui_shared/console_lang/lib'; +import { collapseLiteralStrings } from '../../../../../es_ui_shared/public'; // @ts-ignore import * as es from '../../../lib/es/es'; import { BaseResponseType } from '../../../types'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js b/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js index 6a93d007a6cdc..5c86b0a1d2092 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import '../legacy_core_editor.test.mocks'; const $ = require('jquery'); import RowParser from '../../../../lib/row_parser'; import ace from 'brace'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js index 2c1b30f806f95..29f192f4ea858 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js @@ -18,7 +18,7 @@ */ const ace = require('brace'); -import { addXJsonToRules } from '../../../../../../es_ui_shared/console_lang'; +import { addXJsonToRules } from '../../../../../../es_ui_shared/public'; export function addEOL(tokens, reg, nextIfEOL, normalNext) { if (typeof reg === 'object') { diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js index e27222ebd65e9..c9d538ab6ceb1 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js @@ -19,7 +19,7 @@ const ace = require('brace'); import 'brace/mode/json'; -import { addXJsonToRules } from '../../../../../../es_ui_shared/console_lang'; +import { addXJsonToRules } from '../../../../../../es_ui_shared/public'; const oop = ace.acequire('ace/lib/oop'); const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules').JsonHighlightRules; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js index 13ae329380221..89adea8921c07 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js @@ -18,7 +18,7 @@ */ import ace from 'brace'; -import { ScriptHighlightRules } from '../../../../../../es_ui_shared/console_lang'; +import { ScriptHighlightRules } from '../../../../../../es_ui_shared/public'; const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js index 63f97345bc9ff..6afc03df13b4c 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js @@ -22,7 +22,7 @@ import $ from 'jquery'; import _ from 'lodash'; import { create } from '../create'; -import { collapseLiteralStrings } from '../../../../../../es_ui_shared/console_lang/lib'; +import { collapseLiteralStrings } from '../../../../../../es_ui_shared/public'; const editorInput1 = require('./editor_input1.txt'); describe('Editor', () => { diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts index b1444bdf2bbab..9bcd3a6872196 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts @@ -19,7 +19,7 @@ import _ from 'lodash'; import RowParser from '../../../lib/row_parser'; -import { collapseLiteralStrings } from '../../../../../es_ui_shared/console_lang/lib'; +import { collapseLiteralStrings } from '../../../../../es_ui_shared/public'; import * as utils from '../../../lib/utils'; // @ts-ignore diff --git a/src/plugins/console/public/lib/utils/index.ts b/src/plugins/console/public/lib/utils/index.ts index f66c952dd3af7..0ebea0f9d4055 100644 --- a/src/plugins/console/public/lib/utils/index.ts +++ b/src/plugins/console/public/lib/utils/index.ts @@ -18,10 +18,7 @@ */ import _ from 'lodash'; -import { - expandLiteralStrings, - collapseLiteralStrings, -} from '../../../../es_ui_shared/console_lang/lib'; +import { expandLiteralStrings, collapseLiteralStrings } from '../../../../es_ui_shared/public'; export function textFromRequest(request: any) { let data = request.data; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/index.js b/src/plugins/es_ui_shared/public/console_lang/ace/modes/index.ts similarity index 94% rename from src/plugins/es_ui_shared/console_lang/ace/modes/index.js rename to src/plugins/es_ui_shared/public/console_lang/ace/modes/index.ts index 955f23116f659..f9e016c5078af 100644 --- a/src/plugins/es_ui_shared/console_lang/ace/modes/index.js +++ b/src/plugins/es_ui_shared/public/console_lang/ace/modes/index.ts @@ -24,4 +24,4 @@ export { addXJsonToRules, } from './lexer_rules'; -export { XJsonMode, installXJsonMode } from './x_json'; +export { installXJsonMode, XJsonMode } from './x_json'; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts b/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts similarity index 100% rename from src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts rename to src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js b/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/index.ts similarity index 100% rename from src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js rename to src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/index.ts diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/script_highlight_rules.js b/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/script_highlight_rules.ts similarity index 97% rename from src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/script_highlight_rules.js rename to src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/script_highlight_rules.ts index b3999c76493c0..4b2e965276a3c 100644 --- a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/script_highlight_rules.js +++ b/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/script_highlight_rules.ts @@ -17,13 +17,13 @@ * under the License. */ -const ace = require('brace'); +import ace from 'brace'; const oop = ace.acequire('ace/lib/oop'); const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); const painlessKeywords = 'def|int|long|byte|String|float|double|char|null|if|else|while|do|for|continue|break|new|try|catch|throw|this|instanceof|return|ctx'; -export function ScriptHighlightRules() { +export function ScriptHighlightRules(this: any) { this.name = 'ScriptHighlightRules'; this.$rules = { start: [ diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js b/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.ts similarity index 94% rename from src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js rename to src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.ts index 14323b9320330..3663b92d92a6f 100644 --- a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js +++ b/src/plugins/es_ui_shared/public/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.ts @@ -22,14 +22,14 @@ import ace from 'brace'; import 'brace/mode/json'; import { ElasticsearchSqlHighlightRules } from './elasticsearch_sql_highlight_rules'; -const { ScriptHighlightRules } = require('./script_highlight_rules'); +import { ScriptHighlightRules } from './script_highlight_rules'; const { JsonHighlightRules } = ace.acequire('ace/mode/json_highlight_rules'); const oop = ace.acequire('ace/lib/oop'); -const jsonRules = function(root) { +const jsonRules = function(root: any) { root = root ? root : 'json'; - const rules = {}; + const rules: any = {}; const xJsonRules = [ { token: [ @@ -135,7 +135,7 @@ const jsonRules = function(root) { merge: false, push: true, }, - ].concat(xJsonRules); + ].concat(xJsonRules as any); rules.string_literal = [ { @@ -151,7 +151,7 @@ const jsonRules = function(root) { return rules; }; -export function XJsonHighlightRules() { +export function XJsonHighlightRules(this: any) { this.$rules = { ...jsonRules('start'), }; @@ -175,7 +175,7 @@ export function XJsonHighlightRules() { oop.inherits(XJsonHighlightRules, JsonHighlightRules); -export function addToRules(otherRules, embedUnder) { +export function addToRules(otherRules: any, embedUnder: any) { otherRules.$rules = _.defaultsDeep(otherRules.$rules, jsonRules(embedUnder)); otherRules.embedRules(ScriptHighlightRules, 'script-', [ { diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/index.ts b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/index.ts new file mode 100644 index 0000000000000..6fd819bb4e9eb --- /dev/null +++ b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/index.ts @@ -0,0 +1,19 @@ +/* + * 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 { installXJsonMode, XJsonMode } from './x_json'; diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/index.ts b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/index.ts new file mode 100644 index 0000000000000..0f884765be05e --- /dev/null +++ b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/index.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +// @ts-ignore +import src from '!!raw-loader!./x_json.ace.worker.js'; + +export const workerModule = { + id: 'ace/mode/json_worker', + src, +}; diff --git a/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/worker.d.ts b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/worker.d.ts new file mode 100644 index 0000000000000..d2363a2610689 --- /dev/null +++ b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/worker.d.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +// Satisfy TS's requirements that the module be declared per './index.ts'. +declare module '!!raw-loader!./worker.js' { + const content: string; + // eslint-disable-next-line import/no-default-export + export default content; +} diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.js b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/x_json.ace.worker.js similarity index 100% rename from x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.js rename to src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/worker/x_json.ace.worker.js diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/x_json.ts similarity index 61% rename from src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts rename to src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/x_json.ts index 9f804c29a5d27..9fbfedba1d23f 100644 --- a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts +++ b/src/plugins/es_ui_shared/public/console_lang/ace/modes/x_json/x_json.ts @@ -18,23 +18,50 @@ */ import ace from 'brace'; - import { XJsonHighlightRules } from '../index'; +import { workerModule } from './worker'; + +const { WorkerClient } = ace.acequire('ace/worker/worker_client'); const oop = ace.acequire('ace/lib/oop'); + const { Mode: JSONMode } = ace.acequire('ace/mode/json'); const { Tokenizer: AceTokenizer } = ace.acequire('ace/tokenizer'); const { MatchingBraceOutdent } = ace.acequire('ace/mode/matching_brace_outdent'); const { CstyleBehaviour } = ace.acequire('ace/mode/behaviour/cstyle'); const { FoldMode: CStyleFoldMode } = ace.acequire('ace/mode/folding/cstyle'); -export function XJsonMode(this: any) { - const ruleset: any = new XJsonHighlightRules(); +const XJsonMode: any = function XJsonMode(this: any) { + const ruleset: any = new (XJsonHighlightRules as any)(); ruleset.normalizeRules(); this.$tokenizer = new AceTokenizer(ruleset.getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); this.foldingRules = new CStyleFoldMode(); -} +}; oop.inherits(XJsonMode, JSONMode); + +// Then clobber `createWorker` method to install our worker source. Per ace's wiki: https://github.com/ajaxorg/ace/wiki/Syntax-validation +(XJsonMode.prototype as any).createWorker = function(session: ace.IEditSession) { + const xJsonWorker = new WorkerClient(['ace'], workerModule, 'JsonWorker'); + + xJsonWorker.attachToDocument(session.getDocument()); + + xJsonWorker.on('annotate', function(e: { data: any }) { + session.setAnnotations(e.data); + }); + + xJsonWorker.on('terminate', function() { + session.clearAnnotations(); + }); + + return xJsonWorker; +}; + +export { XJsonMode }; + +export function installXJsonMode(editor: ace.Editor) { + const session = editor.getSession(); + session.setMode(new XJsonMode()); +} diff --git a/src/plugins/es_ui_shared/console_lang/index.ts b/src/plugins/es_ui_shared/public/console_lang/index.ts similarity index 92% rename from src/plugins/es_ui_shared/console_lang/index.ts rename to src/plugins/es_ui_shared/public/console_lang/index.ts index a4958911af412..7d83191569622 100644 --- a/src/plugins/es_ui_shared/console_lang/index.ts +++ b/src/plugins/es_ui_shared/public/console_lang/index.ts @@ -26,4 +26,7 @@ export { XJsonHighlightRules, addXJsonToRules, XJsonMode, + installXJsonMode, } from './ace/modes'; + +export { expandLiteralStrings, collapseLiteralStrings } from './lib'; diff --git a/src/plugins/es_ui_shared/console_lang/lib/index.ts b/src/plugins/es_ui_shared/public/console_lang/lib/index.ts similarity index 100% rename from src/plugins/es_ui_shared/console_lang/lib/index.ts rename to src/plugins/es_ui_shared/public/console_lang/lib/index.ts diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts b/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts similarity index 100% rename from src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts rename to src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt b/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt similarity index 100% rename from src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt rename to src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt b/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt similarity index 100% rename from src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt rename to src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts b/src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/index.ts similarity index 100% rename from src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts rename to src/plugins/es_ui_shared/public/console_lang/lib/json_xjson_translation_tools/index.ts diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts index 6db6248f4c68f..a0371bf351193 100644 --- a/src/plugins/es_ui_shared/public/index.ts +++ b/src/plugins/es_ui_shared/public/index.ts @@ -36,6 +36,17 @@ export { indices } from './indices'; export { useUIAceKeyboardMode } from './use_ui_ace_keyboard_mode'; +export { + installXJsonMode, + XJsonMode, + ElasticsearchSqlHighlightRules, + addXJsonToRules, + ScriptHighlightRules, + XJsonHighlightRules, + collapseLiteralStrings, + expandLiteralStrings, +} from './console_lang'; + /** dummy plugin, we just want esUiShared to have its own bundle */ export function plugin() { return new (class EsUiSharedPlugin { diff --git a/src/plugins/es_ui_shared/static/ace_x_json/hooks/index.ts b/src/plugins/es_ui_shared/static/ace_x_json/hooks/index.ts new file mode 100644 index 0000000000000..1d2c33a9f0f47 --- /dev/null +++ b/src/plugins/es_ui_shared/static/ace_x_json/hooks/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 { useXJsonMode } from './use_x_json'; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts b/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts similarity index 60% rename from src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts rename to src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts index 06c9f9a51ea68..2b0bf0c8a3a7c 100644 --- a/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts +++ b/src/plugins/es_ui_shared/static/ace_x_json/hooks/use_x_json.ts @@ -17,16 +17,22 @@ * under the License. */ -import { Editor } from 'brace'; +import { useState } from 'react'; +import { XJsonMode, collapseLiteralStrings, expandLiteralStrings } from '../../../public'; -export declare const ElasticsearchSqlHighlightRules: FunctionConstructor; -export declare const ScriptHighlightRules: FunctionConstructor; -export declare const XJsonHighlightRules: FunctionConstructor; +const xJsonMode = new XJsonMode(); -export declare const XJsonMode: FunctionConstructor; +export const useXJsonMode = (json: Record | string | null) => { + const [xJson, setXJson] = useState(() => + json === null + ? '' + : expandLiteralStrings(typeof json === 'string' ? json : JSON.stringify(json, null, 2)) + ); -/** - * @param otherRules Another Ace ruleset - * @param embedUnder The state name under which the rules will be embedded. Defaults to "json". - */ -export declare const addXJsonToRules: (otherRules: any, embedUnder?: string) => void; + return { + xJson, + setXJson, + xJsonMode, + convertToJson: collapseLiteralStrings, + }; +}; diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js index 1f4311ae9bcf6..3068cdd0daa5b 100644 --- a/x-pack/dev-tools/jest/create_jest_config.js +++ b/x-pack/dev-tools/jest/create_jest_config.js @@ -28,6 +28,7 @@ export function createJestConfig({ kibanaDirectory, xPackKibanaDirectory }) { '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': fileMockPath, '\\.module.(css|scss)$': `${kibanaDirectory}/src/dev/jest/mocks/css_module_mock.js`, '\\.(css|less|scss)$': `${kibanaDirectory}/src/dev/jest/mocks/style_mock.js`, + '\\.ace\\.worker.js$': `${kibanaDirectory}/src/dev/jest/mocks/ace_worker_module_mock.js`, '^test_utils/enzyme_helpers': `${xPackKibanaDirectory}/test_utils/enzyme_helpers.tsx`, '^test_utils/find_test_subject': `${xPackKibanaDirectory}/test_utils/find_test_subject.ts`, '^test_utils/stub_web_worker': `${xPackKibanaDirectory}/test_utils/stub_web_worker.ts`, diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts deleted file mode 100644 index ae3c9962ecadb..0000000000000 --- a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/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 { installXJsonMode, XJsonMode } from './x_json'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts deleted file mode 100644 index ae3c9962ecadb..0000000000000 --- a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/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 { installXJsonMode, XJsonMode } from './x_json'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/index.ts deleted file mode 100644 index 0e40fd335dd31..0000000000000 --- a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/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. - */ - -// @ts-ignore -import src from '!!raw-loader!./worker.js'; - -export const workerModule = { - id: 'ace/mode/json_worker', - src, -}; diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts deleted file mode 100644 index 4ebad4f2ef91c..0000000000000 --- a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts +++ /dev/null @@ -1,12 +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. - */ - -// Satisfy TS's requirements that the module be declared per './index.ts'. -declare module '!!raw-loader!./worker.js' { - const content: string; - // eslint-disable-next-line import/no-default-export - export default content; -} diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts deleted file mode 100644 index bfeca045bea02..0000000000000 --- a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import ace from 'brace'; -import { XJsonMode } from '../../../../../../../src/plugins/es_ui_shared/console_lang'; -import { workerModule } from './worker'; -const { WorkerClient } = ace.acequire('ace/worker/worker_client'); - -// Then clobber `createWorker` method to install our worker source. Per ace's wiki: https://github.com/ajaxorg/ace/wiki/Syntax-validation -(XJsonMode.prototype as any).createWorker = function(session: ace.IEditSession) { - const xJsonWorker = new WorkerClient(['ace'], workerModule, 'JsonWorker'); - - xJsonWorker.attachToDocument(session.getDocument()); - - xJsonWorker.on('annotate', function(e: { data: any }) { - session.setAnnotations(e.data); - }); - - xJsonWorker.on('terminate', function() { - session.clearAnnotations(); - }); - - return xJsonWorker; -}; - -export { XJsonMode }; - -export function installXJsonMode(editor: ace.Editor) { - const session = editor.getSession(); - session.setMode(new (XJsonMode as any)()); -} diff --git a/x-pack/plugins/es_ui_shared/console_lang/index.ts b/x-pack/plugins/es_ui_shared/console_lang/index.ts deleted file mode 100644 index b5fe3a554e34d..0000000000000 --- a/x-pack/plugins/es_ui_shared/console_lang/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 { XJsonMode, installXJsonMode } from './ace/modes'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/mocks.ts b/x-pack/plugins/es_ui_shared/console_lang/mocks.ts deleted file mode 100644 index 68480282ddc03..0000000000000 --- a/x-pack/plugins/es_ui_shared/console_lang/mocks.ts +++ /dev/null @@ -1,9 +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. - */ - -jest.mock('./ace/modes/x_json/worker', () => ({ - workerModule: { id: 'ace/mode/json_worker', src: '' }, -})); diff --git a/x-pack/plugins/ml/public/application/components/custom_hooks/index.ts b/x-pack/plugins/ml/public/application/components/custom_hooks/index.ts index dfd74d8970cb4..ffead802bd6f9 100644 --- a/x-pack/plugins/ml/public/application/components/custom_hooks/index.ts +++ b/x-pack/plugins/ml/public/application/components/custom_hooks/index.ts @@ -5,4 +5,3 @@ */ export { usePartialState } from './use_partial_state'; -export { useXJsonMode, xJsonMode } from './use_x_json_mode'; diff --git a/x-pack/plugins/ml/public/application/components/custom_hooks/use_x_json_mode.ts b/x-pack/plugins/ml/public/application/components/custom_hooks/use_x_json_mode.ts deleted file mode 100644 index c979632db54d6..0000000000000 --- a/x-pack/plugins/ml/public/application/components/custom_hooks/use_x_json_mode.ts +++ /dev/null @@ -1,26 +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 { useState } from 'react'; -import { - collapseLiteralStrings, - expandLiteralStrings, - XJsonMode, -} from '../../../../shared_imports'; - -// @ts-ignore -export const xJsonMode = new XJsonMode(); - -export const useXJsonMode = (json: string) => { - const [xJson, setXJson] = useState(expandLiteralStrings(json)); - - return { - xJson, - setXJson, - xJsonMode, - convertToJson: collapseLiteralStrings, - }; -}; 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_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx index a3e5da5e2d039..cef03cc0d0c76 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_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx @@ -18,8 +18,11 @@ import { import { i18n } from '@kbn/i18n'; +import { XJsonMode } from '../../../../../../../shared_imports'; + +const xJsonMode = new XJsonMode(); + import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; -import { xJsonMode } from '../../../../../components/custom_hooks'; export const CreateAnalyticsAdvancedEditor: FC = ({ actions, state }) => { const { setAdvancedEditorRawString, setFormState } = actions; 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 ded6e50947035..d55eb14a20e29 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 @@ -11,7 +11,7 @@ import numeral from '@elastic/numeral'; import { isEmpty } from 'lodash'; import { isValidIndexName } from '../../../../../../../common/util/es_utils'; -import { collapseLiteralStrings } from '../../../../../../../../../../src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools'; +import { collapseLiteralStrings } from '../../../../../../../../../../src/plugins/es_ui_shared/public'; import { Action, ACTION } from './actions'; import { getInitialState, getJobConfigFromFormState, State } from './state'; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx index 0633c62f754e0..c10212ee31564 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx @@ -7,10 +7,9 @@ import React, { FC } from 'react'; import { EuiCodeEditor, EuiCodeEditorProps } from '@elastic/eui'; -import { expandLiteralStrings } from '../../../../../../shared_imports'; -import { xJsonMode } from '../../../../components/custom_hooks'; +import { expandLiteralStrings, XJsonMode } from '../../../../../../shared_imports'; -export const ML_EDITOR_MODE = { TEXT: 'text', JSON: 'json', XJSON: xJsonMode }; +export const ML_EDITOR_MODE = { TEXT: 'text', JSON: 'json', XJSON: new XJsonMode() }; interface MlJobEditorProps { value: string; diff --git a/x-pack/plugins/ml/shared_imports.ts b/x-pack/plugins/ml/shared_imports.ts index 94ce8c82f1d95..a82ed5387818d 100644 --- a/x-pack/plugins/ml/shared_imports.ts +++ b/x-pack/plugins/ml/shared_imports.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export { XJsonMode } from '../../../src/plugins/es_ui_shared/console_lang/ace/modes/x_json'; - export { + XJsonMode, collapseLiteralStrings, expandLiteralStrings, -} from '../../../src/plugins/es_ui_shared/console_lang/lib'; +} from '../../../src/plugins/es_ui_shared/public'; diff --git a/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx index ad56b3957eb74..e56fc79156666 100644 --- a/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx +++ b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx @@ -6,8 +6,6 @@ import 'brace'; import 'brace/mode/json'; -import '../../../../es_ui_shared/console_lang/mocks'; - import { registerTestBed } from '../../../../../test_utils'; import { Editor, Props } from '.'; diff --git a/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts b/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts index 6f19ce12eb639..3ad92531e4367 100644 --- a/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts +++ b/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts @@ -5,7 +5,7 @@ */ import ace from 'brace'; -import { installXJsonMode } from '../../../../es_ui_shared/console_lang'; +import { installXJsonMode } from '../../../../../../src/plugins/es_ui_shared/public'; export function initializeEditor({ el, diff --git a/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts index 99687de0f1440..58a62c4636c25 100644 --- a/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts +++ b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { collapseLiteralStrings } from '../../../../../../src/plugins/es_ui_shared/console_lang/lib'; +import { collapseLiteralStrings } from '../../../../../../src/plugins/es_ui_shared/public'; export function checkForParseErrors(json: string) { const sanitizedJson = collapseLiteralStrings(json); diff --git a/x-pack/plugins/transform/public/app/hooks/use_x_json_mode.ts b/x-pack/plugins/transform/public/app/hooks/use_x_json_mode.ts deleted file mode 100644 index 1017ce198ff29..0000000000000 --- a/x-pack/plugins/transform/public/app/hooks/use_x_json_mode.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { useState } from 'react'; -import { collapseLiteralStrings, expandLiteralStrings, XJsonMode } from '../../shared_imports'; - -export const xJsonMode = new XJsonMode(); - -export const useXJsonMode = (json: string) => { - const [xJson, setXJson] = useState(expandLiteralStrings(json)); - - return { - xJson, - setXJson, - xJsonMode, - convertToJson: collapseLiteralStrings, - }; -}; diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx index 5e0eb7ee08361..320e405b5d437 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx @@ -33,11 +33,12 @@ import { QueryStringInput, } from '../../../../../../../../../src/plugins/data/public'; +import { useXJsonMode } from '../../../../../../../../../src/plugins/es_ui_shared/static/ace_x_json/hooks'; + import { PivotPreview } from '../../../../components/pivot_preview'; import { useDocumentationLinks } from '../../../../hooks/use_documentation_links'; import { SavedSearchQuery, SearchItems } from '../../../../hooks/use_search_items'; -import { useXJsonMode, xJsonMode } from '../../../../hooks/use_x_json_mode'; import { useToastNotifications } from '../../../../app_dependencies'; import { TransformPivotConfig } from '../../../../common'; import { dictionaryToArray, Dictionary } from '../../../../../../common/types/common'; @@ -432,6 +433,7 @@ export const StepDefineForm: FC = React.memo(({ overrides = {}, onChange, convertToJson, setXJson: setAdvancedEditorConfig, xJson: advancedEditorConfig, + xJsonMode, } = useXJsonMode(stringifiedPivotConfig); useEffect(() => { diff --git a/x-pack/plugins/transform/public/shared_imports.ts b/x-pack/plugins/transform/public/shared_imports.ts index 8eb42ad677c0f..494b6db6aafe0 100644 --- a/x-pack/plugins/transform/public/shared_imports.ts +++ b/x-pack/plugins/transform/public/shared_imports.ts @@ -5,11 +5,11 @@ */ export { createSavedSearchesLoader } from '../../../../src/plugins/discover/public'; -export { XJsonMode } from '../../es_ui_shared/console_lang/ace/modes/x_json'; export { + XJsonMode, collapseLiteralStrings, expandLiteralStrings, -} from '../../../../src/plugins/es_ui_shared/console_lang/lib'; +} from '../../../../src/plugins/es_ui_shared/public'; export { UseRequestConfig, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx index 9bd6a39d216e3..15f68e6a9f441 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index.tsx @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { useXJsonMode } from '../../../../../../../src/plugins/es_ui_shared/static/ace_x_json/hooks'; import { ActionTypeModel, ActionConnectorFieldsProps, @@ -31,7 +32,6 @@ import { getIndexOptions, getIndexPatterns, } from '../../../common/index_controls'; -import { useXJsonMode } from '../../lib/use_x_json_mode'; import { AddMessageVariables } from '../add_message_variables'; export function getActionType(): ActionTypeModel { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/use_x_json_mode.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/use_x_json_mode.ts deleted file mode 100644 index b677924724ffe..0000000000000 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/use_x_json_mode.ts +++ /dev/null @@ -1,25 +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 { useState } from 'react'; -import { XJsonMode } from '../../../../../../src/plugins/es_ui_shared/console_lang/ace/modes/x_json'; -import { - collapseLiteralStrings, - expandLiteralStrings, -} from '../../../../../../src/plugins/es_ui_shared/console_lang/lib'; -// @ts-ignore -export const xJsonMode = new XJsonMode(); -export const useXJsonMode = (json: Record | null) => { - const [xJson, setXJson] = useState( - json === null ? '' : expandLiteralStrings(JSON.stringify(json, null, 2)) - ); - - return { - xJson, - setXJson, - xJsonMode, - convertToJson: collapseLiteralStrings, - }; -}; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts index 47de4548898cf..a35dd1346dc90 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../es_ui_shared/console_lang/mocks'; - import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers'; import { WatchCreateJsonTestBed } from './helpers/watch_create_json.helpers'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx index e5bdcbbfb82cf..89cd5207fe250 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../es_ui_shared/console_lang/mocks'; - import React from 'react'; import { act } from 'react-dom/test-utils'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts index ced06562b1d20..18acf7339580c 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import '../../../es_ui_shared/console_lang/mocks'; import { act } from 'react-dom/test-utils'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts index 3370e42b2417f..a0327c6dfa1db 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import '../../../es_ui_shared/console_lang/mocks'; import { act } from 'react-dom/test-utils'; import * as fixtures from '../../test/fixtures'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts index 20b7b526705c0..e9cbb2c92491a 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import '../../../es_ui_shared/console_lang/mocks'; import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers, nextTick } from './helpers'; diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx index b3a09d3bc0e65..b5835d862000f 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx @@ -23,14 +23,13 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { serializeJsonWatch } from '../../../../../../common/lib/serialization'; import { ErrableFormRow, SectionError, Error as ServerError } from '../../../../components'; +import { useXJsonMode } from '../../../../shared_imports'; import { onWatchSave } from '../../watch_edit_actions'; import { WatchContext } from '../../watch_context'; import { goToWatchList } from '../../../../lib/navigation'; import { RequestFlyout } from '../request_flyout'; import { useAppContext } from '../../../../app_context'; -import { useXJsonMode } from './use_x_json_mode'; - export const JsonWatchEditForm = () => { const { links: { putWatchApiUrl }, diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx index b9fce52b480ef..fa0b9b0a2566f 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx @@ -40,7 +40,7 @@ import { JsonWatchEditSimulateResults } from './json_watch_edit_simulate_results import { getTimeUnitLabel } from '../../../../lib/get_time_unit_label'; import { useAppContext } from '../../../../app_context'; -import { useXJsonMode } from './use_x_json_mode'; +import { useXJsonMode } from '../../../../shared_imports'; const actionModeOptions = Object.keys(ACTION_MODES).map(mode => ({ text: ACTION_MODES[mode], diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts deleted file mode 100644 index 7aefb0554e0e8..0000000000000 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { useState } from 'react'; -import { XJsonMode } from '../../../../../../../es_ui_shared/console_lang'; -import { - collapseLiteralStrings, - expandLiteralStrings, -} from '../../../../../../../../../src/plugins/es_ui_shared/console_lang/lib'; - -export const xJsonMode = new XJsonMode(); - -export const useXJsonMode = (json: string) => { - const [xJson, setXJson] = useState(expandLiteralStrings(json)); - - return { - xJson, - setXJson, - xJsonMode, - convertToJson: collapseLiteralStrings, - }; -}; diff --git a/x-pack/plugins/watcher/public/application/shared_imports.ts b/x-pack/plugins/watcher/public/application/shared_imports.ts index cbc4dde7448ff..94ef7af1c28d1 100644 --- a/x-pack/plugins/watcher/public/application/shared_imports.ts +++ b/x-pack/plugins/watcher/public/application/shared_imports.ts @@ -11,3 +11,5 @@ export { sendRequest, useRequest, } from '../../../../../src/plugins/es_ui_shared/public/request/np_ready_request'; + +export { useXJsonMode } from '../../../../../src/plugins/es_ui_shared/static/ace_x_json/hooks'; From 77d22f55d9d952ed0d3b6ed6da25def23fcea4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 10 Apr 2020 13:54:48 +0100 Subject: [PATCH 034/121] [APM] Agent config select box doesn't work on IE (#63236) * adding value property to select options * fixing test --- .../SettingsPage/SettingFormRow.tsx | 7 +++++-- .../setting_definitions/__snapshots__/index.test.ts.snap | 4 ++++ .../setting_definitions/general_settings.ts | 8 ++++---- .../agent_configuration/setting_definitions/types.d.ts | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/SettingsPage/SettingFormRow.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/SettingsPage/SettingFormRow.tsx index 30c772bf5f634..baab600145b81 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/SettingsPage/SettingFormRow.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AgentConfigurationCreateEdit/SettingsPage/SettingFormRow.tsx @@ -73,7 +73,10 @@ function FormRow({ return ( onChange(setting.key, e.target.value)} /> @@ -105,7 +108,7 @@ function FormRow({ defaultMessage: 'Select unit' })} value={unit} - options={setting.units?.map(text => ({ text }))} + options={setting.units?.map(text => ({ text, value: text }))} onChange={e => onChange( setting.key, diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap index 49840d2157af7..ea706be9f584a 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap @@ -29,15 +29,19 @@ Array [ "options": Array [ Object { "text": "off", + "value": "off", }, Object { "text": "errors", + "value": "errors", }, Object { "text": "transactions", + "value": "transactions", }, Object { "text": "all", + "value": "all", }, ], "type": "select", diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts index e73aed35e87f9..7477238ba79ae 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts @@ -67,10 +67,10 @@ export const generalSettings: RawSettingDefinition[] = [ } ), options: [ - { text: 'off' }, - { text: 'errors' }, - { text: 'transactions' }, - { text: 'all' } + { text: 'off', value: 'off' }, + { text: 'errors', value: 'errors' }, + { text: 'transactions', value: 'transactions' }, + { text: 'all', value: 'all' } ], excludeAgents: ['js-base', 'rum-js'] }, diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/types.d.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/types.d.ts index 282ced346dda0..815b8cb3d4e83 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/types.d.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/types.d.ts @@ -76,7 +76,7 @@ interface FloatSetting extends BaseSetting { interface SelectSetting extends BaseSetting { type: 'select'; - options: Array<{ text: string }>; + options: Array<{ text: string; value: string }>; } interface BooleanSetting extends BaseSetting { From e8491adbab145590e877e5af9b1efa009400bf46 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Fri, 10 Apr 2020 09:04:17 -0500 Subject: [PATCH 035/121] Use globe icon for "ext" span type on service map (#63205) Both "external" and "ext" can be returned and should have the same icon. --- .../apm/public/components/app/ServiceMap/Cytoscape.stories.tsx | 1 + .../legacy/plugins/apm/public/components/app/ServiceMap/icons.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx index a8d3b843a1f3d..31c227d8bbcab 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/Cytoscape.stories.tsx @@ -85,6 +85,7 @@ storiesOf('app/ServiceMap/Cytoscape', module) } }, { data: { id: 'external', 'span.type': 'external' } }, + { data: { id: 'ext', 'span.type': 'ext' } }, { data: { id: 'messaging', 'span.type': 'messaging' } }, { data: { diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons.ts b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons.ts index dd9b48d312725..095c2d9250e27 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons.ts +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/icons.ts @@ -32,6 +32,7 @@ export const defaultIcon = defaultIconImport; const icons: { [key: string]: string } = { cache: databaseIcon, db: databaseIcon, + ext: globeIcon, external: globeIcon, messaging: documentsIcon, resource: globeIcon From ed975d0169e6728db9d8c5cf98ca655293217192 Mon Sep 17 00:00:00 2001 From: DianaDerevyankina <54894989+DianaDerevyankina@users.noreply.github.com> Date: Fri, 10 Apr 2020 17:59:50 +0300 Subject: [PATCH 036/121] Move shared vislib components into Charts plugin (#62957) * Closes #56310 Move shared vislib components into Charts plugin * Fixed imports in tests * Changed i18n IDs to match charts namespace * Renamed ColorSchemaVislibParams to ColorSchemaParams, added enums and got rid of useValidation function * Renamed ColorSchemaVislibParams to ColorSchemaParams and got rid of useValidation function * Fixed merge conflict * Replaced enums with objects again --- .../public/components/region_map_options.tsx | 6 ++- .../public/components/tile_map_options.tsx | 2 +- .../components/wms_internal_options.tsx | 2 +- .../public/components/wms_options.tsx | 2 +- .../public/settings_options.tsx | 2 +- .../public/components/metric_vis_options.tsx | 4 +- .../vis_type_metric/public/metric_vis_fn.ts | 3 +- .../vis_type_metric/public/metric_vis_type.ts | 3 +- .../vis_type_metric/public/types.ts | 3 +- .../public/components/table_vis_options.tsx | 6 ++- .../public/components/tag_cloud_options.tsx | 2 +- .../vis_type_vislib/public/area.ts | 2 +- .../public/components/common/index.ts | 8 ---- .../components/options/gauge/labels_panel.tsx | 2 +- .../components/options/gauge/ranges_panel.tsx | 14 +++--- .../components/options/gauge/style_panel.tsx | 2 +- .../components/options/heatmap/index.tsx | 6 +-- .../options/heatmap/labels_panel.tsx | 2 +- .../metrics_axes/category_axis_panel.tsx | 2 +- .../options/metrics_axes/chart_options.tsx | 2 +- .../metrics_axes/custom_extents_options.tsx | 2 +- .../options/metrics_axes/label_options.tsx | 3 +- .../metrics_axes/line_options.test.tsx | 2 +- .../options/metrics_axes/line_options.tsx | 6 ++- .../components/options/metrics_axes/mocks.ts | 3 +- .../metrics_axes/value_axis_options.test.tsx | 2 +- .../metrics_axes/value_axis_options.tsx | 6 ++- .../options/metrics_axes/y_extents.test.tsx | 2 +- .../options/metrics_axes/y_extents.tsx | 2 +- .../public/components/options/pie.tsx | 3 +- .../options/point_series/grid_panel.tsx | 2 +- .../options/point_series/point_series.tsx | 3 +- .../options/point_series/threshold_panel.tsx | 12 ++++-- .../vis_type_vislib/public/gauge.ts | 13 ++++-- .../vis_type_vislib/public/goal.ts | 4 +- .../vis_type_vislib/public/heatmap.ts | 6 +-- .../vis_type_vislib/public/histogram.ts | 2 +- .../vis_type_vislib/public/horizontal_bar.ts | 2 +- .../vis_type_vislib/public/index.ts | 14 ------ .../vis_type_vislib/public/line.ts | 2 +- .../vis_type_vislib/public/types.ts | 25 +---------- .../public/utils/collections.ts | 16 +------ .../static/components}/basic_options.tsx | 4 +- .../public/static/components/collections.ts} | 26 +++++------ .../static/components}/color_ranges.tsx | 7 +-- .../static/components}/color_schema.tsx | 18 ++++---- .../charts/public/static/components/index.ts | 30 +++++++++++++ .../static/components}/number_input.tsx | 0 .../public/static/components}/range.tsx | 2 +- .../components}/required_number_input.tsx | 14 +++--- .../public/static/components}/select.tsx | 0 .../public/static/components}/switch.tsx | 0 .../public/static/components}/text_input.tsx | 0 .../charts/public/static/components/types.ts | 43 +++++++++++++++++++ src/plugins/charts/public/static/index.ts | 1 + .../translations/translations/ja-JP.json | 16 +++---- .../translations/translations/zh-CN.json | 16 +++---- 57 files changed, 215 insertions(+), 169 deletions(-) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/basic_options.tsx (90%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common/utils.ts => plugins/charts/public/static/components/collections.ts} (67%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/color_ranges.tsx (93%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/color_schema.tsx (82%) create mode 100644 src/plugins/charts/public/static/components/index.ts rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/number_input.tsx (100%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/range.tsx (96%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/required_number_input.tsx (87%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/select.tsx (100%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/switch.tsx (100%) rename src/{legacy/core_plugins/vis_type_vislib/public/components/common => plugins/charts/public/static/components}/text_input.tsx (100%) create mode 100644 src/plugins/charts/public/static/components/types.ts diff --git a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx index 61cfbf00ded9e..187b27953830d 100644 --- a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx +++ b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx @@ -24,7 +24,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { FileLayerField, VectorLayer, ServiceSettings } from 'ui/vis/map/service_settings'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { NumberInputOption, SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; +import { + NumberInputOption, + SelectOption, + SwitchOption, +} from '../../../../../plugins/charts/public'; import { WmsOptions } from '../../../tile_map/public/components/wms_options'; import { RegionMapVisParams } from '../types'; diff --git a/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx b/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx index 9169647aa2aef..9ca42fe3e4074 100644 --- a/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/tile_map_options.tsx @@ -27,7 +27,7 @@ import { RangeOption, SelectOption, SwitchOption, -} from '../../../vis_type_vislib/public'; +} from '../../../../../plugins/charts/public'; import { WmsOptions } from './wms_options'; import { TileMapVisParams } from '../types'; import { MapTypes } from '../map_types'; diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx index b81667400303d..47f5b8f31e62b 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_internal_options.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { EuiLink, EuiSpacer, EuiText, EuiScreenReaderOnly } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { TextInputOption } from '../../../vis_type_vislib/public'; +import { TextInputOption } from '../../../../../plugins/charts/public'; import { WMSOptions } from '../types'; interface WmsInternalOptions { diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx index 27127b781cd4d..b8535e72e8818 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx @@ -25,7 +25,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { TmsLayer } from 'ui/vis/map/service_settings'; import { Vis } from '../../../../../plugins/visualizations/public'; import { RegionMapVisParams } from '../../../region_map/public/types'; -import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; +import { SelectOption, SwitchOption } from '../../../../../plugins/charts/public'; import { WmsInternalOptions } from './wms_internal_options'; import { WMSOptions, TileMapVisParams } from '../types'; diff --git a/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx index 552fd63373554..16b2749c34e10 100644 --- a/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx +++ b/src/legacy/core_plugins/vis_type_markdown/public/settings_options.tsx @@ -22,7 +22,7 @@ import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { RangeOption, SwitchOption } from '../../vis_type_vislib/public'; +import { RangeOption, SwitchOption } from '../../../../plugins/charts/public'; import { MarkdownVisParams } from './types'; function SettingsOptions({ stateParams, setValue }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx index 5c3032511f09a..56af0ee91878f 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx +++ b/src/legacy/core_plugins/vis_type_metric/public/components/metric_vis_options.tsx @@ -37,9 +37,9 @@ import { SwitchOption, RangeOption, SetColorSchemaOptionsValue, -} from '../../../vis_type_vislib/public'; + SetColorRangeValue, +} from '../../../../../plugins/charts/public'; import { MetricVisParam, VisParams } from '../types'; -import { SetColorRangeValue } from '../../../vis_type_vislib/public/components/common/color_ranges'; function MetricVisOptions({ stateParams, diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts index 03b412c6fff15..52784da1bd73b 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_fn.ts @@ -26,9 +26,8 @@ import { Render, Style, } from '../../../../plugins/expressions/public'; -import { ColorModes } from '../../vis_type_vislib/public'; import { visType, DimensionsVisParam, VisParams } from './types'; -import { ColorSchemas, vislibColorMaps } from '../../../../plugins/charts/public'; +import { ColorSchemas, vislibColorMaps, ColorModes } from '../../../../plugins/charts/public'; export type Input = KibanaDatatable; diff --git a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts index 3bbb8964122e5..ab31c56921412 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/metric_vis_type.ts @@ -21,8 +21,7 @@ import { i18n } from '@kbn/i18n'; import { MetricVisComponent } from './components/metric_vis_component'; import { MetricVisOptions } from './components/metric_vis_options'; -import { ColorModes } from '../../vis_type_vislib/public'; -import { ColorSchemas, colorSchemas } from '../../../../plugins/charts/public'; +import { ColorSchemas, colorSchemas, ColorModes } from '../../../../plugins/charts/public'; import { AggGroupNames } from '../../../../plugins/data/public'; import { Schemas } from '../../../../plugins/vis_default_editor/public'; diff --git a/src/legacy/core_plugins/vis_type_metric/public/types.ts b/src/legacy/core_plugins/vis_type_metric/public/types.ts index cae18dd8a2ab1..cdf62cba934d7 100644 --- a/src/legacy/core_plugins/vis_type_metric/public/types.ts +++ b/src/legacy/core_plugins/vis_type_metric/public/types.ts @@ -19,8 +19,7 @@ import { Range } from '../../../../plugins/expressions/public'; import { SchemaConfig } from '../../../../plugins/visualizations/public'; -import { ColorModes, Labels, Style } from '../../vis_type_vislib/public'; -import { ColorSchemas } from '../../../../plugins/charts/public'; +import { ColorModes, ColorSchemas, Labels, Style } from '../../../../plugins/charts/public'; export const visType = 'metric'; diff --git a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx index d01ab31e0a843..265528f33f9cd 100644 --- a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx +++ b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx @@ -25,7 +25,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; import { search } from '../../../../../plugins/data/public'; -import { NumberInputOption, SwitchOption, SelectOption } from '../../../vis_type_vislib/public'; +import { + SwitchOption, + SelectOption, + NumberInputOption, +} from '../../../../../plugins/charts/public'; import { TableVisParams } from '../types'; import { totalAggregations } from './utils'; diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx index 80e4e1de7ddab..7a64549edd747 100644 --- a/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx +++ b/src/legacy/core_plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx @@ -22,7 +22,7 @@ import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; import { ValidatedDualRange } from '../../../../../../src/plugins/kibana_react/public'; -import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; +import { SelectOption, SwitchOption } from '../../../../../plugins/charts/public'; import { TagCloudVisParams } from '../types'; function TagCloudOptions({ stateParams, setValue, vis }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/area.ts b/src/legacy/core_plugins/vis_type_vislib/public/area.ts index 68decacaaa040..8a196da64fc4b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/area.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/area.ts @@ -33,13 +33,13 @@ import { AxisTypes, ScaleTypes, AxisModes, - Rotates, ThresholdLineStyles, getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; import { createVislibVisController } from './vis_controller'; import { VisTypeVislibDependencies } from './plugin'; +import { Rotates } from '../../../../plugins/charts/public'; export const createAreaVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ name: 'area', diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/common/index.ts index 05972d101f576..f0bec3167cb7c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/common/index.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/common/index.ts @@ -17,13 +17,5 @@ * under the License. */ -export { BasicOptions } from './basic_options'; -export { ColorRanges } from './color_ranges'; -export { ColorSchemaOptions, SetColorSchemaOptionsValue } from './color_schema'; -export { NumberInputOption } from './number_input'; -export { RangeOption } from './range'; -export { SelectOption } from './select'; -export { SwitchOption } from './switch'; -export { TextInputOption } from './text_input'; export { TruncateLabelsOption } from './truncate_labels'; export { ValidationWrapper, ValidationVisOptionsProps } from './validation_wrapper'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx index b9bae1cad35e7..3fca9dc8adc08 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/labels_panel.tsx @@ -22,7 +22,7 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SwitchOption, TextInputOption } from '../../common'; +import { SwitchOption, TextInputOption } from '../../../../../../../plugins/charts/public'; import { GaugeOptionsInternalProps } from '.'; function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInternalProps) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx index 7de64e5888096..433cc4edeb47b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/ranges_panel.tsx @@ -22,12 +22,16 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ColorRanges, ColorSchemaOptions, SwitchOption } from '../../common'; +import { + ColorRanges, + ColorSchemaOptions, + ColorSchemaParams, + SetColorRangeValue, + SwitchOption, + ColorSchemas, +} from '../../../../../../../plugins/charts/public'; import { GaugeOptionsInternalProps } from '.'; -import { ColorSchemaVislibParams } from '../../../types'; import { Gauge } from '../../../gauge'; -import { SetColorRangeValue } from '../../common/color_ranges'; -import { ColorSchemas } from '../../../../../../../plugins/charts/public'; function RangesPanel({ setGaugeValue, @@ -39,7 +43,7 @@ function RangesPanel({ vis, }: GaugeOptionsInternalProps) { const setColorSchemaOptions = useCallback( - (paramName: T, value: ColorSchemaVislibParams[T]) => { + (paramName: T, value: ColorSchemaParams[T]) => { setGaugeValue(paramName, value as Gauge[T]); // set outline if color schema is changed to greys // if outline wasn't set explicitly yet diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx index 9254c3c18347c..48711de7d171a 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/gauge/style_panel.tsx @@ -22,7 +22,7 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SelectOption } from '../../common'; +import { SelectOption } from '../../../../../../../plugins/charts/public'; import { GaugeOptionsInternalProps } from '.'; import { AggGroupNames } from '../../../../../../../plugins/data/public'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/index.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/index.tsx index 715b5902b69da..dc207ad89286f 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/index.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/index.tsx @@ -31,12 +31,12 @@ import { NumberInputOption, SelectOption, SwitchOption, -} from '../../common'; -import { SetColorSchemaOptionsValue } from '../../common/color_schema'; + SetColorSchemaOptionsValue, + SetColorRangeValue, +} from '../../../../../../../plugins/charts/public'; import { HeatmapVisParams } from '../../../heatmap'; import { ValueAxis } from '../../../types'; import { LabelsPanel } from './labels_panel'; -import { SetColorRangeValue } from '../../common/color_ranges'; function HeatmapOptions(props: VisOptionsProps) { const { stateParams, vis, uiState, setValue, setValidity, setTouched } = props; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx index 38811bd836459..3d1629740df2c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/heatmap/labels_panel.tsx @@ -26,7 +26,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; import { ValueAxis } from '../../../types'; import { HeatmapVisParams } from '../../../heatmap'; -import { SwitchOption } from '../../common'; +import { SwitchOption } from '../../../../../../../plugins/charts/public'; const VERTICAL_ROTATION = 270; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx index 915885388640c..246c20a14807c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/category_axis_panel.tsx @@ -25,7 +25,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; import { Axis } from '../../../types'; -import { SelectOption, SwitchOption } from '../../common'; +import { SelectOption, SwitchOption } from '../../../../../../../plugins/charts/public'; import { LabelOptions, SetAxisLabel } from './label_options'; import { Positions } from '../../../utils/collections'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx index ec7a325ba43d1..89aab3a19c589 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/chart_options.tsx @@ -25,7 +25,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { Vis } from '../../../../../../../plugins/visualizations/public'; import { SeriesParam, ValueAxis } from '../../../types'; import { ChartTypes } from '../../../utils/collections'; -import { SelectOption } from '../../common'; +import { SelectOption } from '../../../../../../../plugins/charts/public'; import { LineOptions } from './line_options'; import { SetParamByIndex, ChangeValueAxis } from './'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx index 53b2ffa55a941..a3a97df9e35ae 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/custom_extents_options.tsx @@ -21,7 +21,7 @@ import React, { useCallback, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { ValueAxis } from '../../../types'; -import { NumberInputOption, SwitchOption } from '../../common'; +import { NumberInputOption, SwitchOption } from '../../../../../../../plugins/charts/public'; import { YExtents } from './y_extents'; import { SetScale } from './value_axis_options'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.tsx index b6b54193e9f4a..bc687e56646f6 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/label_options.tsx @@ -24,8 +24,9 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { Axis } from '../../../types'; -import { SelectOption, SwitchOption, TruncateLabelsOption } from '../../common'; +import { TruncateLabelsOption } from '../../common'; import { getRotateOptions } from '../../../utils/collections'; +import { SelectOption, SwitchOption } from '../../../../../../../plugins/charts/public'; export type SetAxisLabel = ( paramName: T, diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.test.tsx index 1d29d39bfcb7f..5354bc9c033e6 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.test.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { LineOptions, LineOptionsParams } from './line_options'; -import { NumberInputOption } from '../../common'; +import { NumberInputOption } from '../../../../../../../plugins/charts/public'; import { seriesParam, vis } from './mocks'; jest.mock('ui/new_platform'); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx index 01a69a6fac70b..76f95bd93caf8 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/line_options.tsx @@ -24,7 +24,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { Vis } from '../../../../../../../plugins/visualizations/public'; import { SeriesParam } from '../../../types'; -import { NumberInputOption, SelectOption, SwitchOption } from '../../common'; +import { + NumberInputOption, + SelectOption, + SwitchOption, +} from '../../../../../../../plugins/charts/public'; import { SetChart } from './chart_options'; export interface LineOptionsParams { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts index 0d9fa8c25a4f7..a296281375dac 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/mocks.ts @@ -18,7 +18,7 @@ */ import { Vis } from '../../../../../../../plugins/visualizations/public'; -import { Axis, ValueAxis, SeriesParam, Style } from '../../../types'; +import { Axis, ValueAxis, SeriesParam } from '../../../types'; import { ChartTypes, ChartModes, @@ -31,6 +31,7 @@ import { getPositions, getInterpolationModes, } from '../../../utils/collections'; +import { Style } from '../../../../../../../plugins/charts/public'; const defaultValueAxisId = 'ValueAxis-1'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx index 955867e66d09f..876a6917ee0b4 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.test.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { ValueAxisOptions, ValueAxisOptionsParams } from './value_axis_options'; import { ValueAxis } from '../../../types'; -import { TextInputOption } from '../../common'; +import { TextInputOption } from '../../../../../../../plugins/charts/public'; import { LabelOptions } from './label_options'; import { ScaleTypes, Positions } from '../../../utils/collections'; import { valueAxis, vis } from './mocks'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx index 8f0327e78c7ab..1b89a766d0591 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/value_axis_options.tsx @@ -24,7 +24,11 @@ import { EuiSpacer, EuiAccordion, EuiHorizontalRule } from '@elastic/eui'; import { Vis } from '../../../../../../../plugins/visualizations/public'; import { ValueAxis } from '../../../types'; import { Positions } from '../../../utils/collections'; -import { SelectOption, SwitchOption, TextInputOption } from '../../common'; +import { + SelectOption, + SwitchOption, + TextInputOption, +} from '../../../../../../../plugins/charts/public'; import { LabelOptions, SetAxisLabel } from './label_options'; import { CustomExtentsOptions } from './custom_extents_options'; import { isAxisHorizontal } from './utils'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx index 17c47b35b20dc..b5ed475ca8e31 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.test.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; import { YExtents, YExtentsProps } from './y_extents'; import { ScaleTypes } from '../../../utils/collections'; -import { NumberInputOption } from '../../common'; +import { NumberInputOption } from '../../../../../../../plugins/charts/public'; jest.mock('ui/new_platform'); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx index c0db58a612e71..faeb6069b5126 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/metrics_axes/y_extents.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { Scale } from '../../../types'; import { ScaleTypes } from '../../../utils/collections'; -import { NumberInputOption } from '../../common'; +import { NumberInputOption } from '../../../../../../../plugins/charts/public'; import { SetScale } from './value_axis_options'; const rangeError = i18n.translate('visTypeVislib.controls.pointSeries.valueAxes.minErrorMessage', { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/pie.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/pie.tsx index 4c0be456aad64..f6be9cd0bd8fe 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/pie.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/pie.tsx @@ -23,7 +23,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { BasicOptions, TruncateLabelsOption, SwitchOption } from '../common'; +import { TruncateLabelsOption } from '../common'; +import { BasicOptions, SwitchOption } from '../../../../../../plugins/charts/public'; import { PieVisParams } from '../../pie'; function PieOptions(props: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx index bb2b3f8fddb49..392d180d2c5f2 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/grid_panel.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; -import { SelectOption, SwitchOption } from '../../common'; +import { SelectOption, SwitchOption } from '../../../../../../../plugins/charts/public'; import { BasicVislibParams, ValueAxis } from '../../../types'; function GridPanel({ stateParams, setValue, hasHistogramAgg }: VisOptionsProps) { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx index b9872ab94bd0b..903c1917751d9 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/point_series.tsx @@ -21,7 +21,8 @@ import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { BasicOptions, SwitchOption, ValidationVisOptionsProps } from '../../common'; +import { ValidationVisOptionsProps } from '../../common'; +import { BasicOptions, SwitchOption } from '../../../../../../../plugins/charts/public'; import { GridPanel } from './grid_panel'; import { ThresholdPanel } from './threshold_panel'; import { BasicVislibParams } from '../../../types'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx index 7866ad74ede7f..12f058ec7dd1f 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx +++ b/src/legacy/core_plugins/vis_type_vislib/public/components/options/point_series/threshold_panel.tsx @@ -21,8 +21,12 @@ import { EuiPanel, EuiTitle, EuiColorPicker, EuiFormRow, EuiSpacer } from '@elas import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SelectOption, SwitchOption, ValidationVisOptionsProps } from '../../common'; -import { NumberInputOption } from '../../common/required_number_input'; +import { ValidationVisOptionsProps } from '../../common'; +import { + SelectOption, + SwitchOption, + RequiredNumberInputOption, +} from '../../../../../../../plugins/charts/public'; import { BasicVislibParams } from '../../../types'; function ThresholdPanel({ @@ -73,7 +77,7 @@ function ThresholdPanel({ {stateParams.thresholdLine.show && ( <> - - ({ name: 'histogram', diff --git a/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts b/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts index dc47252ccd44f..6f73271726660 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/horizontal_bar.ts @@ -32,13 +32,13 @@ import { AxisTypes, ScaleTypes, AxisModes, - Rotates, ThresholdLineStyles, getConfigCollections, } from './utils/collections'; import { getAreaOptionTabs, countLabel } from './utils/common_config'; import { createVislibVisController } from './vis_controller'; import { VisTypeVislibDependencies } from './plugin'; +import { Rotates } from '../../../../plugins/charts/public'; export const createHorizontalBarVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ name: 'horizontal_bar', diff --git a/src/legacy/core_plugins/vis_type_vislib/public/index.ts b/src/legacy/core_plugins/vis_type_vislib/public/index.ts index 1f773c4efcb02..4d7091ffb204b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/index.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/index.ts @@ -24,18 +24,4 @@ export function plugin(initializerContext: PluginInitializerContext) { return new Plugin(initializerContext); } -export { - BasicOptions, - RangeOption, - ColorRanges, - SelectOption, - SetColorSchemaOptionsValue, - ColorSchemaOptions, - NumberInputOption, - SwitchOption, - TextInputOption, -} from './components'; - -export { ColorModes } from './utils/collections'; - export * from './types'; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/line.ts b/src/legacy/core_plugins/vis_type_vislib/public/line.ts index 885ab295d11e1..1f9a8d77398e6 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/line.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/line.ts @@ -32,7 +32,6 @@ import { AxisTypes, ScaleTypes, AxisModes, - Rotates, ThresholdLineStyles, InterpolationModes, getConfigCollections, @@ -40,6 +39,7 @@ import { import { getAreaOptionTabs, countLabel } from './utils/common_config'; import { createVislibVisController } from './vis_controller'; import { VisTypeVislibDependencies } from './plugin'; +import { Rotates } from '../../../../plugins/charts/public'; export const createLineVisTypeDefinition = (deps: VisTypeVislibDependencies) => ({ name: 'line', diff --git a/src/legacy/core_plugins/vis_type_vislib/public/types.ts b/src/legacy/core_plugins/vis_type_vislib/public/types.ts index f33b42483c53e..25c6ae5439fe8 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/types.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/types.ts @@ -25,39 +25,16 @@ import { AxisModes, AxisTypes, InterpolationModes, - Rotates, ScaleTypes, ThresholdLineStyles, } from './utils/collections'; -import { ColorSchemas } from '../../../../plugins/charts/public'; +import { Labels, Style } from '../../../../plugins/charts/public'; export interface CommonVislibParams { addTooltip: boolean; legendPosition: Positions; } -export interface ColorSchemaVislibParams { - colorSchema: ColorSchemas; - invertColors: boolean; -} - -export interface Labels { - color?: string; - filter?: boolean; - overwriteColor?: boolean; - rotate?: Rotates; - show: boolean; - truncate?: number | null; -} - -export interface Style { - bgFill: string; - bgColor: boolean; - labelColor: boolean; - subText: string; - fontSize: number; -} - export interface Scale { boundsMargin?: number | ''; defaultYExtents?: boolean; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts b/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts index f32b765cd6e57..2024c43dd1c8b 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts +++ b/src/legacy/core_plugins/vis_type_vislib/public/utils/collections.ts @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { $Values } from '@kbn/utility-types'; -import { colorSchemas } from '../../../../../plugins/charts/public'; +import { colorSchemas, Rotates } from '../../../../../plugins/charts/public'; export const Positions = Object.freeze({ RIGHT: 'right' as 'right', @@ -203,13 +203,6 @@ const getAxisModes = () => [ }, ]; -export const Rotates = Object.freeze({ - HORIZONTAL: 0, - VERTICAL: 90, - ANGLED: 75, -}); -export type Rotates = $Values; - export const ThresholdLineStyles = Object.freeze({ FULL: 'full' as 'full', DASHED: 'dashed' as 'dashed', @@ -265,13 +258,6 @@ export const GaugeTypes = Object.freeze({ }); export type GaugeTypes = $Values; -export const ColorModes = Object.freeze({ - BACKGROUND: 'Background' as 'Background', - LABELS: 'Labels' as 'Labels', - NONE: 'None' as 'None', -}); -export type ColorModes = $Values; - const getGaugeTypes = () => [ { text: i18n.translate('visTypeVislib.gauge.gaugeTypes.arcText', { diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx b/src/plugins/charts/public/static/components/basic_options.tsx similarity index 90% rename from src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx rename to src/plugins/charts/public/static/components/basic_options.tsx index baf3e8ecd1b28..cac4c8d70d796 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/common/basic_options.tsx +++ b/src/plugins/charts/public/static/components/basic_options.tsx @@ -37,7 +37,7 @@ function BasicOptions({ return ( <> ({ setValue={setValue} /> ( - setValidity: (paramName: ParamName, isValid: boolean) => void, - paramName: ParamName, - isValid: boolean -) { - useEffect(() => { - setValidity(paramName, isValid); +export const ColorModes = Object.freeze({ + BACKGROUND: 'Background' as 'Background', + LABELS: 'Labels' as 'Labels', + NONE: 'None' as 'None', +}); +export type ColorModes = $Values; - return () => setValidity(paramName, true); - }, [isValid, paramName, setValidity]); -} - -export { useValidation }; +export const Rotates = Object.freeze({ + HORIZONTAL: 0, + VERTICAL: 90, + ANGLED: 75, +}); +export type Rotates = $Values; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/color_ranges.tsx b/src/plugins/charts/public/static/components/color_ranges.tsx similarity index 93% rename from src/legacy/core_plugins/vis_type_vislib/public/components/common/color_ranges.tsx rename to src/plugins/charts/public/static/components/color_ranges.tsx index 84c70f10b12da..a9b05d7d91c7c 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/common/color_ranges.tsx +++ b/src/plugins/charts/public/static/components/color_ranges.tsx @@ -22,10 +22,7 @@ import { last } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { - RangeValues, - RangesParamEditor, -} from '../../../../../../plugins/vis_default_editor/public'; +import { RangeValues, RangesParamEditor } from '../../../../vis_default_editor/public'; export type SetColorRangeValue = (paramName: string, value: RangeValues[]) => void; @@ -74,7 +71,7 @@ function ColorRanges({ return ( ( +export type SetColorSchemaOptionsValue = ( paramName: T, - value: ColorSchemaVislibParams[T] + value: ColorSchemaParams[T] ) => void; -interface ColorSchemaOptionsProps extends ColorSchemaVislibParams { +interface ColorSchemaOptionsProps extends ColorSchemaParams { disabled?: boolean; colorSchemas: ColorSchema[]; uiState: VisOptionsProps['uiState']; @@ -67,7 +67,7 @@ function ColorSchemaOptions({ }} >
@@ -80,11 +80,11 @@ function ColorSchemaOptions({ disabled={disabled} helpText={ showHelpText && - i18n.translate('visTypeVislib.controls.colorSchema.howToChangeColorsDescription', { + i18n.translate('charts.controls.colorSchema.howToChangeColorsDescription', { defaultMessage: 'Individual colors can be changed in the legend.', }) } - label={i18n.translate('visTypeVislib.controls.colorSchema.colorSchemaLabel', { + label={i18n.translate('charts.controls.colorSchema.colorSchemaLabel', { defaultMessage: 'Color schema', })} labelAppend={isCustomColors && resetColorsButton} @@ -96,7 +96,7 @@ function ColorSchemaOptions({ ({ const [stateValue, setStateValue] = useState(value); const [isValidState, setIsValidState] = useState(true); - const error = i18n.translate('visTypeVislib.controls.rangeErrorMessage', { + const error = i18n.translate('charts.controls.rangeErrorMessage', { defaultMessage: 'Values must be on or between {min} and {max}', values: { min, max }, }); diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/required_number_input.tsx b/src/plugins/charts/public/static/components/required_number_input.tsx similarity index 87% rename from src/legacy/core_plugins/vis_type_vislib/public/components/common/required_number_input.tsx rename to src/plugins/charts/public/static/components/required_number_input.tsx index 7b62016c4e502..7594c775b07ad 100644 --- a/src/legacy/core_plugins/vis_type_vislib/public/components/common/required_number_input.tsx +++ b/src/plugins/charts/public/static/components/required_number_input.tsx @@ -17,9 +17,8 @@ * under the License. */ -import React, { ReactNode, useCallback, ChangeEvent } from 'react'; +import React, { ReactNode, useCallback, ChangeEvent, useEffect } from 'react'; import { EuiFormRow, EuiFieldNumber } from '@elastic/eui'; -import { useValidation } from './utils'; interface NumberInputOptionProps { disabled?: boolean; @@ -42,7 +41,7 @@ interface NumberInputOptionProps { * * @param {number} props.value Should be numeric only */ -function NumberInputOption({ +function RequiredNumberInputOption({ disabled, error, isInvalid, @@ -57,7 +56,12 @@ function NumberInputOption({ 'data-test-subj': dataTestSubj, }: NumberInputOptionProps) { const isValid = value !== null; - useValidation(setValidity, paramName, isValid); + + useEffect(() => { + setValidity(paramName, isValid); + + return () => setValidity(paramName, true); + }, [isValid, paramName, setValidity]); const onChange = useCallback( (ev: ChangeEvent) => @@ -84,4 +88,4 @@ function NumberInputOption({ ); } -export { NumberInputOption }; +export { RequiredNumberInputOption }; diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx b/src/plugins/charts/public/static/components/select.tsx similarity index 100% rename from src/legacy/core_plugins/vis_type_vislib/public/components/common/select.tsx rename to src/plugins/charts/public/static/components/select.tsx diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/switch.tsx b/src/plugins/charts/public/static/components/switch.tsx similarity index 100% rename from src/legacy/core_plugins/vis_type_vislib/public/components/common/switch.tsx rename to src/plugins/charts/public/static/components/switch.tsx diff --git a/src/legacy/core_plugins/vis_type_vislib/public/components/common/text_input.tsx b/src/plugins/charts/public/static/components/text_input.tsx similarity index 100% rename from src/legacy/core_plugins/vis_type_vislib/public/components/common/text_input.tsx rename to src/plugins/charts/public/static/components/text_input.tsx diff --git a/src/plugins/charts/public/static/components/types.ts b/src/plugins/charts/public/static/components/types.ts new file mode 100644 index 0000000000000..196eb60b06aec --- /dev/null +++ b/src/plugins/charts/public/static/components/types.ts @@ -0,0 +1,43 @@ +/* + * 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 { ColorSchemas } from '../color_maps'; +import { Rotates } from './collections'; + +export interface ColorSchemaParams { + colorSchema: ColorSchemas; + invertColors: boolean; +} + +export interface Labels { + color?: string; + filter?: boolean; + overwriteColor?: boolean; + rotate?: Rotates; + show: boolean; + truncate?: number | null; +} + +export interface Style { + bgFill: string; + bgColor: boolean; + labelColor: boolean; + subText: string; + fontSize: number; +} diff --git a/src/plugins/charts/public/static/index.ts b/src/plugins/charts/public/static/index.ts index bee58e4f1e3e1..6fc097d05467f 100644 --- a/src/plugins/charts/public/static/index.ts +++ b/src/plugins/charts/public/static/index.ts @@ -18,3 +18,4 @@ */ export * from './color_maps'; +export * from './components'; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c07ec68e99b4f..09903c34e2e5e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -130,6 +130,14 @@ "charts.colormaps.greysText": "グレー", "charts.colormaps.redsText": "赤", "charts.colormaps.yellowToRedText": "黄色から赤", + "charts.controls.colorRanges.errorText": "各範囲は前の範囲よりも大きくなければなりません。", + "charts.controls.colorSchema.colorSchemaLabel": "配色", + "charts.controls.colorSchema.howToChangeColorsDescription": "それぞれの色は凡例で変更できます。", + "charts.controls.colorSchema.resetColorsButtonLabel": "色をリセット", + "charts.controls.colorSchema.reverseColorSchemaLabel": "図表を反転", + "charts.controls.rangeErrorMessage": "値は {min} と {max} の間でなければなりません", + "charts.controls.vislibBasicOptions.legendPositionLabel": "凡例位置", + "charts.controls.vislibBasicOptions.showTooltipLabel": "ツールヒントを表示", "common.ui.errorAutoCreateIndex.breadcrumbs.errorText": "エラー", "common.ui.errorAutoCreateIndex.errorDescription": "Elasticsearch クラスターの {autoCreateIndexActionConfig} 設定が原因で、Kibana が保存されたオブジェクトを格納するインデックスを自動的に作成できないようです。Kibana は、保存されたオブジェクトインデックスが適切なマッピング/スキーマを使用し Kibana から Elasticsearch へのポーリングの回数を減らすための最適な手段であるため、この Elasticsearch の機能を使用します。", "common.ui.errorAutoCreateIndex.errorDisclaimer": "申し訳ございませんが、この問題が解決されるまで Kibana で何も保存することができません。", @@ -3831,11 +3839,6 @@ "visTypeVislib.chartTypes.areaText": "エリア", "visTypeVislib.chartTypes.barText": "バー", "visTypeVislib.chartTypes.lineText": "折れ線", - "visTypeVislib.controls.colorRanges.errorText": "各範囲は前の範囲よりも大きくなければなりません。", - "visTypeVislib.controls.colorSchema.colorSchemaLabel": "配色", - "visTypeVislib.controls.colorSchema.howToChangeColorsDescription": "それぞれの色は凡例で変更できます。", - "visTypeVislib.controls.colorSchema.resetColorsButtonLabel": "色をリセット", - "visTypeVislib.controls.colorSchema.reverseColorSchemaLabel": "図表を反転", "visTypeVislib.controls.gaugeOptions.alignmentLabel": "アラインメント", "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張", "visTypeVislib.controls.gaugeOptions.displayWarningsLabel": "警告を表示", @@ -3902,10 +3905,7 @@ "visTypeVislib.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "カスタム範囲を切り替える", "visTypeVislib.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "{axisName} オプションを切り替える", "visTypeVislib.controls.pointSeries.valueAxes.yAxisTitle": "Y 軸", - "visTypeVislib.controls.rangeErrorMessage": "値は {min} と {max} の間でなければなりません", "visTypeVislib.controls.truncateLabel": "切り捨て", - "visTypeVislib.controls.vislibBasicOptions.legendPositionLabel": "凡例位置", - "visTypeVislib.controls.vislibBasicOptions.showTooltipLabel": "ツールヒントを表示", "visTypeVislib.editors.heatmap.basicSettingsTitle": "基本設定", "visTypeVislib.editors.heatmap.heatmapSettingsTitle": "ヒートマップ設定", "visTypeVislib.editors.heatmap.highlightLabel": "ハイライト範囲", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index de8aaa75632ee..cc1b7d7980a0b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -130,6 +130,14 @@ "charts.colormaps.greysText": "灰色", "charts.colormaps.redsText": "红色", "charts.colormaps.yellowToRedText": "黄到红", + "charts.controls.colorRanges.errorText": "每个范围应大于前一范围。", + "charts.controls.colorSchema.colorSchemaLabel": "颜色模式", + "charts.controls.colorSchema.howToChangeColorsDescription": "可以更改图例中的各个颜色。", + "charts.controls.colorSchema.resetColorsButtonLabel": "重置颜色", + "charts.controls.colorSchema.reverseColorSchemaLabel": "反转模式", + "charts.controls.rangeErrorMessage": "值必须是在 {min} 到 {max} 的范围内", + "charts.controls.vislibBasicOptions.legendPositionLabel": "图例位置", + "charts.controls.vislibBasicOptions.showTooltipLabel": "显示工具提示", "common.ui.errorAutoCreateIndex.breadcrumbs.errorText": "错误", "common.ui.errorAutoCreateIndex.errorDescription": "似乎 Elasticsearch 集群的 {autoCreateIndexActionConfig} 设置使 Kibana 无法自动创建用于存储已保存对象的索引。Kibana 将使用此 Elasticsearch 功能,因为这是确保已保存对象索引使用正确映射/架构的最好方式,而且其允许 Kibana 较少地轮询 Elasticsearch。", "common.ui.errorAutoCreateIndex.errorDisclaimer": "但是,只有解决了此问题后,您才能在 Kibana 保存内容。", @@ -3832,11 +3840,6 @@ "visTypeVislib.chartTypes.areaText": "面积图", "visTypeVislib.chartTypes.barText": "条形图", "visTypeVislib.chartTypes.lineText": "折线图", - "visTypeVislib.controls.colorRanges.errorText": "每个范围应大于前一范围。", - "visTypeVislib.controls.colorSchema.colorSchemaLabel": "颜色模式", - "visTypeVislib.controls.colorSchema.howToChangeColorsDescription": "可以更改图例中的各个颜色。", - "visTypeVislib.controls.colorSchema.resetColorsButtonLabel": "重置颜色", - "visTypeVislib.controls.colorSchema.reverseColorSchemaLabel": "反转模式", "visTypeVislib.controls.gaugeOptions.alignmentLabel": "对齐方式", "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "自动扩展范围", "visTypeVislib.controls.gaugeOptions.displayWarningsLabel": "显示警告", @@ -3903,10 +3906,7 @@ "visTypeVislib.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "切换定制范围", "visTypeVislib.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "切换 {axisName} 选项", "visTypeVislib.controls.pointSeries.valueAxes.yAxisTitle": "Y 轴", - "visTypeVislib.controls.rangeErrorMessage": "值必须是在 {min} 到 {max} 的范围内", "visTypeVislib.controls.truncateLabel": "截断", - "visTypeVislib.controls.vislibBasicOptions.legendPositionLabel": "图例位置", - "visTypeVislib.controls.vislibBasicOptions.showTooltipLabel": "显示工具提示", "visTypeVislib.editors.heatmap.basicSettingsTitle": "基本设置", "visTypeVislib.editors.heatmap.heatmapSettingsTitle": "热图设置", "visTypeVislib.editors.heatmap.highlightLabel": "高亮范围", From 36acb373876f3c6ea5077caae81d3a1cad239dfd Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Fri, 10 Apr 2020 11:18:12 -0400 Subject: [PATCH 037/121] Make uptime alert flyout test a little more resilient (#62702) --- .../apps/uptime/alert_flyout.ts | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts index 2a0358160da51..3e5a8c57c4c7e 100644 --- a/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/uptime/alert_flyout.ts @@ -33,7 +33,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // put the fetch code in a retry block with a timeout. let alert: any; await retry.tryForTime(15000, async () => { - const apiResponse = await supertest.get('/api/alert/_find'); + const apiResponse = await supertest.get('/api/alert/_find?search=uptime-test'); const alertsFromThisTest = apiResponse.body.data.filter( ({ name }: { name: string }) => name === 'uptime-test' ); @@ -54,25 +54,27 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { tags, } = alert; - // we're not testing the flyout's ability to associate alerts with action connectors - expect(actions).to.eql([]); + try { + // we're not testing the flyout's ability to associate alerts with action connectors + expect(actions).to.eql([]); - expect(alertTypeId).to.eql('xpack.uptime.alerts.monitorStatus'); - expect(consumer).to.eql('uptime'); - expect(interval).to.eql('11m'); - expect(tags).to.eql(['uptime', 'another']); - expect(numTimes).to.be(3); - expect(timerange.from).to.be('now-1h'); - expect(timerange.to).to.be('now'); - expect(locations).to.eql(['mpls']); - expect(filters).to.eql( - '{"bool":{"should":[{"match_phrase":{"monitor.id":"0001-up"}}],"minimum_should_match":1}}' - ); - - await supertest - .delete(`/api/alert/${id}`) - .set('kbn-xsrf', 'true') - .expect(204); + expect(alertTypeId).to.eql('xpack.uptime.alerts.monitorStatus'); + expect(consumer).to.eql('uptime'); + expect(interval).to.eql('11m'); + expect(tags).to.eql(['uptime', 'another']); + expect(numTimes).to.be(3); + expect(timerange.from).to.be('now-1h'); + expect(timerange.to).to.be('now'); + expect(locations).to.eql(['mpls']); + expect(filters).to.eql( + '{"bool":{"should":[{"match_phrase":{"monitor.id":"0001-up"}}],"minimum_should_match":1}}' + ); + } finally { + await supertest + .delete(`/api/alert/${id}`) + .set('kbn-xsrf', 'true') + .expect(204); + } }); }); }; From 55a3cc45835ccf267c06c2d0d62000027d2bf006 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Fri, 10 Apr 2020 09:55:38 -0600 Subject: [PATCH 038/121] [SIEM] [Cases] Unit tests for case UI components (#63005) --- .../components/filter_popover/index.tsx | 1 + .../components/header_page/editable_title.tsx | 9 +- .../siem/public/containers/case/api.ts | 4 +- .../case/configure/use_configure.tsx | 4 +- .../plugins/siem/public/pages/case/case.tsx | 9 +- .../siem/public/pages/case/case_details.tsx | 6 +- .../case/components/__mock__/case_data.tsx | 226 ++++++++++++ .../pages/case/components/__mock__/form.ts | 37 ++ .../pages/case/components/__mock__/router.ts | 39 +++ .../components/add_comment/index.test.tsx | 144 ++++++++ .../case/components/add_comment/index.tsx | 6 +- .../components/all_cases/__mock__/index.tsx | 115 ------ .../components/all_cases/columns.test.tsx | 48 +++ .../case/components/all_cases/columns.tsx | 14 +- .../case/components/all_cases/index.test.tsx | 66 +++- .../all_cases/table_filters.test.tsx | 121 +++++++ .../components/all_cases/table_filters.tsx | 7 +- .../case/components/all_cases/translations.ts | 4 + .../pages/case/components/callout/helpers.tsx | 4 +- .../case/components/callout/index.test.tsx | 71 ++++ .../pages/case/components/callout/index.tsx | 10 +- .../case/components/case_status/index.tsx | 2 +- .../components/case_view/__mock__/index.tsx | 93 ----- .../components/case_view/actions.test.tsx | 10 +- .../case/components/case_view/actions.tsx | 1 - .../case/components/case_view/index.test.tsx | 320 +++++++++++++---- .../pages/case/components/case_view/index.tsx | 8 +- .../case/components/create/index.test.tsx | 121 +++++++ .../pages/case/components/create/index.tsx | 7 +- .../case/components/tag_list/index.test.tsx | 138 ++++++++ .../pages/case/components/tag_list/index.tsx | 17 +- .../use_push_to_service/index.test.tsx | 192 ++++++++++ .../components/use_push_to_service/index.tsx | 5 +- .../user_action_tree/helpers.test.tsx | 143 ++++++++ .../components/user_action_tree/helpers.tsx | 12 +- .../user_action_tree/index.test.tsx | 331 ++++++++++++++++++ .../components/user_action_tree/index.tsx | 10 +- .../user_action_tree/user_action_item.tsx | 15 +- .../user_action_tree/user_action_markdown.tsx | 20 +- .../user_action_title.test.tsx | 57 +++ .../user_action_tree/user_action_title.tsx | 16 +- .../siem/public/pages/case/translations.ts | 4 + .../scripts/generate_case_and_comment_data.sh | 6 +- .../case/server/scripts/generate_case_data.sh | 4 +- 44 files changed, 2117 insertions(+), 360 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/form.ts create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/router.ts create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.test.tsx delete mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/__mock__/index.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.test.tsx delete mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/create/index.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx diff --git a/x-pack/legacy/plugins/siem/public/components/filter_popover/index.tsx b/x-pack/legacy/plugins/siem/public/components/filter_popover/index.tsx index 3c01ec18a879f..fca6396a53745 100644 --- a/x-pack/legacy/plugins/siem/public/components/filter_popover/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/filter_popover/index.tsx @@ -89,6 +89,7 @@ export const FilterPopoverComponent = ({ {options.map((option, index) => ( diff --git a/x-pack/legacy/plugins/siem/public/components/header_page/editable_title.tsx b/x-pack/legacy/plugins/siem/public/components/header_page/editable_title.tsx index 165be00384779..0c6f7258d09dc 100644 --- a/x-pack/legacy/plugins/siem/public/components/header_page/editable_title.tsx +++ b/x-pack/legacy/plugins/siem/public/components/header_page/editable_title.tsx @@ -60,12 +60,9 @@ const EditableTitleComponent: React.FC = ({ }, [changedTitle, title]); const handleOnChange = useCallback( - (e: ChangeEvent) => { - onTitleChange(e.target.value); - }, - [onTitleChange] + (e: ChangeEvent) => onTitleChange(e.target.value), + [] ); - return editMode ? ( @@ -107,7 +104,7 @@ const EditableTitleComponent: React.FC = ({ </EuiFlexItem> <EuiFlexItem grow={false}> - {isLoading && <MySpinner />} + {isLoading && <MySpinner data-test-subj="editable-title-loading" />} {!isLoading && ( <MyEuiButtonIcon isDisabled={disabled} diff --git a/x-pack/legacy/plugins/siem/public/containers/case/api.ts b/x-pack/legacy/plugins/siem/public/containers/case/api.ts index 69e1602b3d981..12b4c80a2dd89 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/api.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/api.ts @@ -204,13 +204,13 @@ export const patchComment = async ( return convertToCamelCase<CaseResponse, Case>(decodeCaseResponse(response)); }; -export const deleteCases = async (caseIds: string[], signal: AbortSignal): Promise<boolean> => { +export const deleteCases = async (caseIds: string[], signal: AbortSignal): Promise<string> => { const response = await KibanaServices.get().http.fetch<string>(CASES_URL, { method: 'DELETE', query: { ids: JSON.stringify(caseIds) }, signal, }); - return response === 'true' ? true : false; + return response; }; export const pushCase = async ( diff --git a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx index 7f57149d4e56d..1c03a09a8c2ea 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/configure/use_configure.tsx @@ -55,7 +55,6 @@ export const useCaseConfigure = ({ setLoading(true); const res = await getCaseConfigure({ signal: abortCtrl.signal }); if (!didCancel) { - setLoading(false); if (res != null) { setConnector(res.connectorId, res.connectorName); if (setClosureType != null) { @@ -73,6 +72,7 @@ export const useCaseConfigure = ({ } } } + setLoading(false); } } catch (error) { if (!didCancel) { @@ -117,7 +117,6 @@ export const useCaseConfigure = ({ abortCtrl.signal ); if (!didCancel) { - setPersistLoading(false); setConnector(res.connectorId); if (setClosureType) { setClosureType(res.closureType); @@ -131,6 +130,7 @@ export const useCaseConfigure = ({ } displaySuccessToast(i18n.SUCCESS_CONFIGURE, dispatchToaster); + setPersistLoading(false); } } catch (error) { if (!didCancel) { diff --git a/x-pack/legacy/plugins/siem/public/pages/case/case.tsx b/x-pack/legacy/plugins/siem/public/pages/case/case.tsx index 2ae35796387b8..aefb0a93366b8 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/case.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/case.tsx @@ -11,11 +11,9 @@ import { useGetUserSavedObjectPermissions } from '../../lib/kibana'; import { SpyRoute } from '../../utils/route/spy_routes'; import { AllCases } from './components/all_cases'; -import { getSavedObjectReadOnly, CaseCallOut } from './components/callout'; +import { savedObjectReadOnly, CaseCallOut } from './components/callout'; import { CaseSavedObjectNoPermissions } from './saved_object_no_permissions'; -const infoReadSavedObject = getSavedObjectReadOnly(); - export const CasesPage = React.memo(() => { const userPermissions = useGetUserSavedObjectPermissions(); @@ -24,10 +22,11 @@ export const CasesPage = React.memo(() => { <WrapperPage> {userPermissions != null && !userPermissions?.crud && userPermissions?.read && ( <CaseCallOut - title={infoReadSavedObject.title} - message={infoReadSavedObject.description} + title={savedObjectReadOnly.title} + message={savedObjectReadOnly.description} /> )} + <CaseCallOut title={savedObjectReadOnly.title} message={savedObjectReadOnly.description} /> <AllCases userCanCrud={userPermissions?.crud ?? false} /> </WrapperPage> <SpyRoute /> diff --git a/x-pack/legacy/plugins/siem/public/pages/case/case_details.tsx b/x-pack/legacy/plugins/siem/public/pages/case/case_details.tsx index cbc7bbc62fbf9..4bb8afa7f8d42 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/case_details.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/case_details.tsx @@ -13,9 +13,7 @@ import { SpyRoute } from '../../utils/route/spy_routes'; import { getCaseUrl } from '../../components/link_to'; import { navTabs } from '../home/home_navigations'; import { CaseView } from './components/case_view'; -import { getSavedObjectReadOnly, CaseCallOut } from './components/callout'; - -const infoReadSavedObject = getSavedObjectReadOnly(); +import { savedObjectReadOnly, CaseCallOut } from './components/callout'; export const CaseDetailsPage = React.memo(() => { const userPermissions = useGetUserSavedObjectPermissions(); @@ -29,7 +27,7 @@ export const CaseDetailsPage = React.memo(() => { return caseId != null ? ( <> {userPermissions != null && !userPermissions?.crud && userPermissions?.read && ( - <CaseCallOut title={infoReadSavedObject.title} message={infoReadSavedObject.description} /> + <CaseCallOut title={savedObjectReadOnly.title} message={savedObjectReadOnly.description} /> )} <CaseView caseId={caseId} userCanCrud={userPermissions?.crud ?? false} /> <SpyRoute /> diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx new file mode 100644 index 0000000000000..64c6276fc1be2 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx @@ -0,0 +1,226 @@ +/* + * 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 { CaseProps } from '../case_view'; +import { Case, Comment, SortFieldCase } from '../../../../containers/case/types'; +import { UseGetCasesState } from '../../../../containers/case/use_get_cases'; +import { UserAction, UserActionField } from '../../../../../../../../plugins/case/common/api/cases'; + +const updateCase = jest.fn(); +const fetchCase = jest.fn(); + +const basicCaseId = 'basic-case-id'; +const basicCommentId = 'basic-comment-id'; +const basicCreatedAt = '2020-02-20T23:06:33.798Z'; +const elasticUser = { + fullName: 'Leslie Knope', + username: 'lknope', + email: 'leslie.knope@elastic.co', +}; + +export const basicComment: Comment = { + comment: 'Solve this fast!', + id: basicCommentId, + createdAt: basicCreatedAt, + createdBy: elasticUser, + pushedAt: null, + pushedBy: null, + updatedAt: '2020-02-20T23:06:33.798Z', + updatedBy: { + username: 'elastic', + }, + version: 'WzQ3LDFc', +}; + +export const basicCase: Case = { + closedAt: null, + closedBy: null, + id: basicCaseId, + comments: [basicComment], + createdAt: '2020-02-13T19:44:23.627Z', + createdBy: elasticUser, + description: 'Security banana Issue', + externalService: null, + status: 'open', + tags: ['defacement'], + title: 'Another horrible breach!!', + totalComment: 1, + updatedAt: '2020-02-19T15:02:57.995Z', + updatedBy: { + username: 'elastic', + }, + version: 'WzQ3LDFd', +}; + +export const caseProps: CaseProps = { + caseId: basicCaseId, + userCanCrud: true, + caseData: basicCase, + fetchCase, + updateCase, +}; + +export const caseClosedProps: CaseProps = { + ...caseProps, + caseData: { + ...caseProps.caseData, + closedAt: '2020-02-20T23:06:33.798Z', + closedBy: { + username: 'elastic', + }, + status: 'closed', + }, +}; + +export const basicCaseClosed: Case = { + ...caseClosedProps.caseData, +}; + +const basicAction = { + actionAt: basicCreatedAt, + actionBy: elasticUser, + oldValue: null, + newValue: 'what a cool value', + caseId: basicCaseId, + commentId: null, +}; +export const caseUserActions = [ + { + ...basicAction, + actionBy: elasticUser, + actionField: ['comment'], + action: 'create', + actionId: 'tt', + }, +]; + +export const useGetCasesMockState: UseGetCasesState = { + data: { + countClosedCases: 0, + countOpenCases: 5, + cases: [ + basicCase, + { + closedAt: null, + closedBy: null, + id: '362a5c10-4e99-11ea-9290-35d05cb55c15', + createdAt: '2020-02-13T19:44:13.328Z', + createdBy: { username: 'elastic' }, + comments: [], + description: 'Security banana Issue', + externalService: { + pushedAt: '2020-02-13T19:45:01.901Z', + pushedBy: 'elastic', + connectorId: 'string', + connectorName: 'string', + externalId: 'string', + externalTitle: 'string', + externalUrl: 'string', + }, + status: 'open', + tags: ['phishing'], + title: 'Bad email', + totalComment: 0, + updatedAt: '2020-02-13T15:45:01.901Z', + updatedBy: { username: 'elastic' }, + version: 'WzQ3LDFd', + }, + { + closedAt: null, + closedBy: null, + id: '34f8b9e0-4e99-11ea-9290-35d05cb55c15', + createdAt: '2020-02-13T19:44:11.328Z', + createdBy: { username: 'elastic' }, + comments: [], + description: 'Security banana Issue', + externalService: { + pushedAt: '2020-02-13T19:45:01.901Z', + pushedBy: 'elastic', + connectorId: 'string', + connectorName: 'string', + externalId: 'string', + externalTitle: 'string', + externalUrl: 'string', + }, + status: 'open', + tags: ['phishing'], + title: 'Bad email', + totalComment: 0, + updatedAt: '2020-02-14T19:45:01.901Z', + updatedBy: { username: 'elastic' }, + version: 'WzQ3LDFd', + }, + { + closedAt: '2020-02-13T19:44:13.328Z', + closedBy: { username: 'elastic' }, + id: '31890e90-4e99-11ea-9290-35d05cb55c15', + createdAt: '2020-02-13T19:44:05.563Z', + createdBy: { username: 'elastic' }, + comments: [], + description: 'Security banana Issue', + externalService: null, + status: 'closed', + tags: ['phishing'], + title: 'Uh oh', + totalComment: 0, + updatedAt: null, + updatedBy: null, + version: 'WzQ3LDFd', + }, + { + closedAt: null, + closedBy: null, + id: '2f5b3210-4e99-11ea-9290-35d05cb55c15', + createdAt: '2020-02-13T19:44:01.901Z', + createdBy: { username: 'elastic' }, + comments: [], + description: 'Security banana Issue', + externalService: null, + status: 'open', + tags: ['phishing'], + title: 'Uh oh', + totalComment: 0, + updatedAt: null, + updatedBy: null, + version: 'WzQ3LDFd', + }, + ], + page: 1, + perPage: 5, + total: 10, + }, + loading: [], + selectedCases: [], + isError: false, + queryParams: { + page: 1, + perPage: 5, + sortField: SortFieldCase.createdAt, + sortOrder: 'desc', + }, + filterOptions: { search: '', reporters: [], tags: [], status: 'open' }, +}; + +const basicPush = { + connector_id: 'connector_id', + connector_name: 'connector name', + external_id: 'external_id', + external_title: 'external title', + external_url: 'basicPush.com', + pushed_at: basicCreatedAt, + pushed_by: elasticUser, +}; +export const getUserAction = (af: UserActionField, a: UserAction) => ({ + ...basicAction, + actionId: `${af[0]}-${a}`, + actionField: af, + action: a, + commentId: af[0] === 'comment' ? basicCommentId : null, + newValue: + a === 'push-to-service' && af[0] === 'pushed' + ? JSON.stringify(basicPush) + : basicAction.newValue, +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/form.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/form.ts new file mode 100644 index 0000000000000..9d2ac29bc47d7 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/form.ts @@ -0,0 +1,37 @@ +/* + * 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 mockFormHook = { + isSubmitted: false, + isSubmitting: false, + isValid: true, + submit: jest.fn(), + subscribe: jest.fn(), + setFieldValue: jest.fn(), + setFieldErrors: jest.fn(), + getFields: jest.fn(), + getFormData: jest.fn(), + getFieldDefaultValue: jest.fn(), + /* Returns a list of all errors in the form */ + getErrors: jest.fn(), + reset: jest.fn(), + __options: {}, + __formData$: {}, + __addField: jest.fn(), + __removeField: jest.fn(), + __validateFields: jest.fn(), + __updateFormDataAt: jest.fn(), + __readFieldConfigFromSchema: jest.fn(), +}; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const getFormMock = (sampleData: any) => ({ + ...mockFormHook, + submit: () => + Promise.resolve({ + data: sampleData, + isValid: true, + }), + getFormData: () => sampleData, +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/router.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/router.ts new file mode 100644 index 0000000000000..a20ab00852a36 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/router.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 { Router } from 'react-router-dom'; +// eslint-disable-next-line @kbn/eslint/module_migration +import routeData from 'react-router'; +type Action = 'PUSH' | 'POP' | 'REPLACE'; +const pop: Action = 'POP'; +const location = { + pathname: '/network', + search: '', + state: '', + hash: '', +}; +export const mockHistory = { + length: 2, + location, + action: pop, + push: jest.fn(), + replace: jest.fn(), + go: jest.fn(), + goBack: jest.fn(), + goForward: jest.fn(), + block: jest.fn(), + createHref: jest.fn(), + listen: jest.fn(), +}; + +export const mockLocation = { + pathname: '/welcome', + hash: '', + search: '', + state: '', +}; + +export { Router, routeData }; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.test.tsx new file mode 100644 index 0000000000000..74f6411f17fa0 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.test.tsx @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { AddComment } from './'; +import { TestProviders } from '../../../../mock'; +import { getFormMock } from '../__mock__/form'; +import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router'; + +import { useInsertTimeline } from '../../../../components/timeline/insert_timeline_popover/use_insert_timeline'; +import { usePostComment } from '../../../../containers/case/use_post_comment'; +import { useForm } from '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form'; +import { wait } from '../../../../lib/helpers'; +jest.mock( + '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form' +); +jest.mock('../../../../components/timeline/insert_timeline_popover/use_insert_timeline'); +jest.mock('../../../../containers/case/use_post_comment'); + +export const useFormMock = useForm as jest.Mock; + +const useInsertTimelineMock = useInsertTimeline as jest.Mock; +const usePostCommentMock = usePostComment as jest.Mock; + +const onCommentSaving = jest.fn(); +const onCommentPosted = jest.fn(); +const postComment = jest.fn(); +const handleCursorChange = jest.fn(); +const handleOnTimelineChange = jest.fn(); + +const addCommentProps = { + caseId: '1234', + disabled: false, + insertQuote: null, + onCommentSaving, + onCommentPosted, + showLoading: false, +}; + +const defaultInsertTimeline = { + cursorPosition: { + start: 0, + end: 0, + }, + handleCursorChange, + handleOnTimelineChange, +}; + +const defaultPostCommment = { + isLoading: false, + isError: false, + postComment, +}; +const sampleData = { + comment: 'what a cool comment', +}; +describe('AddComment ', () => { + const formHookMock = getFormMock(sampleData); + + beforeEach(() => { + jest.resetAllMocks(); + useInsertTimelineMock.mockImplementation(() => defaultInsertTimeline); + usePostCommentMock.mockImplementation(() => defaultPostCommment); + useFormMock.mockImplementation(() => ({ form: formHookMock })); + jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation); + }); + + it('should post comment on submit click', async () => { + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <AddComment {...addCommentProps} /> + </Router> + </TestProviders> + ); + expect(wrapper.find(`[data-test-subj="add-comment"]`).exists()).toBeTruthy(); + expect(wrapper.find(`[data-test-subj="loading-spinner"]`).exists()).toBeFalsy(); + + wrapper + .find(`[data-test-subj="submit-comment"]`) + .first() + .simulate('click'); + await wait(); + expect(onCommentSaving).toBeCalled(); + expect(postComment).toBeCalledWith(sampleData, onCommentPosted); + expect(formHookMock.reset).toBeCalled(); + }); + + it('should render spinner and disable submit when loading', () => { + usePostCommentMock.mockImplementation(() => ({ ...defaultPostCommment, isLoading: true })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <AddComment {...{ ...addCommentProps, showLoading: true }} /> + </Router> + </TestProviders> + ); + expect(wrapper.find(`[data-test-subj="loading-spinner"]`).exists()).toBeTruthy(); + expect( + wrapper + .find(`[data-test-subj="submit-comment"]`) + .first() + .prop('isDisabled') + ).toBeTruthy(); + }); + + it('should disable submit button when disabled prop passed', () => { + usePostCommentMock.mockImplementation(() => ({ ...defaultPostCommment, isLoading: true })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <AddComment {...{ ...addCommentProps, disabled: true }} /> + </Router> + </TestProviders> + ); + expect( + wrapper + .find(`[data-test-subj="submit-comment"]`) + .first() + .prop('isDisabled') + ).toBeTruthy(); + }); + + it('should insert a quote if one is available', () => { + const sampleQuote = 'what a cool quote'; + mount( + <TestProviders> + <Router history={mockHistory}> + <AddComment {...{ ...addCommentProps, insertQuote: sampleQuote }} /> + </Router> + </TestProviders> + ); + + expect(formHookMock.setFieldValue).toBeCalledWith( + 'comment', + `${sampleData.comment}\n\n${sampleQuote}` + ); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx index ecc57c50e28eb..eaba708948a99 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/add_comment/index.tsx @@ -71,10 +71,9 @@ export const AddComment = React.memo<AddCommentProps>( form.reset(); } }, [form, onCommentPosted, onCommentSaving]); - return ( <span id="add-comment-permLink"> - {isLoading && showLoading && <MySpinner size="xl" />} + {isLoading && showLoading && <MySpinner data-test-subj="loading-spinner" size="xl" />} <Form form={form}> <UseField path="comment" @@ -82,11 +81,12 @@ export const AddComment = React.memo<AddCommentProps>( componentProps={{ idAria: 'caseComment', isDisabled: isLoading, - dataTestSubj: 'caseComment', + dataTestSubj: 'add-comment', placeholder: i18n.ADD_COMMENT_HELP_TEXT, onCursorPositionUpdate: handleCursorChange, bottomRightContent: ( <EuiButton + data-test-subj="submit-comment" iconType="plusInCircle" isDisabled={isLoading || disabled} isLoading={isLoading} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/__mock__/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/__mock__/index.tsx deleted file mode 100644 index d4ec32dfd070b..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/__mock__/index.tsx +++ /dev/null @@ -1,115 +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 { SortFieldCase } from '../../../../../containers/case/types'; -import { UseGetCasesState } from '../../../../../containers/case/use_get_cases'; - -export const useGetCasesMockState: UseGetCasesState = { - data: { - countClosedCases: 0, - countOpenCases: 5, - cases: [ - { - closedAt: null, - closedBy: null, - id: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:23.627Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: null, - status: 'open', - tags: ['defacement'], - title: 'Another horrible breach', - totalComment: 0, - updatedAt: null, - updatedBy: null, - version: 'WzQ3LDFd', - }, - { - closedAt: null, - closedBy: null, - id: '362a5c10-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:13.328Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: null, - status: 'open', - tags: ['phishing'], - title: 'Bad email', - totalComment: 0, - updatedAt: null, - updatedBy: null, - version: 'WzQ3LDFd', - }, - { - closedAt: null, - closedBy: null, - id: '34f8b9e0-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:11.328Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: null, - status: 'open', - tags: ['phishing'], - title: 'Bad email', - totalComment: 0, - updatedAt: null, - updatedBy: null, - version: 'WzQ3LDFd', - }, - { - closedAt: '2020-02-13T19:44:13.328Z', - closedBy: { username: 'elastic' }, - id: '31890e90-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:05.563Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: null, - status: 'closed', - tags: ['phishing'], - title: 'Uh oh', - totalComment: 0, - updatedAt: null, - updatedBy: null, - version: 'WzQ3LDFd', - }, - { - closedAt: null, - closedBy: null, - id: '2f5b3210-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:01.901Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: null, - status: 'open', - tags: ['phishing'], - title: 'Uh oh', - totalComment: 0, - updatedAt: null, - updatedBy: null, - version: 'WzQ3LDFd', - }, - ], - page: 1, - perPage: 5, - total: 10, - }, - loading: [], - selectedCases: [], - isError: false, - queryParams: { - page: 1, - perPage: 5, - sortField: SortFieldCase.createdAt, - sortOrder: 'desc', - }, - filterOptions: { search: '', reporters: [], tags: [], status: 'open' }, -}; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx new file mode 100644 index 0000000000000..e008b94ab9e16 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { ServiceNowColumn } from './columns'; + +import { useGetCasesMockState } from '../__mock__/case_data'; + +describe('ServiceNowColumn ', () => { + it('Not pushed render', () => { + const wrapper = mount( + <ServiceNowColumn {...{ theCase: useGetCasesMockState.data.cases[0] }} /> + ); + expect( + wrapper + .find(`[data-test-subj="case-table-column-external-notPushed"]`) + .last() + .exists() + ).toBeTruthy(); + }); + it('Up to date', () => { + const wrapper = mount( + <ServiceNowColumn {...{ theCase: useGetCasesMockState.data.cases[1] }} /> + ); + expect( + wrapper + .find(`[data-test-subj="case-table-column-external-upToDate"]`) + .last() + .exists() + ).toBeTruthy(); + }); + it('Needs update', () => { + const wrapper = mount( + <ServiceNowColumn {...{ theCase: useGetCasesMockState.data.cases[2] }} /> + ); + expect( + wrapper + .find(`[data-test-subj="case-table-column-external-requiresUpdate"]`) + .last() + .exists() + ).toBeTruthy(); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx index 0e12f78e29bc2..e48e5cb0c5959 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.tsx @@ -114,7 +114,9 @@ export const getCasesColumns = ( name: i18n.COMMENTS, sortable: true, render: (totalComment: Case['totalComment']) => - renderStringField(`${totalComment}`, `case-table-column-commentCount`), + totalComment != null + ? renderStringField(`${totalComment}`, `case-table-column-commentCount`) + : getEmptyTagValue(), }, filterStatus === 'open' ? { @@ -150,7 +152,7 @@ export const getCasesColumns = ( }, }, { - name: 'ServiceNow Incident', + name: i18n.SERVICENOW_INCIDENT, render: (theCase: Case) => { if (theCase.id != null) { return <ServiceNowColumn theCase={theCase} />; @@ -159,7 +161,7 @@ export const getCasesColumns = ( }, }, { - name: 'Actions', + name: i18n.ACTIONS, actions, }, ]; @@ -168,7 +170,7 @@ interface Props { theCase: Case; } -const ServiceNowColumn: React.FC<Props> = ({ theCase }) => { +export const ServiceNowColumn: React.FC<Props> = ({ theCase }) => { const handleRenderDataToPush = useCallback(() => { const lastCaseUpdate = theCase.updatedAt != null ? new Date(theCase.updatedAt) : null; const lastCasePush = @@ -190,7 +192,9 @@ const ServiceNowColumn: React.FC<Props> = ({ theCase }) => { > {theCase.externalService?.externalTitle} </EuiLink> - {hasDataToPush ? i18n.REQUIRES_UPDATE : i18n.UP_TO_DATE} + {hasDataToPush + ? renderStringField(i18n.REQUIRES_UPDATE, `case-table-column-external-requiresUpdate`) + : renderStringField(i18n.UP_TO_DATE, `case-table-column-external-upToDate`)} </p> ); }, [theCase]); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx index a6da45a8c5bb1..f65736e7cd109 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx @@ -9,11 +9,15 @@ import { mount } from 'enzyme'; import moment from 'moment-timezone'; import { AllCases } from './'; import { TestProviders } from '../../../../mock'; -import { useGetCasesMockState } from './__mock__'; +import { useGetCasesMockState } from '../__mock__/case_data'; +import * as i18n from './translations'; + +import { getEmptyTagValue } from '../../../../components/empty_value'; import { useDeleteCases } from '../../../../containers/case/use_delete_cases'; import { useGetCases } from '../../../../containers/case/use_get_cases'; import { useGetCasesStatus } from '../../../../containers/case/use_get_cases_status'; import { useUpdateCases } from '../../../../containers/case/use_bulk_update_case'; +import { getCasesColumns } from './columns'; jest.mock('../../../../containers/case/use_bulk_update_case'); jest.mock('../../../../containers/case/use_delete_cases'); jest.mock('../../../../containers/case/use_get_cases'); @@ -35,6 +39,7 @@ describe('AllCases', () => { const setSelectedCases = jest.fn(); const updateBulkStatus = jest.fn(); const fetchCasesStatus = jest.fn(); + const emptyTag = getEmptyTagValue().props.children; const defaultGetCases = { ...useGetCasesMockState, @@ -115,7 +120,7 @@ describe('AllCases', () => { .find(`[data-test-subj="case-table-column-createdBy"]`) .first() .text() - ).toEqual(useGetCasesMockState.data.cases[0].createdBy.username); + ).toEqual(useGetCasesMockState.data.cases[0].createdBy.fullName); expect( wrapper .find(`[data-test-subj="case-table-column-createdAt"]`) @@ -129,6 +134,39 @@ describe('AllCases', () => { .text() ).toEqual('Showing 10 cases'); }); + it('should render empty fields', () => { + useGetCasesMock.mockImplementation(() => ({ + ...defaultGetCases, + data: { + ...defaultGetCases.data, + cases: [ + { + ...defaultGetCases.data.cases[0], + id: null, + createdAt: null, + createdBy: null, + tags: null, + title: null, + totalComment: null, + }, + ], + }, + })); + const wrapper = mount( + <TestProviders> + <AllCases userCanCrud={true} /> + </TestProviders> + ); + const checkIt = (columnName: string, key: number) => { + const column = wrapper.find('[data-test-subj="cases-table"] tbody .euiTableRowCell').at(key); + if (columnName === i18n.ACTIONS) { + return; + } + 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)); + }); it('should tableHeaderSortButton AllCases', () => { const wrapper = mount( <TestProviders> @@ -165,6 +203,30 @@ describe('AllCases', () => { version: firstCase.version, }); }); + it('opens case when row action icon clicked', () => { + useGetCasesMock.mockImplementation(() => ({ + ...defaultGetCases, + filterOptions: { ...defaultGetCases.filterOptions, status: 'closed' }, + })); + + const wrapper = mount( + <TestProviders> + <AllCases userCanCrud={true} /> + </TestProviders> + ); + wrapper + .find('[data-test-subj="action-open"]') + .first() + .simulate('click'); + const firstCase = useGetCasesMockState.data.cases[0]; + expect(dispatchUpdateCaseProperty).toBeCalledWith({ + caseId: firstCase.id, + updateKey: 'status', + updateValue: 'open', + refetchCasesStatus: fetchCasesStatus, + version: firstCase.version, + }); + }); it('Bulk delete', () => { useGetCasesMock.mockImplementation(() => ({ ...defaultGetCases, diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.test.tsx new file mode 100644 index 0000000000000..615d052347203 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.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 { mount } from 'enzyme'; + +import { CasesTableFilters } from './table_filters'; +import { TestProviders } from '../../../../mock'; + +import { useGetTags } from '../../../../containers/case/use_get_tags'; +import { useGetReporters } from '../../../../containers/case/use_get_reporters'; +import { DEFAULT_FILTER_OPTIONS } from '../../../../containers/case/use_get_cases'; +jest.mock('../../../../components/timeline/insert_timeline_popover/use_insert_timeline'); +jest.mock('../../../../containers/case/use_get_reporters'); +jest.mock('../../../../containers/case/use_get_tags'); + +const onFilterChanged = jest.fn(); +const fetchReporters = jest.fn(); + +const props = { + countClosedCases: 1234, + countOpenCases: 99, + onFilterChanged, + initial: DEFAULT_FILTER_OPTIONS, +}; +describe('CasesTableFilters ', () => { + beforeEach(() => { + jest.resetAllMocks(); + (useGetTags as jest.Mock).mockReturnValue({ tags: ['coke', 'pepsi'] }); + (useGetReporters as jest.Mock).mockReturnValue({ + reporters: ['casetester'], + respReporters: [{ username: 'casetester' }], + isLoading: true, + isError: false, + fetchReporters, + }); + }); + it('should render the initial case count', () => { + const wrapper = mount( + <TestProviders> + <CasesTableFilters {...props} /> + </TestProviders> + ); + expect( + wrapper + .find(`[data-test-subj="open-case-count"]`) + .last() + .text() + ).toEqual('Open cases (99)'); + expect( + wrapper + .find(`[data-test-subj="closed-case-count"]`) + .last() + .text() + ).toEqual('Closed cases (1234)'); + }); + it('should call onFilterChange when tags change', () => { + const wrapper = mount( + <TestProviders> + <CasesTableFilters {...props} /> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="options-filter-popover-button-Tags"]`) + .last() + .simulate('click'); + wrapper + .find(`[data-test-subj="options-filter-popover-item-0"]`) + .last() + .simulate('click'); + + expect(onFilterChanged).toBeCalledWith({ tags: ['coke'] }); + }); + it('should call onFilterChange when reporters change', () => { + const wrapper = mount( + <TestProviders> + <CasesTableFilters {...props} /> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="options-filter-popover-button-Reporter"]`) + .last() + .simulate('click'); + + wrapper + .find(`[data-test-subj="options-filter-popover-item-0"]`) + .last() + .simulate('click'); + + expect(onFilterChanged).toBeCalledWith({ reporters: [{ username: 'casetester' }] }); + }); + it('should call onFilterChange when search changes', () => { + const wrapper = mount( + <TestProviders> + <CasesTableFilters {...props} /> + </TestProviders> + ); + + wrapper + .find(`[data-test-subj="search-cases"]`) + .last() + .simulate('keyup', { keyCode: 13, target: { value: 'My search' } }); + expect(onFilterChanged).toBeCalledWith({ search: 'My search' }); + }); + it('should call onFilterChange when status toggled', () => { + const wrapper = mount( + <TestProviders> + <CasesTableFilters {...props} /> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="closed-case-count"]`) + .last() + .simulate('click'); + + expect(onFilterChanged).toBeCalledWith({ status: 'closed' }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.tsx index a344dd7891010..da477a56c0a22 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/table_filters.tsx @@ -42,7 +42,7 @@ const CasesTableFiltersComponent = ({ onFilterChanged, initial = defaultInitial, }: CasesTableFiltersProps) => { - const [selectedReporters, setselectedReporters] = useState( + const [selectedReporters, setSelectedReporters] = useState( initial.reporters.map(r => r.full_name ?? r.username ?? '') ); const [search, setSearch] = useState(initial.search); @@ -54,7 +54,7 @@ const CasesTableFiltersComponent = ({ const handleSelectedReporters = useCallback( newReporters => { if (!isEqual(newReporters, selectedReporters)) { - setselectedReporters(newReporters); + setSelectedReporters(newReporters); const reportersObj = respReporters.filter( r => newReporters.includes(r.username) || newReporters.includes(r.full_name) ); @@ -97,6 +97,7 @@ const CasesTableFiltersComponent = ({ <EuiFlexItem grow={true}> <EuiFieldSearch aria-label={i18n.SEARCH_CASES} + data-test-subj="search-cases" fullWidth incremental={false} placeholder={i18n.SEARCH_PLACEHOLDER} @@ -107,6 +108,7 @@ const CasesTableFiltersComponent = ({ <EuiFlexItem grow={false}> <EuiFilterGroup> <EuiFilterButton + data-test-subj="open-case-count" withNext hasActiveFilters={showOpenCases} onClick={handleToggleFilter.bind(null, true)} @@ -115,6 +117,7 @@ const CasesTableFiltersComponent = ({ {countOpenCases != null ? ` (${countOpenCases})` : ''} </EuiFilterButton> <EuiFilterButton + data-test-subj="closed-case-count" hasActiveFilters={!showOpenCases} onClick={handleToggleFilter.bind(null, false)} > diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts index 1bee96bc23fff..d3dcfa50ecfa5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/translations.ts @@ -46,6 +46,10 @@ export const BULK_ACTIONS = i18n.translate('xpack.siem.case.caseTable.bulkAction defaultMessage: 'Bulk actions', }); +export const SERVICENOW_INCIDENT = i18n.translate('xpack.siem.case.caseTable.snIncident', { + defaultMessage: 'ServiceNow Incident', +}); + export const SEARCH_PLACEHOLDER = i18n.translate('xpack.siem.case.caseTable.searchPlaceholder', { defaultMessage: 'e.g. case name', }); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/callout/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/callout/helpers.tsx index 929e8640dceb6..3237104274473 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/callout/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/callout/helpers.tsx @@ -6,7 +6,7 @@ import * as i18n from './translations'; -export const getSavedObjectReadOnly = () => ({ +export const savedObjectReadOnly = { title: i18n.READ_ONLY_SAVED_OBJECT_TITLE, description: i18n.READ_ONLY_SAVED_OBJECT_MSG, -}); +}; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.test.tsx new file mode 100644 index 0000000000000..126ea13e96af6 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.test.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; + +import { CaseCallOut } from './'; + +const defaultProps = { + title: 'hey title', +}; + +describe('CaseCallOut ', () => { + it('Renders single message callout', () => { + const props = { + ...defaultProps, + message: 'we have one message', + }; + const wrapper = mount(<CaseCallOut {...props} />); + expect( + wrapper + .find(`[data-test-subj="callout-message"]`) + .last() + .exists() + ).toBeTruthy(); + expect( + wrapper + .find(`[data-test-subj="callout-messages"]`) + .last() + .exists() + ).toBeFalsy(); + }); + it('Renders multi message callout', () => { + const props = { + ...defaultProps, + messages: [ + { ...defaultProps, description: <p>{'we have two messages'}</p> }, + { ...defaultProps, description: <p>{'for real'}</p> }, + ], + }; + const wrapper = mount(<CaseCallOut {...props} />); + expect( + wrapper + .find(`[data-test-subj="callout-message"]`) + .last() + .exists() + ).toBeFalsy(); + expect( + wrapper + .find(`[data-test-subj="callout-messages"]`) + .last() + .exists() + ).toBeTruthy(); + }); + it('Dismisses callout', () => { + const props = { + ...defaultProps, + message: 'we have one message', + }; + const wrapper = mount(<CaseCallOut {...props} />); + expect(wrapper.find(`[data-test-subj="case-call-out"]`).exists()).toBeTruthy(); + wrapper + .find(`[data-test-subj="callout-dismiss"]`) + .last() + .simulate('click'); + expect(wrapper.find(`[data-test-subj="case-call-out"]`).exists()).toBeFalsy(); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.tsx index 30a95db2d82a5..0fc93af7f318d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/callout/index.tsx @@ -24,10 +24,12 @@ const CaseCallOutComponent = ({ title, message, messages }: CaseCallOutProps) => return showCallOut ? ( <> - <EuiCallOut title={title} color="primary" iconType="gear"> - {!isEmpty(messages) && <EuiDescriptionList listItems={messages} />} - {!isEmpty(message) && <p>{message}</p>} - <EuiButton color="primary" onClick={handleCallOut}> + <EuiCallOut title={title} color="primary" iconType="gear" data-test-subj="case-call-out"> + {!isEmpty(messages) && ( + <EuiDescriptionList data-test-subj="callout-messages" listItems={messages} /> + )} + {!isEmpty(message) && <p data-test-subj="callout-message">{message}</p>} + <EuiButton data-test-subj="callout-dismiss" color="primary" onClick={handleCallOut}> {i18n.DISMISS_CALLOUT} </EuiButton> </EuiCallOut> diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx index 2b16dfa150d61..718eb95767f2e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_status/index.tsx @@ -84,7 +84,7 @@ const CaseStatusComp: React.FC<CaseStatusProps> = ({ <EuiFlexItem grow={false}> <EuiFlexGroup gutterSize="l" alignItems="center"> <EuiFlexItem> - <EuiButtonEmpty iconType="refresh" onClick={onRefresh}> + <EuiButtonEmpty data-test-subj="case-refresh" iconType="refresh" onClick={onRefresh}> {i18n.CASE_REFRESH} </EuiButtonEmpty> </EuiFlexItem> diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx deleted file mode 100644 index 0e57326707e97..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/__mock__/index.tsx +++ /dev/null @@ -1,93 +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 { CaseProps } from '../index'; -import { Case } from '../../../../../containers/case/types'; - -const updateCase = jest.fn(); -const fetchCase = jest.fn(); - -export const caseProps: CaseProps = { - caseId: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15', - userCanCrud: true, - caseData: { - closedAt: null, - closedBy: null, - id: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15', - comments: [ - { - comment: 'Solve this fast!', - id: 'a357c6a0-5435-11ea-b427-fb51a1fcb7b8', - createdAt: '2020-02-20T23:06:33.798Z', - createdBy: { - fullName: 'Steph Milovic', - username: 'smilovic', - email: 'notmyrealemailfool@elastic.co', - }, - pushedAt: null, - pushedBy: null, - updatedAt: '2020-02-20T23:06:33.798Z', - updatedBy: { - username: 'elastic', - }, - version: 'WzQ3LDFd', - }, - ], - createdAt: '2020-02-13T19:44:23.627Z', - createdBy: { fullName: null, email: 'testemail@elastic.co', username: 'elastic' }, - description: 'Security banana Issue', - externalService: null, - status: 'open', - tags: ['defacement'], - title: 'Another horrible breach!!', - totalComment: 1, - updatedAt: '2020-02-19T15:02:57.995Z', - updatedBy: { - username: 'elastic', - }, - version: 'WzQ3LDFd', - }, - fetchCase, - updateCase, -}; - -export const caseClosedProps: CaseProps = { - ...caseProps, - caseData: { - ...caseProps.caseData, - closedAt: '2020-02-20T23:06:33.798Z', - closedBy: { - username: 'elastic', - }, - status: 'closed', - }, -}; - -export const data: Case = { - ...caseProps.caseData, -}; - -export const dataClosed: Case = { - ...caseClosedProps.caseData, -}; - -export const caseUserActions = [ - { - actionField: ['comment'], - action: 'create', - actionAt: '2020-03-20T17:10:09.814Z', - actionBy: { - fullName: 'Steph Milovic', - username: 'smilovic', - email: 'notmyrealemailfool@elastic.co', - }, - newValue: 'Solve this fast!', - oldValue: null, - actionId: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15', - caseId: '9b833a50-6acd-11ea-8fad-af86b1071bd9', - commentId: 'a357c6a0-5435-11ea-b427-fb51a1fcb7b8', - }, -]; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx index 49f5f44cba271..8a25a2121104d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx @@ -9,7 +9,7 @@ import { mount } from 'enzyme'; import { useDeleteCases } from '../../../../containers/case/use_delete_cases'; import { TestProviders } from '../../../../mock'; -import { data } from './__mock__'; +import { basicCase } from '../__mock__/case_data'; import { CaseViewActions } from './actions'; jest.mock('../../../../containers/case/use_delete_cases'); const useDeleteCasesMock = useDeleteCases as jest.Mock; @@ -34,7 +34,7 @@ describe('CaseView actions', () => { it('clicking trash toggles modal', () => { const wrapper = mount( <TestProviders> - <CaseViewActions caseData={data} /> + <CaseViewActions caseData={basicCase} /> </TestProviders> ); @@ -54,12 +54,14 @@ describe('CaseView actions', () => { })); const wrapper = mount( <TestProviders> - <CaseViewActions caseData={data} /> + <CaseViewActions caseData={basicCase} /> </TestProviders> ); expect(wrapper.find('[data-test-subj="confirm-delete-case-modal"]').exists()).toBeTruthy(); wrapper.find('button[data-test-subj="confirmModalConfirmButton"]').simulate('click'); - expect(handleOnDeleteConfirm.mock.calls[0][0]).toEqual([{ id: data.id, title: data.title }]); + expect(handleOnDeleteConfirm.mock.calls[0][0]).toEqual([ + { id: basicCase.id, title: basicCase.title }, + ]); }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx index 0b08b866df964..216180eb2cf0a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.tsx @@ -40,7 +40,6 @@ const CaseViewActionsComponent: React.FC<CaseViewActions> = ({ caseData, disable ), [isDisplayConfirmDeleteModal, caseData] ); - // TO DO refactor each of these const's into their own components const propertyActions = useMemo( () => [ { diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx index 3f5b3a3127177..3721a5a727ca5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx @@ -5,56 +5,43 @@ */ import React from 'react'; -import { Router } from 'react-router-dom'; import { mount } from 'enzyme'; -/* eslint-disable @kbn/eslint/module_migration */ -import routeData from 'react-router'; -/* eslint-enable @kbn/eslint/module_migration */ -import { CaseComponent } from './'; -import { caseProps, caseClosedProps, data, dataClosed, caseUserActions } from './__mock__'; + +import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router'; +import { CaseComponent, CaseView } from './'; +import { + basicCaseClosed, + caseClosedProps, + caseProps, + caseUserActions, +} from '../__mock__/case_data'; import { TestProviders } from '../../../../mock'; import { useUpdateCase } from '../../../../containers/case/use_update_case'; +import { useGetCase } from '../../../../containers/case/use_get_case'; import { useGetCaseUserActions } from '../../../../containers/case/use_get_case_user_actions'; import { wait } from '../../../../lib/helpers'; import { usePushToService } from '../use_push_to_service'; jest.mock('../../../../containers/case/use_update_case'); jest.mock('../../../../containers/case/use_get_case_user_actions'); +jest.mock('../../../../containers/case/use_get_case'); jest.mock('../use_push_to_service'); const useUpdateCaseMock = useUpdateCase as jest.Mock; const useGetCaseUserActionsMock = useGetCaseUserActions as jest.Mock; const usePushToServiceMock = usePushToService as jest.Mock; -type Action = 'PUSH' | 'POP' | 'REPLACE'; -const pop: Action = 'POP'; -const location = { - pathname: '/network', - search: '', - state: '', - hash: '', -}; -const mockHistory = { - length: 2, - location, - action: pop, - push: jest.fn(), - replace: jest.fn(), - go: jest.fn(), - goBack: jest.fn(), - goForward: jest.fn(), - block: jest.fn(), - createHref: jest.fn(), - listen: jest.fn(), -}; - -const mockLocation = { - pathname: '/welcome', - hash: '', - search: '', - state: '', -}; describe('CaseView ', () => { const updateCaseProperty = jest.fn(); const fetchCaseUserActions = jest.fn(); + const fetchCase = jest.fn(); + const updateCase = jest.fn(); + const data = caseProps.caseData; + const defaultGetCase = { + isLoading: false, + isError: false, + data, + updateCase, + fetchCase, + }; /* eslint-disable no-console */ // Silence until enzyme fixed to use ReactTestUtils.act() const originalError = console.error; @@ -84,17 +71,23 @@ describe('CaseView ', () => { participants: [data.createdBy], }; - const defaultUsePushToServiceMock = { - pushButton: <>{'Hello Button'}</>, - pushCallouts: null, - }; - beforeEach(() => { jest.resetAllMocks(); useUpdateCaseMock.mockImplementation(() => defaultUpdateCaseState); jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation); useGetCaseUserActionsMock.mockImplementation(() => defaultUseGetCaseUserActions); - usePushToServiceMock.mockImplementation(() => defaultUsePushToServiceMock); + usePushToServiceMock.mockImplementation(({ updateCase: updateCaseMockCall }) => ({ + pushButton: ( + <button + data-test-subj="mock-button" + onClick={() => updateCaseMockCall(caseProps.caseData)} + type="button" + > + {'Hello Button'} + </button> + ), + pushCallouts: null, + })); }); it('should render CaseComponent', async () => { @@ -120,7 +113,7 @@ describe('CaseView ', () => { ).toEqual(data.status); expect( wrapper - .find(`[data-test-subj="case-view-tag-list"] .euiBadge__text`) + .find(`[data-test-subj="case-view-tag-list"] [data-test-subj="case-tag"]`) .first() .text() ).toEqual(data.tags[0]); @@ -139,7 +132,7 @@ describe('CaseView ', () => { ).toEqual(data.createdAt); expect( wrapper - .find(`[data-test-subj="case-view-description"]`) + .find(`[data-test-subj="description-action"] [data-test-subj="user-action-markdown"]`) .first() .prop('raw') ).toEqual(data.description); @@ -148,7 +141,7 @@ describe('CaseView ', () => { it('should show closed indicators in header when case is closed', async () => { useUpdateCaseMock.mockImplementation(() => ({ ...defaultUpdateCaseState, - caseData: dataClosed, + caseData: basicCaseClosed, })); const wrapper = mount( <TestProviders> @@ -164,13 +157,13 @@ describe('CaseView ', () => { .find(`[data-test-subj="case-view-closedAt"]`) .first() .prop('value') - ).toEqual(dataClosed.closedAt); + ).toEqual(basicCaseClosed.closedAt); expect( wrapper .find(`[data-test-subj="case-view-status"]`) .first() .text() - ).toEqual(dataClosed.status); + ).toEqual(basicCaseClosed.status); }); it('should dispatch update state when button is toggled', async () => { @@ -188,7 +181,12 @@ describe('CaseView ', () => { expect(updateCaseProperty).toHaveBeenCalled(); }); - it('should render comments', async () => { + it('should display EditableTitle isLoading', () => { + useUpdateCaseMock.mockImplementation(() => ({ + ...defaultUpdateCaseState, + isLoading: true, + updateKey: 'title', + })); const wrapper = mount( <TestProviders> <Router history={mockHistory}> @@ -196,32 +194,230 @@ describe('CaseView ', () => { </Router> </TestProviders> ); - await wait(); expect( wrapper - .find( - `div[data-test-subj="user-action-${data.comments[0].id}-avatar"] [data-test-subj="user-action-avatar"]` - ) + .find('[data-test-subj="editable-title-loading"]') + .first() + .exists() + ).toBeTruthy(); + expect( + wrapper + .find('[data-test-subj="editable-title-edit-icon"]') .first() - .prop('name') - ).toEqual(data.comments[0].createdBy.fullName); + .exists() + ).toBeFalsy(); + }); + it('should display Toggle Status isLoading', () => { + useUpdateCaseMock.mockImplementation(() => ({ + ...defaultUpdateCaseState, + isLoading: true, + updateKey: 'status', + })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseComponent {...caseProps} /> + </Router> + </TestProviders> + ); expect( wrapper - .find( - `div[data-test-subj="user-action-${data.comments[0].id}"] [data-test-subj="user-action-title"] strong` - ) + .find('[data-test-subj="toggle-case-status"]') .first() - .text() - ).toEqual(data.comments[0].createdBy.username); + .prop('isLoading') + ).toBeTruthy(); + }); + it('should display description isLoading', () => { + useUpdateCaseMock.mockImplementation(() => ({ + ...defaultUpdateCaseState, + isLoading: true, + updateKey: 'description', + })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseComponent {...caseProps} /> + </Router> + </TestProviders> + ); + expect( + wrapper + .find('[data-test-subj="description-action"] [data-test-subj="user-action-title-loading"]') + .first() + .exists() + ).toBeTruthy(); + expect( + wrapper + .find('[data-test-subj="description-action"] [data-test-subj="property-actions"]') + .first() + .exists() + ).toBeFalsy(); + }); + + it('should display tags isLoading', () => { + useUpdateCaseMock.mockImplementation(() => ({ + ...defaultUpdateCaseState, + isLoading: true, + updateKey: 'tags', + })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseComponent {...caseProps} /> + </Router> + </TestProviders> + ); + expect( + wrapper + .find('[data-test-subj="case-view-tag-list"] [data-test-subj="tag-list-loading"]') + .first() + .exists() + ).toBeTruthy(); expect( wrapper - .find( - `div[data-test-subj="user-action-${data.comments[0].id}"] [data-test-subj="markdown"]` - ) + .find('[data-test-subj="tag-list-edit"]') .first() - .prop('source') - ).toEqual(data.comments[0].comment); + .exists() + ).toBeFalsy(); + }); + + it('should update title', () => { + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseComponent {...caseProps} /> + </Router> + </TestProviders> + ); + const newTitle = 'The new title'; + wrapper + .find(`[data-test-subj="editable-title-edit-icon"]`) + .first() + .simulate('click'); + wrapper.update(); + wrapper + .find(`[data-test-subj="editable-title-input-field"]`) + .last() + .simulate('change', { target: { value: newTitle } }); + + wrapper.update(); + wrapper + .find(`[data-test-subj="editable-title-submit-btn"]`) + .first() + .simulate('click'); + + wrapper.update(); + const updateObject = updateCaseProperty.mock.calls[0][0]; + expect(updateObject.updateKey).toEqual('title'); + expect(updateObject.updateValue).toEqual(newTitle); + }); + + it('should push updates on button click', async () => { + useGetCaseUserActionsMock.mockImplementation(() => ({ + ...defaultUseGetCaseUserActions, + hasDataToPush: true, + })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseComponent {...{ ...caseProps, updateCase }} /> + </Router> + </TestProviders> + ); + expect( + wrapper + .find('[data-test-subj="has-data-to-push-button"]') + .first() + .exists() + ).toBeTruthy(); + wrapper + .find('[data-test-subj="mock-button"]') + .first() + .simulate('click'); + wrapper.update(); + await wait(); + expect(updateCase).toBeCalledWith(caseProps.caseData); + expect(fetchCaseUserActions).toBeCalledWith(caseProps.caseData.id); + }); + + it('should return null if error', () => { + (useGetCase as jest.Mock).mockImplementation(() => ({ + ...defaultGetCase, + isError: true, + })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseView + {...{ + caseId: '1234', + userCanCrud: true, + }} + /> + </Router> + </TestProviders> + ); + expect(wrapper).toEqual({}); + }); + + it('should return spinner if loading', () => { + (useGetCase as jest.Mock).mockImplementation(() => ({ + ...defaultGetCase, + isLoading: true, + })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseView + {...{ + caseId: '1234', + userCanCrud: true, + }} + /> + </Router> + </TestProviders> + ); + expect(wrapper.find('[data-test-subj="case-view-loading"]').exists()).toBeTruthy(); + }); + + it('should return case view when data is there', () => { + (useGetCase as jest.Mock).mockImplementation(() => defaultGetCase); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseView + {...{ + caseId: '1234', + userCanCrud: true, + }} + /> + </Router> + </TestProviders> + ); + expect(wrapper.find('[data-test-subj="case-view-title"]').exists()).toBeTruthy(); + }); + + it('should refresh data on refresh', () => { + (useGetCase as jest.Mock).mockImplementation(() => defaultGetCase); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <CaseView + {...{ + caseId: '1234', + userCanCrud: true, + }} + /> + </Router> + </TestProviders> + ); + wrapper + .find('[data-test-subj="case-refresh"]') + .first() + .simulate('click'); + expect(fetchCaseUserActions).toBeCalledWith(caseProps.caseData.id); + expect(fetchCase).toBeCalled(); }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx index 947da51365d66..3cf0405f40637 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.tsx @@ -271,7 +271,11 @@ export const CaseComponent = React.memo<CaseProps>( onChange={toggleStatusCase} /> </EuiFlexItem> - {hasDataToPush && <EuiFlexItem grow={false}>{pushButton}</EuiFlexItem>} + {hasDataToPush && ( + <EuiFlexItem data-test-subj="has-data-to-push-button" grow={false}> + {pushButton} + </EuiFlexItem> + )} </EuiFlexGroup> </> )} @@ -316,7 +320,7 @@ export const CaseView = React.memo(({ caseId, userCanCrud }: Props) => { return ( <MyEuiFlexGroup justifyContent="center" alignItems="center"> <EuiFlexItem grow={false}> - <EuiLoadingSpinner size="xl" /> + <EuiLoadingSpinner data-test-subj="case-view-loading" size="xl" /> </EuiFlexItem> </MyEuiFlexGroup> ); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.test.tsx new file mode 100644 index 0000000000000..d480744fc932a --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/create/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 { mount } from 'enzyme'; + +import { Create } from './'; +import { TestProviders } from '../../../../mock'; +import { getFormMock } from '../__mock__/form'; +import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router'; + +import { useInsertTimeline } from '../../../../components/timeline/insert_timeline_popover/use_insert_timeline'; +import { usePostCase } from '../../../../containers/case/use_post_case'; +jest.mock('../../../../components/timeline/insert_timeline_popover/use_insert_timeline'); +jest.mock('../../../../containers/case/use_post_case'); +import { useForm } from '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks'; +import { wait } from '../../../../lib/helpers'; +import { SiemPageName } from '../../../home/types'; +jest.mock( + '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form' +); + +export const useFormMock = useForm as jest.Mock; + +const useInsertTimelineMock = useInsertTimeline as jest.Mock; +const usePostCaseMock = usePostCase as jest.Mock; + +const postCase = jest.fn(); +const handleCursorChange = jest.fn(); +const handleOnTimelineChange = jest.fn(); + +const defaultInsertTimeline = { + cursorPosition: { + start: 0, + end: 0, + }, + handleCursorChange, + handleOnTimelineChange, +}; +const sampleData = { + description: 'what a great description', + tags: ['coke', 'pepsi'], + title: 'what a cool title', +}; +const defaultPostCase = { + isLoading: false, + isError: false, + caseData: null, + postCase, +}; +describe('Create case', () => { + const formHookMock = getFormMock(sampleData); + + beforeEach(() => { + jest.resetAllMocks(); + useInsertTimelineMock.mockImplementation(() => defaultInsertTimeline); + usePostCaseMock.mockImplementation(() => defaultPostCase); + useFormMock.mockImplementation(() => ({ form: formHookMock })); + jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation); + }); + + it('should post case on submit click', async () => { + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <Create /> + </Router> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="create-case-submit"]`) + .first() + .simulate('click'); + await wait(); + expect(postCase).toBeCalledWith(sampleData); + }); + + it('should redirect to all cases on cancel click', () => { + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <Create /> + </Router> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="create-case-cancel"]`) + .first() + .simulate('click'); + expect(mockHistory.replace.mock.calls[0][0].pathname).toEqual(`/${SiemPageName.case}`); + }); + it('should redirect to new case when caseData is there', () => { + const sampleId = '777777'; + usePostCaseMock.mockImplementation(() => ({ ...defaultPostCase, caseData: { id: sampleId } })); + mount( + <TestProviders> + <Router history={mockHistory}> + <Create /> + </Router> + </TestProviders> + ); + expect(mockHistory.replace.mock.calls[0][0].pathname).toEqual( + `/${SiemPageName.case}/${sampleId}` + ); + }); + + it('should render spinner when loading', () => { + usePostCaseMock.mockImplementation(() => ({ ...defaultPostCase, isLoading: true })); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <Create /> + </Router> + </TestProviders> + ); + expect(wrapper.find(`[data-test-subj="create-case-loading-spinner"]`).exists()).toBeTruthy(); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx index 740909db408ec..53b792bb9b5eb 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/create/index.tsx @@ -73,7 +73,7 @@ export const Create = React.memo(() => { const handleSetIsCancel = useCallback(() => { setIsCancel(true); - }, [isCancel]); + }, []); if (caseData != null && caseData.id) { return <Redirect to={`/${SiemPageName.case}/${caseData.id}`} />; @@ -85,7 +85,7 @@ export const Create = React.memo(() => { return ( <EuiPanel> - {isLoading && <MySpinner size="xl" />} + {isLoading && <MySpinner data-test-subj="create-case-loading-spinner" size="xl" />} <Form form={form}> <CommonUseField path="title" @@ -107,7 +107,7 @@ export const Create = React.memo(() => { euiFieldProps: { fullWidth: true, placeholder: '', - isDisabled: isLoading, + disabled: isLoading, }, }} /> @@ -151,6 +151,7 @@ export const Create = React.memo(() => { </EuiFlexItem> <EuiFlexItem grow={false}> <EuiButton + data-test-subj="create-case-submit" fill iconType="plusInCircle" isDisabled={isLoading} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.test.tsx new file mode 100644 index 0000000000000..8ad2f8f8cb737 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.test.tsx @@ -0,0 +1,138 @@ +/* + * 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 { mount } from 'enzyme'; + +import { TagList } from './'; +import { getFormMock } from '../__mock__/form'; +import { TestProviders } from '../../../../mock'; +import { wait } from '../../../../lib/helpers'; +import { useForm } from '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks'; +import { act } from 'react-dom/test-utils'; + +jest.mock( + '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form' +); +const onSubmit = jest.fn(); +const defaultProps = { + disabled: false, + isLoading: false, + onSubmit, + tags: [], +}; + +describe('TagList ', () => { + const sampleTags = ['coke', 'pepsi']; + const formHookMock = getFormMock({ tags: sampleTags }); + beforeEach(() => { + jest.resetAllMocks(); + (useForm as jest.Mock).mockImplementation(() => ({ form: formHookMock })); + }); + it('Renders no tags, and then edit', () => { + const wrapper = mount( + <TestProviders> + <TagList {...defaultProps} /> + </TestProviders> + ); + expect( + wrapper + .find(`[data-test-subj="no-tags"]`) + .last() + .exists() + ).toBeTruthy(); + wrapper + .find(`[data-test-subj="tag-list-edit-button"]`) + .last() + .simulate('click'); + expect( + wrapper + .find(`[data-test-subj="no-tags"]`) + .last() + .exists() + ).toBeFalsy(); + expect( + wrapper + .find(`[data-test-subj="edit-tags"]`) + .last() + .exists() + ).toBeTruthy(); + }); + it('Edit tag on submit', async () => { + const wrapper = mount( + <TestProviders> + <TagList {...defaultProps} /> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="tag-list-edit-button"]`) + .last() + .simulate('click'); + await act(async () => { + wrapper + .find(`[data-test-subj="edit-tags-submit"]`) + .last() + .simulate('click'); + await wait(); + expect(onSubmit).toBeCalledWith(sampleTags); + }); + }); + it('Cancels on cancel', async () => { + const props = { + ...defaultProps, + tags: ['pepsi'], + }; + const wrapper = mount( + <TestProviders> + <TagList {...props} /> + </TestProviders> + ); + expect( + wrapper + .find(`[data-test-subj="case-tag"]`) + .last() + .exists() + ).toBeTruthy(); + wrapper + .find(`[data-test-subj="tag-list-edit-button"]`) + .last() + .simulate('click'); + await act(async () => { + expect( + wrapper + .find(`[data-test-subj="case-tag"]`) + .last() + .exists() + ).toBeFalsy(); + wrapper + .find(`[data-test-subj="edit-tags-cancel"]`) + .last() + .simulate('click'); + await wait(); + wrapper.update(); + expect( + wrapper + .find(`[data-test-subj="case-tag"]`) + .last() + .exists() + ).toBeTruthy(); + }); + }); + it('Renders disabled button', () => { + const props = { ...defaultProps, disabled: true }; + const wrapper = mount( + <TestProviders> + <TagList {...props} /> + </TestProviders> + ); + expect( + wrapper + .find(`[data-test-subj="tag-list-edit-button"]`) + .last() + .prop('disabled') + ).toBeTruthy(); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.tsx index f7d890ca60b16..9bac000b93235 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/tag_list/index.tsx @@ -61,10 +61,11 @@ export const TagList = React.memo( <EuiFlexItem grow={false}> <h4>{i18n.TAGS}</h4> </EuiFlexItem> - {isLoading && <EuiLoadingSpinner />} + {isLoading && <EuiLoadingSpinner data-test-subj="tag-list-loading" />} {!isLoading && ( - <EuiFlexItem grow={false}> + <EuiFlexItem data-test-subj="tag-list-edit" grow={false}> <EuiButtonIcon + data-test-subj="tag-list-edit-button" isDisabled={disabled} aria-label={i18n.EDIT_TAGS_ARIA} iconType={'pencil'} @@ -74,17 +75,19 @@ export const TagList = React.memo( )} </EuiFlexGroup> <EuiHorizontalRule margin="xs" /> - <MyFlexGroup gutterSize="xs"> - {tags.length === 0 && !isEditTags && <p>{i18n.NO_TAGS}</p>} + <MyFlexGroup gutterSize="xs" data-test-subj="grr"> + {tags.length === 0 && !isEditTags && <p data-test-subj="no-tags">{i18n.NO_TAGS}</p>} {tags.length > 0 && !isEditTags && tags.map((tag, key) => ( <EuiFlexItem grow={false} key={`${tag}${key}`}> - <EuiBadge color="hollow">{tag}</EuiBadge> + <EuiBadge data-test-subj="case-tag" color="hollow"> + {tag} + </EuiBadge> </EuiFlexItem> ))} {isEditTags && ( - <EuiFlexGroup direction="column"> + <EuiFlexGroup data-test-subj="edit-tags" direction="column"> <EuiFlexItem> <Form form={form}> <CommonUseField @@ -105,6 +108,7 @@ export const TagList = React.memo( <EuiFlexItem grow={false}> <EuiButton color="secondary" + data-test-subj="edit-tags-submit" fill iconType="save" onClick={onSubmitTags} @@ -115,6 +119,7 @@ export const TagList = React.memo( </EuiFlexItem> <EuiFlexItem grow={false}> <EuiButtonEmpty + data-test-subj="edit-tags-cancel" iconType="cross" onClick={setIsEditTags.bind(null, false)} size="s" diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.test.tsx new file mode 100644 index 0000000000000..77215e2318ded --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.test.tsx @@ -0,0 +1,192 @@ +/* + * 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 react/display-name */ +import React from 'react'; +import { renderHook, act } from '@testing-library/react-hooks'; +import { usePushToService, ReturnUsePushToService, UsePushToService } from './'; +import { TestProviders } from '../../../../mock'; +import { usePostPushToService } from '../../../../containers/case/use_post_push_to_service'; +import { ClosureType } from '../../../../../../../../plugins/case/common/api/cases'; +import * as i18n from './translations'; +import { useGetActionLicense } from '../../../../containers/case/use_get_action_license'; +import { getKibanaConfigError, getLicenseError } from './helpers'; +import * as api from '../../../../containers/case/configure/api'; +jest.mock('../../../../containers/case/use_get_action_license'); +jest.mock('../../../../containers/case/use_post_push_to_service'); +jest.mock('../../../../containers/case/configure/api'); + +describe('usePushToService', () => { + const caseId = '12345'; + const updateCase = jest.fn(); + const postPushToService = jest.fn(); + const mockPostPush = { + isLoading: false, + postPushToService, + }; + const closureType: ClosureType = 'close-by-user'; + const mockConnector = { + connectorId: 'c00l', + connectorName: 'name', + }; + const mockCaseConfigure = { + ...mockConnector, + createdAt: 'string', + createdBy: {}, + closureType, + updatedAt: 'string', + updatedBy: {}, + version: 'string', + }; + const getConfigureMock = jest.spyOn(api, 'getCaseConfigure'); + const actionLicense = { + id: '.servicenow', + name: 'ServiceNow', + minimumLicenseRequired: 'platinum', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + }; + beforeEach(() => { + jest.resetAllMocks(); + (usePostPushToService as jest.Mock).mockImplementation(() => mockPostPush); + (useGetActionLicense as jest.Mock).mockImplementation(() => ({ + isLoading: false, + actionLicense, + })); + getConfigureMock.mockImplementation(() => Promise.resolve(mockCaseConfigure)); + }); + it('push case button posts the push with correct args', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<UsePushToService, ReturnUsePushToService>( + () => + usePushToService({ + caseId, + caseStatus: 'open', + isNew: false, + updateCase, + userCanCrud: true, + }), + { + wrapper: ({ children }) => <TestProviders> {children}</TestProviders>, + } + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(getConfigureMock).toBeCalled(); + result.current.pushButton.props.children.props.onClick(); + expect(postPushToService).toBeCalledWith({ ...mockConnector, caseId, updateCase }); + expect(result.current.pushCallouts).toBeNull(); + }); + }); + it('Displays message when user does not have premium license', async () => { + (useGetActionLicense as jest.Mock).mockImplementation(() => ({ + isLoading: false, + actionLicense: { + ...actionLicense, + enabledInLicense: false, + }, + })); + await act(async () => { + const { result, waitForNextUpdate } = renderHook<UsePushToService, ReturnUsePushToService>( + () => + usePushToService({ + caseId, + caseStatus: 'open', + isNew: false, + updateCase, + userCanCrud: true, + }), + { + wrapper: ({ children }) => <TestProviders> {children}</TestProviders>, + } + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + const errorsMsg = result.current.pushCallouts?.props.messages; + expect(errorsMsg).toHaveLength(1); + expect(errorsMsg[0].title).toEqual(getLicenseError().title); + }); + }); + it('Displays message when user does not have case enabled in config', async () => { + (useGetActionLicense as jest.Mock).mockImplementation(() => ({ + isLoading: false, + actionLicense: { + ...actionLicense, + enabledInConfig: false, + }, + })); + await act(async () => { + const { result, waitForNextUpdate } = renderHook<UsePushToService, ReturnUsePushToService>( + () => + usePushToService({ + caseId, + caseStatus: 'open', + isNew: false, + updateCase, + userCanCrud: true, + }), + { + wrapper: ({ children }) => <TestProviders> {children}</TestProviders>, + } + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + const errorsMsg = result.current.pushCallouts?.props.messages; + expect(errorsMsg).toHaveLength(1); + expect(errorsMsg[0].title).toEqual(getKibanaConfigError().title); + }); + }); + it('Displays message when user does not have a connector configured', async () => { + getConfigureMock.mockImplementation(() => + Promise.resolve({ + ...mockCaseConfigure, + connectorId: 'none', + }) + ); + await act(async () => { + const { result, waitForNextUpdate } = renderHook<UsePushToService, ReturnUsePushToService>( + () => + usePushToService({ + caseId, + caseStatus: 'open', + isNew: false, + updateCase, + userCanCrud: true, + }), + { + wrapper: ({ children }) => <TestProviders> {children}</TestProviders>, + } + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + const errorsMsg = result.current.pushCallouts?.props.messages; + expect(errorsMsg).toHaveLength(1); + expect(errorsMsg[0].title).toEqual(i18n.PUSH_DISABLE_BY_NO_CASE_CONFIG_TITLE); + }); + }); + it('Displays message when case is closed', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<UsePushToService, ReturnUsePushToService>( + () => + usePushToService({ + caseId, + caseStatus: 'closed', + isNew: false, + updateCase, + userCanCrud: true, + }), + { + wrapper: ({ children }) => <TestProviders> {children}</TestProviders>, + } + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + const errorsMsg = result.current.pushCallouts?.props.messages; + expect(errorsMsg).toHaveLength(1); + expect(errorsMsg[0].title).toEqual(i18n.PUSH_DISABLE_BECAUSE_CASE_CLOSED_TITLE); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx index 4f370ec978906..5092cba6872e3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/use_push_to_service/index.tsx @@ -19,7 +19,7 @@ import { CaseCallOut } from '../callout'; import { getLicenseError, getKibanaConfigError } from './helpers'; import * as i18n from './translations'; -interface UsePushToService { +export interface UsePushToService { caseId: string; caseStatus: string; isNew: boolean; @@ -32,7 +32,7 @@ interface Connector { connectorName: string; } -interface ReturnUsePushToService { +export interface ReturnUsePushToService { pushButton: JSX.Element; pushCallouts: JSX.Element | null; } @@ -122,6 +122,7 @@ export const usePushToService = ({ const pushToServiceButton = useMemo( () => ( <EuiButton + data-test-subj="push-to-service-now" fill iconType="importAction" onClick={handlePushToService} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx new file mode 100644 index 0000000000000..5c342538f0feb --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx @@ -0,0 +1,143 @@ +/* + * 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 { getUserAction } from '../__mock__/case_data'; +import { getLabelTitle } from './helpers'; +import * as i18n from '../case_view/translations'; +import { mount } from 'enzyme'; + +describe('User action tree helpers', () => { + it('label title generated for update tags', () => { + const action = getUserAction(['title'], 'update'); + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'tags', + firstIndexPushToService: 0, + index: 0, + }); + + const wrapper = mount(<>{result}</>); + expect( + wrapper + .find(`[data-test-subj="ua-tags-label"]`) + .first() + .text() + ).toEqual(` ${i18n.TAGS.toLowerCase()}`); + + expect( + wrapper + .find(`[data-test-subj="ua-tag"]`) + .first() + .text() + ).toEqual(action.newValue); + }); + it('label title generated for update title', () => { + const action = getUserAction(['title'], 'update'); + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'title', + firstIndexPushToService: 0, + index: 0, + }); + + expect(result).toEqual( + `${i18n.CHANGED_FIELD.toLowerCase()} ${i18n.CASE_NAME.toLowerCase()} ${i18n.TO} "${ + action.newValue + }"` + ); + }); + it('label title generated for update description', () => { + const action = getUserAction(['description'], 'update'); + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'description', + firstIndexPushToService: 0, + index: 0, + }); + + expect(result).toEqual(`${i18n.EDITED_FIELD} ${i18n.DESCRIPTION.toLowerCase()}`); + }); + it('label title generated for update status to open', () => { + const action = { ...getUserAction(['status'], 'update'), newValue: 'open' }; + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'status', + firstIndexPushToService: 0, + index: 0, + }); + + expect(result).toEqual(`${i18n.REOPENED_CASE.toLowerCase()} ${i18n.CASE}`); + }); + it('label title generated for update status to closed', () => { + const action = { ...getUserAction(['status'], 'update'), newValue: 'closed' }; + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'status', + firstIndexPushToService: 0, + index: 0, + }); + + expect(result).toEqual(`${i18n.CLOSED_CASE.toLowerCase()} ${i18n.CASE}`); + }); + it('label title generated for update comment', () => { + const action = getUserAction(['comment'], 'update'); + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'comment', + firstIndexPushToService: 0, + index: 0, + }); + + expect(result).toEqual(`${i18n.EDITED_FIELD} ${i18n.COMMENT.toLowerCase()}`); + }); + it('label title generated for pushed incident', () => { + const action = getUserAction(['pushed'], 'push-to-service'); + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'pushed', + firstIndexPushToService: 0, + index: 0, + }); + + const wrapper = mount(<>{result}</>); + expect( + wrapper + .find(`[data-test-subj="pushed-label"]`) + .first() + .text() + ).toEqual(i18n.PUSHED_NEW_INCIDENT); + expect( + wrapper + .find(`[data-test-subj="pushed-value"]`) + .first() + .prop('href') + ).toEqual(JSON.parse(action.newValue).external_url); + }); + it('label title generated for needs update incident', () => { + const action = getUserAction(['pushed'], 'push-to-service'); + const result: string | JSX.Element = getLabelTitle({ + action, + field: 'pushed', + firstIndexPushToService: 0, + index: 1, + }); + + const wrapper = mount(<>{result}</>); + expect( + wrapper + .find(`[data-test-subj="pushed-label"]`) + .first() + .text() + ).toEqual(i18n.UPDATE_INCIDENT); + expect( + wrapper + .find(`[data-test-subj="pushed-value"]`) + .first() + .prop('href') + ).toEqual(JSON.parse(action.newValue).external_url); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.tsx index 008f4d7048f56..d6016e540bdc0 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.tsx @@ -41,14 +41,16 @@ export const getLabelTitle = ({ action, field, firstIndexPushToService, index }: const getTagsLabelTitle = (action: CaseUserActions) => ( <EuiFlexGroup alignItems="baseline" gutterSize="xs" component="span"> - <EuiFlexItem> + <EuiFlexItem data-test-subj="ua-tags-label"> {action.action === 'add' && i18n.ADDED_FIELD} {action.action === 'delete' && i18n.REMOVED_FIELD} {i18n.TAGS.toLowerCase()} </EuiFlexItem> {action.newValue != null && action.newValue.split(',').map(tag => ( <EuiFlexItem grow={false} key={tag}> - <EuiBadge color="default">{tag}</EuiBadge> + <EuiBadge data-test-subj={`ua-tag`} color="default"> + {tag} + </EuiBadge> </EuiFlexItem> ))} </EuiFlexGroup> @@ -61,12 +63,12 @@ const getPushedServiceLabelTitle = ( ) => { const pushedVal = JSON.parse(action.newValue ?? '') as CaseFullExternalService; return ( - <EuiFlexGroup alignItems="baseline" gutterSize="xs"> - <EuiFlexItem> + <EuiFlexGroup alignItems="baseline" gutterSize="xs" data-test-subj="pushed-service-label-title"> + <EuiFlexItem data-test-subj="pushed-label"> {firstIndexPushToService === index ? i18n.PUSHED_NEW_INCIDENT : i18n.UPDATE_INCIDENT} </EuiFlexItem> <EuiFlexItem grow={false}> - <EuiLink href={pushedVal?.external_url} target="_blank"> + <EuiLink data-test-subj="pushed-value" href={pushedVal?.external_url} target="_blank"> {pushedVal?.connector_name} {pushedVal?.external_title} </EuiLink> </EuiFlexItem> diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx new file mode 100644 index 0000000000000..0d8cd729b4a1d --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx @@ -0,0 +1,331 @@ +/* + * 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 { mount } from 'enzyme'; + +import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router'; +import { getFormMock } from '../__mock__/form'; +import { useUpdateComment } from '../../../../containers/case/use_update_comment'; +import { basicCase, getUserAction } from '../__mock__/case_data'; +import { UserActionTree } from './'; +import { TestProviders } from '../../../../mock'; +import { useFormMock } from '../create/index.test'; +import { wait } from '../../../../lib/helpers'; +import { act } from 'react-dom/test-utils'; +jest.mock( + '../../../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_form' +); + +const fetchUserActions = jest.fn(); +const onUpdateField = jest.fn(); +const updateCase = jest.fn(); +const defaultProps = { + data: basicCase, + caseUserActions: [], + firstIndexPushToService: -1, + isLoadingDescription: false, + isLoadingUserActions: false, + lastIndexPushToService: -1, + userCanCrud: true, + fetchUserActions, + onUpdateField, + updateCase, +}; +const useUpdateCommentMock = useUpdateComment as jest.Mock; +jest.mock('../../../../containers/case/use_update_comment'); + +const patchComment = jest.fn(); +describe('UserActionTree ', () => { + const sampleData = { + content: 'what a great comment update', + }; + beforeEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + useUpdateCommentMock.mockImplementation(() => ({ + isLoadingIds: [], + patchComment, + })); + const formHookMock = getFormMock(sampleData); + useFormMock.mockImplementation(() => ({ form: formHookMock })); + jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation); + }); + + it('Loading spinner when user actions loading and displays fullName/username', () => { + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...{ ...defaultProps, isLoadingUserActions: true }} /> + </Router> + </TestProviders> + ); + expect(wrapper.find(`[data-test-subj="user-actions-loading"]`).exists()).toBeTruthy(); + + expect( + wrapper + .find(`[data-test-subj="user-action-avatar"]`) + .first() + .prop('name') + ).toEqual(defaultProps.data.createdBy.fullName); + expect( + wrapper + .find(`[data-test-subj="user-action-title"] strong`) + .first() + .text() + ).toEqual(defaultProps.data.createdBy.username); + }); + it('Renders service now update line with top and bottom when push is required', () => { + const ourActions = [ + getUserAction(['comment'], 'push-to-service'), + getUserAction(['comment'], 'update'), + ]; + const props = { + ...defaultProps, + caseUserActions: ourActions, + lastIndexPushToService: 0, + }; + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + expect(wrapper.find(`[data-test-subj="show-top-footer"]`).exists()).toBeTruthy(); + expect(wrapper.find(`[data-test-subj="show-bottom-footer"]`).exists()).toBeTruthy(); + }); + it('Renders service now update line with top only when push is up to date', () => { + const ourActions = [getUserAction(['comment'], 'push-to-service')]; + const props = { + ...defaultProps, + caseUserActions: ourActions, + lastIndexPushToService: 0, + }; + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + expect(wrapper.find(`[data-test-subj="show-top-footer"]`).exists()).toBeTruthy(); + expect(wrapper.find(`[data-test-subj="show-bottom-footer"]`).exists()).toBeFalsy(); + }); + + it('Outlines comment when update move to link is clicked', () => { + const ourActions = [getUserAction(['comment'], 'create'), getUserAction(['comment'], 'update')]; + const props = { + ...defaultProps, + caseUserActions: ourActions, + }; + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + expect( + wrapper + .find(`[data-test-subj="comment-create-action"]`) + .first() + .prop('idToOutline') + ).toEqual(''); + wrapper + .find(`[data-test-subj="comment-update-action"] [data-test-subj="move-to-link"]`) + .first() + .simulate('click'); + expect( + wrapper + .find(`[data-test-subj="comment-create-action"]`) + .first() + .prop('idToOutline') + ).toEqual(ourActions[0].commentId); + }); + + it('Switches to markdown when edit is clicked and back to panel when canceled', () => { + const ourActions = [getUserAction(['comment'], 'create')]; + const props = { + ...defaultProps, + caseUserActions: ourActions, + }; + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + expect( + wrapper + .find( + `[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-markdown-form"]` + ) + .exists() + ).toEqual(false); + wrapper + .find(`[data-test-subj="comment-create-action"] [data-test-subj="property-actions-ellipses"]`) + .first() + .simulate('click'); + wrapper + .find(`[data-test-subj="comment-create-action"] [data-test-subj="property-actions-pencil"]`) + .first() + .simulate('click'); + expect( + wrapper + .find( + `[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-markdown-form"]` + ) + .exists() + ).toEqual(true); + wrapper + .find( + `[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-cancel-markdown"]` + ) + .first() + .simulate('click'); + expect( + wrapper + .find( + `[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-markdown-form"]` + ) + .exists() + ).toEqual(false); + }); + + it('calls update comment when comment markdown is saved', async () => { + const ourActions = [getUserAction(['comment'], 'create')]; + const props = { + ...defaultProps, + caseUserActions: ourActions, + }; + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="comment-create-action"] [data-test-subj="property-actions-ellipses"]`) + .first() + .simulate('click'); + wrapper + .find(`[data-test-subj="comment-create-action"] [data-test-subj="property-actions-pencil"]`) + .first() + .simulate('click'); + wrapper + .find( + `[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-save-markdown"]` + ) + .first() + .simulate('click'); + await act(async () => { + await wait(); + wrapper.update(); + expect( + wrapper + .find( + `[data-test-subj="user-action-${props.data.comments[0].id}"] [data-test-subj="user-action-markdown-form"]` + ) + .exists() + ).toEqual(false); + expect(patchComment).toBeCalledWith({ + commentUpdate: sampleData.content, + caseId: props.data.id, + commentId: props.data.comments[0].id, + fetchUserActions, + updateCase, + version: props.data.comments[0].version, + }); + }); + }); + + it('calls update description when description markdown is saved', async () => { + const props = defaultProps; + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="description-action"] [data-test-subj="property-actions-ellipses"]`) + .first() + .simulate('click'); + wrapper + .find(`[data-test-subj="description-action"] [data-test-subj="property-actions-pencil"]`) + .first() + .simulate('click'); + wrapper + .find( + `[data-test-subj="user-action-description"] [data-test-subj="user-action-save-markdown"]` + ) + .first() + .simulate('click'); + await act(async () => { + await wait(); + expect( + wrapper + .find( + `[data-test-subj="user-action-${props.data.id}"] [data-test-subj="user-action-markdown-form"]` + ) + .exists() + ).toEqual(false); + expect(onUpdateField).toBeCalledWith('description', sampleData.content); + }); + }); + + it('quotes', async () => { + const commentData = { + comment: '', + }; + const formHookMock = getFormMock(commentData); + const setFieldValue = jest.fn(); + useFormMock.mockImplementation(() => ({ form: { ...formHookMock, setFieldValue } })); + const props = defaultProps; + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="description-action"] [data-test-subj="property-actions-ellipses"]`) + .first() + .simulate('click'); + wrapper + .find(`[data-test-subj="description-action"] [data-test-subj="property-actions-quote"]`) + .first() + .simulate('click'); + expect(setFieldValue).toBeCalledWith('comment', `> ${props.data.description} \n`); + }); + it('Outlines comment when url param is provided', () => { + const commentId = 'neat-comment-id'; + const ourActions = [getUserAction(['comment'], 'create')]; + const props = { + ...defaultProps, + caseUserActions: ourActions, + }; + jest.spyOn(routeData, 'useParams').mockReturnValue({ commentId }); + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTree {...props} /> + </Router> + </TestProviders> + ); + expect( + wrapper + .find(`[data-test-subj="comment-create-action"]`) + .first() + .prop('idToOutline') + ).toEqual(commentId); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx index 0892d5dcb3ee7..f8f3f0651fa3c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx @@ -60,7 +60,6 @@ export const UserActionTree = React.memo( const currentUser = useCurrentUser(); const [manageMarkdownEditIds, setManangeMardownEditIds] = useState<string[]>([]); const [insertQuote, setInsertQuote] = useState<string | null>(null); - const handleManageMarkdownEditId = useCallback( (id: string) => { if (!manageMarkdownEditIds.includes(id)) { @@ -74,7 +73,6 @@ export const UserActionTree = React.memo( const handleSaveComment = useCallback( ({ id, version }: { id: string; version: string }, content: string) => { - handleManageMarkdownEditId(id); patchComment({ caseId: caseData.id, commentId: id, @@ -135,7 +133,6 @@ export const UserActionTree = React.memo( content={caseData.description} isEditable={manageMarkdownEditIds.includes(DESCRIPTION_ID)} onSaveContent={(content: string) => { - handleManageMarkdownEditId(DESCRIPTION_ID); onUpdateField(DESCRIPTION_ID, content); }} onChangeEditable={handleManageMarkdownEditId} @@ -166,11 +163,11 @@ export const UserActionTree = React.memo( } } }, [commentId, initLoading, isLoadingUserActions, isLoadingIds]); - return ( <> <UserActionItem createdAt={caseData.createdAt} + data-test-subj="description-action" disabled={!userCanCrud} id={DESCRIPTION_ID} isEditable={manageMarkdownEditIds.includes(DESCRIPTION_ID)} @@ -193,6 +190,7 @@ export const UserActionTree = React.memo( <UserActionItem key={action.actionId} createdAt={comment.createdAt} + data-test-subj={`comment-create-action`} disabled={!userCanCrud} id={comment.id} idToOutline={selectedOutlineCommentId} @@ -236,6 +234,7 @@ export const UserActionTree = React.memo( <UserActionItem key={action.actionId} createdAt={action.actionAt} + data-test-subj={`${action.actionField[0]}-${action.action}-action`} disabled={!userCanCrud} id={action.actionId} isEditable={false} @@ -263,11 +262,12 @@ export const UserActionTree = React.memo( {(isLoadingUserActions || isLoadingIds.includes(NEW_ID)) && ( <MyEuiFlexGroup justifyContent="center" alignItems="center"> <EuiFlexItem grow={false}> - <EuiLoadingSpinner size="l" /> + <EuiLoadingSpinner data-test-subj="user-actions-loading" size="l" /> </EuiFlexItem> </MyEuiFlexGroup> )} <UserActionItem + data-test-subj={`add-comment`} createdAt={new Date().toISOString()} disabled={!userCanCrud} id={NEW_ID} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx index bcb4edd6129a6..0acd0623f9413 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_item.tsx @@ -21,6 +21,7 @@ import * as i18n from './translations'; interface UserActionItemProps { createdAt: string; + 'data-test-subj'?: string; disabled: boolean; id: string; isEditable: boolean; @@ -112,6 +113,7 @@ const PushedInfoContainer = styled.div` export const UserActionItem = ({ createdAt, disabled, + 'data-test-subj': dataTestSubj, id, idToOutline, isEditable, @@ -130,7 +132,7 @@ export const UserActionItem = ({ username, updatedAt, }: UserActionItemProps) => ( - <UserActionItemContainer gutterSize={'none'} direction="column"> + <UserActionItemContainer data-test-subj={dataTestSubj} gutterSize={'none'} direction="column"> <EuiFlexItem> <EuiFlexGroup gutterSize={'none'}> <EuiFlexItem data-test-subj={`user-action-${id}-avatar`} grow={false}> @@ -145,24 +147,25 @@ export const UserActionItem = ({ {!isEditable && ( <MyEuiPanel className="userAction__panel" + data-test-subj={`user-action-panel`} paddingSize="none" showoutline={id === idToOutline ? 'true' : 'false'} > <UserActionTitle createdAt={createdAt} disabled={disabled} + fullName={fullName} id={id} isLoading={isLoading} labelEditAction={labelEditAction} labelQuoteAction={labelQuoteAction} labelTitle={labelTitle ?? <></>} linkId={linkId} - fullName={fullName} - username={username} - updatedAt={updatedAt} onEdit={onEdit} onQuote={onQuote} outlineComment={outlineComment} + updatedAt={updatedAt} + username={username} /> {markdown} </MyEuiPanel> @@ -171,7 +174,7 @@ export const UserActionItem = ({ </EuiFlexGroup> </EuiFlexItem> {showTopFooter && ( - <PushedContainer> + <PushedContainer data-test-subj="show-top-footer"> <PushedInfoContainer> <EuiText size="xs" color="subdued"> {i18n.ALREADY_PUSHED_TO_SERVICE} @@ -179,7 +182,7 @@ export const UserActionItem = ({ </PushedInfoContainer> <EuiHorizontalRule /> {showBottomFooter && ( - <PushedInfoContainer> + <PushedInfoContainer data-test-subj="show-bottom-footer"> <EuiText size="xs" color="subdued"> {i18n.REQUIRED_UPDATE_TO_SERVICE} </EuiText> diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_markdown.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_markdown.tsx index e8503bf43375c..827fe2df120ab 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_markdown.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_markdown.tsx @@ -62,12 +62,24 @@ export const UserActionMarkdown = ({ return ( <EuiFlexGroup gutterSize="s" alignItems="center"> <EuiFlexItem grow={false}> - <EuiButtonEmpty size="s" onClick={cancelAction} iconType="cross"> + <EuiButtonEmpty + data-test-subj="user-action-cancel-markdown" + size="s" + onClick={cancelAction} + iconType="cross" + > {i18n.CANCEL} </EuiButtonEmpty> </EuiFlexItem> <EuiFlexItem grow={false}> - <EuiButton color="secondary" fill iconType="save" onClick={saveAction} size="s"> + <EuiButton + data-test-subj="user-action-save-markdown" + color="secondary" + fill + iconType="save" + onClick={saveAction} + size="s" + > {i18n.SAVE} </EuiButton> </EuiFlexItem> @@ -77,7 +89,7 @@ export const UserActionMarkdown = ({ [handleCancelAction, handleSaveAction] ); return isEditable ? ( - <Form form={form}> + <Form form={form} data-test-subj="user-action-markdown-form"> <UseField path="content" component={MarkdownEditorForm} @@ -99,7 +111,7 @@ export const UserActionMarkdown = ({ </Form> ) : ( <ContentWrapper> - <Markdown raw={content} data-test-subj="case-view-description" /> + <Markdown raw={content} data-test-subj="user-action-markdown" /> </ContentWrapper> ); }; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx new file mode 100644 index 0000000000000..e2189367068ca --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import copy from 'copy-to-clipboard'; +import { Router, routeData, mockHistory } from '../__mock__/router'; +import { caseUserActions as basicUserActions } from '../__mock__/case_data'; +import { UserActionTitle } from './user_action_title'; +import { TestProviders } from '../../../../mock'; + +const outlineComment = jest.fn(); +const onEdit = jest.fn(); +const onQuote = jest.fn(); + +jest.mock('copy-to-clipboard'); +const defaultProps = { + createdAt: basicUserActions[0].actionAt, + disabled: false, + fullName: basicUserActions[0].actionBy.fullName, + id: basicUserActions[0].actionId, + isLoading: false, + labelEditAction: 'labelEditAction', + labelQuoteAction: 'labelQuoteAction', + labelTitle: <>{'cool'}</>, + linkId: basicUserActions[0].commentId, + onEdit, + onQuote, + outlineComment, + updatedAt: basicUserActions[0].actionAt, + username: basicUserActions[0].actionBy.username, +}; + +describe('UserActionTitle ', () => { + beforeEach(() => { + jest.resetAllMocks(); + jest.spyOn(routeData, 'useParams').mockReturnValue({ commentId: '123' }); + }); + + it('Calls copy when copy link is clicked', async () => { + const wrapper = mount( + <TestProviders> + <Router history={mockHistory}> + <UserActionTitle {...defaultProps} /> + </Router> + </TestProviders> + ); + wrapper + .find(`[data-test-subj="copy-link"]`) + .first() + .simulate('click'); + expect(copy).toBeCalledTimes(1); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx index 9ccf921c87602..a1edbab7e1fa2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx @@ -52,18 +52,18 @@ interface UserActionTitleProps { export const UserActionTitle = ({ createdAt, disabled, + fullName, id, isLoading, labelEditAction, labelQuoteAction, labelTitle, linkId, - fullName, - username, - updatedAt, onEdit, onQuote, outlineComment, + updatedAt, + username, }: UserActionTitleProps) => { const { detailName: caseId } = useParams(); const urlSearch = useGetUrlSearch(navTabs.case); @@ -94,10 +94,7 @@ export const UserActionTitle = ({ const handleAnchorLink = useCallback(() => { copy( - `${window.location.origin}${window.location.pathname}#${SiemPageName.case}/${caseId}/${id}${urlSearch}`, - { - debug: true, - } + `${window.location.origin}${window.location.pathname}#${SiemPageName.case}/${caseId}/${id}${urlSearch}` ); }, [caseId, id, urlSearch]); @@ -106,7 +103,6 @@ export const UserActionTitle = ({ outlineComment(linkId); } }, [linkId, outlineComment]); - return ( <EuiText size="s" className="userAction__title" data-test-subj={`user-action-title`}> <EuiFlexGroup @@ -155,6 +151,7 @@ export const UserActionTitle = ({ <EuiToolTip position="top" content={<p>{i18n.MOVE_TO_ORIGINAL_COMMENT}</p>}> <EuiButtonIcon aria-label={i18n.MOVE_TO_ORIGINAL_COMMENT} + data-test-subj={`move-to-link`} onClick={handleMoveToLink} iconType="arrowUp" /> @@ -165,6 +162,7 @@ export const UserActionTitle = ({ <EuiToolTip position="top" content={<p>{i18n.COPY_REFERENCE_LINK}</p>}> <EuiButtonIcon aria-label={i18n.COPY_REFERENCE_LINK} + data-test-subj={`copy-link`} onClick={handleAnchorLink} iconType="link" id={`${id}-permLink`} @@ -173,7 +171,7 @@ export const UserActionTitle = ({ </EuiFlexItem> {propertyActions.length > 0 && ( <EuiFlexItem grow={false}> - {isLoading && <MySpinner />} + {isLoading && <MySpinner data-test-subj="user-action-title-loading" />} {!isLoading && <PropertyActions propertyActions={propertyActions} />} </EuiFlexItem> )} diff --git a/x-pack/legacy/plugins/siem/public/pages/case/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/translations.ts index 0d1e6d1435ca3..097b8220156e2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/case/translations.ts @@ -131,6 +131,10 @@ export const TAGS = i18n.translate('xpack.siem.case.caseView.tags', { defaultMessage: 'Tags', }); +export const ACTIONS = i18n.translate('xpack.siem.case.allCases.actions', { + defaultMessage: 'Actions', +}); + export const NO_TAGS_AVAILABLE = i18n.translate('xpack.siem.case.allCases.noTagsAvailable', { defaultMessage: 'No tags available', }); diff --git a/x-pack/plugins/case/server/scripts/generate_case_and_comment_data.sh b/x-pack/plugins/case/server/scripts/generate_case_and_comment_data.sh index 9b6f472d798e0..7ec7dc5a70e92 100755 --- a/x-pack/plugins/case/server/scripts/generate_case_and_comment_data.sh +++ b/x-pack/plugins/case/server/scripts/generate_case_and_comment_data.sh @@ -22,9 +22,9 @@ POSTED_COMMENT="$(curl -s -k \ -u ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD} \ -X POST "${KIBANA_URL}${SPACE_URL}/api/cases/$CASE_ID/comments" \ -d @${COMMENT} \ - | jq '{ commentId: .id, commentVersion: .version }' -)" + | jq '{ commentId: .comments[0].id, commentVersion: .comments[0].version }' \ +-j)" POSTED_CASE=$(./get_case.sh $CASE_ID | jq '{ caseId: .id, caseVersion: .version }' -j) echo ${POSTED_COMMENT} ${POSTED_CASE} \ - | jq -s add; \ No newline at end of file +| jq -s add; diff --git a/x-pack/plugins/case/server/scripts/generate_case_data.sh b/x-pack/plugins/case/server/scripts/generate_case_data.sh index f8f6142a5d733..d3a4d3833ad2e 100755 --- a/x-pack/plugins/case/server/scripts/generate_case_data.sh +++ b/x-pack/plugins/case/server/scripts/generate_case_data.sh @@ -11,6 +11,6 @@ # ./generate_case_data.sh set -e -./check_env_variables.sh -./post_case.sh | jq '{ id: .id, version: .version }' -j; + ./check_env_variables.sh + ./post_case.sh | jq '{ id: .id, version: .version }'; From d5d610f168895ba373dec0db3d0caa64bf6a4b47 Mon Sep 17 00:00:00 2001 From: Robert Austin <robert.austin@elastic.co> Date: Fri, 10 Apr 2020 12:19:29 -0400 Subject: [PATCH 039/121] Endpoint: Remove unused `lib` module (#63248) --- .../public/applications/endpoint/lib/index.ts | 7 - .../applications/endpoint/lib/saga.test.ts | 114 ------------- .../public/applications/endpoint/lib/saga.ts | 159 ------------------ 3 files changed, 280 deletions(-) delete mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/lib/index.ts delete mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts delete mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/lib/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/lib/index.ts deleted file mode 100644 index ba2e1ce8f9fe6..0000000000000 --- a/x-pack/plugins/endpoint/public/applications/endpoint/lib/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './saga'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts deleted file mode 100644 index 7c06681184085..0000000000000 --- a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.test.ts +++ /dev/null @@ -1,114 +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 { createSagaMiddleware, SagaContext, SagaMiddleware } from './index'; -import { applyMiddleware, createStore, Reducer, Store } from 'redux'; - -describe('saga', () => { - const INCREMENT_COUNTER = 'INCREMENT'; - const DELAYED_INCREMENT_COUNTER = 'DELAYED INCREMENT COUNTER'; - const STOP_SAGA_PROCESSING = 'BREAK ASYNC ITERATOR'; - - const sleep = (ms = 100) => new Promise(resolve => setTimeout(resolve, ms)); - let store: Store; - let reducerA: Reducer; - let sideAffect: (a: unknown, s: unknown) => void; - let sagaExe: (sagaContext: SagaContext) => Promise<void>; - let sagaExeReduxMiddleware: SagaMiddleware; - - beforeEach(() => { - reducerA = jest.fn((prevState = { count: 0 }, { type }) => { - switch (type) { - case INCREMENT_COUNTER: - return { ...prevState, count: prevState.count + 1 }; - default: - return prevState; - } - }); - - sideAffect = jest.fn(); - - sagaExe = jest.fn(async ({ actionsAndState, dispatch }: SagaContext) => { - for await (const { action, state } of actionsAndState()) { - expect(action).toBeDefined(); - expect(state).toBeDefined(); - - if (action.type === STOP_SAGA_PROCESSING) { - break; - } - - sideAffect(action, state); - - if (action.type === DELAYED_INCREMENT_COUNTER) { - await sleep(1); - dispatch({ - type: INCREMENT_COUNTER, - }); - } - } - }); - - sagaExeReduxMiddleware = createSagaMiddleware(sagaExe); - store = createStore(reducerA, applyMiddleware(sagaExeReduxMiddleware)); - }); - - afterEach(() => { - sagaExeReduxMiddleware.stop(); - }); - - test('it does nothing if saga is not started', () => { - expect(sagaExe).not.toHaveBeenCalled(); - }); - - test('it can dispatch store actions once running', async () => { - sagaExeReduxMiddleware.start(); - expect(store.getState()).toEqual({ count: 0 }); - expect(sagaExe).toHaveBeenCalled(); - - store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); - expect(store.getState()).toEqual({ count: 0 }); - - await sleep(); - - expect(sideAffect).toHaveBeenCalled(); - expect(store.getState()).toEqual({ count: 1 }); - }); - - test('it stops processing if break out of loop', async () => { - sagaExeReduxMiddleware.start(); - store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); - await sleep(); - - expect(store.getState()).toEqual({ count: 1 }); - expect(sideAffect).toHaveBeenCalledTimes(2); - - store.dispatch({ type: STOP_SAGA_PROCESSING }); - await sleep(); - - store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); - await sleep(); - - expect(store.getState()).toEqual({ count: 1 }); - expect(sideAffect).toHaveBeenCalledTimes(2); - }); - - test('it stops saga middleware when stop() is called', async () => { - sagaExeReduxMiddleware.start(); - store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); - await sleep(); - - expect(store.getState()).toEqual({ count: 1 }); - expect(sideAffect).toHaveBeenCalledTimes(2); - - sagaExeReduxMiddleware.stop(); - - store.dispatch({ type: DELAYED_INCREMENT_COUNTER }); - await sleep(); - - expect(store.getState()).toEqual({ count: 1 }); - expect(sideAffect).toHaveBeenCalledTimes(2); - }); -}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts b/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts deleted file mode 100644 index 2a79827847f2e..0000000000000 --- a/x-pack/plugins/endpoint/public/applications/endpoint/lib/saga.ts +++ /dev/null @@ -1,159 +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 { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux'; -import { GlobalState } from '../types'; - -interface QueuedAction<TAction = AnyAction> { - /** - * The Redux action that was dispatched - */ - action: TAction; - /** - * The Global state at the time the action was dispatched - */ - state: GlobalState; -} - -interface IteratorInstance { - queue: QueuedAction[]; - nextResolve: null | ((inst: QueuedAction) => void); -} - -type Saga = (storeContext: SagaContext) => Promise<void>; - -type StoreActionsAndState<TAction = AnyAction> = AsyncIterableIterator<QueuedAction<TAction>>; - -export interface SagaContext<TAction extends AnyAction = AnyAction> { - /** - * A generator function that will `yield` `Promise`s that resolve with a `QueuedAction` - */ - actionsAndState: () => StoreActionsAndState<TAction>; - dispatch: Dispatch<TAction>; -} - -export interface SagaMiddleware extends Middleware { - /** - * Start the saga. Should be called after the `store` has been created - */ - start: () => void; - - /** - * Stop the saga by exiting the internal generator `for await...of` loop. - */ - stop: () => void; -} - -const noop = () => {}; -const STOP = Symbol('STOP'); - -/** - * Creates Saga Middleware for use with Redux. - * - * @param {Saga} saga The `saga` should initialize a long-running `for await...of` loop against - * the return value of the `actionsAndState()` method provided by the `SagaContext`. - * - * @return {SagaMiddleware} - * - * @example - * - * type TPossibleActions = { type: 'add', payload: any[] }; - * //... - * const endpointsSaga = async ({ actionsAndState, dispatch }: SagaContext<TPossibleActions>) => { - * for await (const { action, state } of actionsAndState()) { - * if (action.type === "userRequestedResource") { - * const resourceData = await doApiFetch('of/some/resource'); - * dispatch({ - * type: 'add', - * payload: [ resourceData ] - * }); - * } - * } - * } - * const endpointsSagaMiddleware = createSagaMiddleware(endpointsSaga); - * //.... - * const store = createStore(reducers, [ endpointsSagaMiddleware ]); - */ -export function createSagaMiddleware(saga: Saga): SagaMiddleware { - const iteratorInstances = new Set<IteratorInstance>(); - let runSaga: () => void = noop; - let stopSaga: () => void = noop; - let runningPromise: Promise<symbol>; - - async function* getActionsAndStateIterator(): StoreActionsAndState { - const instance: IteratorInstance = { queue: [], nextResolve: null }; - iteratorInstances.add(instance); - - try { - while (true) { - const actionAndState = await Promise.race([nextActionAndState(), runningPromise]); - - if (actionAndState === STOP) { - break; - } - - yield actionAndState as QueuedAction; - } - } finally { - // If the consumer stops consuming this (e.g. `break` or `return` is called in the `for await` - // then this `finally` block will run and unregister this instance and reset `runSaga` - iteratorInstances.delete(instance); - runSaga = stopSaga = noop; - } - - function nextActionAndState() { - if (instance.queue.length) { - return Promise.resolve(instance.queue.shift() as QueuedAction); - } else { - return new Promise<QueuedAction>(function(resolve) { - instance.nextResolve = resolve; - }); - } - } - } - - function enqueue(value: QueuedAction) { - for (const iteratorInstance of iteratorInstances) { - iteratorInstance.queue.push(value); - if (iteratorInstance.nextResolve !== null) { - iteratorInstance.nextResolve(iteratorInstance.queue.shift() as QueuedAction); - iteratorInstance.nextResolve = null; - } - } - } - - function middleware({ getState, dispatch }: MiddlewareAPI) { - if (runSaga === noop) { - runSaga = saga.bind<null, SagaContext, any[], Promise<void>>(null, { - actionsAndState: getActionsAndStateIterator, - dispatch, - }); - } - return (next: Dispatch<AnyAction>) => (action: AnyAction) => { - // Call the next dispatch method in the middleware chain. - const returnValue = next(action); - - enqueue({ - action, - state: getState(), - }); - - // This will likely be the action itself, unless a middleware further in chain changed it. - return returnValue; - }; - } - - middleware.start = () => { - runningPromise = new Promise(resolve => (stopSaga = () => resolve(STOP))); - runSaga(); - }; - - middleware.stop = () => { - stopSaga(); - }; - - return middleware; -} From f96f928e6990d64cd7abdb4bedadc1d84557d39c Mon Sep 17 00:00:00 2001 From: Wylie Conlon <william.conlon@elastic.co> Date: Fri, 10 Apr 2020 12:29:26 -0400 Subject: [PATCH 040/121] [Lens] Fix error in query from generated suggestion (#63018) * [Lens] Fix error in query from generated suggestion * Update from review comments * Fix test Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../indexpattern_suggestions.test.tsx | 4 ++-- .../indexpattern_suggestions.ts | 15 +++++++-------- .../operations/definitions/terms.test.tsx | 2 +- .../operations/definitions/terms.tsx | 2 +- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx index e36622f876acd..fe14e5de5c1e3 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx @@ -824,10 +824,10 @@ describe('IndexPattern Data Source suggestions', () => { state: expect.objectContaining({ layers: expect.objectContaining({ currentLayer: expect.objectContaining({ - columnOrder: ['cola', 'id1'], + columnOrder: ['cola', 'colb'], columns: { cola: initialState.layers.currentLayer.columns.cola, - id1: expect.objectContaining({ + colb: expect.objectContaining({ operationType: 'avg', sourceField: 'memory', }), diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts index 96127caa67bb4..d339171a5ae1f 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts +++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts @@ -15,8 +15,8 @@ import { operationDefinitionMap, IndexPatternColumn, } from './operations'; -import { hasField } from './utils'; import { operationDefinitions } from './operations/definitions'; +import { hasField } from './utils'; import { IndexPattern, IndexPatternPrivateState, @@ -196,7 +196,7 @@ function addFieldAsMetricOperation( suggestedPriority: undefined, field, }); - const newColumnId = generateId(); + const addedColumnId = generateId(); const [, metrics] = separateBucketColumns(layer); @@ -206,20 +206,19 @@ function addFieldAsMetricOperation( indexPatternId: indexPattern.id, columns: { ...layer.columns, - [newColumnId]: newColumn, + [addedColumnId]: newColumn, }, - columnOrder: [...layer.columnOrder, newColumnId], + columnOrder: [...layer.columnOrder, addedColumnId], }; } - // If only one metric, replace instead of add - const newColumns = { ...layer.columns, [newColumnId]: newColumn }; - delete newColumns[metrics[0]]; + // Replacing old column with new column, keeping the old ID + const newColumns = { ...layer.columns, [metrics[0]]: newColumn }; return { indexPatternId: indexPattern.id, columns: newColumns, - columnOrder: [...layer.columnOrder.filter(c => c !== metrics[0]), newColumnId], + columnOrder: layer.columnOrder, // Order is kept by replacing }; } diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx index 226246714f18d..fc0c9746b2f98 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx @@ -274,7 +274,7 @@ describe('terms', () => { expect(updatedColumn).toBe(initialColumn); }); - it('should switch to alphabetical ordering if the order column is removed', () => { + it('should switch to alphabetical ordering if there are no columns to order by', () => { const termsColumn = termsOperation.onOtherColumnChanged!( { label: 'Top value of category', diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx index cd0dcc0b7e9ce..387b197c9235c 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx @@ -135,7 +135,7 @@ export const termsOperation: OperationDefinition<TermsIndexPatternColumn> = { } return currentColumn; }, - paramEditor: ({ state, setState, currentColumn, columnId: currentColumnId, layerId }) => { + paramEditor: ({ state, setState, currentColumn, layerId }) => { const SEPARATOR = '$$$'; function toValue(orderBy: TermsIndexPatternColumn['params']['orderBy']) { if (orderBy.type === 'alphabetical') { From 9d2ecc7c06d16ece27449fe2907801024dd438ec Mon Sep 17 00:00:00 2001 From: Brent Kimmel <bkimmel@users.noreply.github.com> Date: Fri, 10 Apr 2020 12:38:26 -0400 Subject: [PATCH 041/121] Resolver/node svg 2 html (#62958) * Remove some SVG in Resolver nodes and replace with HTML --- .../public/embeddables/resolver/view/defs.tsx | 44 +--- .../resolver/view/process_event_dot.tsx | 199 ++++++++++-------- 2 files changed, 113 insertions(+), 130 deletions(-) diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx index 8ee9bfafc630e..de9c3c7e8f8f3 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/defs.tsx @@ -5,7 +5,7 @@ */ import React, { memo } from 'react'; -import { saturate, lighten } from 'polished'; +import { saturate } from 'polished'; import { htmlIdGenerator, @@ -79,8 +79,6 @@ const idGenerator = htmlIdGenerator(); * Ids of paint servers to be referenced by fill and stroke attributes */ export const PaintServerIds = { - runningProcess: idGenerator('psRunningProcess'), - runningTrigger: idGenerator('psRunningTrigger'), runningProcessCube: idGenerator('psRunningProcessCube'), runningTriggerCube: idGenerator('psRunningTriggerCube'), terminatedProcessCube: idGenerator('psTerminatedProcessCube'), @@ -93,46 +91,6 @@ export const PaintServerIds = { */ const PaintServers = memo(() => ( <> - <linearGradient - id={PaintServerIds.runningProcess} - x1="0" - y1="0" - x2="1" - y2="0" - spreadMethod="reflect" - gradientUnits="objectBoundingBox" - > - <stop - offset="0%" - stopColor={saturate(0.7, lighten(0.05, NamedColors.runningProcessStart))} - stopOpacity="1" - /> - <stop - offset="100%" - stopColor={saturate(0.7, lighten(0.05, NamedColors.runningProcessEnd))} - stopOpacity="1" - /> - </linearGradient> - <linearGradient - id={PaintServerIds.runningTrigger} - x1="0" - y1="0" - x2="1" - y2="0" - spreadMethod="reflect" - gradientUnits="objectBoundingBox" - > - <stop - offset="0%" - stopColor={saturate(0.7, lighten(0.05, NamedColors.runningTriggerStart))} - stopOpacity="1" - /> - <stop - offset="100%" - stopColor={saturate(0.7, lighten(0.05, NamedColors.runningTriggerEnd))} - stopOpacity="1" - /> - </linearGradient> <linearGradient id={PaintServerIds.terminatedProcessCube} x1="-381.23752" diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 2e3981de74d34..10e331ffff02d 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -11,7 +11,7 @@ import { htmlIdGenerator, EuiKeyboardAccessible } from '@elastic/eui'; import { useSelector } from 'react-redux'; import { applyMatrix3 } from '../lib/vector2'; import { Vector2, Matrix3, AdjacentProcessMap, ResolverProcessType } from '../types'; -import { SymbolIds, NamedColors, PaintServerIds } from './defs'; +import { SymbolIds, NamedColors } from './defs'; import { ResolverEvent } from '../../../../common/types'; import { useResolverDispatch } from './use_resolver_dispatch'; import * as eventModel from '../../../../common/models/event'; @@ -21,7 +21,7 @@ import * as selectors from '../store/selectors'; const nodeAssets = { runningProcessCube: { cubeSymbol: `#${SymbolIds.runningProcessCube}`, - labelFill: `url(#${PaintServerIds.runningProcess})`, + labelBackground: NamedColors.fullLabelBackground, descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.runningProcess', { defaultMessage: 'Running Process', @@ -29,7 +29,7 @@ const nodeAssets = { }, runningTriggerCube: { cubeSymbol: `#${SymbolIds.runningTriggerCube}`, - labelFill: `url(#${PaintServerIds.runningTrigger})`, + labelBackground: NamedColors.fullLabelBackground, descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.runningTrigger', { defaultMessage: 'Running Trigger', @@ -37,7 +37,7 @@ const nodeAssets = { }, terminatedProcessCube: { cubeSymbol: `#${SymbolIds.terminatedProcessCube}`, - labelFill: NamedColors.fullLabelBackground, + labelBackground: NamedColors.fullLabelBackground, descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.terminatedProcess', { defaultMessage: 'Terminated Process', @@ -45,7 +45,7 @@ const nodeAssets = { }, terminatedTriggerCube: { cubeSymbol: `#${SymbolIds.terminatedTriggerCube}`, - labelFill: NamedColors.fullLabelBackground, + labelBackground: NamedColors.fullLabelBackground, descriptionFill: NamedColors.empty, descriptionText: i18n.translate('xpack.endpoint.resolver.terminatedTrigger', { defaultMessage: 'Terminated Trigger', @@ -114,14 +114,21 @@ export const ProcessEventDot = styled( [left, magFactorX, top] ); + /** + * Type in non-SVG components scales as follows: + * (These values were adjusted to match the proportions in the comps provided by UX/Design) + * 18.75 : The smallest readable font size at which labels/descriptions can be read. Font size will not scale below this. + * 12.5 : A 'slope' at which the font size will scale w.r.t. to zoom level otherwise + */ + const minimumFontSize = 18.75; + const slopeOfFontScale = 12.5; + const fontSizeAdjustmentForScale = magFactorX > 1 ? slopeOfFontScale * (magFactorX - 1) : 0; + const scaledTypeSize = minimumFontSize + fontSizeAdjustmentForScale; + const markerBaseSize = 15; const markerSize = markerBaseSize; const markerPositionOffset = -markerBaseSize / 2; - const labelYOffset = markerPositionOffset + 0.25 * markerSize - 0.5; - - const labelYHeight = markerSize / 1.7647; - /** * An element that should be animated when the node is clicked. */ @@ -136,9 +143,7 @@ export const ProcessEventDot = styled( }) | null; } = React.createRef(); - const { cubeSymbol, labelFill, descriptionFill, descriptionText } = nodeAssets[ - nodeType(event) - ]; + const { cubeSymbol, labelBackground, descriptionText } = nodeAssets[nodeType(event)]; const resolverNodeIdGenerator = useMemo(() => htmlIdGenerator('resolverNode'), []); const nodeId = useMemo(() => resolverNodeIdGenerator(selfId), [ @@ -154,7 +159,7 @@ export const ProcessEventDot = styled( const dispatch = useResolverDispatch(); const handleFocus = useCallback( - (focusEvent: React.FocusEvent<SVGSVGElement>) => { + (focusEvent: React.FocusEvent<HTMLDivElement>) => { dispatch({ type: 'userFocusedOnResolverNode', payload: { @@ -166,7 +171,7 @@ export const ProcessEventDot = styled( ); const handleClick = useCallback( - (clickEvent: React.MouseEvent<SVGSVGElement, MouseEvent>) => { + (clickEvent: React.MouseEvent<HTMLDivElement, MouseEvent>) => { if (animationTarget.current !== null) { (animationTarget.current as any).beginElement(); } @@ -179,14 +184,15 @@ export const ProcessEventDot = styled( }, [animationTarget, dispatch, nodeId] ); - + /* eslint-disable jsx-a11y/click-events-have-key-events */ + /** + * Key event handling (e.g. 'Enter'/'Space') is provisioned by the `EuiKeyboardAccessible` component + */ return ( <EuiKeyboardAccessible> - <svg + <div data-test-subj={'resolverNode'} className={className + ' kbn-resetFocusState'} - viewBox="-15 -15 90 30" - preserveAspectRatio="xMidYMid meet" role="treeitem" aria-level={adjacentNodeMap.level} aria-flowto={ @@ -203,81 +209,100 @@ export const ProcessEventDot = styled( onFocus={handleFocus} tabIndex={-1} > - <g> - <use - xlinkHref={`#${SymbolIds.processCubeActiveBacking}`} - x={-11.35} - y={-11.35} - width={markerSize * 1.5} - height={markerSize * 1.5} - className="backing" - /> - <rect x="7" y="-12.75" width="15" height="10" fill={NamedColors.resolverBackground} /> - <use - role="presentation" - xlinkHref={cubeSymbol} - x={markerPositionOffset} - y={markerPositionOffset} - width={markerSize} - height={markerSize} - opacity="1" - className="cube" - > - <animateTransform - attributeType="XML" - attributeName="transform" - type="scale" - values="1 1; 1 .83; 1 .8; 1 .83; 1 1" - dur="0.2s" - begin="click" - repeatCount="1" - className="squish" - ref={animationTarget} + <svg + viewBox="-15 -15 90 30" + preserveAspectRatio="xMidYMid meet" + style={{ + display: 'block', + width: '100%', + height: '100%', + position: 'absolute', + top: '0', + left: '0', + }} + > + <g> + <use + xlinkHref={`#${SymbolIds.processCubeActiveBacking}`} + x={-11.35} + y={-11.35} + width={markerSize * 1.5} + height={markerSize * 1.5} + className="backing" /> - </use> - <use - role="presentation" - xlinkHref={`#${SymbolIds.processNodeLabel}`} - x={markerPositionOffset + markerSize - 0.5} - y={labelYOffset} - width={(markerSize / 1.7647) * 5} - height={markerSize / 1.7647} - opacity="1" - fill={labelFill} - /> - <text - x={markerPositionOffset + 0.7 * markerSize + 50 / 2} - y={labelYOffset + labelYHeight / 2} - textAnchor="middle" - dominantBaseline="middle" - fontSize="3.75" - fontWeight="bold" - fill={NamedColors.empty} - paintOrder="stroke" - tabIndex={-1} - style={{ letterSpacing: '-0.02px' }} - id={labelId} - > - {eventModel.eventName(event)} - </text> - <text - x={markerPositionOffset + markerSize} - y={labelYOffset - 1} - textAnchor="start" - dominantBaseline="middle" - fontSize="2.67" - fill={descriptionFill} + <use + role="presentation" + xlinkHref={cubeSymbol} + x={markerPositionOffset} + y={markerPositionOffset} + width={markerSize} + height={markerSize} + opacity="1" + className="cube" + > + <animateTransform + attributeType="XML" + attributeName="transform" + type="scale" + values="1 1; 1 .83; 1 .8; 1 .83; 1 1" + dur="0.2s" + begin="click" + repeatCount="1" + className="squish" + ref={animationTarget} + /> + </use> + </g> + </svg> + <div + style={{ + left: '25%', + top: '30%', + position: 'absolute', + width: '50%', + color: 'white', + fontSize: `${scaledTypeSize}px`, + lineHeight: '140%', + }} + > + <div id={descriptionId} - paintOrder="stroke" - fontWeight="bold" - style={{ textTransform: 'uppercase', letterSpacing: '-0.01px' }} + style={{ + textTransform: 'uppercase', + letterSpacing: '-0.01px', + backgroundColor: NamedColors.resolverBackground, + lineHeight: '1.2', + fontWeight: 'bold', + fontSize: '.5em', + width: '100%', + margin: '0 0 .05em 0', + textAlign: 'left', + padding: '0', + }} > {descriptionText} - </text> - </g> - </svg> + </div> + <div + data-test-subject="nodeLabel" + id={labelId} + style={{ + backgroundColor: labelBackground, + padding: '.15em 0', + textAlign: 'center', + maxWidth: '100%', + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + contain: 'content', + }} + > + {eventModel.eventName(event)} + </div> + </div> + </div> </EuiKeyboardAccessible> ); + /* eslint-enable jsx-a11y/click-events-have-key-events */ } ) )` From aed5253b53fdf53781b6220dbe937510cb7ed378 Mon Sep 17 00:00:00 2001 From: Tim Sullivan <tsullivan@users.noreply.github.com> Date: Fri, 10 Apr 2020 09:57:59 -0700 Subject: [PATCH 042/121] [Reporting] convert all server unit tests to TypeScript (#62873) * [Reporting] convert all server unit tests to TypeScript * fix ts * revert unrelated change --- ...{index.test.js.snap => index.test.ts.snap} | 0 ...xecute_job.test.js => execute_job.test.ts} | 227 ++++++++++-------- .../{index.test.js => index.test.ts} | 61 +++-- .../{index.test.js => index.test.ts} | 52 ++-- .../{index.test.js => index.test.ts} | 2 +- .../routes/{jobs.test.js => jobs.test.ts} | 36 +-- ...t.js => reporting_usage_collector.test.ts} | 58 +++-- .../create_mock_browserdriverfactory.ts | 2 +- x-pack/legacy/plugins/reporting/types.d.ts | 2 +- 9 files changed, 273 insertions(+), 167 deletions(-) rename x-pack/legacy/plugins/reporting/__snapshots__/{index.test.js.snap => index.test.ts.snap} (100%) rename x-pack/legacy/plugins/reporting/export_types/csv/server/{execute_job.test.js => execute_job.test.ts} (88%) rename x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/{index.test.js => index.test.ts} (58%) rename x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/{index.test.js => index.test.ts} (57%) rename x-pack/legacy/plugins/reporting/{index.test.js => index.test.ts} (94%) rename x-pack/legacy/plugins/reporting/server/routes/{jobs.test.js => jobs.test.ts} (91%) rename x-pack/legacy/plugins/reporting/server/usage/{reporting_usage_collector.test.js => reporting_usage_collector.test.ts} (90%) diff --git a/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap b/x-pack/legacy/plugins/reporting/__snapshots__/index.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap rename to x-pack/legacy/plugins/reporting/__snapshots__/index.test.ts.snap diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts similarity index 88% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts index 4870e1e35cdaf..f0afade8629ab 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +// @ts-ignore import Puid from 'puid'; import sinon from 'sinon'; import nodeCrypto from '@elastic/node-crypto'; @@ -13,36 +14,40 @@ import { createMockReportingCore } from '../../../test_helpers'; import { LevelLogger } from '../../../server/lib/level_logger'; import { setFieldFormats } from '../../../server/services'; import { executeJobFactory } from './execute_job'; +import { JobDocPayloadDiscoverCsv } from '../types'; import { CSV_BOM_CHARS } from '../../../common/constants'; -const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms)); +const delay = (ms: number) => new Promise(resolve => setTimeout(() => resolve(), ms)); const puid = new Puid(); const getRandomScrollId = () => { return puid.generate(); }; +const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadDiscoverCsv; + describe('CSV Execute Job', function() { const encryptionKey = 'testEncryptionKey'; const headers = { sid: 'test', }; const mockLogger = new LevelLogger({ - get: () => ({ - debug: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }), + get: () => + ({ + debug: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + } as any), }); - let defaultElasticsearchResponse; - let encryptedHeaders; + let defaultElasticsearchResponse: any; + let encryptedHeaders: any; - let clusterStub; - let configGetStub; - let mockReportingConfig; - let mockReportingPlugin; - let callAsCurrentUserStub; - let cancellationToken; + let clusterStub: any; + let configGetStub: any; + let mockReportingConfig: any; + let mockReportingPlugin: any; + let callAsCurrentUserStub: any; + let cancellationToken: any; const mockElasticsearch = { dataClient: { @@ -78,7 +83,7 @@ describe('CSV Execute Job', function() { _scroll_id: 'defaultScrollId', }; clusterStub = { - callAsCurrentUser: function() {}, + callAsCurrentUser() {}, }; callAsCurrentUserStub = sinon @@ -89,17 +94,19 @@ describe('CSV Execute Job', function() { mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true); setFieldFormats({ - fieldFormatServiceFactory: function() { + fieldFormatServiceFactory() { const uiConfigMock = {}; - uiConfigMock['format:defaultTypeMap'] = { + (uiConfigMock as any)['format:defaultTypeMap'] = { _default_: { id: 'string', params: {} }, }; const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry(); - fieldFormatsRegistry.init(key => uiConfigMock[key], {}, [fieldFormats.StringFormat]); + fieldFormatsRegistry.init(key => (uiConfigMock as any)[key], {}, [ + fieldFormats.StringFormat, + ]); - return fieldFormatsRegistry; + return Promise.resolve(fieldFormatsRegistry); }, }); }); @@ -109,7 +116,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); expect(callAsCurrentUserStub.called).toBe(true); @@ -123,14 +134,14 @@ describe('CSV Execute Job', function() { }; const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const job = { + const job = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index, body, }, - }; + }); await executeJob('job777', job, cancellationToken); @@ -152,7 +163,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -166,7 +181,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -196,7 +215,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -231,7 +254,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -257,12 +284,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: undefined, searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot(`[TypeError: Cannot read property 'indexOf' of undefined]`); @@ -284,12 +311,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -309,12 +336,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['=SUM(A1:A2)', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -334,12 +361,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -359,12 +386,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -386,12 +413,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toEqual(`${CSV_BOM_CHARS}one,two\none,bar\n`); @@ -407,12 +434,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toEqual('one,two\none,bar\n'); @@ -423,11 +450,11 @@ describe('CSV Execute Job', function() { it('should reject Promise if search call errors out', async function() { callAsCurrentUserStub.rejects(new Error()); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot(`[Error]`); @@ -442,11 +469,11 @@ describe('CSV Execute Job', function() { }); callAsCurrentUserStub.onSecondCall().rejects(new Error()); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot(`[Error]`); @@ -463,11 +490,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -484,11 +511,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -512,11 +539,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -540,11 +567,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -578,7 +605,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); executeJob( 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -593,13 +624,17 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); executeJob( 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); cancellationToken.cancel(); for (let i = 0; i < callAsCurrentUserStub.callCount; ++i) { - expect(callAsCurrentUserStub.getCall(i).args[1]).to.not.be('clearScroll'); + expect(callAsCurrentUserStub.getCall(i).args[1]).not.toBe('clearScroll'); // dead code? } }); @@ -607,7 +642,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); executeJob( 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); await delay(100); @@ -623,11 +662,11 @@ describe('CSV Execute Job', function() { describe('csv content', function() { it('should write column headers to output, even if there are no results', async function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`one,two\n`); }); @@ -635,11 +674,11 @@ describe('CSV Execute Job', function() { it('should use custom uiSettings csv:separator for header', async function() { mockUiSettingsClient.get.withArgs('csv:separator').returns(';'); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`one;two\n`); }); @@ -647,11 +686,11 @@ describe('CSV Execute Job', function() { it('should escape column headers if uiSettings csv:quoteValues is true', async function() { mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one and a half', 'two', 'three-and-four', 'five & six'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`"one and a half",two,"three-and-four","five & six"\n`); }); @@ -659,11 +698,11 @@ describe('CSV Execute Job', function() { it(`shouldn't escape column headers if uiSettings csv:quoteValues is false`, async function() { mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(false); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one and a half', 'two', 'three-and-four', 'five & six'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`one and a half,two,three-and-four,five & six\n`); }); @@ -677,11 +716,11 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); const headerLine = lines[0]; @@ -697,12 +736,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); const valuesLine = lines[1]; @@ -724,12 +763,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); @@ -746,7 +785,7 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], @@ -760,7 +799,7 @@ describe('CSV Execute Job', function() { fieldFormatMap: '{"one":{"id":"string","params":{"transform": "upper"}}}', }, }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); @@ -774,18 +813,18 @@ describe('CSV Execute Job', function() { // tests use these 'simple' characters to make the math easier describe('when only the headers exceed the maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { configGetStub.withArgs('csv', 'maxSizeBytes').returns(1); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -804,18 +843,18 @@ describe('CSV Execute Job', function() { }); describe('when headers are equal to maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { configGetStub.withArgs('csv', 'maxSizeBytes').returns(9); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -834,8 +873,8 @@ describe('CSV Execute Job', function() { }); describe('when the data exceeds the maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { configGetStub.withArgs('csv', 'maxSizeBytes').returns(9); @@ -848,12 +887,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -872,8 +911,8 @@ describe('CSV Execute Job', function() { }); describe('when headers and data equal the maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { mockReportingPlugin.getUiSettingsServiceFactory = () => mockUiSettingsClient; @@ -887,12 +926,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -924,12 +963,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); await executeJob('job123', jobParams, cancellationToken); @@ -950,12 +989,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); await executeJob('job123', jobParams, cancellationToken); @@ -976,12 +1015,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); await executeJob('job123', jobParams, cancellationToken); diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.ts similarity index 58% rename from x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js rename to x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.ts index cb63e7dad2fdf..c9cba64a732b6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.ts @@ -5,19 +5,22 @@ */ import * as Rx from 'rxjs'; -import { createMockReportingCore } from '../../../../test_helpers'; +import { createMockReportingCore, createMockBrowserDriverFactory } from '../../../../test_helpers'; import { cryptoFactory } from '../../../../server/lib/crypto'; import { executeJobFactory } from './index'; import { generatePngObservableFactory } from '../lib/generate_png'; +import { CancellationToken } from '../../../../common/cancellation_token'; import { LevelLogger } from '../../../../server/lib'; +import { ReportingCore, CaptureConfig } from '../../../../server/types'; +import { JobDocPayloadPNG } from '../../types'; jest.mock('../lib/generate_png', () => ({ generatePngObservableFactory: jest.fn() })); -let mockReporting; +let mockReporting: ReportingCore; -const cancellationToken = { +const cancellationToken = ({ on: jest.fn(), -}; +} as unknown) as CancellationToken; const mockLoggerFactory = { get: jest.fn().mockImplementation(() => ({ @@ -28,12 +31,16 @@ const mockLoggerFactory = { }; const getMockLogger = () => new LevelLogger(mockLoggerFactory); +const captureConfig = {} as CaptureConfig; + const mockEncryptionKey = 'abcabcsecuresecret'; -const encryptHeaders = async headers => { +const encryptHeaders = async (headers: Record<string, string>) => { const crypto = cryptoFactory(mockEncryptionKey); return await crypto.encrypt(headers); }; +const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadPNG; + beforeEach(async () => { const kbnConfig = { 'server.basePath': '/sbp', @@ -45,8 +52,8 @@ beforeEach(async () => { 'kibanaServer.protocol': 'http', }; const mockReportingConfig = { - get: (...keys) => reportingConfig[keys.join('.')], - kbnConfig: { get: (...keys) => kbnConfig[keys.join('.')] }, + get: (...keys: string[]) => (reportingConfig as any)[keys.join('.')], + kbnConfig: { get: (...keys: string[]) => (kbnConfig as any)[keys.join('.')] }, }; mockReporting = await createMockReportingCore(mockReportingConfig); @@ -60,22 +67,30 @@ beforeEach(async () => { mockGetElasticsearch.mockImplementation(() => Promise.resolve(mockElasticsearch)); mockReporting.getElasticsearchService = mockGetElasticsearch; - generatePngObservableFactory.mockReturnValue(jest.fn()); + (generatePngObservableFactory as jest.Mock).mockReturnValue(jest.fn()); }); -afterEach(() => generatePngObservableFactory.mockReset()); +afterEach(() => (generatePngObservableFactory as jest.Mock).mockReset()); test(`passes browserTimezone to generatePng`, async () => { const encryptedHeaders = await encryptHeaders({}); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); - const generatePngObservable = generatePngObservableFactory(); - generatePngObservable.mockReturnValue(Rx.of(Buffer.from(''))); + const generatePngObservable = generatePngObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from(''))); const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const browserTimezone = 'UTC'; await executeJob( 'pngJobId', - { relativeUrl: '/app/kibana#/something', browserTimezone, headers: encryptedHeaders }, + getJobDocPayload({ + relativeUrl: '/app/kibana#/something', + browserTimezone, + headers: encryptedHeaders, + }), cancellationToken ); @@ -92,12 +107,17 @@ test(`returns content_type of application/png`, async () => { const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); - const generatePngObservable = generatePngObservableFactory(); - generatePngObservable.mockReturnValue(Rx.of(Buffer.from(''))); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); + + const generatePngObservable = generatePngObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from(''))); const { content_type: contentType } = await executeJob( 'pngJobId', - { relativeUrl: '/app/kibana#/something', timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }), cancellationToken ); expect(contentType).toBe('image/png'); @@ -106,14 +126,19 @@ test(`returns content_type of application/png`, async () => { test(`returns content of generatePng getBuffer base64 encoded`, async () => { const testContent = 'test content'; - const generatePngObservable = generatePngObservableFactory(); - generatePngObservable.mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); + + const generatePngObservable = generatePngObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pngJobId', - { relativeUrl: '/app/kibana#/something', timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }), cancellationToken ); diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.ts similarity index 57% rename from x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js rename to x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.ts index c6f07f8ad2d34..c3c0d38584bc1 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.ts @@ -5,19 +5,24 @@ */ import * as Rx from 'rxjs'; -import { createMockReportingCore } from '../../../../test_helpers'; +import { createMockReportingCore, createMockBrowserDriverFactory } from '../../../../test_helpers'; import { cryptoFactory } from '../../../../server/lib/crypto'; -import { executeJobFactory } from './index'; -import { generatePdfObservableFactory } from '../lib/generate_pdf'; import { LevelLogger } from '../../../../server/lib'; +import { CancellationToken } from '../../../../types'; +import { ReportingCore, CaptureConfig } from '../../../../server/types'; +import { generatePdfObservableFactory } from '../lib/generate_pdf'; +import { JobDocPayloadPDF } from '../../types'; +import { executeJobFactory } from './index'; jest.mock('../lib/generate_pdf', () => ({ generatePdfObservableFactory: jest.fn() })); -let mockReporting; +let mockReporting: ReportingCore; -const cancellationToken = { +const cancellationToken = ({ on: jest.fn(), -}; +} as unknown) as CancellationToken; + +const captureConfig = {} as CaptureConfig; const mockLoggerFactory = { get: jest.fn().mockImplementation(() => ({ @@ -29,11 +34,13 @@ const mockLoggerFactory = { const getMockLogger = () => new LevelLogger(mockLoggerFactory); const mockEncryptionKey = 'testencryptionkey'; -const encryptHeaders = async headers => { +const encryptHeaders = async (headers: Record<string, string>) => { const crypto = cryptoFactory(mockEncryptionKey); return await crypto.encrypt(headers); }; +const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadPDF; + beforeEach(async () => { const kbnConfig = { 'server.basePath': '/sbp', @@ -45,8 +52,8 @@ beforeEach(async () => { 'kibanaServer.protocol': 'http', }; const mockReportingConfig = { - get: (...keys) => reportingConfig[keys.join('.')], - kbnConfig: { get: (...keys) => kbnConfig[keys.join('.')] }, + get: (...keys: string[]) => (reportingConfig as any)[keys.join('.')], + kbnConfig: { get: (...keys: string[]) => (kbnConfig as any)[keys.join('.')] }, }; mockReporting = await createMockReportingCore(mockReportingConfig); @@ -60,21 +67,26 @@ beforeEach(async () => { mockGetElasticsearch.mockImplementation(() => Promise.resolve(mockElasticsearch)); mockReporting.getElasticsearchService = mockGetElasticsearch; - generatePdfObservableFactory.mockReturnValue(jest.fn()); + (generatePdfObservableFactory as jest.Mock).mockReturnValue(jest.fn()); }); -afterEach(() => generatePdfObservableFactory.mockReset()); +afterEach(() => (generatePdfObservableFactory as jest.Mock).mockReset()); test(`returns content_type of application/pdf`, async () => { - const executeJob = await executeJobFactory(mockReporting, getMockLogger()); + const logger = getMockLogger(); + const executeJob = await executeJobFactory(mockReporting, logger); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(logger); const encryptedHeaders = await encryptHeaders({}); - const generatePdfObservable = generatePdfObservableFactory(); - generatePdfObservable.mockReturnValue(Rx.of(Buffer.from(''))); + const generatePdfObservable = generatePdfObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from(''))); const { content_type: contentType } = await executeJob( 'pdfJobId', - { relativeUrls: [], timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrls: [], headers: encryptedHeaders }), cancellationToken ); expect(contentType).toBe('application/pdf'); @@ -82,15 +94,19 @@ test(`returns content_type of application/pdf`, async () => { test(`returns content of generatePdf getBuffer base64 encoded`, async () => { const testContent = 'test content'; + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); - const generatePdfObservable = generatePdfObservableFactory(); - generatePdfObservable.mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); + const generatePdfObservable = generatePdfObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pdfJobId', - { relativeUrls: [], timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrls: [], headers: encryptedHeaders }), cancellationToken ); diff --git a/x-pack/legacy/plugins/reporting/index.test.js b/x-pack/legacy/plugins/reporting/index.test.ts similarity index 94% rename from x-pack/legacy/plugins/reporting/index.test.js rename to x-pack/legacy/plugins/reporting/index.test.ts index 0d9a717bd7d81..8148adab67874 100644 --- a/x-pack/legacy/plugins/reporting/index.test.js +++ b/x-pack/legacy/plugins/reporting/index.test.ts @@ -27,7 +27,7 @@ const describeWithContext = describe.each([ describeWithContext('config schema with context %j', context => { it('produces correct config', async () => { const schema = await getConfigSchema(reporting); - const value = await schema.validate({}, { context }); + const value: any = await schema.validate({}, { context }); value.capture.browser.chromium.disableSandbox = '<platform dependent>'; await expect(value).toMatchSnapshot(); }); diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts similarity index 91% rename from x-pack/legacy/plugins/reporting/server/routes/jobs.test.js rename to x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts index 9f0de844df369..5c58a7dfa0110 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts @@ -6,7 +6,10 @@ import Hapi from 'hapi'; import { createMockReportingCore } from '../../test_helpers'; +import { ExportTypeDefinition } from '../../types'; import { ExportTypesRegistry } from '../lib/export_types_registry'; +import { LevelLogger } from '../lib/level_logger'; +import { ReportingConfig, ReportingCore, ReportingSetupDeps } from '../types'; jest.mock('./lib/authorized_user_pre_routing', () => ({ authorizedUserPreRoutingFactory: () => () => ({}), @@ -19,14 +22,14 @@ jest.mock('./lib/reporting_feature_pre_routing', () => ({ import { registerJobInfoRoutes } from './jobs'; -let mockServer; -let exportTypesRegistry; -let mockReportingPlugin; -let mockReportingConfig; -const mockLogger = { +let mockServer: any; +let exportTypesRegistry: ExportTypesRegistry; +let mockReportingPlugin: ReportingCore; +let mockReportingConfig: ReportingConfig; +const mockLogger = ({ error: jest.fn(), debug: jest.fn(), -}; +} as unknown) as LevelLogger; beforeEach(async () => { mockServer = new Hapi.Server({ debug: false, port: 8080, routes: { log: { collect: true } } }); @@ -35,38 +38,39 @@ beforeEach(async () => { id: 'unencoded', jobType: 'unencodedJobType', jobContentExtension: 'csv', - }); + } as ExportTypeDefinition<unknown, unknown, unknown, unknown>); exportTypesRegistry.register({ id: 'base64Encoded', jobType: 'base64EncodedJobType', jobContentEncoding: 'base64', jobContentExtension: 'pdf', - }); + } as ExportTypeDefinition<unknown, unknown, unknown, unknown>); mockReportingConfig = { get: jest.fn(), kbnConfig: { get: jest.fn() } }; mockReportingPlugin = await createMockReportingCore(mockReportingConfig); mockReportingPlugin.getExportTypesRegistry = () => exportTypesRegistry; }); -const mockPlugins = { +const mockPlugins = ({ elasticsearch: { adminClient: { callAsInternalUser: jest.fn() }, }, security: null, -}; +} as unknown) as ReportingSetupDeps; -const getHits = (...sources) => { +const getHits = (...sources: any) => { return { hits: { - hits: sources.map(source => ({ _source: source })), + hits: sources.map((source: object) => ({ _source: source })), }, }; }; -const getErrorsFromRequest = request => - request.logs.filter(log => log.tags.includes('error')).map(log => log.error); +const getErrorsFromRequest = (request: any) => + request.logs.filter((log: any) => log.tags.includes('error')).map((log: any) => log.error); test(`returns 404 if job not found`, async () => { + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(getHits())), }; @@ -84,6 +88,7 @@ test(`returns 404 if job not found`, async () => { }); test(`returns 401 if not valid job type`, async () => { + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest .fn() @@ -103,6 +108,7 @@ test(`returns 401 if not valid job type`, async () => { describe(`when job is incomplete`, () => { const getIncompleteResponse = async () => { + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest .fn() @@ -149,6 +155,7 @@ describe(`when job is failed`, () => { status: 'failed', output: { content: 'job failure message' }, }); + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)), }; @@ -194,6 +201,7 @@ describe(`when job is completed`, () => { title, }, }); + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)), }; diff --git a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts similarity index 90% rename from x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js rename to x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts index 929109e66914d..dbc674ce36ec8 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js +++ b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts @@ -11,18 +11,21 @@ import { registerReportingUsageCollector, getReportingUsageCollector, } from './reporting_usage_collector'; +import { ReportingConfig } from '../types'; const exportTypesRegistry = getExportTypesRegistry(); function getMockUsageCollection() { class MockUsageCollector { - constructor(_server, { fetch }) { + // @ts-ignore fetch is not used + private fetch: any; + constructor(_server: any, { fetch }: any) { this.fetch = fetch; } } return { - makeUsageCollector: options => { - return new MockUsageCollector(this, options); + makeUsageCollector: (options: any) => { + return new MockUsageCollector(null, options); }, registerCollector: sinon.stub(), }; @@ -51,7 +54,7 @@ function getPluginsMock( xpack_main: mockXpackMain, }, }, - }; + } as any; } const getMockReportingConfig = () => ({ @@ -61,13 +64,13 @@ const getMockReportingConfig = () => ({ const getResponseMock = (customization = {}) => customization; describe('license checks', () => { - let mockConfig; + let mockConfig: ReportingConfig; beforeAll(async () => { mockConfig = getMockReportingConfig(); }); describe('with a basic license', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'basic' }); const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); @@ -75,9 +78,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -94,7 +100,7 @@ describe('license checks', () => { }); describe('with no license', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'none' }); const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); @@ -102,9 +108,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -121,7 +130,7 @@ describe('license checks', () => { }); describe('with platinum license', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'platinum' }); const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); @@ -129,9 +138,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -148,7 +160,7 @@ describe('license checks', () => { }); describe('with no usage data', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'basic' }); const callClusterMock = jest.fn(() => Promise.resolve({})); @@ -156,9 +168,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -179,7 +194,10 @@ describe('data modeling', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); const callClusterMock = jest.fn(() => Promise.resolve( @@ -303,7 +321,7 @@ describe('data modeling', () => { ) ); - const usageStats = await fetch(callClusterMock); + const usageStats = await fetch(callClusterMock as any); expect(usageStats).toMatchInlineSnapshot(` Object { "PNG": Object { @@ -406,7 +424,7 @@ describe('Ready for collection observable', () => { const makeCollectorSpy = sinon.spy(); usageCollection.makeUsageCollector = makeCollectorSpy; - const plugins = getPluginsMock({ usageCollection }); + const plugins = getPluginsMock({ usageCollection } as any); registerReportingUsageCollector(mockReporting, plugins); const [args] = makeCollectorSpy.firstCall.args; diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts index 930aa7601b8cb..6e95bed2ecf92 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts @@ -92,7 +92,7 @@ const defaultOpts: CreateMockBrowserDriverFactoryOpts = { export const createMockBrowserDriverFactory = async ( logger: Logger, - opts: Partial<CreateMockBrowserDriverFactoryOpts> + opts: Partial<CreateMockBrowserDriverFactoryOpts> = {} ): Promise<HeadlessChromiumDriverFactory> => { const captureConfig = { timeouts: { openUrl: 30000, waitForElements: 30000, renderComplete: 30000 }, diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 7334a859005e0..eec7da7dc6733 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -186,7 +186,7 @@ export type ESQueueWorkerExecuteFn<JobDocPayloadType> = ( jobId: string, job: JobDocPayloadType, cancellationToken?: CancellationToken -) => void; +) => Promise<any>; /* * ImmediateExecuteFn receives the job doc payload because the payload was From d8a295dcbc272cfb7479169e2f99c4665c811816 Mon Sep 17 00:00:00 2001 From: Ryland Herrick <ryalnd@gmail.com> Date: Fri, 10 Apr 2020 14:00:11 -0500 Subject: [PATCH 043/121] [SIEM] Link ML Rule card CTA to license_management (#63210) * Link ML Rule card CTA to license_management Taking the user directly to the license management page within kibana (where they could immediately start a trial subscription) is much more actionable than taking them to the subscriptions marketing page. * Revert translation key change Neither of these is totally accurate, and there've already been translations written for the old one. --- .../components/select_rule_type/index.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx index 9d3b37f1788fa..6f3d299da8d45 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/select_rule_type/index.tsx @@ -19,9 +19,16 @@ import { import { isMlRule } from '../../../../../../common/detection_engine/ml_helpers'; import { RuleType } from '../../../../../../common/detection_engine/types'; import { FieldHook } from '../../../../../shared_imports'; +import { useKibana } from '../../../../../lib/kibana'; import * as i18n from './translations'; -const MlCardDescription = ({ hasValidLicense = false }: { hasValidLicense?: boolean }) => ( +const MlCardDescription = ({ + subscriptionUrl, + hasValidLicense = false, +}: { + subscriptionUrl: string; + hasValidLicense?: boolean; +}) => ( <EuiText size="s"> {hasValidLicense ? ( i18n.ML_TYPE_DESCRIPTION @@ -31,7 +38,7 @@ const MlCardDescription = ({ hasValidLicense = false }: { hasValidLicense?: bool defaultMessage="Access to ML requires a {subscriptionsLink}." values={{ subscriptionsLink: ( - <EuiLink href="https://www.elastic.co/subscriptions" target="_blank"> + <EuiLink href={subscriptionUrl} target="_blank"> <FormattedMessage id="xpack.siem.components.stepDefineRule.ruleTypeField.subscriptionsLink" defaultMessage="Platinum subscription" @@ -69,6 +76,9 @@ export const SelectRuleType: React.FC<SelectRuleTypeProps> = ({ const setMl = useCallback(() => setType('machine_learning'), [setType]); const setQuery = useCallback(() => setType('query'), [setType]); const mlCardDisabled = isReadOnly || !hasValidLicense || !isMlAdmin; + const licensingUrl = useKibana().services.application.getUrlForApp('kibana', { + path: '#/management/elasticsearch/license_management', + }); return ( <EuiFormRow @@ -95,7 +105,9 @@ export const SelectRuleType: React.FC<SelectRuleTypeProps> = ({ <EuiCard data-test-subj="machineLearningRuleType" title={i18n.ML_TYPE_TITLE} - description={<MlCardDescription hasValidLicense={hasValidLicense} />} + description={ + <MlCardDescription subscriptionUrl={licensingUrl} hasValidLicense={hasValidLicense} /> + } icon={<EuiIcon size="l" type="machineLearningApp" />} isDisabled={mlCardDisabled} selectable={{ From 8a283de3c5884e21c245b1136f39132eeb2d976f Mon Sep 17 00:00:00 2001 From: CJ Cenizal <cj@cenizal.com> Date: Fri, 10 Apr 2020 12:05:20 -0700 Subject: [PATCH 044/121] Correctly type ILM's optional dependencies as optional (#63255) And guard against their absence. --- .../public/application/services/ui_metric.ts | 8 +++++--- x-pack/plugins/index_lifecycle_management/public/types.ts | 2 +- .../plugins/index_lifecycle_management/server/plugin.ts | 2 +- x-pack/plugins/index_lifecycle_management/server/types.ts | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts index ca6c0b44d5804..ca987441c7ce9 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts @@ -23,10 +23,12 @@ import { import { defaultColdPhase, defaultWarmPhase, defaultHotPhase } from '../store/defaults'; -export let trackUiMetric: (metricType: UiStatsMetricType, eventName: string) => void; +export let trackUiMetric = (metricType: UiStatsMetricType, eventName: string) => {}; -export function init(usageCollection: UsageCollectionSetup): void { - trackUiMetric = usageCollection.reportUiStats.bind(usageCollection, UIM_APP_NAME); +export function init(usageCollection?: UsageCollectionSetup): void { + if (usageCollection) { + trackUiMetric = usageCollection.reportUiStats.bind(usageCollection, UIM_APP_NAME); + } } export function getUiMetricsForPhases(phases: any): any { diff --git a/x-pack/plugins/index_lifecycle_management/public/types.ts b/x-pack/plugins/index_lifecycle_management/public/types.ts index f9e0abae56cb4..178884a7ee679 100644 --- a/x-pack/plugins/index_lifecycle_management/public/types.ts +++ b/x-pack/plugins/index_lifecycle_management/public/types.ts @@ -9,7 +9,7 @@ import { ManagementSetup } from '../../../../src/plugins/management/public'; import { IndexManagementPluginSetup } from '../../index_management/public'; export interface PluginsDependencies { - usageCollection: UsageCollectionSetup; + usageCollection?: UsageCollectionSetup; management: ManagementSetup; indexManagement?: IndexManagementPluginSetup; } diff --git a/x-pack/plugins/index_lifecycle_management/server/plugin.ts b/x-pack/plugins/index_lifecycle_management/server/plugin.ts index 48c50f9a48ee5..faeac67f62a21 100644 --- a/x-pack/plugins/index_lifecycle_management/server/plugin.ts +++ b/x-pack/plugins/index_lifecycle_management/server/plugin.ts @@ -75,7 +75,7 @@ export class IndexLifecycleManagementServerPlugin implements Plugin<void, void, }); if (config.ui.enabled) { - if (indexManagement.indexDataEnricher) { + if (indexManagement && indexManagement.indexDataEnricher) { indexManagement.indexDataEnricher.add(indexLifecycleDataEnricher); } } diff --git a/x-pack/plugins/index_lifecycle_management/server/types.ts b/x-pack/plugins/index_lifecycle_management/server/types.ts index 7f64c1a47197a..734d05a82000e 100644 --- a/x-pack/plugins/index_lifecycle_management/server/types.ts +++ b/x-pack/plugins/index_lifecycle_management/server/types.ts @@ -14,7 +14,7 @@ import { isEsError } from './lib/is_es_error'; export interface Dependencies { licensing: LicensingPluginSetup; - indexManagement: IndexManagementPluginSetup; + indexManagement?: IndexManagementPluginSetup; } export interface RouteDependencies { From ed5dd0a32542f9f24656dd3aa9c642362d40801b Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh <ahmadbamieh@gmail.com> Date: Fri, 10 Apr 2020 22:18:11 +0300 Subject: [PATCH 045/121] [Telemetry] use prod keys (#63263) --- package.json | 2 +- .../server/encryption/encrypt.test.mocks.ts | 27 +++++++++++++++++++ .../server/encryption/encrypt.test.ts | 27 ++++++++++++------- .../server/encryption/encrypt.ts | 2 +- .../server/plugin.ts | 5 ++-- yarn.lock | 8 +++--- 6 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.mocks.ts diff --git a/package.json b/package.json index ec72d5b660345..a5d46e7f2bf40 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.4.0", - "@elastic/request-crypto": "1.1.2", + "@elastic/request-crypto": "1.1.4", "@elastic/ui-ace": "0.2.3", "@hapi/good-squeeze": "5.2.1", "@hapi/wreck": "^15.0.2", diff --git a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.mocks.ts b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.mocks.ts new file mode 100644 index 0000000000000..9a7cb8ba28d04 --- /dev/null +++ b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.mocks.ts @@ -0,0 +1,27 @@ +/* + * 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 const mockEncrypt = jest.fn(); +export const createRequestEncryptor = jest.fn().mockResolvedValue({ + encrypt: mockEncrypt, +}); + +jest.doMock('@elastic/request-crypto', () => ({ + createRequestEncryptor, +})); diff --git a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts index 4a4ba7aa1f321..c04625eb1dd42 100644 --- a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts +++ b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts @@ -16,16 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - +import { createRequestEncryptor, mockEncrypt } from './encrypt.test.mocks'; import { telemetryJWKS } from './telemetry_jwks'; import { encryptTelemetry, getKID } from './encrypt'; -import { createRequestEncryptor } from '@elastic/request-crypto'; - -jest.mock('@elastic/request-crypto', () => ({ - createRequestEncryptor: jest.fn().mockResolvedValue({ - encrypt: jest.fn(), - }), -})); describe('getKID', () => { it(`returns 'kibana_dev' kid for development`, async () => { @@ -42,9 +35,25 @@ describe('getKID', () => { }); describe('encryptTelemetry', () => { + afterEach(() => { + mockEncrypt.mockReset(); + }); + it('encrypts payload', async () => { const payload = { some: 'value' }; - await encryptTelemetry(payload, true); + await encryptTelemetry(payload, { isProd: true }); expect(createRequestEncryptor).toBeCalledWith(telemetryJWKS); }); + + it('uses kibana kid on { isProd: true }', async () => { + const payload = { some: 'value' }; + await encryptTelemetry(payload, { isProd: true }); + expect(mockEncrypt).toBeCalledWith('kibana', payload); + }); + + it('uses kibana_dev kid on { isProd: false }', async () => { + const payload = { some: 'value' }; + await encryptTelemetry(payload, { isProd: false }); + expect(mockEncrypt).toBeCalledWith('kibana_dev', payload); + }); }); diff --git a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts index c20f4b768b7dc..44f053064cfcb 100644 --- a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts +++ b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts @@ -24,7 +24,7 @@ export function getKID(isProd = false): string { return isProd ? 'kibana' : 'kibana_dev'; } -export async function encryptTelemetry(payload: any, isProd = false): Promise<string[]> { +export async function encryptTelemetry(payload: any, { isProd = false } = {}): Promise<string[]> { const kid = getKID(isProd); const encryptor = await createRequestEncryptor(telemetryJWKS); const clusters = [].concat(payload); diff --git a/src/plugins/telemetry_collection_manager/server/plugin.ts b/src/plugins/telemetry_collection_manager/server/plugin.ts index 7e8dff9e0aec1..f2f20e215c535 100644 --- a/src/plugins/telemetry_collection_manager/server/plugin.ts +++ b/src/plugins/telemetry_collection_manager/server/plugin.ts @@ -158,7 +158,7 @@ export class TelemetryCollectionManagerPlugin if (config.unencrypted) { return optInStats; } - return encryptTelemetry(optInStats, this.isDev); + return encryptTelemetry(optInStats, { isProd: !this.isDev }); } } catch (err) { this.logger.debug(`Failed to collect any opt in stats with registered collections.`); @@ -205,7 +205,8 @@ export class TelemetryCollectionManagerPlugin if (config.unencrypted) { return usageData; } - return encryptTelemetry(usageData, this.isDev); + + return encryptTelemetry(usageData, { isProd: !this.isDev }); } } catch (err) { this.logger.debug( diff --git a/yarn.lock b/yarn.lock index 11abd95498c8d..42f891aa24e25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1401,10 +1401,10 @@ resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.4.0.tgz#883197b7f4bf3c2dd994f53b274769ddfa2bf79a" integrity sha512-uGBKGCNghTgUZPHClji/00v+AKt5nidPTGOIbcT+lbTPVxNB6QPpPLGWtXyrg3QZAxobPM/LAZB1mAqtJeq44Q== -"@elastic/request-crypto@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@elastic/request-crypto/-/request-crypto-1.1.2.tgz#2e323550f546f6286994126d462a9ea480a3bfb1" - integrity sha512-i73wjj1Qi8dGJIy170Z8xyJ760mFNjTbdmcp/nEczqWD0miNW6I5wZ5MNrv7M6CXn2m1wMXiT6qzDYd93Hv1Dw== +"@elastic/request-crypto@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@elastic/request-crypto/-/request-crypto-1.1.4.tgz#2189d5fea65f7afe1de9f5fa3d0dd420e93e3124" + integrity sha512-D5CzSGKkM6BdrVB/HRRTheMsNQOcd2FMUup0O/1hIGUBE8zHh2AYbmSNSpD6LyQAgY39mGkARUi/x+SO0ccVvg== dependencies: "@elastic/node-crypto" "1.1.1" "@types/node-jose" "1.1.0" From eb3fe8eb50be7876128bc592f9ce913259be3ee4 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko <dzmitry.lemechko@elastic.co> Date: Fri, 10 Apr 2020 23:05:20 +0300 Subject: [PATCH 046/121] update chromedriver dependency to 81.0.0 (#63266) --- package.json | 2 +- yarn.lock | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index a5d46e7f2bf40..2bad3116c9ef2 100644 --- a/package.json +++ b/package.json @@ -401,7 +401,7 @@ "chai": "3.5.0", "chance": "1.0.18", "cheerio": "0.22.0", - "chromedriver": "^80.0.1", + "chromedriver": "^81.0.0", "classnames": "2.2.6", "dedent": "^0.7.0", "delete-empty": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index 42f891aa24e25..8ca25cc18a8a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5061,6 +5061,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yauzl@^2.9.1": + version "2.9.1" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af" + integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA== + dependencies: + "@types/node" "*" + "@types/zen-observable@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" @@ -8723,16 +8730,16 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" -chromedriver@^80.0.1: - version "80.0.1" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-80.0.1.tgz#35c1642e2d864b9e8262f291003e455b0e422917" - integrity sha512-VfRtZUpBUIjeypS+xM40+VD9g4Drv7L2VibG/4+0zX3mMx4KayN6gfKETycPfO6JwQXTLSxEr58fRcrsa8r5xQ== +chromedriver@^81.0.0: + version "81.0.0" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-81.0.0.tgz#690ba333aedf2b4c4933b6590c3242d3e5f28f3c" + integrity sha512-BA++IQ7O1FzHmNpzMlOfLiSBvPZ946uuhtJjZHEIr/Gb+Ha9jiuGbHiT45l6O3XGbQ8BAwvbmdisjl4rTxro4A== dependencies: "@testim/chrome-version" "^1.0.7" axios "^0.19.2" del "^5.1.0" - extract-zip "^1.6.7" - mkdirp "^1.0.3" + extract-zip "^2.0.0" + mkdirp "^1.0.4" tcp-port-used "^1.0.1" ci-info@^1.0.0: @@ -13161,6 +13168,17 @@ extract-zip@^1.6.6, extract-zip@^1.6.7, extract-zip@^1.7.0: mkdirp "^0.5.4" yauzl "^2.10.0" +extract-zip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.0.tgz#f53b71d44f4ff5a4527a2259ade000fb8b303492" + integrity sha512-i42GQ498yibjdvIhivUsRslx608whtGoFIhF26Z7O4MYncBxp8CwalOs1lnHy21A9sIohWO2+uiE4SRtC9JXDg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -20622,10 +20640,10 @@ mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkd dependencies: minimist "^1.2.5" -mkdirp@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" - integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== mocha-junit-reporter@^1.23.1: version "1.23.1" From 6393e08ce3ba7cee6f138f2dac6db3a37f6953dc Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Fri, 10 Apr 2020 17:20:40 -0400 Subject: [PATCH 047/121] task/mac-eventing-form (#62999) adds mac events form for endpoint policy details Co-authored-by: oatkiller <robert.austin@elastic.co> --- .../applications/endpoint/models/policy.ts | 4 + .../endpoint/models/policy_details_config.ts | 30 +++++ .../store/policy_details/index.test.ts | 31 ++++- .../endpoint/store/policy_details/reducer.ts | 12 +- .../store/policy_details/selectors.ts | 30 +++-- .../public/applications/endpoint/types.ts | 70 ++++++------ .../endpoint/view/policy/policy_details.tsx | 6 +- .../policy/policy_forms/eventing/checkbox.tsx | 53 --------- .../policy/policy_forms/events/checkbox.tsx | 49 ++++++++ .../view/policy/policy_forms/events/index.tsx | 8 ++ .../view/policy/policy_forms/events/mac.tsx | 106 ++++++++++++++++++ .../{eventing => events}/windows.tsx | 59 +++++----- 12 files changed, 325 insertions(+), 133 deletions(-) delete mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/checkbox.tsx create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/checkbox.tsx create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx rename x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/{eventing => events}/windows.tsx (61%) diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts index 9ac53f9be609f..30f45e54c2005 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts @@ -42,6 +42,8 @@ export const generatePolicy = (): PolicyConfig => { mac: { events: { process: true, + file: true, + network: true, }, malware: { mode: ProtectionModes.detect, @@ -67,6 +69,8 @@ export const generatePolicy = (): PolicyConfig => { linux: { events: { process: true, + file: true, + network: true, }, logging: { stdout: 'debug', diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/models/policy_details_config.ts b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy_details_config.ts index 1145d1d19242a..bf96942e83a91 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/models/policy_details_config.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy_details_config.ts @@ -43,3 +43,33 @@ export function clone(policyDetailsConfig: UIPolicyConfig): UIPolicyConfig { */ return clonedConfig as UIPolicyConfig; } + +/** + * Returns value from `configuration` + */ +export const getIn = (a: UIPolicyConfig) => <Key extends keyof UIPolicyConfig>(key: Key) => < + subKey extends keyof UIPolicyConfig[Key] +>( + subKey: subKey +) => <LeafKey extends keyof UIPolicyConfig[Key][subKey]>( + leafKey: LeafKey +): UIPolicyConfig[Key][subKey][LeafKey] => { + return a[key][subKey][leafKey]; +}; + +/** + * Returns cloned `configuration` with `value` set by the `keyPath`. + */ +export const setIn = (a: UIPolicyConfig) => <Key extends keyof UIPolicyConfig>(key: Key) => < + subKey extends keyof UIPolicyConfig[Key] +>( + subKey: subKey +) => <LeafKey extends keyof UIPolicyConfig[Key][subKey]>(leafKey: LeafKey) => < + V extends UIPolicyConfig[Key][subKey][LeafKey] +>( + v: V +): UIPolicyConfig => { + const c = clone(a); + c[key][subKey][leafKey] = v; + return c; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts index cf14092953227..e09a62b235e35 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts @@ -7,7 +7,7 @@ import { PolicyDetailsState } from '../../types'; import { createStore, Dispatch, Store } from 'redux'; import { policyDetailsReducer, PolicyDetailsAction } from './index'; -import { policyConfig, windowsEventing } from './selectors'; +import { policyConfig } from './selectors'; import { clone } from '../../models/policy_details_config'; import { generatePolicy } from '../../models/policy'; @@ -55,7 +55,7 @@ describe('policy details: ', () => { }); }); - describe('when the user has enabled windows process eventing', () => { + describe('when the user has enabled windows process events', () => { beforeEach(() => { const config = policyConfig(getState()); if (!config) { @@ -71,8 +71,31 @@ describe('policy details: ', () => { }); }); - it('windows process eventing is enabled', async () => { - expect(windowsEventing(getState())!.process).toEqual(true); + it('windows process events is enabled', () => { + const config = policyConfig(getState()); + expect(config!.windows.events.process).toEqual(true); + }); + }); + + describe('when the user has enabled mac file events', () => { + beforeEach(() => { + const config = policyConfig(getState()); + if (!config) { + throw new Error(); + } + + const newPayload1 = clone(config); + newPayload1.mac.events.file = true; + + dispatch({ + type: 'userChangedPolicyConfig', + payload: { policyConfig: newPayload1 }, + }); + }); + + it('mac file events is enabled', () => { + const config = policyConfig(getState()); + expect(config!.mac.events.file).toEqual(true); }); }); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/reducer.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/reducer.ts index fb3e26157ef32..fb0f371cdae0d 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/reducer.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/reducer.ts @@ -5,7 +5,7 @@ */ import { Reducer } from 'redux'; -import { PolicyData, PolicyDetailsState, UIPolicyConfig } from '../../types'; +import { PolicyDetailsState, UIPolicyConfig } from '../../types'; import { AppAction } from '../action'; import { fullPolicy, isOnPolicyDetailsPage } from './selectors'; @@ -89,10 +89,12 @@ export const policyDetailsReducer: Reducer<PolicyDetailsState, AppAction> = ( } if (action.type === 'userChangedPolicyConfig') { - const newState = { ...state, policyItem: { ...(state.policyItem as PolicyData) } }; - const newPolicy = (newState.policyItem.inputs[0].config.policy.value = { - ...fullPolicy(state), - }); + if (!state.policyItem) { + return state; + } + const newState = { ...state, policyItem: { ...state.policyItem } }; + const newPolicy: any = { ...fullPolicy(state) }; + newState.policyItem.inputs[0].config.policy.value = newPolicy; Object.entries(action.payload.policyConfig).forEach(([section, newSettings]) => { newPolicy[section as keyof UIPolicyConfig] = { diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts index 0d505931c9ec5..4b4dc9d9bee43 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts @@ -79,14 +79,8 @@ export const policyConfig: (s: PolicyDetailsState) => UIPolicyConfig = createSel } ); -/** Returns an object of all the windows eventing configuration */ -export const windowsEventing = (state: PolicyDetailsState) => { - const config = policyConfig(state); - return config && config.windows.events; -}; - /** Returns the total number of possible windows eventing configurations */ -export const totalWindowsEventing = (state: PolicyDetailsState): number => { +export const totalWindowsEvents = (state: PolicyDetailsState): number => { const config = policyConfig(state); if (config) { return Object.keys(config.windows.events).length; @@ -95,7 +89,7 @@ export const totalWindowsEventing = (state: PolicyDetailsState): number => { }; /** Returns the number of selected windows eventing configurations */ -export const selectedWindowsEventing = (state: PolicyDetailsState): number => { +export const selectedWindowsEvents = (state: PolicyDetailsState): number => { const config = policyConfig(state); if (config) { return Object.values(config.windows.events).reduce((count, event) => { @@ -105,6 +99,26 @@ export const selectedWindowsEventing = (state: PolicyDetailsState): number => { return 0; }; +/** Returns the total number of possible mac eventing configurations */ +export const totalMacEvents = (state: PolicyDetailsState): number => { + const config = policyConfig(state); + if (config) { + return Object.keys(config.mac.events).length; + } + return 0; +}; + +/** Returns the number of selected mac eventing configurations */ +export const selectedMacEvents = (state: PolicyDetailsState): number => { + const config = policyConfig(state); + if (config) { + return Object.values(config.mac.events).reduce((count, event) => { + return event === true ? count + 1 : count; + }, 0); + } + return 0; +}; + /** is there an api call in flight */ export const isLoading = (state: PolicyDetailsState) => state.isLoading; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index d4f6d2457254e..dda50847169e7 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -118,34 +118,21 @@ export interface PolicyDetailsState { * Endpoint Policy configuration */ export interface PolicyConfig { - windows: { - events: { - process: boolean; - network: boolean; - }; - /** malware mode can be off, detect, prevent or prevent and notify user */ - malware: MalwareFields; + windows: UIPolicyConfig['windows'] & { logging: { stdout: string; file: string; }; advanced: PolicyConfigAdvancedOptions; }; - mac: { - events: { - process: boolean; - }; - malware: MalwareFields; + mac: UIPolicyConfig['mac'] & { logging: { stdout: string; file: string; }; advanced: PolicyConfigAdvancedOptions; }; - linux: { - events: { - process: boolean; - }; + linux: UIPolicyConfig['linux'] & { logging: { stdout: string; file: string; @@ -168,29 +155,39 @@ interface PolicyConfigAdvancedOptions { }; } -/** - * Windows-specific policy configuration that is supported via the UI - */ -type WindowsPolicyConfig = Pick<PolicyConfig['windows'], 'events' | 'malware'>; - -/** - * Mac-specific policy configuration that is supported via the UI - */ -type MacPolicyConfig = Pick<PolicyConfig['mac'], 'malware' | 'events'>; - -/** - * Linux-specific policy configuration that is supported via the UI - */ -type LinuxPolicyConfig = Pick<PolicyConfig['linux'], 'events'>; - /** * The set of Policy configuration settings that are show/edited via the UI */ -export interface UIPolicyConfig { - windows: WindowsPolicyConfig; - mac: MacPolicyConfig; - linux: LinuxPolicyConfig; -} +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +export type UIPolicyConfig = { + windows: { + events: { + process: boolean; + network: boolean; + }; + /** malware mode can be off, detect, prevent or prevent and notify user */ + malware: MalwareFields; + }; + mac: { + events: { + file: boolean; + process: boolean; + network: boolean; + }; + malware: MalwareFields; + }; + + /** + * Linux-specific policy configuration that is supported via the UI + */ + linux: { + events: { + file: boolean; + process: boolean; + network: boolean; + }; + }; +}; /** OS used in Policy */ export enum OS { @@ -203,6 +200,7 @@ export enum OS { export enum EventingFields { process = 'process', network = 'network', + file = 'file', } /** diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx index bc56e5e6f6329..1e723e32615eb 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx @@ -29,12 +29,12 @@ import { isLoading, apiError, } from '../../store/policy_details/selectors'; -import { WindowsEventing } from './policy_forms/eventing/windows'; import { PageView, PageViewHeaderTitle } from '../../components/page_view'; import { AppAction } from '../../types'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { AgentsSummary } from './agents_summary'; import { VerticalDivider } from './vertical_divider'; +import { WindowsEvents, MacEvents } from './policy_forms/events'; import { MalwareProtections } from './policy_forms/protections/malware'; export const PolicyDetails = React.memo(() => { @@ -206,7 +206,9 @@ export const PolicyDetails = React.memo(() => { </h4> </EuiText> <EuiSpacer size="xs" /> - <WindowsEventing /> + <WindowsEvents /> + <EuiSpacer size="l" /> + <MacEvents /> </PageView> </> ); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/checkbox.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/checkbox.tsx deleted file mode 100644 index 8b7fb89ed1646..0000000000000 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/checkbox.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useCallback } from 'react'; -import { EuiCheckbox } from '@elastic/eui'; -import { useDispatch } from 'react-redux'; -import { usePolicyDetailsSelector } from '../../policy_hooks'; -import { policyConfig, windowsEventing } from '../../../../store/policy_details/selectors'; -import { PolicyDetailsAction } from '../../../../store/policy_details'; -import { OS, EventingFields } from '../../../../types'; -import { clone } from '../../../../models/policy_details_config'; - -export const EventingCheckbox: React.FC<{ - id: string; - name: string; - os: OS; - protectionField: EventingFields; -}> = React.memo(({ id, name, os, protectionField }) => { - const policyDetailsConfig = usePolicyDetailsSelector(policyConfig); - const eventing = usePolicyDetailsSelector(windowsEventing); - const dispatch = useDispatch<(action: PolicyDetailsAction) => void>(); - - const handleRadioChange = useCallback( - (event: React.ChangeEvent<HTMLInputElement>) => { - if (policyDetailsConfig) { - const newPayload = clone(policyDetailsConfig); - if (os === OS.linux || os === OS.mac) { - newPayload[os].events.process = event.target.checked; - } else { - newPayload[os].events[protectionField] = event.target.checked; - } - - dispatch({ - type: 'userChangedPolicyConfig', - payload: { policyConfig: newPayload }, - }); - } - }, - [dispatch, os, policyDetailsConfig, protectionField] - ); - - return ( - <EuiCheckbox - id={id} - label={name} - checked={eventing && eventing[protectionField]} - onChange={handleRadioChange} - /> - ); -}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/checkbox.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/checkbox.tsx new file mode 100644 index 0000000000000..bec6b33b85c7f --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/checkbox.tsx @@ -0,0 +1,49 @@ +/* + * 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, { useCallback, useMemo } from 'react'; +import { EuiCheckbox } from '@elastic/eui'; +import { useDispatch } from 'react-redux'; +import { htmlIdGenerator } from '@elastic/eui'; +import { usePolicyDetailsSelector } from '../../policy_hooks'; +import { policyConfig } from '../../../../store/policy_details/selectors'; +import { PolicyDetailsAction } from '../../../../store/policy_details'; +import { UIPolicyConfig } from '../../../../types'; + +export const EventsCheckbox = React.memo(function({ + name, + setter, + getter, +}: { + name: string; + setter: (config: UIPolicyConfig, checked: boolean) => UIPolicyConfig; + getter: (config: UIPolicyConfig) => boolean; +}) { + const policyDetailsConfig = usePolicyDetailsSelector(policyConfig); + const selected = getter(policyDetailsConfig); + const dispatch = useDispatch<(action: PolicyDetailsAction) => void>(); + + const handleCheckboxChange = useCallback( + (event: React.ChangeEvent<HTMLInputElement>) => { + if (policyDetailsConfig) { + dispatch({ + type: 'userChangedPolicyConfig', + payload: { policyConfig: setter(policyDetailsConfig, event.target.checked) }, + }); + } + }, + [dispatch, policyDetailsConfig, setter] + ); + + return ( + <EuiCheckbox + id={useMemo(() => htmlIdGenerator()(), [])} + label={name} + checked={selected} + onChange={handleCheckboxChange} + /> + ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx new file mode 100644 index 0000000000000..44716d8183041 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { WindowsEvents } from './windows'; +export { MacEvents } from './mac'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx new file mode 100644 index 0000000000000..3b69c21d2b150 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx @@ -0,0 +1,106 @@ +/* + * 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, { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; +import { EventsCheckbox } from './checkbox'; +import { OS, UIPolicyConfig } from '../../../../types'; +import { usePolicyDetailsSelector } from '../../policy_hooks'; +import { selectedMacEvents, totalMacEvents } from '../../../../store/policy_details/selectors'; +import { ConfigForm } from '../config_form'; +import { getIn, setIn } from '../../../../models/policy_details_config'; + +export const MacEvents = React.memo(() => { + const selected = usePolicyDetailsSelector(selectedMacEvents); + const total = usePolicyDetailsSelector(totalMacEvents); + + const checkboxes: Array<{ + name: string; + os: 'mac'; + protectionField: keyof UIPolicyConfig['mac']['events']; + }> = useMemo( + () => [ + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.mac.events.file', { + defaultMessage: 'File', + }), + os: OS.mac, + protectionField: 'file', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.mac.events.process', { + defaultMessage: 'Process', + }), + os: OS.mac, + protectionField: 'process', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.mac.events.network', { + defaultMessage: 'Network', + }), + os: OS.mac, + protectionField: 'network', + }, + ], + [] + ); + + const renderCheckboxes = () => { + return ( + <> + <EuiTitle size="xxs"> + <h5> + <FormattedMessage + id="xpack.endpoint.policyDetailsConfig.eventingEvents" + defaultMessage="Events" + /> + </h5> + </EuiTitle> + <EuiSpacer size="s" /> + {checkboxes.map((item, index) => { + return ( + <EventsCheckbox + name={item.name} + key={index} + setter={(config, checked) => + setIn(config)(item.os)('events')(item.protectionField)(checked) + } + getter={config => getIn(config)(item.os)('events')(item.protectionField)} + /> + ); + })} + </> + ); + }; + + const collectionsEnabled = () => { + return ( + <EuiText size="s" color="subdued"> + <FormattedMessage + id="xpack.endpoint.policy.details.eventCollectionsEnabled" + defaultMessage="{selected} / {total} event collections enabled" + values={{ selected, total }} + /> + </EuiText> + ); + }; + + return ( + <ConfigForm + type={i18n.translate('xpack.endpoint.policy.details.eventCollection', { + defaultMessage: 'Event Collection', + })} + supportedOss={[ + i18n.translate('xpack.endpoint.policy.details.mac', { defaultMessage: 'Mac' }), + ]} + id="macEventingForm" + rightCorner={collectionsEnabled()} + children={renderCheckboxes()} + /> + ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/windows.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx similarity index 61% rename from x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/windows.tsx rename to x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx index 7bec2c4c742d2..63a140912437d 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/eventing/windows.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx @@ -8,40 +8,45 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; -import { EventingCheckbox } from './checkbox'; -import { OS, EventingFields } from '../../../../types'; +import { EventsCheckbox } from './checkbox'; +import { OS, UIPolicyConfig } from '../../../../types'; import { usePolicyDetailsSelector } from '../../policy_hooks'; import { - selectedWindowsEventing, - totalWindowsEventing, + selectedWindowsEvents, + totalWindowsEvents, } from '../../../../store/policy_details/selectors'; import { ConfigForm } from '../config_form'; +import { setIn, getIn } from '../../../../models/policy_details_config'; -export const WindowsEventing = React.memo(() => { - const selected = usePolicyDetailsSelector(selectedWindowsEventing); - const total = usePolicyDetailsSelector(totalWindowsEventing); +export const WindowsEvents = React.memo(() => { + const selected = usePolicyDetailsSelector(selectedWindowsEvents); + const total = usePolicyDetailsSelector(totalWindowsEvents); - const checkboxes = useMemo( + const checkboxes: Array<{ + name: string; + os: 'windows'; + protectionField: keyof UIPolicyConfig['windows']['events']; + }> = useMemo( () => [ { - name: i18n.translate('xpack.endpoint.policyDetailsConfig.eventingProcess', { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.process', { defaultMessage: 'Process', }), os: OS.windows, - protectionField: EventingFields.process, + protectionField: 'process', }, { - name: i18n.translate('xpack.endpoint.policyDetailsConfig.eventingNetwork', { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.network', { defaultMessage: 'Network', }), os: OS.windows, - protectionField: EventingFields.network, + protectionField: 'network', }, ], [] ); - const renderCheckboxes = () => { + const renderCheckboxes = useMemo(() => { return ( <> <EuiTitle size="xxs"> @@ -55,20 +60,21 @@ export const WindowsEventing = React.memo(() => { <EuiSpacer size="s" /> {checkboxes.map((item, index) => { return ( - <EventingCheckbox - id={`eventing${item.name}`} + <EventsCheckbox name={item.name} key={index} - os={item.os} - protectionField={item.protectionField} + setter={(config, checked) => + setIn(config)(item.os)('events')(item.protectionField)(checked) + } + getter={config => getIn(config)(item.os)('events')(item.protectionField)} /> ); })} </> ); - }; + }, [checkboxes]); - const collectionsEnabled = () => { + const collectionsEnabled = useMemo(() => { return ( <EuiText size="s" color="subdued"> <FormattedMessage @@ -78,19 +84,22 @@ export const WindowsEventing = React.memo(() => { /> </EuiText> ); - }; + }, [selected, total]); return ( <ConfigForm type={i18n.translate('xpack.endpoint.policy.details.eventCollection', { defaultMessage: 'Event Collection', })} - supportedOss={[ - i18n.translate('xpack.endpoint.policy.details.windows', { defaultMessage: 'Windows' }), - ]} + supportedOss={useMemo( + () => [ + i18n.translate('xpack.endpoint.policy.details.windows', { defaultMessage: 'Windows' }), + ], + [] + )} id="windowsEventingForm" - rightCorner={collectionsEnabled()} - children={renderCheckboxes()} + rightCorner={collectionsEnabled} + children={renderCheckboxes} /> ); }); From 39fbc5e103a50a2d9ef929b05696d478c1090269 Mon Sep 17 00:00:00 2001 From: The SpaceCake Project <randomuserid@users.noreply.github.com> Date: Fri, 10 Apr 2020 17:50:23 -0400 Subject: [PATCH 048/121] bc6 rule import april 9 (#63152) * bc6 rule import april 9 Increased the lookback of the ML rules * re-import with LF chars Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../prepackaged_rules/linux_anomalous_network_activity.json | 2 +- .../linux_anomalous_network_port_activity.json | 2 +- .../prepackaged_rules/linux_anomalous_network_service.json | 2 +- .../prepackaged_rules/linux_anomalous_network_url_activity.json | 2 +- .../prepackaged_rules/linux_anomalous_process_all_hosts.json | 2 +- .../rules/prepackaged_rules/linux_anomalous_user_name.json | 2 +- .../rules/prepackaged_rules/packetbeat_dns_tunneling.json | 2 +- .../rules/prepackaged_rules/packetbeat_rare_dns_question.json | 2 +- .../rules/prepackaged_rules/packetbeat_rare_server_domain.json | 2 +- .../rules/prepackaged_rules/packetbeat_rare_urls.json | 2 +- .../rules/prepackaged_rules/packetbeat_rare_user_agent.json | 2 +- .../rules/prepackaged_rules/rare_process_by_host_linux.json | 2 +- .../rules/prepackaged_rules/rare_process_by_host_windows.json | 2 +- .../rules/prepackaged_rules/suspicious_login_activity.json | 2 +- .../prepackaged_rules/windows_anomalous_network_activity.json | 2 +- .../prepackaged_rules/windows_anomalous_path_activity.json | 2 +- .../prepackaged_rules/windows_anomalous_process_all_hosts.json | 2 +- .../prepackaged_rules/windows_anomalous_process_creation.json | 2 +- .../rules/prepackaged_rules/windows_anomalous_script.json | 2 +- .../rules/prepackaged_rules/windows_anomalous_service.json | 2 +- .../rules/prepackaged_rules/windows_anomalous_user_name.json | 2 +- .../rules/prepackaged_rules/windows_rare_user_runas_event.json | 2 +- .../windows_rare_user_type10_remote_login.json | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json index 1123c1161c4ce..fe248a6c1e23e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that rarely uses the network could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "linux_anomalous_network_activity_ecs", "name": "Unusual Linux Network Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json index 19dd643945b17..d435d4c10f05c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that rarely uses the network could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "linux_anomalous_network_port_activity_ecs", "name": "Unusual Linux Network Port Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json index e2e5803618d06..0b82ce99d0b7f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that rarely uses the network could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "linux_anomalous_network_service", "name": "Unusual Linux Network Service", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json index 40dd2e76c7214..26af34e18a4c8 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json @@ -4,7 +4,7 @@ "false_positives": [ "A new and unusual program or artifact download in the course of software upgrades, debugging, or troubleshooting could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "linux_anomalous_network_url_activity_ecs", "name": "Unusual Linux Web Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json index 6bac2f25fd7de..d15c4fc794378 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that runs rarely as part of a monthly or quarterly workflow could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "linux_anomalous_process_all_hosts_ecs", "name": "Anomalous Process For a Linux Population", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json index 8b7e6c89482f7..2f33948b0a93e 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json @@ -4,7 +4,7 @@ "false_positives": [ "Uncommon user activity can be due to an engineer logging onto a server instance in order to perform manual troubleshooting or reconfiguration." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "linux_anomalous_user_name_ecs", "name": "Unusual Linux Username", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json index c70725dcb645a..765515ffda27c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json @@ -4,7 +4,7 @@ "false_positives": [ "DNS domains that use large numbers of child domains, such as software or content distribution networks, can trigger this signal and such parent domains can be excluded." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "packetbeat_dns_tunneling", "name": "DNS Tunneling", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json index 3ed40ddf27864..79c30c5b38378 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that runs rarely as part of a monthly or quarterly workflow could trigger this signal. Network activity that occurs rarely, in small quantities, can trigger this signal. Possible examples are browsing technical support or vendor networks sparsely. A user who visits a new or unique web destination may trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "packetbeat_rare_dns_question", "name": "Unusual DNS Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json index c49bc95be75d2..7b14ad62f6c93 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json @@ -4,7 +4,7 @@ "false_positives": [ "Web activity that occurs rarely in small quantities can trigger this signal. Possible examples are browsing technical support or vendor URLs that are used very sparsely. A user who visits a new and unique web destination may trigger this signal when the activity is sparse. Web applications that generate URLs unique to a transaction may trigger this when they are used sparsely. Web domains can be excluded in cases such as these." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "packetbeat_rare_server_domain", "name": "Unusual Network Destination Domain Name", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json index 02a4a5f729a16..76767545e794a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json @@ -4,7 +4,7 @@ "false_positives": [ "Web activity that occurs rarely in small quantities can trigger this signal. Possible examples are browsing technical support or vendor URLs that are used very sparsely. A user who visits a new and unique web destination may trigger this signal when the activity is sparse. Web applications that generate URLs unique to a transaction may trigger this when they are used sparsely. Web domains can be excluded in cases such as these." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "packetbeat_rare_urls", "name": "Unusual Web Request", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json index 76ed6b263a704..1dc49203f31c1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json @@ -4,7 +4,7 @@ "false_positives": [ "Web activity that is uncommon, like security scans, may trigger this signal and may need to be excluded. A new or rarely used program that calls web services may trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "packetbeat_rare_user_agent", "name": "Unusual Web User Agent", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json index 048f93e170656..f071677ae8d33 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that runs rarely as part of a monthly or quarterly workflow could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "rare_process_by_host_linux_ecs", "name": "Unusual Process For a Linux Host", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json index 7bc46cdc04dd2..5e0050c6c25ec 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that runs rarely as part of a monthly or quarterly workflow could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "rare_process_by_host_windows_ecs", "name": "Unusual Process For a Windows Host", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json index 915bc1bcfc051..4b94fdc6da147 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json @@ -4,7 +4,7 @@ "false_positives": [ "Security audits may trigger this signal. Conditions that generate bursts of failed logins, such as misconfigured applications or account lockouts could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "suspicious_login_activity_ecs", "name": "Unusual Login Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json index 72671760c9c8d..ca18fe95b1fc1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that rarely uses the network could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_anomalous_network_activity_ecs", "name": "Unusual Windows Network Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json index 082fce438ca9e..8a88607b9d5c9 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json @@ -4,7 +4,7 @@ "false_positives": [ "A new and unusual program or artifact download in the course of software upgrades, debugging, or troubleshooting could trigger this signal. Users downloading and running programs from unusual locations, such as temporary directories, browser caches, or profile paths could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_anomalous_path_activity_ecs", "name": "Unusual Windows Path Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json index 93469b5a06223..1229c4a52b97d 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that runs rarely as part of a monthly or quarterly workflow could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_anomalous_process_all_hosts_ecs", "name": "Anomalous Process For a Windows Population", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json index 1b80e443baae6..98a078ccea4a4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json @@ -4,7 +4,7 @@ "false_positives": [ "Users running scripts in the course of technical support operations of software upgrades could trigger this signal. A newly installed program or one that runs rarely as part of a monthly or quarterly workflow could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_anomalous_process_creation", "name": "Anomalous Windows Process Creation", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json index 4de5443bcaf3f..564ca1782526f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json @@ -4,7 +4,7 @@ "false_positives": [ "Certain kinds of security testing may trigger this signal. PowerShell scripts that use high levels of obfuscation or have unusual script block payloads may trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_anomalous_script", "name": "Suspicious Powershell Script", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json index 7e0641fee68c2..afef569f4ebb4 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json @@ -4,7 +4,7 @@ "false_positives": [ "A newly installed program or one that runs rarely as part of a monthly or quarterly workflow could trigger this signal." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_anomalous_service", "name": "Unusual Windows Service", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json index 217404b6eb474..703dc1a1dc633 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json @@ -4,7 +4,7 @@ "false_positives": [ "Uncommon user activity can be due to an administrator or help desk technician logging onto a workstation or server in order to perform manual troubleshooting or reconfiguration." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_anomalous_user_name_ecs", "name": "Unusual Windows Username", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json index 3dca119b5a28e..febaa57443f76 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json @@ -4,7 +4,7 @@ "false_positives": [ "Uncommon user privilege elevation activity can be due to an administrator, help desk technician, or a user performing manual troubleshooting or reconfiguration." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_rare_user_runas_event", "name": "Unusual Windows User Privilege Elevation Activity", diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json index 09ff2a0cedf41..946cdb95b8e70 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json @@ -4,7 +4,7 @@ "false_positives": [ "Uncommon username activity can be due to an engineer logging onto a server instance in order to perform manual troubleshooting or reconfiguration." ], - "from": "now-16m", + "from": "now-45m", "interval": "15m", "machine_learning_job_id": "windows_rare_user_type10_remote_login", "name": "Unusual Windows Remote User", From fbd15ec8675029a398381ef063fa8a817e21146c Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko <jo.naumenko@gmail.com> Date: Fri, 10 Apr 2020 14:55:03 -0700 Subject: [PATCH 049/121] Added UI for pre-configured connectors. (#63074) * Added UI for pre-configured connectors. * fixed due to comments * Fixed jest tests * Fixed due to comments and added some functional tests * test fix * Fixed failed checks * Fixed functional tests failing --- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../components/add_message_variables.tsx | 3 +- .../action_connector_form/action_form.tsx | 15 +- .../connector_edit_flyout.test.tsx | 56 +++++++ .../connector_edit_flyout.tsx | 137 +++++++++++++----- .../actions_connectors_list.test.tsx | 16 +- .../components/actions_connectors_list.tsx | 78 +++++++--- .../apps/triggers_actions_ui/alerts.ts | 22 ++- .../apps/triggers_actions_ui/connectors.ts | 25 ++++ x-pack/test/functional_with_es_ssl/config.ts | 10 ++ 11 files changed, 286 insertions(+), 78 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 09903c34e2e5e..fe0c58e83e544 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -16102,7 +16102,6 @@ "xpack.triggersActionsUI.sections.builtinActionTypes.emailAction.userTextFieldLabel": "ユーザー名", "xpack.triggersActionsUI.sections.editConnectorForm.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.sections.editConnectorForm.cancelButtonLabel": "キャンセル", - "xpack.triggersActionsUI.sections.editConnectorForm.flyoutTitle": "コネクターを編集", "xpack.triggersActionsUI.sections.editConnectorForm.saveButtonLabel": "保存", "xpack.triggersActionsUI.sections.editConnectorForm.updateErrorNotificationText": "コネクターを更新できません。", "xpack.triggersActionsUI.sections.editConnectorForm.updateSuccessNotificationText": "「{connectorName}」を更新しました", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index cc1b7d7980a0b..fd2a92c2c402f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -16107,7 +16107,6 @@ "xpack.triggersActionsUI.sections.builtinActionTypes.emailAction.userTextFieldLabel": "用户名", "xpack.triggersActionsUI.sections.editConnectorForm.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.editConnectorForm.cancelButtonLabel": "取消", - "xpack.triggersActionsUI.sections.editConnectorForm.flyoutTitle": "编辑连接器", "xpack.triggersActionsUI.sections.editConnectorForm.saveButtonLabel": "保存", "xpack.triggersActionsUI.sections.editConnectorForm.updateErrorNotificationText": "无法更新连接器。", "xpack.triggersActionsUI.sections.editConnectorForm.updateSuccessNotificationText": "已更新“{connectorName}”", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx index ab9b5c2586c17..957c79a5c5123 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx @@ -22,9 +22,10 @@ export const AddMessageVariables: React.FunctionComponent<Props> = ({ const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState<boolean>(false); const getMessageVariables = () => - messageVariables?.map((variable: string) => ( + messageVariables?.map((variable: string, i: number) => ( <EuiContextMenuItem key={variable} + data-test-subj={`variableMenuButton-${i}`} icon="empty" onClick={() => { onSelectEventHandler(variable); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx index 6b011ac84bc6f..5890d9fe07f0e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx @@ -141,15 +141,22 @@ export const ActionForm = ({ }); } } + const preconfiguredMessage = i18n.translate( + 'xpack.triggersActionsUI.sections.actionForm.preconfiguredTitleMessage', + { + defaultMessage: '(pre-configured)', + } + ); const getSelectedOptions = (actionItemId: string) => { const val = connectors.find(connector => connector.id === actionItemId); if (!val) { return []; } + const optionTitle = `${val.name} ${val.isPreconfigured ? preconfiguredMessage : ''}`; return [ { - label: val.name, - value: val.name, + label: optionTitle, + value: optionTitle, id: actionItemId, }, ]; @@ -264,7 +271,9 @@ export const ActionForm = ({ defaultMessage="{actionConnectorName}" id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeEditTitle" values={{ - actionConnectorName: actionConnector.name, + actionConnectorName: `${actionConnector.name} ${ + actionConnector.isPreconfigured ? preconfiguredMessage : '' + }`, }} /> </EuiFlexItem> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.test.tsx index 2c063ea6b4fa6..6659888797679 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.test.tsx @@ -95,4 +95,60 @@ describe('connector_edit_flyout', () => { expect(connectorNameField.exists()).toBeTruthy(); expect(connectorNameField.first().prop('value')).toBe('action-connector'); }); + + test('if pre-configured connector rendered correct in the edit form', () => { + const connector = { + secrets: {}, + id: 'test', + actionTypeId: 'test-action-type-id', + actionType: 'test-action-type-name', + name: 'pre-configured-connector', + isPreconfigured: true, + referencedByCount: 0, + config: {}, + }; + + const actionType = { + id: 'test-action-type-id', + iconClass: 'test', + selectMessage: 'test', + validateConnector: (): ValidationResult => { + return { errors: {} }; + }, + validateParams: (): ValidationResult => { + const validationResult = { errors: {} }; + return validationResult; + }, + actionConnectorFields: null, + actionParamsFields: null, + }; + actionTypeRegistry.get.mockReturnValue(actionType); + actionTypeRegistry.has.mockReturnValue(true); + + const wrapper = mountWithIntl( + <AppContextProvider appDeps={deps}> + <ActionsConnectorsContextProvider + value={{ + http: deps.http, + toastNotifications: deps.toastNotifications, + capabilities: deps.capabilities, + actionTypeRegistry: deps.actionTypeRegistry, + reloadConnectors: () => { + return new Promise<void>(() => {}); + }, + }} + > + <ConnectorEditFlyout + initialConnector={connector} + editFlyoutVisible={true} + setEditFlyoutVisibility={state => {}} + /> + </ActionsConnectorsContextProvider> + </AppContextProvider> + ); + + const preconfiguredBadge = wrapper.find('[data-test-subj="preconfiguredBadge"]'); + expect(preconfiguredBadge.exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="saveEditedActionButton"]').exists()).toBeFalsy(); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx index ed8811d26331b..a81d6c285f460 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React, { useCallback, useReducer, useState } from 'react'; +import React, { useCallback, useReducer, useState, Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, @@ -17,6 +17,8 @@ import { EuiButtonEmpty, EuiButton, EuiBetaBadge, + EuiText, + EuiLink, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ActionConnectorForm, validateBaseProperties } from './action_connector_form'; @@ -91,8 +93,77 @@ export const ConnectorEditFlyout = ({ return undefined; }); + const flyoutTitle = connector.isPreconfigured ? ( + <Fragment> + <EuiTitle size="s"> + <h3 id="flyoutTitle"> + <FormattedMessage + defaultMessage="{connectorName}" + id="xpack.triggersActionsUI.sections.preconfiguredConnectorForm.flyoutTitle" + values={{ connectorName: initialConnector.name }} + /> +   + <EuiBetaBadge + label="Pre-configured" + data-test-subj="preconfiguredBadge" + tooltipContent={i18n.translate( + 'xpack.triggersActionsUI.sections.preconfiguredConnectorForm.tooltipContent', + { + defaultMessage: 'This connector is preconfigured and cannot be edited', + } + )} + /> +   + <EuiBetaBadge + label="Beta" + tooltipContent={i18n.translate( + 'xpack.triggersActionsUI.sections.preconfiguredConnectorForm.betaBadgeTooltipContent', + { + defaultMessage: + '{pluginName} is in beta and is subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.', + values: { + pluginName: PLUGIN.getI18nName(i18n), + }, + } + )} + /> + </h3> + </EuiTitle> + <EuiText size="s"> + <FormattedMessage + defaultMessage="{actionDescription}" + id="xpack.triggersActionsUI.sections.editConnectorForm.actionTypeDescription" + values={{ actionDescription: actionTypeModel.selectMessage }} + /> + </EuiText> + </Fragment> + ) : ( + <EuiTitle size="s"> + <h3 id="flyoutTitle"> + <FormattedMessage + defaultMessage="Edit connector" + id="xpack.triggersActionsUI.sections.editConnectorForm.flyoutPreconfiguredTitle" + /> +   + <EuiBetaBadge + label="Beta" + tooltipContent={i18n.translate( + 'xpack.triggersActionsUI.sections.editConnectorForm.betaBadgeTooltipContent', + { + defaultMessage: + '{pluginName} is in beta and is subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.', + values: { + pluginName: PLUGIN.getI18nName(i18n), + }, + } + )} + /> + </h3> + </EuiTitle> + ); + return ( - <EuiFlyout onClose={closeFlyout} aria-labelledby="flyoutActionAddTitle" size="m"> + <EuiFlyout onClose={closeFlyout} aria-labelledby="flyoutActionEditTitle" size="m"> <EuiFlyoutHeader hasBorder> <EuiFlexGroup gutterSize="s" alignItems="center"> {actionTypeModel ? ( @@ -100,41 +171,37 @@ export const ConnectorEditFlyout = ({ <EuiIcon type={actionTypeModel.iconClass} size="m" /> </EuiFlexItem> ) : null} - <EuiFlexItem> - <EuiTitle size="s"> - <h3 id="flyoutTitle"> - <FormattedMessage - defaultMessage="Edit connector" - id="xpack.triggersActionsUI.sections.editConnectorForm.flyoutTitle" - /> -   - <EuiBetaBadge - label="Beta" - tooltipContent={i18n.translate( - 'xpack.triggersActionsUI.sections.editConnectorForm.betaBadgeTooltipContent', - { - defaultMessage: - '{pluginName} is in beta and is subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.', - values: { - pluginName: PLUGIN.getI18nName(i18n), - }, - } - )} - /> - </h3> - </EuiTitle> - </EuiFlexItem> + <EuiFlexItem>{flyoutTitle}</EuiFlexItem> </EuiFlexGroup> </EuiFlyoutHeader> <EuiFlyoutBody> - <ActionConnectorForm - connector={connector} - errors={errors} - actionTypeName={connector.actionType} - dispatch={dispatch} - actionTypeRegistry={actionTypeRegistry} - http={http} - /> + {!connector.isPreconfigured ? ( + <ActionConnectorForm + connector={connector} + errors={errors} + actionTypeName={connector.actionType} + dispatch={dispatch} + actionTypeRegistry={actionTypeRegistry} + http={http} + /> + ) : ( + <Fragment> + <EuiText> + {i18n.translate( + 'xpack.triggersActionsUI.sections.editConnectorForm.descriptionText', + { + defaultMessage: 'This connector is readonly.', + } + )} + </EuiText> + <EuiLink href="https://www.elastic.co/guide" target="_blank"> + <FormattedMessage + id="xpack.triggersActionsUI.sections.editConnectorForm.preconfiguredHelpLabel" + defaultMessage="Learn more about pre-configured connectors." + /> + </EuiLink> + </Fragment> + )} </EuiFlyoutBody> <EuiFlyoutFooter> <EuiFlexGroup justifyContent="spaceBetween"> @@ -148,7 +215,7 @@ export const ConnectorEditFlyout = ({ )} </EuiButtonEmpty> </EuiFlexItem> - {canSave && actionTypeModel ? ( + {canSave && actionTypeModel && !connector.isPreconfigured ? ( <EuiFlexItem grow={false}> <EuiButton fill diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx index 4fa1e7e4c6e4d..01d21e954bbf3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.test.tsx @@ -111,6 +111,7 @@ describe('actions_connectors_list component with items', () => { id: '1', actionTypeId: 'test', description: 'My test', + isPreconfigured: false, referencedByCount: 1, config: {}, }, @@ -119,6 +120,15 @@ describe('actions_connectors_list component with items', () => { actionTypeId: 'test2', description: 'My test 2', referencedByCount: 1, + isPreconfigured: false, + config: {}, + }, + { + id: '3', + actionTypeId: 'test2', + description: 'My preconfigured test 2', + referencedByCount: 1, + isPreconfigured: true, config: {}, }, ]); @@ -185,7 +195,11 @@ describe('actions_connectors_list component with items', () => { it('renders table of connectors', () => { expect(wrapper.find('EuiInMemoryTable')).toHaveLength(1); - expect(wrapper.find('EuiTableRow')).toHaveLength(2); + expect(wrapper.find('EuiTableRow')).toHaveLength(3); + }); + + it('renders table with preconfigured connectors', () => { + expect(wrapper.find('[data-test-subj="preConfiguredTitleMessage"]')).toHaveLength(2); }); test('if select item for edit should render ConnectorEditFlyout', () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index 47e058f473946..043a644489d82 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -15,6 +15,9 @@ import { EuiIconTip, EuiFlexGroup, EuiFlexItem, + EuiBetaBadge, + EuiToolTip, + EuiButtonIcon, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -200,31 +203,58 @@ export const ActionsConnectorsList: React.FunctionComponent = () => { }, }, { - field: '', + field: 'isPreconfigured', name: '', - actions: [ - { - enabled: () => canDelete, - 'data-test-subj': 'deleteConnector', - name: i18n.translate( - 'xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionName', - { defaultMessage: 'Delete' } - ), - description: canDelete - ? i18n.translate( - 'xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionDescription', - { defaultMessage: 'Delete this connector' } - ) - : i18n.translate( - 'xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionDisabledDescription', - { defaultMessage: 'Unable to delete connectors' } - ), - type: 'icon', - icon: 'trash', - color: 'danger', - onClick: (item: ActionConnectorTableItem) => setConnectorsToDelete([item.id]), - }, - ], + render: (value: number, item: ActionConnectorTableItem) => { + if (item.isPreconfigured) { + return ( + <EuiFlexGroup justifyContent="flexEnd" alignItems="flexEnd"> + <EuiFlexItem grow={false}> + <EuiBetaBadge + data-test-subj="preConfiguredTitleMessage" + label={i18n.translate( + 'xpack.triggersActionsUI.sections.alertForm.preconfiguredTitleMessage', + { + defaultMessage: 'Pre-configured', + } + )} + tooltipContent="This connector can't be deleted." + /> + </EuiFlexItem> + </EuiFlexGroup> + ); + } + return ( + <EuiFlexGroup justifyContent="flexEnd" alignItems="flexEnd"> + <EuiFlexItem grow={false}> + <EuiToolTip + content={ + canDelete + ? i18n.translate( + 'xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionDescription', + { defaultMessage: 'Delete this connector' } + ) + : i18n.translate( + 'xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionDisabledDescription', + { defaultMessage: 'Unable to delete connectors' } + ) + } + > + <EuiButtonIcon + isDisabled={!canDelete} + data-test-subj="deleteConnector" + aria-label={i18n.translate( + 'xpack.triggersActionsUI.sections.actionsConnectorsList.connectorsListTable.columns.actions.deleteActionName', + { defaultMessage: 'Delete' } + )} + onClick={() => setConnectorsToDelete([item.id])} + iconType={'trash'} + /> + </EuiToolTip> + </EuiFlexItem> + </EuiFlexGroup> + ); + }, }, ]; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts index 029af1ea06e4f..c94e7116c5cea 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts.ts @@ -65,23 +65,21 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // need this two out of popup clicks to close them await nameInput.click(); + // test for normal connector + await testSubjects.click('.webhook-ActionTypeSelectOption'); + const webhookBodyInput = await find.byCssSelector('.ace_text-input'); + await webhookBodyInput.focus(); + await webhookBodyInput.type('{\\"test\\":1}'); + + await testSubjects.click('addAlertActionButton'); + // pre-configured connector is loaded an displayed correctly await testSubjects.click('.slack-ActionTypeSelectOption'); - await testSubjects.click('createActionConnectorButton'); - const connectorNameInput = await testSubjects.find('nameInput'); - await connectorNameInput.click(); - await connectorNameInput.clearValue(); - const connectorName = generateUniqueKey(); - await connectorNameInput.type(connectorName); - const slackWebhookUrlInput = await testSubjects.find('slackWebhookUrlInput'); - await slackWebhookUrlInput.click(); - await slackWebhookUrlInput.clearValue(); - await slackWebhookUrlInput.type('https://test'); - await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)'); + expect(await (await find.byCssSelector('#my-slack1')).isDisplayed()).to.be(true); const loggingMessageInput = await testSubjects.find('slackMessageTextArea'); await loggingMessageInput.click(); await loggingMessageInput.clearValue(); await loggingMessageInput.type('test message'); - await testSubjects.click('slackAddVariableButton'); + await testSubjects.click('messageAddVariableButton'); const variableMenuButton = await testSubjects.find('variableMenuButton-0'); await variableMenuButton.click(); await testSubjects.click('saveAlertButton'); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts index b5bcd33c3b9ab..0e6f991be24d0 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts @@ -184,5 +184,30 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const searchResultsAfterDelete = await pageObjects.triggersActionsUI.getConnectorsList(); expect(searchResultsAfterDelete.length).to.eql(0); }); + + it('should not be able to delete a pre-configured connector', async () => { + const preconfiguredConnectorName = 'xyz'; + await pageObjects.triggersActionsUI.searchConnectors(preconfiguredConnectorName); + + const searchResults = await pageObjects.triggersActionsUI.getConnectorsList(); + expect(searchResults.length).to.eql(1); + + expect(await testSubjects.exists('deleteConnector')).to.be(false); + expect(await testSubjects.exists('preConfiguredTitleMessage')).to.be(true); + }); + + it('should not be able to edit a pre-configured connector', async () => { + const preconfiguredConnectorName = 'xyz'; + + await pageObjects.triggersActionsUI.searchConnectors(preconfiguredConnectorName); + + const searchResultsBeforeEdit = await pageObjects.triggersActionsUI.getConnectorsList(); + expect(searchResultsBeforeEdit.length).to.eql(1); + + await find.clickByCssSelector('[data-test-subj="connectorsTableCell-name"] button'); + + expect(await testSubjects.exists('preconfiguredBadge')).to.be(true); + expect(await testSubjects.exists('saveEditedActionButton')).to.be(false); + }); }); }; diff --git a/x-pack/test/functional_with_es_ssl/config.ts b/x-pack/test/functional_with_es_ssl/config.ts index 538817bd9d14c..a620b1d953376 100644 --- a/x-pack/test/functional_with_es_ssl/config.ts +++ b/x-pack/test/functional_with_es_ssl/config.ts @@ -52,6 +52,16 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) { `--plugin-path=${join(__dirname, 'fixtures', 'plugins', 'alerts')}`, '--xpack.actions.enabled=true', '--xpack.alerting.enabled=true', + `--xpack.actions.preconfigured=${JSON.stringify([ + { + id: 'my-slack1', + actionTypeId: '.slack', + name: 'Slack#xyz', + config: { + webhookUrl: 'https://hooks.slack.com/services/abcd/efgh/ijklmnopqrstuvwxyz', + }, + }, + ])}`, ], }, }; From cc85573c8adec5ad5f3828688136c190b8d79e8b Mon Sep 17 00:00:00 2001 From: Brandon Kobel <brandon.kobel@elastic.co> Date: Fri, 10 Apr 2020 16:01:30 -0700 Subject: [PATCH 050/121] TaskManager tasks scheduled without attempting to run (#62078) * TaskManager tasks scheduled without attempting to run * Removing unused import Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- x-pack/plugins/task_manager/server/task_manager.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/task_manager/server/task_manager.ts b/x-pack/plugins/task_manager/server/task_manager.ts index c3f24a4aae88a..a7c67d190e72e 100644 --- a/x-pack/plugins/task_manager/server/task_manager.ts +++ b/x-pack/plugins/task_manager/server/task_manager.ts @@ -9,7 +9,7 @@ import { filter } from 'rxjs/operators'; import { performance } from 'perf_hooks'; import { pipe } from 'fp-ts/lib/pipeable'; -import { Option, none, some, map as mapOptional } from 'fp-ts/lib/Option'; +import { Option, some, map as mapOptional } from 'fp-ts/lib/Option'; import { SavedObjectsSerializer, IScopedClusterClient, @@ -156,8 +156,8 @@ export class TaskManager { this.events$.next(event); }; - private attemptToRun(task: Option<string> = none) { - this.claimRequests$.next(task); + private attemptToRun(task: string) { + this.claimRequests$.next(some(task)); } private createTaskRunnerForTask = (instance: ConcreteTaskInstance) => { @@ -280,9 +280,7 @@ export class TaskManager { ...options, taskInstance: ensureDeprecatedFieldsAreCorrected(taskInstance, this.logger), }); - const result = await this.store.schedule(modifiedTask); - this.attemptToRun(); - return result; + return await this.store.schedule(modifiedTask); } /** @@ -298,7 +296,7 @@ export class TaskManager { .then(resolve) .catch(reject); - this.attemptToRun(some(taskId)); + this.attemptToRun(taskId); }); } From 53ee20b306556b9cecc7f94533481c43eed25b35 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko <jo.naumenko@gmail.com> Date: Fri, 10 Apr 2020 19:18:19 -0700 Subject: [PATCH 051/121] Changed alerting wrong param name for help xpack.encrypted_saved_objects.encryptionKey to xpack.encryptedSavedObjects.encryptionKey (#63307) --- docs/settings/alert-action-settings.asciidoc | 4 ++-- docs/user/alerting/index.asciidoc | 2 +- rfcs/text/0002_encrypted_attributes.md | 2 +- .../public/application/components/health_check.test.tsx | 2 +- .../public/application/components/health_check.tsx | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index d7f1ec637d1df..d4dbe9407b7a9 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -9,7 +9,7 @@ Alerts and actions are enabled by default in {kib}, but require you configure th . <<using-kibana-with-security,Set up {kib} to work with {stack} {security-features}>>. . <<configuring-tls-kib-es,Set up TLS encryption between {kib} and {es}>>. -. <<general-alert-action-settings,Specify a value for `xpack.encrypted_saved_objects.encryptionKey`>>. +. <<general-alert-action-settings,Specify a value for `xpack.encryptedSavedObjects.encryptionKey`>>. You can configure the following settings in the `kibana.yml` file. @@ -18,7 +18,7 @@ You can configure the following settings in the `kibana.yml` file. [[general-alert-action-settings]] ==== General settings -`xpack.encrypted_saved_objects.encryptionKey`:: +`xpack.encryptedSavedObjects.encryptionKey`:: A string of 32 or more characters used to encrypt sensitive properties on alerts and actions before they're stored in {es}. Third party credentials — such as the username and password used to connect to an SMTP service — are an example of encrypted properties. + diff --git a/docs/user/alerting/index.asciidoc b/docs/user/alerting/index.asciidoc index c7cf1186a44be..f556cf71bf06c 100644 --- a/docs/user/alerting/index.asciidoc +++ b/docs/user/alerting/index.asciidoc @@ -157,7 +157,7 @@ Pre-packaged *alert types* simplify setup, hide the details complex domain-speci If you are using an *on-premises* Elastic Stack deployment with <<using-kibana-with-security, *security*>>: * TLS must be configured for communication <<configuring-tls-kib-es, between {es} and {kib}>>. {kib} alerting uses <<api-keys, API keys>> to secure background alert checks and actions, and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. -* In the kibana.yml configuration file, add the <<alert-action-settings-kb,`xpack.encrypted_saved_objects.encryptionKey` setting>> +* In the kibana.yml configuration file, add the <<alert-action-settings-kb,`xpack.encryptedSavedObjects.encryptionKey` setting>> [float] [[alerting-security]] diff --git a/rfcs/text/0002_encrypted_attributes.md b/rfcs/text/0002_encrypted_attributes.md index aa7307edb66bd..c6553c177d995 100644 --- a/rfcs/text/0002_encrypted_attributes.md +++ b/rfcs/text/0002_encrypted_attributes.md @@ -166,7 +166,7 @@ take a look at the source code of this library to know how encryption is perform parameters are used, but in short it's AES Encryption with AES-256-GCM that uses random initialization vector and salt. As with encryption key for Kibana's session cookie, master encryption key used by `encrypted_saved_objects` plugin can be -defined as a configuration value (`xpack.encrypted_saved_objects.encryptionKey`) via `kibana.yml`, but it's **highly +defined as a configuration value (`xpack.encryptedSavedObjects.encryptionKey`) via `kibana.yml`, but it's **highly recommended** to define this key in the [Kibana Keystore](https://www.elastic.co/guide/en/kibana/current/secure-settings.html) instead. The master key should be cryptographically safe and be equal or greater than 32 bytes. diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx index 9c51139993b3f..3fbcd13e98f5d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx @@ -92,7 +92,7 @@ describe('health check', () => { const description = queryByRole(/banner/i); expect(description!.textContent).toMatchInlineSnapshot( - `"To create an alert, set a value for xpack.encrypted_saved_objects.encryptionKey in your kibana.yml file. Learn how."` + `"To create an alert, set a value for xpack.encryptedSavedObjects.encryptionKey in your kibana.yml file. Learn how."` ); const action = queryByText(/Learn/i); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx index c967cf5de0771..afd5e08f52f25 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx @@ -132,7 +132,7 @@ const EncryptionError = ({ defaultMessage: 'To create an alert, set a value for ', } )} - <EuiCode>{'xpack.encrypted_saved_objects.encryptionKey'}</EuiCode> + <EuiCode>{'xpack.encryptedSavedObjects.encryptionKey'}</EuiCode> {i18n.translate( 'xpack.triggersActionsUI.components.healthCheck.encryptionErrorAfterKey', { From bd159c7d59979d66c09c94402daf2c30373ee9f9 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet <pierre.gayvallet@elastic.co> Date: Sat, 11 Apr 2020 09:27:45 +0200 Subject: [PATCH 052/121] fix ScopedHistory.createHref to prepend location with scoped history basePath (#62407) * fix createHref to prepend with scoped history basePath + add option to exclude it. * fix prependBasePath behavior * fix test plugins urls * add pathname to endpoint url builder methods * Revert "add pathname to endpoint url builder methods" This reverts commit 7604932b * adapt createHref instead of prependBasePath * use object options for createHref * update generated doc --- ...in-core-public.scopedhistory.createhref.md | 6 +++-- ...kibana-plugin-core-public.scopedhistory.md | 2 +- .../public/application/scoped_history.test.ts | 25 +++++++++++++++++-- src/core/public/application/scoped_history.ts | 20 ++++++++++++--- src/core/public/public.api.md | 4 ++- .../core_plugin_a/public/application.tsx | 2 +- .../core_plugin_b/public/application.tsx | 2 +- 7 files changed, 50 insertions(+), 11 deletions(-) diff --git a/docs/development/core/public/kibana-plugin-core-public.scopedhistory.createhref.md b/docs/development/core/public/kibana-plugin-core-public.scopedhistory.createhref.md index 7058656d09947..6bbab43ff6ffc 100644 --- a/docs/development/core/public/kibana-plugin-core-public.scopedhistory.createhref.md +++ b/docs/development/core/public/kibana-plugin-core-public.scopedhistory.createhref.md @@ -4,10 +4,12 @@ ## ScopedHistory.createHref property -Creates an href (string) to the location. +Creates an href (string) to the location. If `prependBasePath` is true (default), it will prepend the location's path with the scoped history basePath. <b>Signature:</b> ```typescript -createHref: (location: LocationDescriptorObject<HistoryLocationState>) => string; +createHref: (location: LocationDescriptorObject<HistoryLocationState>, { prependBasePath }?: { + prependBasePath?: boolean | undefined; + }) => string; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md b/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md index 5ea47d2090d71..fa29b32c0bafc 100644 --- a/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md +++ b/docs/development/core/public/kibana-plugin-core-public.scopedhistory.md @@ -28,7 +28,7 @@ export declare class ScopedHistory<HistoryLocationState = unknown> implements Hi | --- | --- | --- | --- | | [action](./kibana-plugin-core-public.scopedhistory.action.md) | | <code>Action</code> | The last action dispatched on the history stack. | | [block](./kibana-plugin-core-public.scopedhistory.block.md) | | <code>(prompt?: string | boolean | History.TransitionPromptHook<HistoryLocationState> | undefined) => UnregisterCallback</code> | Not supported. Use [AppMountParameters.onAppLeave](./kibana-plugin-core-public.appmountparameters.onappleave.md)<!-- -->. | -| [createHref](./kibana-plugin-core-public.scopedhistory.createhref.md) | | <code>(location: LocationDescriptorObject<HistoryLocationState>) => string</code> | Creates an href (string) to the location. | +| [createHref](./kibana-plugin-core-public.scopedhistory.createhref.md) | | <code>(location: LocationDescriptorObject<HistoryLocationState>, { prependBasePath }?: {</code><br/><code> prependBasePath?: boolean | undefined;</code><br/><code> }) => string</code> | Creates an href (string) to the location. If <code>prependBasePath</code> is true (default), it will prepend the location's path with the scoped history basePath. | | [createSubHistory](./kibana-plugin-core-public.scopedhistory.createsubhistory.md) | | <code><SubHistoryLocationState = unknown>(basePath: string) => ScopedHistory<SubHistoryLocationState></code> | Creates a <code>ScopedHistory</code> for a subpath of this <code>ScopedHistory</code>. Useful for applications that may have sub-apps that do not need access to the containing application's history. | | [go](./kibana-plugin-core-public.scopedhistory.go.md) | | <code>(n: number) => void</code> | Send the user forward or backwards in the history stack. | | [goBack](./kibana-plugin-core-public.scopedhistory.goback.md) | | <code>() => void</code> | Send the user one location back in the history stack. Equivalent to calling [ScopedHistory.go(-1)](./kibana-plugin-core-public.scopedhistory.go.md)<!-- -->. If no more entries are available backwards, this is a no-op. | diff --git a/src/core/public/application/scoped_history.test.ts b/src/core/public/application/scoped_history.test.ts index c01eb50830516..a56cffef1e2f2 100644 --- a/src/core/public/application/scoped_history.test.ts +++ b/src/core/public/application/scoped_history.test.ts @@ -268,11 +268,32 @@ describe('ScopedHistory', () => { const gh = createMemoryHistory(); gh.push('/app/wow'); const h = new ScopedHistory(gh, '/app/wow'); - expect(h.createHref({ pathname: '' })).toEqual(`/`); + expect(h.createHref({ pathname: '' })).toEqual(`/app/wow`); + expect(h.createHref({})).toEqual(`/app/wow`); expect(h.createHref({ pathname: '/new-page', search: '?alpha=true' })).toEqual( - `/new-page?alpha=true` + `/app/wow/new-page?alpha=true` ); }); + + it('behave correctly with slash-ending basePath', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow/'); + const h = new ScopedHistory(gh, '/app/wow/'); + expect(h.createHref({ pathname: '' })).toEqual(`/app/wow/`); + expect(h.createHref({ pathname: '/new-page', search: '?alpha=true' })).toEqual( + `/app/wow/new-page?alpha=true` + ); + }); + + it('skips the scoped history path when `prependBasePath` is false', () => { + const gh = createMemoryHistory(); + gh.push('/app/wow'); + const h = new ScopedHistory(gh, '/app/wow'); + expect(h.createHref({ pathname: '' }, { prependBasePath: false })).toEqual(`/`); + expect( + h.createHref({ pathname: '/new-page', search: '?alpha=true' }, { prependBasePath: false }) + ).toEqual(`/new-page?alpha=true`); + }); }); describe('action', () => { diff --git a/src/core/public/application/scoped_history.ts b/src/core/public/application/scoped_history.ts index c5febc7604feb..9fa8f0b7f8148 100644 --- a/src/core/public/application/scoped_history.ts +++ b/src/core/public/application/scoped_history.ts @@ -219,11 +219,26 @@ export class ScopedHistory<HistoryLocationState = unknown> /** * Creates an href (string) to the location. + * If `prependBasePath` is true (default), it will prepend the location's path with the scoped history basePath. * * @param location + * @param prependBasePath */ - public createHref = (location: LocationDescriptorObject<HistoryLocationState>): Href => { + public createHref = ( + location: LocationDescriptorObject<HistoryLocationState>, + { prependBasePath = true }: { prependBasePath?: boolean } = {} + ): Href => { this.verifyActive(); + if (prependBasePath) { + location = this.prependBasePath(location); + if (location.pathname === undefined) { + // we always want to create an url relative to the basePath + // so if pathname is not present, we use the history's basePath as default + // we are doing that here because `prependBasePath` should not + // alter pathname for other method calls + location.pathname = this.basePath; + } + } return this.parentHistory.createHref(location); }; @@ -254,8 +269,7 @@ export class ScopedHistory<HistoryLocationState = unknown> * Prepends the base path to string. */ private prependBasePathToString(path: string): string { - path = path.startsWith('/') ? path.slice(1) : path; - return path.length ? `${this.basePath}/${path}` : this.basePath; + return path.length ? `${this.basePath}/${path}`.replace(/\/{2,}/g, '/') : this.basePath; } /** diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a5aa37becabc2..6d95d1bc7069c 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -1196,7 +1196,9 @@ export class ScopedHistory<HistoryLocationState = unknown> implements History<Hi constructor(parentHistory: History, basePath: string); get action(): Action; block: (prompt?: string | boolean | History.TransitionPromptHook<HistoryLocationState> | undefined) => UnregisterCallback; - createHref: (location: LocationDescriptorObject<HistoryLocationState>) => string; + createHref: (location: LocationDescriptorObject<HistoryLocationState>, { prependBasePath }?: { + prependBasePath?: boolean | undefined; + }) => string; createSubHistory: <SubHistoryLocationState = unknown>(basePath: string) => ScopedHistory<SubHistoryLocationState>; go: (n: number) => void; goBack: () => void; diff --git a/test/plugin_functional/plugins/core_plugin_a/public/application.tsx b/test/plugin_functional/plugins/core_plugin_a/public/application.tsx index abea970749cbc..159bb54f50903 100644 --- a/test/plugin_functional/plugins/core_plugin_a/public/application.tsx +++ b/test/plugin_functional/plugins/core_plugin_a/public/application.tsx @@ -95,7 +95,7 @@ const Nav = withRouter(({ history, navigateToApp }: NavProps) => ( { id: 'home', name: 'Home', - onClick: () => history.push('/'), + onClick: () => history.push(''), 'data-test-subj': 'fooNavHome', }, { diff --git a/test/plugin_functional/plugins/core_plugin_b/public/application.tsx b/test/plugin_functional/plugins/core_plugin_b/public/application.tsx index 447307920c04c..01a63f9782563 100644 --- a/test/plugin_functional/plugins/core_plugin_b/public/application.tsx +++ b/test/plugin_functional/plugins/core_plugin_b/public/application.tsx @@ -102,7 +102,7 @@ const Nav = withRouter(({ history, navigateToApp }: NavProps) => ( { id: 'home', name: 'Home', - onClick: () => navigateToApp('bar', { path: '/' }), + onClick: () => navigateToApp('bar', { path: '' }), 'data-test-subj': 'barNavHome', }, { From 2be6b7fdcecbe2848cc1da23eb98af756f513d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Sat, 11 Apr 2020 10:06:39 +0100 Subject: [PATCH 053/121] fixing custom link popover size and hiding scroll (#63240) --- .../TransactionActionMenu/CustomLink/CustomLinkPopover.tsx | 1 + .../shared/TransactionActionMenu/TransactionActionMenu.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx index a20bc7e21cfc5..3aed1b7ac2953 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/CustomLink/CustomLinkPopover.tsx @@ -19,6 +19,7 @@ import { ManageCustomLink } from './ManageCustomLink'; import { px } from '../../../../style/variables'; const ScrollableContainer = styled.div` + -ms-overflow-style: none; max-height: ${px(535)}; overflow: scroll; `; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx index e3fbcf8485d54..7ebfe26b83630 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx @@ -124,7 +124,7 @@ export const TransactionActionMenu: FunctionComponent<Props> = ({ <ActionMenuButton onClick={() => setIsActionPopoverOpen(true)} /> } > - <div style={{ maxHeight: px(600) }}> + <div style={{ maxHeight: px(600), width: px(335) }}> {isCustomLinksPopoverOpen ? ( <CustomLinkPopover customLinks={customLinks.slice(3, customLinks.length)} From 1199c8c8b0c988d9013149b586bb9a5c941f1072 Mon Sep 17 00:00:00 2001 From: Anton Dosov <anton.dosov@elastic.co> Date: Sun, 12 Apr 2020 17:06:03 +0200 Subject: [PATCH 054/121] Bugfix dashboard unpins filters (#62301) Fixes following cases: Saving dashboard with pinned filter unpins it. Do not save pinned filters with dashboard see #62301 (comment) When navigating with global filter to dashboard with same saved filter, filter becomes unpinned When navigating from listing to dashboard with saved filter, back button didn't work Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../application/dashboard_app_controller.tsx | 14 +++++-- .../application/dashboard_state_manager.ts | 7 ++-- .../public/application/lib/filter_utils.ts | 2 +- .../application/lib/update_saved_dashboard.ts | 7 ++++ .../filter_manager/filter_manager.test.ts | 11 +++--- .../query/filter_manager/filter_manager.ts | 17 ++------- .../data/public/ui/filter_bar/filter_item.tsx | 3 +- .../apps/dashboard/dashboard_filter_bar.js | 38 +++++++++++++++++++ test/functional/services/filter_bar.ts | 15 +++++++- 9 files changed, 85 insertions(+), 29 deletions(-) diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx index d1c7d2d9eba3e..babd1fac274eb 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx @@ -143,6 +143,7 @@ export class DashboardAppController { }); // sync initial app filters from state to filterManager + // if there is an existing similar global filter, then leave it as global filterManager.setAppFilters(_.cloneDeep(dashboardStateManager.appState.filters)); // setup syncing of app filters between appState and filterManager const stopSyncingAppFilters = connectToQueryState( @@ -150,7 +151,11 @@ export class DashboardAppController { { set: ({ filters }) => dashboardStateManager.setFilters(filters || []), get: () => ({ filters: dashboardStateManager.appState.filters }), - state$: dashboardStateManager.appState$.pipe(map(state => ({ filters: state.filters }))), + state$: dashboardStateManager.appState$.pipe( + map(state => ({ + filters: state.filters, + })) + ), }, { filters: esFilters.FilterStateStore.APP_STATE, @@ -170,13 +175,16 @@ export class DashboardAppController { } // starts syncing `_g` portion of url with query services - // note: dashboard_state_manager.ts syncs `_a` portion of url // it is important to start this syncing after `dashboardStateManager.syncTimefilterWithDashboard(timefilter);` above is run, - // otherwise it will case redundant browser history record + // otherwise it will case redundant browser history records const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl( queryService, kbnUrlStateStorage ); + + // starts syncing `_a` portion of url + dashboardStateManager.startStateSyncing(); + $scope.showSaveQuery = dashboardCapabilities.saveQuery as boolean; const getShouldShowEditHelp = () => diff --git a/src/plugins/dashboard/public/application/dashboard_state_manager.ts b/src/plugins/dashboard/public/application/dashboard_state_manager.ts index 6025f535ae761..13ba3c6d0b60d 100644 --- a/src/plugins/dashboard/public/application/dashboard_state_manager.ts +++ b/src/plugins/dashboard/public/application/dashboard_state_manager.ts @@ -164,9 +164,6 @@ export class DashboardStateManager { this.changeListeners.forEach(listener => listener({ dirty: this.isDirty })); }); - // make sure url ('_a') matches initial state - this.kbnUrlStateStorage.set(this.STATE_STORAGE_KEY, initialState, { replace: true }); - // setup state syncing utils. state container will be synced with url into `this.STATE_STORAGE_KEY` query param this.stateSyncRef = syncState<DashboardAppState>({ storageKey: this.STATE_STORAGE_KEY, @@ -201,8 +198,10 @@ export class DashboardStateManager { }, stateStorage: this.kbnUrlStateStorage, }); + } - // actually start syncing state with container + public startStateSyncing() { + this.saveState({ replace: true }); this.stateSyncRef.start(); } diff --git a/src/plugins/dashboard/public/application/lib/filter_utils.ts b/src/plugins/dashboard/public/application/lib/filter_utils.ts index 1ec231db0c3d2..775bf90643a21 100644 --- a/src/plugins/dashboard/public/application/lib/filter_utils.ts +++ b/src/plugins/dashboard/public/application/lib/filter_utils.ts @@ -19,7 +19,7 @@ import _ from 'lodash'; import moment, { Moment } from 'moment'; -import { Filter } from 'src/plugins/data/public'; +import { Filter } from '../../../../data/public'; /** * @typedef {Object} QueryFilter diff --git a/src/plugins/dashboard/public/application/lib/update_saved_dashboard.ts b/src/plugins/dashboard/public/application/lib/update_saved_dashboard.ts index 53dc7d9b460de..fc519327b41ee 100644 --- a/src/plugins/dashboard/public/application/lib/update_saved_dashboard.ts +++ b/src/plugins/dashboard/public/application/lib/update_saved_dashboard.ts @@ -22,6 +22,7 @@ import { RefreshInterval, TimefilterContract } from 'src/plugins/data/public'; import { FilterUtils } from './filter_utils'; import { SavedObjectDashboard } from '../../saved_dashboards'; import { DashboardAppState } from '../../types'; +import { esFilters } from '../../../../data/public'; export function updateSavedDashboard( savedDashboard: SavedObjectDashboard, @@ -48,4 +49,10 @@ export function updateSavedDashboard( 'value', ]); savedDashboard.refreshInterval = savedDashboard.timeRestore ? timeRestoreObj : undefined; + + // save only unpinned filters + const unpinnedFilters = savedDashboard + .getFilters() + .filter(filter => !esFilters.isFilterPinned(filter)); + savedDashboard.searchSource.setField('filter', unpinnedFilters); } diff --git a/src/plugins/data/public/query/filter_manager/filter_manager.test.ts b/src/plugins/data/public/query/filter_manager/filter_manager.test.ts index ce574ace45705..3b4ca08cbbf14 100644 --- a/src/plugins/data/public/query/filter_manager/filter_manager.test.ts +++ b/src/plugins/data/public/query/filter_manager/filter_manager.test.ts @@ -204,18 +204,19 @@ describe('filter_manager', () => { ).toBe(3); }); - test('should set app filters and remove any duplicated global filters', async function() { - filterManager.addFilters(readyFilters, true); + test('should set app filters and merge them with duplicate global filters', async function() { + const [filter, ...otherFilters] = readyFilters; + filterManager.addFilters(otherFilters, true); const appFilter1 = _.cloneDeep(readyFilters[1]); const appFilter2 = _.cloneDeep(readyFilters[2]); - filterManager.setAppFilters([appFilter1, appFilter2]); + filterManager.setAppFilters([filter, appFilter1, appFilter2]); const newGlobalFilters = filterManager.getGlobalFilters(); const newAppFilters = filterManager.getAppFilters(); - expect(newGlobalFilters).toHaveLength(1); - expect(newAppFilters).toHaveLength(2); + expect(newGlobalFilters).toHaveLength(2); + expect(newAppFilters).toHaveLength(1); }); test('should set global filters and remove any duplicated app filters', async function() { diff --git a/src/plugins/data/public/query/filter_manager/filter_manager.ts b/src/plugins/data/public/query/filter_manager/filter_manager.ts index fba1866ebd615..e206286bce147 100644 --- a/src/plugins/data/public/query/filter_manager/filter_manager.ts +++ b/src/plugins/data/public/query/filter_manager/filter_manager.ts @@ -177,13 +177,9 @@ export class FilterManager { public setGlobalFilters(newGlobalFilters: Filter[]) { newGlobalFilters = mapAndFlattenFilters(newGlobalFilters); FilterManager.setFiltersStore(newGlobalFilters, FilterStateStore.GLOBAL_STATE, true); - const { appFilters: currentAppFilters } = this.getPartitionedFilters(); - // remove duplicates from current app filters, to make sure global will take precedence - const filteredAppFilters = currentAppFilters.filter( - appFilter => !newGlobalFilters.find(globalFilter => compareFilters(globalFilter, appFilter)) - ); + const { appFilters } = this.getPartitionedFilters(); const newFilters = this.mergeIncomingFilters({ - appFilters: filteredAppFilters, + appFilters, globalFilters: newGlobalFilters, }); @@ -198,14 +194,9 @@ export class FilterManager { public setAppFilters(newAppFilters: Filter[]) { newAppFilters = mapAndFlattenFilters(newAppFilters); FilterManager.setFiltersStore(newAppFilters, FilterStateStore.APP_STATE, true); - const { globalFilters: currentGlobalFilters } = this.getPartitionedFilters(); - // remove duplicates from current global filters, to make sure app will take precedence - const filteredGlobalFilters = currentGlobalFilters.filter( - globalFilter => !newAppFilters.find(appFilter => compareFilters(appFilter, globalFilter)) - ); - + const { globalFilters } = this.getPartitionedFilters(); const newFilters = this.mergeIncomingFilters({ - globalFilters: filteredGlobalFilters, + globalFilters, appFilters: newAppFilters, }); this.handleStateUpdate(newFilters); diff --git a/src/plugins/data/public/ui/filter_bar/filter_item.tsx b/src/plugins/data/public/ui/filter_bar/filter_item.tsx index 6b5fd41dc06ea..528ec4800e7b9 100644 --- a/src/plugins/data/public/ui/filter_bar/filter_item.tsx +++ b/src/plugins/data/public/ui/filter_bar/filter_item.tsx @@ -88,6 +88,7 @@ class FilterItemUI extends Component<Props, State> { const dataTestSubjDisabled = `filter-${ this.props.filter.meta.disabled ? 'disabled' : 'enabled' }`; + const dataTestSubjPinned = `filter-${isFilterPinned(filter) ? 'pinned' : 'unpinned'}`; const classes = classNames( 'globalFilterItem', @@ -107,7 +108,7 @@ class FilterItemUI extends Component<Props, State> { className={classes} iconOnClick={() => this.props.onRemove()} onClick={this.handleBadgeClick} - data-test-subj={`filter ${dataTestSubjDisabled} ${dataTestSubjKey} ${dataTestSubjValue}`} + data-test-subj={`filter ${dataTestSubjDisabled} ${dataTestSubjKey} ${dataTestSubjValue} ${dataTestSubjPinned}`} /> ); diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.js b/test/functional/apps/dashboard/dashboard_filter_bar.js index 6d2a30fa85325..f6089871010c3 100644 --- a/test/functional/apps/dashboard/dashboard_filter_bar.js +++ b/test/functional/apps/dashboard/dashboard_filter_bar.js @@ -27,6 +27,7 @@ export default function({ getService, getPageObjects }) { const pieChart = getService('pieChart'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + const browser = getService('browser'); const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'timePicker']); describe('dashboard filter bar', () => { @@ -126,9 +127,46 @@ export default function({ getService, getPageObjects }) { const filterCount = await filterBar.getFilterCount(); expect(filterCount).to.equal(1); + await pieChart.expectPieSliceCount(1); + }); + it("restoring filters doesn't break back button", async () => { + await browser.goBack(); + await PageObjects.dashboard.expectExistsDashboardLandingPage(); + await browser.goForward(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); await pieChart.expectPieSliceCount(1); }); + + it("saving with pinned filter doesn't unpin them", async () => { + const filterKey = 'bytes'; + await filterBar.toggleFilterPinned(filterKey); + await PageObjects.dashboard.switchToEditMode(); + await PageObjects.dashboard.saveDashboard('saved with pinned filters', { + saveAsNew: true, + }); + expect(await filterBar.isFilterPinned(filterKey)).to.be(true); + await pieChart.expectPieSliceCount(1); + }); + + it("navigating to a dashboard with global filter doesn't unpin it if same filter is saved with dashboard", async () => { + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.loadSavedDashboard('with filters'); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await filterBar.isFilterPinned('bytes')).to.be(true); + await pieChart.expectPieSliceCount(1); + }); + + it("pinned filters aren't saved", async () => { + await filterBar.removeFilter('bytes'); + await PageObjects.dashboard.gotoDashboardLandingPage(); + await PageObjects.dashboard.loadSavedDashboard('saved with pinned filters'); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await filterBar.getFilterCount()).to.be(0); + await pieChart.expectPieSliceCount(5); + }); }); describe('saved search filtering', function() { diff --git a/test/functional/services/filter_bar.ts b/test/functional/services/filter_bar.ts index 9d494b1e6d950..a463a593e9e04 100644 --- a/test/functional/services/filter_bar.ts +++ b/test/functional/services/filter_bar.ts @@ -32,10 +32,16 @@ export function FilterBarProvider({ getService, getPageObjects }: FtrProviderCon * @param value filter value * @param enabled filter status */ - public async hasFilter(key: string, value: string, enabled: boolean = true): Promise<boolean> { + public async hasFilter( + key: string, + value: string, + enabled: boolean = true, + pinned: boolean = false + ): Promise<boolean> { const filterActivationState = enabled ? 'enabled' : 'disabled'; + const filterPinnedState = pinned ? 'pinned' : 'unpinned'; return testSubjects.exists( - `filter filter-${filterActivationState} filter-key-${key} filter-value-${value}`, + `filter filter-${filterActivationState} filter-key-${key} filter-value-${value} filter-${filterPinnedState}`, { allowHidden: true, } @@ -80,6 +86,11 @@ export function FilterBarProvider({ getService, getPageObjects }: FtrProviderCon await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); } + public async isFilterPinned(key: string): Promise<boolean> { + const filter = await testSubjects.find(`~filter & ~filter-key-${key}`); + return (await filter.getAttribute('data-test-subj')).includes('filter-pinned'); + } + public async getFilterCount(): Promise<number> { const filters = await testSubjects.findAll('~filter'); return filters.length; From 358d13919bc597d13e6a98ec97fae2615093027e Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet <pierre.gayvallet@elastic.co> Date: Mon, 13 Apr 2020 13:28:09 +0200 Subject: [PATCH 055/121] Migrate SO management section to NP (#61700) * move libs to new plugin * adapt libs to use NP apis * add required plugins * add get_allowed_types route * move object_view components * add service registry * migrate table header component * migrate table component * migrate saved_objects_table component * remove migrated legacy files * fix re-export from legacy management + section label * migrate services registration * adapt management section mock * fix imports * migrate flyout component * migrate relationships component * migrate saved_objects_table tests * migrate breadcrumb * add redirect if unauthorized check * migrate translations to new savedObjectsManagement prefix * remove obsolete translations * convert action registry to service pattern * wire extra actions * remove importAndExportableTypes from injected vars * handle newIndexPatternUrl * remove duplicate dashboard dependency * remove old TODO * remove old TODO * properly mock lodash in tests * add async management section loading * expose createSavedSearchesLoader from discover plugin contract * address most review comments * fix merge conflicts --- src/core/public/mocks.ts | 6 +- .../server/saved_objects/service/index.ts | 1 - src/core/server/server.api.md | 2 - src/legacy/core_plugins/kibana/inject_vars.js | 3 - .../core_plugins/kibana/public/index.ts | 2 +- .../management/saved_object_registry.ts | 64 +-- .../public/management/sections/index.js | 1 - .../management/sections/objects/_objects.html | 5 - .../management/sections/objects/_objects.js | 104 ----- .../management/sections/objects/_view.html | 5 - .../management/sections/objects/_view.js | 85 ---- .../sections/objects/breadcrumbs.js | 50 --- .../objects/components/objects_table/index.js | 20 - .../saved_objects/saved_objects_mixin.js | 5 - src/plugins/data/public/mocks.ts | 1 + src/plugins/discover/public/mocks.ts | 3 + src/plugins/discover/public/plugin.ts | 12 + src/plugins/management/public/mocks/index.ts | 13 +- .../saved_objects_management/common/index.ts} | 2 +- .../saved_objects_management/common}/types.ts | 30 +- .../saved_objects_management/kibana.json | 3 +- .../saved_objects_management/public/index.ts | 6 +- .../public}/lib/case_conversion.test.ts | 0 .../public}/lib/case_conversion.ts | 0 .../public}/lib/create_field_list.test.ts | 4 +- .../public}/lib/create_field_list.ts | 8 +- .../lib/extract_export_details.test.ts | 0 .../public}/lib/extract_export_details.ts | 0 .../lib/fetch_export_by_type_and_search.ts | 7 +- .../public}/lib/fetch_export_objects.ts | 7 +- .../public}/lib/find_objects.ts | 29 +- .../public/lib/get_allowed_types.ts | 31 ++ .../public}/lib/get_default_title.ts | 0 .../public}/lib/get_relationships.test.ts | 37 +- .../public}/lib/get_relationships.ts | 32 +- .../public}/lib/get_saved_object_counts.ts | 17 +- .../public}/lib/get_saved_object_label.ts | 0 .../public}/lib/import_file.ts | 14 +- .../public}/lib/import_legacy_file.test.ts | 0 .../public}/lib/import_legacy_file.ts | 0 .../public}/lib/in_app_url.test.ts | 2 +- .../public}/lib/in_app_url.ts | 0 .../public}/lib/index.ts | 2 + .../public}/lib/log_legacy_import.ts | 9 +- .../public}/lib/numeric.ts | 0 .../public}/lib/parse_query.test.ts | 2 +- .../public}/lib/parse_query.ts | 15 +- .../lib/process_import_response.test.ts | 0 .../public}/lib/process_import_response.ts | 0 .../public}/lib/resolve_import_errors.test.ts | 35 +- .../public}/lib/resolve_import_errors.ts | 12 +- .../public}/lib/resolve_saved_objects.test.ts | 7 +- .../public}/lib/resolve_saved_objects.ts | 26 +- .../public/management_section/index.ts} | 2 +- .../management_section/mount_section.tsx | 211 +++++++++ .../__snapshots__/header.test.tsx.snap | 6 +- .../__snapshots__/intro.test.tsx.snap | 6 +- .../not_found_errors.test.tsx.snap | 30 +- .../object_view/components}/field.test.tsx | 0 .../object_view/components}/field.tsx | 4 +- .../object_view/components}/form.tsx | 18 +- .../object_view/components}/header.test.tsx | 0 .../object_view/components}/header.tsx | 8 +- .../object_view/components}/index.ts | 0 .../object_view/components}/intro.test.tsx | 0 .../object_view/components}/intro.tsx | 4 +- .../components}/not_found_errors.test.tsx | 0 .../components}/not_found_errors.tsx | 10 +- .../management_section/object_view/index.ts} | 2 +- .../object_view}/saved_object_view.tsx | 18 +- .../saved_objects_table.test.tsx.snap} | 116 ++++- .../__snapshots__/flyout.test.tsx.snap} | 84 ++-- .../__snapshots__/header.test.tsx.snap} | 10 +- .../relationships.test.tsx.snap} | 2 +- .../__snapshots__/table.test.tsx.snap} | 24 +- .../components/flyout.test.mocks.ts | 44 ++ .../objects_table/components/flyout.test.tsx} | 183 ++++---- .../objects_table/components/flyout.tsx} | 260 ++++++----- .../objects_table/components/header.test.tsx} | 3 +- .../objects_table/components/header.tsx} | 31 +- .../objects_table/components/index.ts | 23 + .../components/relationships.test.tsx} | 44 +- .../components/relationships.tsx} | 89 ++-- .../objects_table/components/table.test.tsx} | 31 +- .../objects_table/components/table.tsx} | 154 ++++--- .../objects_table/index.ts} | 2 +- .../saved_objects_table.test.mocks.ts | 67 +++ .../saved_objects_table.test.tsx} | 419 ++++++++---------- .../objects_table/saved_objects_table.tsx} | 260 ++++++----- .../public/management_section/types.ts | 38 ++ .../saved_objects_management/public/mocks.ts | 12 +- .../public/plugin.test.ts | 10 +- .../saved_objects_management/public/plugin.ts | 71 ++- .../public/register_services.ts | 59 +++ .../public/services/action_service.mock.ts | 57 +++ ...egistry.test.ts => action_service.test.ts} | 30 +- .../{action_registry.ts => action_service.ts} | 48 +- .../public/services/index.ts | 14 +- ...istry.mock.ts => service_registry.mock.ts} | 13 +- .../public/services/service_registry.ts | 49 ++ .../services/{action_types.ts => types.ts} | 0 .../saved_objects_management/public/types.ts | 20 + .../server/routes/get_allowed_types.ts} | 34 +- .../server/routes/index.test.ts | 8 +- .../server/routes/index.ts | 2 + .../saved_objects_management/server/types.ts | 30 +- ...opy_saved_objects_to_space_service.test.ts | 4 +- .../copy_saved_objects_to_space_service.ts | 2 +- .../translations/translations/ja-JP.json | 245 +++++----- .../translations/translations/zh-CN.json | 243 +++++----- 110 files changed, 2184 insertions(+), 1689 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.html delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/index.js rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/index.js => plugins/saved_objects_management/common/index.ts} (89%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/common}/types.ts (74%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/case_conversion.test.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/case_conversion.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/create_field_list.test.ts (96%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/create_field_list.ts (92%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/extract_export_details.test.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/extract_export_details.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/fetch_export_by_type_and_search.ts (89%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/fetch_export_objects.ts (89%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/find_objects.ts (57%) create mode 100644 src/plugins/saved_objects_management/public/lib/get_allowed_types.ts rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/get_default_title.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/get_relationships.test.ts (67%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/get_relationships.ts (67%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/get_saved_object_counts.ts (72%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/get_saved_object_label.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/import_file.ts (75%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/import_legacy_file.test.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/import_legacy_file.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/in_app_url.test.ts (98%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/in_app_url.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/index.ts (94%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/log_legacy_import.ts (81%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/numeric.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/parse_query.test.ts (92%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/parse_query.ts (77%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/process_import_response.test.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/process_import_response.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/resolve_import_errors.test.ts (90%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/resolve_import_errors.ts (95%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/resolve_saved_objects.test.ts (98%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public}/lib/resolve_saved_objects.ts (94%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/index.js => plugins/saved_objects_management/public/management_section/index.ts} (93%) create mode 100644 src/plugins/saved_objects_management/public/management_section/mount_section.tsx rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/__snapshots__/header.test.tsx.snap (96%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/__snapshots__/intro.test.tsx.snap (90%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/__snapshots__/not_found_errors.test.tsx.snap (89%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/field.test.tsx (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/field.tsx (97%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/form.tsx (89%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/header.test.tsx (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/header.tsx (92%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/index.ts (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/intro.test.tsx (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/intro.tsx (92%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/not_found_errors.test.tsx (100%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/object_view => plugins/saved_objects_management/public/management_section/object_view/components}/not_found_errors.tsx (87%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/index.js => plugins/saved_objects_management/public/management_section/object_view/index.ts} (93%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects => plugins/saved_objects_management/public/management_section/object_view}/saved_object_view.tsx (89%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap => plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap} (73%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap => plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap} (85%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap => plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap} (88%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap => plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap} (99%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap => plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap} (93%) create mode 100644 src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.mocks.ts rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js => plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx} (75%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js => plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx} (77%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/header.test.js => plugins/saved_objects_management/public/management_section/objects_table/components/header.test.tsx} (96%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/header.js => plugins/saved_objects_management/public/management_section/objects_table/components/header.tsx} (83%) create mode 100644 src/plugins/saved_objects_management/public/management_section/objects_table/components/index.ts rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/relationships.test.js => plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx} (88%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/relationships.js => plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx} (75%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js => plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx} (87%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js => plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx} (71%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/index.js => plugins/saved_objects_management/public/management_section/objects_table/index.ts} (93%) create mode 100644 src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.mocks.ts rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js => plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx} (58%) rename src/{legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/objects_table.js => plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx} (73%) create mode 100644 src/plugins/saved_objects_management/public/management_section/types.ts create mode 100644 src/plugins/saved_objects_management/public/register_services.ts create mode 100644 src/plugins/saved_objects_management/public/services/action_service.mock.ts rename src/plugins/saved_objects_management/public/services/{action_registry.test.ts => action_service.test.ts} (69%) rename src/plugins/saved_objects_management/public/services/{action_registry.ts => action_service.ts} (56%) rename src/plugins/saved_objects_management/public/services/{action_registry.mock.ts => service_registry.mock.ts} (79%) create mode 100644 src/plugins/saved_objects_management/public/services/service_registry.ts rename src/plugins/saved_objects_management/public/services/{action_types.ts => types.ts} (100%) create mode 100644 src/plugins/saved_objects_management/public/types.ts rename src/{legacy/core_plugins/kibana/public/management/sections/objects/index.js => plugins/saved_objects_management/server/routes/get_allowed_types.ts} (61%) diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index 0c4930592b233..959ffaa7e7e08 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -48,6 +48,7 @@ export { overlayServiceMock } from './overlays/overlay_service.mock'; export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; export { scopedHistoryMock } from './application/scoped_history.mock'; +export { applicationServiceMock } from './application/application_service.mock'; function createCoreSetupMock({ basePath = '', @@ -62,9 +63,8 @@ function createCoreSetupMock({ application: applicationServiceMock.createSetupContract(), context: contextServiceMock.createSetupContract(), fatalErrors: fatalErrorsServiceMock.createSetupContract(), - getStartServices: jest.fn<Promise<[ReturnType<typeof createCoreStartMock>, object, any]>, []>( - () => - Promise.resolve([createCoreStartMock({ basePath }), pluginStartDeps, pluginStartContract]) + getStartServices: jest.fn<Promise<[ReturnType<typeof createCoreStartMock>, any, any]>, []>(() => + Promise.resolve([createCoreStartMock({ basePath }), pluginStartDeps, pluginStartContract]) ), http: httpServiceMock.createSetupContract({ basePath }), notifications: notificationServiceMock.createSetupContract(), diff --git a/src/core/server/saved_objects/service/index.ts b/src/core/server/saved_objects/service/index.ts index f44824238aa21..9f625b4732e26 100644 --- a/src/core/server/saved_objects/service/index.ts +++ b/src/core/server/saved_objects/service/index.ts @@ -36,7 +36,6 @@ export interface SavedObjectsLegacyService { getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; SavedObjectsClient: typeof SavedObjectsClient; types: string[]; - importAndExportableTypes: string[]; schema: SavedObjectsSchema; getSavedObjectsRepository(...rest: any[]): any; importExport: { diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index a35bca7375286..37051da4b17da 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2084,8 +2084,6 @@ export interface SavedObjectsLegacyService { // (undocumented) getScopedSavedObjectsClient: SavedObjectsClientProvider['getClient']; // (undocumented) - importAndExportableTypes: string[]; - // (undocumented) importExport: { objectLimit: number; importSavedObjects(options: SavedObjectsImportOptions): Promise<SavedObjectsImportResponse>; diff --git a/src/legacy/core_plugins/kibana/inject_vars.js b/src/legacy/core_plugins/kibana/inject_vars.js index 76d1704907ab5..c3b906ee842e3 100644 --- a/src/legacy/core_plugins/kibana/inject_vars.js +++ b/src/legacy/core_plugins/kibana/inject_vars.js @@ -20,10 +20,7 @@ export function injectVars(server) { const serverConfig = server.config(); - const { importAndExportableTypes } = server.savedObjects; - return { - importAndExportableTypes, autocompleteTerminateAfter: serverConfig.get('kibana.autocompleteTerminateAfter'), autocompleteTimeout: serverConfig.get('kibana.autocompleteTimeout'), }; diff --git a/src/legacy/core_plugins/kibana/public/index.ts b/src/legacy/core_plugins/kibana/public/index.ts index a4fffc6eec26d..be22652ab2c1c 100644 --- a/src/legacy/core_plugins/kibana/public/index.ts +++ b/src/legacy/core_plugins/kibana/public/index.ts @@ -20,4 +20,4 @@ export { ProcessedImportResponse, processImportResponse, -} from './management/sections/objects/lib/process_import_response'; +} from '../../../../plugins/saved_objects_management/public/lib'; diff --git a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts index 705be68a141e7..587a372f91555 100644 --- a/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts +++ b/src/legacy/core_plugins/kibana/public/management/saved_object_registry.ts @@ -17,66 +17,8 @@ * under the License. */ -import _ from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; -import { SavedObjectLoader } from '../../../../../plugins/saved_objects/public'; -import { createSavedSearchesLoader } from '../../../../../plugins/discover/public'; +import { npSetup } from 'ui/new_platform'; -/** - * This registry is used for the editing mode of Saved Searches, Visualizations, - * Dashboard and Time Lion saved objects. - */ -interface SavedObjectRegistryEntry { - id: string; - service: SavedObjectLoader; - title: string; -} - -export interface ISavedObjectsManagementRegistry { - register(service: SavedObjectRegistryEntry): void; - all(): SavedObjectRegistryEntry[]; - get(id: string): SavedObjectRegistryEntry | undefined; -} - -const registry: SavedObjectRegistryEntry[] = []; - -export const savedObjectManagementRegistry: ISavedObjectsManagementRegistry = { - register: (service: SavedObjectRegistryEntry) => { - registry.push(service); - }, - all: () => { - return registry; - }, - get: (id: string) => { - return _.find(registry, { id }); - }, -}; - -const services = { - savedObjectsClient: npStart.core.savedObjects.client, - indexPatterns: npStart.plugins.data.indexPatterns, - search: npStart.plugins.data.search, - chrome: npStart.core.chrome, - overlays: npStart.core.overlays, -}; - -savedObjectManagementRegistry.register({ - id: 'savedVisualizations', - service: npStart.plugins.visualizations.savedVisualizationsLoader, - title: 'visualizations', -}); - -savedObjectManagementRegistry.register({ - id: 'savedDashboards', - service: npStart.plugins.dashboard.getSavedDashboardLoader(), - title: i18n.translate('kbn.dashboard.savedDashboardsTitle', { - defaultMessage: 'dashboards', - }), -}); +const registry = npSetup.plugins.savedObjectsManagement?.serviceRegistry; -savedObjectManagementRegistry.register({ - id: 'savedSearches', - service: createSavedSearchesLoader(services), - title: 'searches', -}); +export const savedObjectManagementRegistry = registry!; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index.js index 54717ad003ade..adc1741f57263 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index.js @@ -17,5 +17,4 @@ * under the License. */ -import './objects'; import './index_patterns'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.html b/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.html deleted file mode 100644 index 090fb7b636685..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.html +++ /dev/null @@ -1,5 +0,0 @@ -<kbn-management-app section="kibana/objects"> - <kbn-management-objects> - <div id="reactSavedObjectsTable"></div> - </kbn-management-objects> -</kbn-management-app> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js deleted file mode 100644 index c5901ca6ee6bf..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js +++ /dev/null @@ -1,104 +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 { savedObjectManagementRegistry } from '../../saved_object_registry'; -import objectIndexHTML from './_objects.html'; -import uiRoutes from 'ui/routes'; -import chrome from 'ui/chrome'; -import { uiModules } from 'ui/modules'; -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { ObjectsTable } from './components/objects_table'; -import { I18nContext } from 'ui/i18n'; -import { get } from 'lodash'; -import { npStart } from 'ui/new_platform'; -import { getIndexBreadcrumbs } from './breadcrumbs'; - -const REACT_OBJECTS_TABLE_DOM_ELEMENT_ID = 'reactSavedObjectsTable'; - -function updateObjectsTable($scope, $injector) { - const indexPatterns = npStart.plugins.data.indexPatterns; - const $http = $injector.get('$http'); - const kbnUrl = $injector.get('kbnUrl'); - const config = $injector.get('config'); - - const savedObjectsClient = npStart.core.savedObjects.client; - const services = savedObjectManagementRegistry.all().map(obj => obj.service); - const uiCapabilites = npStart.core.application.capabilities; - - $scope.$$postDigest(() => { - const node = document.getElementById(REACT_OBJECTS_TABLE_DOM_ELEMENT_ID); - if (!node) { - return; - } - - render( - <I18nContext> - <ObjectsTable - savedObjectsClient={savedObjectsClient} - confirmModalPromise={npStart.core.overlays.openConfirm} - services={services} - indexPatterns={indexPatterns} - $http={$http} - perPageConfig={config.get('savedObjects:perPage')} - basePath={chrome.getBasePath()} - newIndexPatternUrl={kbnUrl.eval('#/management/kibana/index_pattern')} - uiCapabilities={uiCapabilites} - goInspectObject={object => { - if (object.meta.editUrl) { - kbnUrl.change(object.meta.editUrl); - $scope.$apply(); - } - }} - canGoInApp={object => { - const { inAppUrl } = object.meta; - return inAppUrl && get(uiCapabilites, inAppUrl.uiCapabilitiesPath); - }} - /> - </I18nContext>, - node - ); - }); -} - -function destroyObjectsTable() { - const node = document.getElementById(REACT_OBJECTS_TABLE_DOM_ELEMENT_ID); - node && unmountComponentAtNode(node); -} - -uiRoutes - .when('/management/kibana/objects', { - template: objectIndexHTML, - k7Breadcrumbs: getIndexBreadcrumbs, - requireUICapability: 'management.kibana.objects', - }) - .when('/management/kibana/objects/:service', { - redirectTo: '/management/kibana/objects', - }); - -uiModules.get('apps/management').directive('kbnManagementObjects', function() { - return { - restrict: 'E', - controllerAs: 'managementObjectsController', - controller: function($scope, $injector) { - updateObjectsTable($scope, $injector); - $scope.$on('$destroy', destroyObjectsTable); - }, - }; -}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html deleted file mode 100644 index 8bce0aabcd64a..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.html +++ /dev/null @@ -1,5 +0,0 @@ -<kbn-management-app section="kibana/objects" data-test-subj="savedObjectsEdit"> - <kbn-management-objects-view> - <div id="reactSavedObjectsView"></div> - </kbn-management-objects-view> -</kbn-management-app> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js deleted file mode 100644 index a847055b40015..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/_view.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import 'angular'; -import 'angular-elastic/elastic'; -import uiRoutes from 'ui/routes'; -import { uiModules } from 'ui/modules'; -import { I18nContext } from 'ui/i18n'; -import { npStart } from 'ui/new_platform'; -import objectViewHTML from './_view.html'; -import { getViewBreadcrumbs } from './breadcrumbs'; -import { savedObjectManagementRegistry } from '../../saved_object_registry'; -import { SavedObjectEdition } from './saved_object_view'; - -const REACT_OBJECTS_VIEW_DOM_ELEMENT_ID = 'reactSavedObjectsView'; - -uiRoutes.when('/management/kibana/objects/:service/:id', { - template: objectViewHTML, - k7Breadcrumbs: getViewBreadcrumbs, - requireUICapability: 'management.kibana.objects', -}); - -function createReactView($scope, $routeParams) { - const { service: serviceName, id: objectId, notFound } = $routeParams; - - const { savedObjects, overlays, notifications, application } = npStart.core; - - $scope.$$postDigest(() => { - const node = document.getElementById(REACT_OBJECTS_VIEW_DOM_ELEMENT_ID); - if (!node) { - return; - } - - render( - <I18nContext> - <SavedObjectEdition - id={objectId} - serviceName={serviceName} - serviceRegistry={savedObjectManagementRegistry} - savedObjectsClient={savedObjects.client} - overlays={overlays} - notifications={notifications} - capabilities={application.capabilities} - notFoundType={notFound} - /> - </I18nContext>, - node - ); - }); -} - -function destroyReactView() { - const node = document.getElementById(REACT_OBJECTS_VIEW_DOM_ELEMENT_ID); - node && unmountComponentAtNode(node); -} - -uiModules - .get('apps/management', ['monospaced.elastic']) - .directive('kbnManagementObjectsView', function() { - return { - restrict: 'E', - controller: function($scope, $routeParams) { - createReactView($scope, $routeParams); - $scope.$on('$destroy', destroyReactView); - }, - }; - }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js deleted file mode 100644 index e9082bfeb680d..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/breadcrumbs.js +++ /dev/null @@ -1,50 +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 { MANAGEMENT_BREADCRUMB } from 'ui/management'; -import { i18n } from '@kbn/i18n'; - -import { savedObjectManagementRegistry } from '../../saved_object_registry'; - -export function getIndexBreadcrumbs() { - return [ - MANAGEMENT_BREADCRUMB, - { - text: i18n.translate('kbn.management.savedObjects.indexBreadcrumb', { - defaultMessage: 'Saved objects', - }), - href: '#/management/kibana/objects', - }, - ]; -} - -export function getViewBreadcrumbs($routeParams) { - const serviceObj = savedObjectManagementRegistry.get($routeParams.service); - const { service } = serviceObj; - - return [ - ...getIndexBreadcrumbs(), - { - text: i18n.translate('kbn.management.savedObjects.editBreadcrumb', { - defaultMessage: 'Edit {savedObjectType}', - values: { savedObjectType: service.type }, - }), - }, - ]; -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/index.js b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/index.js deleted file mode 100644 index 601dea544361c..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { ObjectsTable } from './objects_table'; diff --git a/src/legacy/server/saved_objects/saved_objects_mixin.js b/src/legacy/server/saved_objects/saved_objects_mixin.js index bcf766231dc9c..3e71e1989ae7a 100644 --- a/src/legacy/server/saved_objects/saved_objects_mixin.js +++ b/src/legacy/server/saved_objects/saved_objects_mixin.js @@ -78,13 +78,8 @@ export function savedObjectsMixin(kbnServer, server) { const provider = kbnServer.newPlatform.__internals.savedObjectsClientProvider; - const importAndExportableTypes = typeRegistry - .getImportableAndExportableTypes() - .map(type => type.name); - const service = { types: visibleTypes, - importAndExportableTypes, SavedObjectsClient, SavedObjectsRepository, getSavedObjectsRepository: createRepository, diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index ea1c27550867e..2d43cae79ac98 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -62,6 +62,7 @@ const createStartContract = (): Start => { }, }), get: jest.fn().mockReturnValue(Promise.resolve({})), + clearCache: jest.fn(), } as unknown) as IndexPatternsContract, }; }; diff --git a/src/plugins/discover/public/mocks.ts b/src/plugins/discover/public/mocks.ts index bb05e3d412001..218c59b5db07b 100644 --- a/src/plugins/discover/public/mocks.ts +++ b/src/plugins/discover/public/mocks.ts @@ -37,6 +37,9 @@ const createStartContract = (): Start => { docViews: { DocViewer: jest.fn(() => null), }, + savedSearches: { + createLoader: jest.fn(), + }, }; return startContract; }; diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts index d2797586bfdfb..aa54823e6ec4d 100644 --- a/src/plugins/discover/public/plugin.ts +++ b/src/plugins/discover/public/plugin.ts @@ -21,12 +21,14 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { auto } from 'angular'; import { CoreSetup, Plugin } from 'kibana/public'; +import { SavedObjectLoader, SavedObjectKibanaServices } from '../../saved_objects/public'; import { DocViewInput, DocViewInputFn, DocViewRenderProps } from './doc_views/doc_views_types'; import { DocViewsRegistry } from './doc_views/doc_views_registry'; import { DocViewTable } from './components/table/table'; import { JsonCodeBlock } from './components/json_code_block/json_code_block'; import { DocViewer } from './components/doc_viewer/doc_viewer'; import { setDocViewsRegistry } from './services'; +import { createSavedSearchesLoader } from './saved_searches'; import './index.scss'; @@ -62,6 +64,13 @@ export interface DiscoverStart { */ DocViewer: React.ComponentType<DocViewRenderProps>; }; + savedSearches: { + /** + * Create a {@link SavedObjectLoader | loader} to handle the saved searches type. + * @param services + */ + createLoader(services: SavedObjectKibanaServices): SavedObjectLoader; + }; } /** @@ -105,6 +114,9 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> { docViews: { DocViewer, }, + savedSearches: { + createLoader: createSavedSearchesLoader, + }, }; } } diff --git a/src/plugins/management/public/mocks/index.ts b/src/plugins/management/public/mocks/index.ts index 6099a2cc32afc..82789d3c3f55f 100644 --- a/src/plugins/management/public/mocks/index.ts +++ b/src/plugins/management/public/mocks/index.ts @@ -18,12 +18,21 @@ */ import { ManagementSetup, ManagementStart } from '../types'; +import { ManagementSection } from '../management_section'; + +const createManagementSectionMock = (): jest.Mocked<PublicMethodsOf<ManagementSection>> => { + return { + registerApp: jest.fn(), + getApp: jest.fn(), + getAppsEnabled: jest.fn().mockReturnValue([]), + }; +}; const createSetupContract = (): DeeplyMockedKeys<ManagementSetup> => ({ sections: { register: jest.fn(), - getSection: jest.fn(), - getAllSections: jest.fn(), + getSection: jest.fn().mockReturnValue(createManagementSectionMock()), + getAllSections: jest.fn().mockReturnValue([]), }, }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/index.js b/src/plugins/saved_objects_management/common/index.ts similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/index.js rename to src/plugins/saved_objects_management/common/index.ts index ac1e7bac06c87..67c3ae6d934ab 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/index.js +++ b/src/plugins/saved_objects_management/common/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { Header } from './header'; +export { SavedObjectRelation, SavedObjectWithMetadata, SavedObjectMetadata } from './types'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts b/src/plugins/saved_objects_management/common/types.ts similarity index 74% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts rename to src/plugins/saved_objects_management/common/types.ts index 6a89142bc9798..be52d8e6486e2 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/types.ts +++ b/src/plugins/saved_objects_management/common/types.ts @@ -17,8 +17,12 @@ * under the License. */ -import { SavedObject, SavedObjectReference } from 'src/core/public'; +import { SavedObject } from 'src/core/types'; +/** + * The metadata injected into a {@link SavedObject | saved object} when returning + * {@link SavedObjectWithMetadata | enhanced objects} from the plugin API endpoints. + */ export interface SavedObjectMetadata { icon?: string; title?: string; @@ -26,31 +30,19 @@ export interface SavedObjectMetadata { inAppUrl?: { path: string; uiCapabilitiesPath: string }; } +/** + * A {@link SavedObject | saved object} enhanced with meta properties used by the client-side plugin. + */ export type SavedObjectWithMetadata<T = unknown> = SavedObject<T> & { meta: SavedObjectMetadata; }; +/** + * Represents a relation between two {@link SavedObject | saved object} + */ export interface SavedObjectRelation { id: string; type: string; relationship: 'child' | 'parent'; meta: SavedObjectMetadata; } - -export interface ObjectField { - type: FieldType; - name: string; - value: any; -} - -export type FieldType = 'text' | 'number' | 'boolean' | 'array' | 'json'; - -export interface FieldState { - value?: any; - invalid?: boolean; -} - -export interface SubmittedFormData { - attributes: any; - references: SavedObjectReference[]; -} diff --git a/src/plugins/saved_objects_management/kibana.json b/src/plugins/saved_objects_management/kibana.json index e1f14b0e3c59d..22135ce4558ae 100644 --- a/src/plugins/saved_objects_management/kibana.json +++ b/src/plugins/saved_objects_management/kibana.json @@ -3,5 +3,6 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["home"] + "requiredPlugins": ["home", "management", "data"], + "optionalPlugins": ["dashboard", "visualizations", "discover"] } diff --git a/src/plugins/saved_objects_management/public/index.ts b/src/plugins/saved_objects_management/public/index.ts index 7fb2f137d7d84..b20b320bc6645 100644 --- a/src/plugins/saved_objects_management/public/index.ts +++ b/src/plugins/saved_objects_management/public/index.ts @@ -22,10 +22,14 @@ import { SavedObjectsManagementPlugin } from './plugin'; export { SavedObjectsManagementPluginSetup, SavedObjectsManagementPluginStart } from './plugin'; export { - ISavedObjectsManagementActionRegistry, + SavedObjectsManagementActionServiceSetup, + SavedObjectsManagementActionServiceStart, SavedObjectsManagementAction, SavedObjectsManagementRecord, + ISavedObjectsManagementServiceRegistry, + SavedObjectsManagementServiceRegistryEntry, } from './services'; +export { SavedObjectRelation, SavedObjectWithMetadata, SavedObjectMetadata } from './types'; export function plugin(initializerContext: PluginInitializerContext) { return new SavedObjectsManagementPlugin(); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/case_conversion.test.ts b/src/plugins/saved_objects_management/public/lib/case_conversion.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/case_conversion.test.ts rename to src/plugins/saved_objects_management/public/lib/case_conversion.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/case_conversion.ts b/src/plugins/saved_objects_management/public/lib/case_conversion.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/case_conversion.ts rename to src/plugins/saved_objects_management/public/lib/case_conversion.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.test.ts b/src/plugins/saved_objects_management/public/lib/create_field_list.test.ts similarity index 96% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.test.ts rename to src/plugins/saved_objects_management/public/lib/create_field_list.test.ts index 345716f91ea88..e7d6754ac4d05 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.test.ts +++ b/src/plugins/saved_objects_management/public/lib/create_field_list.test.ts @@ -17,8 +17,8 @@ * under the License. */ -import { SimpleSavedObject, SavedObjectReference } from '../../../../../../../../core/public'; -import { savedObjectsServiceMock } from '../../../../../../../../core/public/mocks'; +import { SimpleSavedObject, SavedObjectReference } from '../../../../core/public'; +import { savedObjectsServiceMock } from '../../../../core/public/mocks'; import { createFieldList } from './create_field_list'; const savedObjectClientMock = savedObjectsServiceMock.createStartContract().client; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.ts b/src/plugins/saved_objects_management/public/lib/create_field_list.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.ts rename to src/plugins/saved_objects_management/public/lib/create_field_list.ts index 88a1184d5d70f..5d87c11a87198 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/create_field_list.ts +++ b/src/plugins/saved_objects_management/public/lib/create_field_list.ts @@ -18,10 +18,10 @@ */ import { forOwn, indexBy, isNumber, isBoolean, isPlainObject, isString } from 'lodash'; -import { SimpleSavedObject } from '../../../../../../../../core/public'; -import { castEsToKbnFieldTypeName } from '../../../../../../../../plugins/data/public'; -import { ObjectField } from '../types'; -import { SavedObjectLoader } from '../../../../../../../../plugins/saved_objects/public'; +import { SimpleSavedObject } from '../../../../core/public'; +import { castEsToKbnFieldTypeName } from '../../../data/public'; +import { ObjectField } from '../management_section/types'; +import { SavedObjectLoader } from '../../../saved_objects/public'; const maxRecursiveIterations = 20; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/extract_export_details.test.ts b/src/plugins/saved_objects_management/public/lib/extract_export_details.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/extract_export_details.test.ts rename to src/plugins/saved_objects_management/public/lib/extract_export_details.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/extract_export_details.ts b/src/plugins/saved_objects_management/public/lib/extract_export_details.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/extract_export_details.ts rename to src/plugins/saved_objects_management/public/lib/extract_export_details.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.ts b/src/plugins/saved_objects_management/public/lib/fetch_export_by_type_and_search.ts similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.ts rename to src/plugins/saved_objects_management/public/lib/fetch_export_by_type_and_search.ts index d3e527b9f96b7..e0f005fab2a3b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_by_type_and_search.ts +++ b/src/plugins/saved_objects_management/public/lib/fetch_export_by_type_and_search.ts @@ -17,16 +17,15 @@ * under the License. */ -import { kfetch } from 'ui/kfetch'; +import { HttpStart } from 'src/core/public'; export async function fetchExportByTypeAndSearch( + http: HttpStart, types: string[], search: string | undefined, includeReferencesDeep: boolean = false ): Promise<Blob> { - return await kfetch({ - method: 'POST', - pathname: '/api/saved_objects/_export', + return http.post('/api/saved_objects/_export', { body: JSON.stringify({ type: types, search, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.ts b/src/plugins/saved_objects_management/public/lib/fetch_export_objects.ts similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.ts rename to src/plugins/saved_objects_management/public/lib/fetch_export_objects.ts index 744f8ef38af47..745d3758371a3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/fetch_export_objects.ts +++ b/src/plugins/saved_objects_management/public/lib/fetch_export_objects.ts @@ -17,15 +17,14 @@ * under the License. */ -import { kfetch } from 'ui/kfetch'; +import { HttpStart } from 'src/core/public'; export async function fetchExportObjects( + http: HttpStart, objects: any[], includeReferencesDeep: boolean = false ): Promise<Blob> { - return await kfetch({ - method: 'POST', - pathname: '/api/saved_objects/_export', + return http.post('/api/saved_objects/_export', { body: JSON.stringify({ objects, includeReferencesDeep, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.ts b/src/plugins/saved_objects_management/public/lib/find_objects.ts similarity index 57% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.ts rename to src/plugins/saved_objects_management/public/lib/find_objects.ts index 24e08f0524f62..5a77d3ae2f663 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/find_objects.ts +++ b/src/plugins/saved_objects_management/public/lib/find_objects.ts @@ -17,16 +17,27 @@ * under the License. */ -import { kfetch } from 'ui/kfetch'; -import { SavedObjectsFindOptions } from 'src/core/public'; +import { HttpStart, SavedObjectsFindOptions } from 'src/core/public'; import { keysToCamelCaseShallow } from './case_conversion'; +import { SavedObjectWithMetadata } from '../types'; -export async function findObjects(findOptions: SavedObjectsFindOptions) { - const response = await kfetch({ - method: 'GET', - pathname: '/api/kibana/management/saved_objects/_find', - query: findOptions as Record<string, any>, - }); +interface SavedObjectsFindResponse { + total: number; + page: number; + perPage: number; + savedObjects: SavedObjectWithMetadata[]; +} + +export async function findObjects( + http: HttpStart, + findOptions: SavedObjectsFindOptions +): Promise<SavedObjectsFindResponse> { + const response = await http.get<Record<string, any>>( + '/api/kibana/management/saved_objects/_find', + { + query: findOptions as Record<string, any>, + } + ); - return keysToCamelCaseShallow(response); + return keysToCamelCaseShallow(response) as SavedObjectsFindResponse; } diff --git a/src/plugins/saved_objects_management/public/lib/get_allowed_types.ts b/src/plugins/saved_objects_management/public/lib/get_allowed_types.ts new file mode 100644 index 0000000000000..7d952ebf2ca14 --- /dev/null +++ b/src/plugins/saved_objects_management/public/lib/get_allowed_types.ts @@ -0,0 +1,31 @@ +/* + * 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 { HttpStart } from 'src/core/public'; + +interface GetAllowedTypesResponse { + types: string[]; +} + +export async function getAllowedTypes(http: HttpStart) { + const response = await http.get<GetAllowedTypesResponse>( + '/api/kibana/management/saved_objects/_allowed_types' + ); + return response.types; +} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.ts b/src/plugins/saved_objects_management/public/lib/get_default_title.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_default_title.ts rename to src/plugins/saved_objects_management/public/lib/get_default_title.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.test.ts b/src/plugins/saved_objects_management/public/lib/get_relationships.test.ts similarity index 67% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.test.ts rename to src/plugins/saved_objects_management/public/lib/get_relationships.test.ts index b45b51b4de293..d79447378dde5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.test.ts +++ b/src/plugins/saved_objects_management/public/lib/get_relationships.test.ts @@ -17,44 +17,43 @@ * under the License. */ +import { httpServiceMock } from '../../../../core/public/mocks'; import { getRelationships } from './get_relationships'; describe('getRelationships', () => { - it('should make an http request', async () => { - const $http = jest.fn() as any; - const basePath = 'test'; + let httpMock: ReturnType<typeof httpServiceMock.createSetupContract>; - await getRelationships('dashboard', '1', ['search', 'index-pattern'], $http, basePath); - expect($http.mock.calls.length).toBe(1); + beforeEach(() => { + httpMock = httpServiceMock.createSetupContract(); + }); + + it('should make an http request', async () => { + await getRelationships(httpMock, 'dashboard', '1', ['search', 'index-pattern']); + expect(httpMock.get).toHaveBeenCalledTimes(1); }); it('should handle successful responses', async () => { - const $http = jest.fn().mockImplementation(() => ({ data: [1, 2] })) as any; - const basePath = 'test'; - - const response = await getRelationships( - 'dashboard', - '1', - ['search', 'index-pattern'], - $http, - basePath - ); + httpMock.get.mockResolvedValue([1, 2]); + + const response = await getRelationships(httpMock, 'dashboard', '1', [ + 'search', + 'index-pattern', + ]); expect(response).toEqual([1, 2]); }); it('should handle errors', async () => { - const $http = jest.fn().mockImplementation(() => { + httpMock.get.mockImplementation(() => { const err = new Error(); (err as any).data = { error: 'Test error', statusCode: 500, }; throw err; - }) as any; - const basePath = 'test'; + }); await expect( - getRelationships('dashboard', '1', ['search', 'index-pattern'], $http, basePath) + getRelationships(httpMock, 'dashboard', '1', ['search', 'index-pattern']) ).rejects.toThrowErrorMatchingInlineSnapshot(`"Test error"`); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.ts b/src/plugins/saved_objects_management/public/lib/get_relationships.ts similarity index 67% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.ts rename to src/plugins/saved_objects_management/public/lib/get_relationships.ts index 07bdf2db68fa2..bf2e651aa6593 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_relationships.ts +++ b/src/plugins/saved_objects_management/public/lib/get_relationships.ts @@ -17,36 +17,30 @@ * under the License. */ -import { IHttpService } from 'angular'; +import { HttpStart } from 'src/core/public'; import { get } from 'lodash'; import { SavedObjectRelation } from '../types'; export async function getRelationships( + http: HttpStart, type: string, id: string, - savedObjectTypes: string[], - $http: IHttpService, - basePath: string + savedObjectTypes: string[] ): Promise<SavedObjectRelation[]> { - const url = `${basePath}/api/kibana/management/saved_objects/relationships/${encodeURIComponent( + const url = `/api/kibana/management/saved_objects/relationships/${encodeURIComponent( type )}/${encodeURIComponent(id)}`; - const options = { - method: 'GET', - url, - params: { - savedObjectTypes, - }, - }; - try { - const response = await $http<SavedObjectRelation[]>(options); - return response?.data; - } catch (resp) { - const respBody = get(resp, 'data', {}) as any; - const err = new Error(respBody.message || respBody.error || `${resp.status} Response`); + return await http.get<SavedObjectRelation[]>(url, { + query: { + savedObjectTypes, + }, + }); + } catch (respError) { + const respBody = get(respError, 'data', {}) as any; + const err = new Error(respBody.message || respBody.error || `${respError.status} Response`); - (err as any).statusCode = respBody.statusCode || resp.status; + (err as any).statusCode = respBody.statusCode || respError.status; (err as any).body = respBody; throw err; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.ts b/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts similarity index 72% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.ts rename to src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts index d4dda1190bc43..dcf59142e73e3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_counts.ts +++ b/src/plugins/saved_objects_management/public/lib/get_saved_object_counts.ts @@ -17,18 +17,15 @@ * under the License. */ -import { IHttpService } from 'angular'; -import chrome from 'ui/chrome'; +import { HttpStart } from 'src/core/public'; -const apiBase = chrome.addBasePath('/api/kibana/management/saved_objects/scroll'); export async function getSavedObjectCounts( - $http: IHttpService, + http: HttpStart, typesToInclude: string[], - searchString: string + searchString?: string ): Promise<Record<string, number>> { - const results = await $http.post<Record<string, number>>(`${apiBase}/counts`, { - typesToInclude, - searchString, - }); - return results.data; + return await http.post<Record<string, number>>( + `/api/kibana/management/saved_objects/scroll/counts`, + { body: JSON.stringify({ typesToInclude, searchString }) } + ); } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.ts b/src/plugins/saved_objects_management/public/lib/get_saved_object_label.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/get_saved_object_label.ts rename to src/plugins/saved_objects_management/public/lib/get_saved_object_label.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.ts b/src/plugins/saved_objects_management/public/lib/import_file.ts similarity index 75% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.ts rename to src/plugins/saved_objects_management/public/lib/import_file.ts index 9bd5fbeed3a4c..96263452253ba 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_file.ts +++ b/src/plugins/saved_objects_management/public/lib/import_file.ts @@ -17,14 +17,18 @@ * under the License. */ -import { kfetch } from 'ui/kfetch'; +import { HttpStart, SavedObjectsImportError } from 'src/core/public'; -export async function importFile(file: Blob, overwriteAll: boolean = false) { +interface ImportResponse { + success: boolean; + successCount: number; + errors?: SavedObjectsImportError[]; +} + +export async function importFile(http: HttpStart, file: File, overwriteAll: boolean = false) { const formData = new FormData(); formData.append('file', file); - return await kfetch({ - method: 'POST', - pathname: '/api/saved_objects/_import', + return await http.post<ImportResponse>('/api/saved_objects/_import', { body: formData, headers: { // Important to be undefined, it forces proper headers to be set for FormData diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.test.ts b/src/plugins/saved_objects_management/public/lib/import_legacy_file.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.test.ts rename to src/plugins/saved_objects_management/public/lib/import_legacy_file.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.ts b/src/plugins/saved_objects_management/public/lib/import_legacy_file.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/import_legacy_file.ts rename to src/plugins/saved_objects_management/public/lib/import_legacy_file.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.test.ts b/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.test.ts rename to src/plugins/saved_objects_management/public/lib/in_app_url.test.ts index c0d6716391a1f..09e08e6ec333b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.test.ts +++ b/src/plugins/saved_objects_management/public/lib/in_app_url.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Capabilities } from '../../../../../../../../core/public'; +import { Capabilities } from '../../../../core/public'; import { canViewInApp } from './in_app_url'; const createCapabilities = (sections: Record<string, any>): Capabilities => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.ts b/src/plugins/saved_objects_management/public/lib/in_app_url.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/in_app_url.ts rename to src/plugins/saved_objects_management/public/lib/in_app_url.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.ts b/src/plugins/saved_objects_management/public/lib/index.ts similarity index 94% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.ts rename to src/plugins/saved_objects_management/public/lib/index.ts index ecdfa6549a54e..7021744095651 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/index.ts +++ b/src/plugins/saved_objects_management/public/lib/index.ts @@ -43,3 +43,5 @@ export { export { getDefaultTitle } from './get_default_title'; export { findObjects } from './find_objects'; export { extractExportDetails, SavedObjectsExportResultDetails } from './extract_export_details'; +export { createFieldList } from './create_field_list'; +export { getAllowedTypes } from './get_allowed_types'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/log_legacy_import.ts b/src/plugins/saved_objects_management/public/lib/log_legacy_import.ts similarity index 81% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/log_legacy_import.ts rename to src/plugins/saved_objects_management/public/lib/log_legacy_import.ts index 9bbafe3e69c98..9ec3c85b91c22 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/log_legacy_import.ts +++ b/src/plugins/saved_objects_management/public/lib/log_legacy_import.ts @@ -17,11 +17,8 @@ * under the License. */ -import { kfetch } from 'ui/kfetch'; +import { HttpStart } from 'src/core/public'; -export async function logLegacyImport() { - return await kfetch({ - method: 'POST', - pathname: '/api/saved_objects/_log_legacy_import', - }); +export async function logLegacyImport(http: HttpStart) { + return http.post('/api/saved_objects/_log_legacy_import'); } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/numeric.ts b/src/plugins/saved_objects_management/public/lib/numeric.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/numeric.ts rename to src/plugins/saved_objects_management/public/lib/numeric.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.test.ts b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.test.ts rename to src/plugins/saved_objects_management/public/lib/parse_query.test.ts index 77b34eccd9c6f..f62234eaf4e94 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.test.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts @@ -25,6 +25,6 @@ describe('getQueryText', () => { getTermClauses: () => [{ value: 'foo' }, { value: 'bar' }], getFieldClauses: () => [{ value: 'lala' }, { value: 'lolo' }], }; - expect(parseQuery({ ast })).toEqual({ queryText: 'foo bar', visibleTypes: 'lala' }); + expect(parseQuery({ ast } as any)).toEqual({ queryText: 'foo bar', visibleTypes: 'lala' }); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.ts b/src/plugins/saved_objects_management/public/lib/parse_query.ts similarity index 77% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.ts rename to src/plugins/saved_objects_management/public/lib/parse_query.ts index 9b33deedafd95..f5b7b69ea049c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/parse_query.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.ts @@ -17,9 +17,16 @@ * under the License. */ -export function parseQuery(query: any) { - let queryText; - let visibleTypes; +import { Query } from '@elastic/eui'; + +interface ParsedQuery { + queryText?: string; + visibleTypes?: string[]; +} + +export function parseQuery(query: Query): ParsedQuery { + let queryText: string | undefined; + let visibleTypes: string[] | undefined; if (query) { if (query.ast.getTermClauses().length) { @@ -29,7 +36,7 @@ export function parseQuery(query: any) { .join(' '); } if (query.ast.getFieldClauses('type')) { - visibleTypes = query.ast.getFieldClauses('type')[0].value; + visibleTypes = query.ast.getFieldClauses('type')[0].value as string[]; } } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.test.ts b/src/plugins/saved_objects_management/public/lib/process_import_response.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.test.ts rename to src/plugins/saved_objects_management/public/lib/process_import_response.test.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts b/src/plugins/saved_objects_management/public/lib/process_import_response.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/process_import_response.ts rename to src/plugins/saved_objects_management/public/lib/process_import_response.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.test.ts b/src/plugins/saved_objects_management/public/lib/resolve_import_errors.test.ts similarity index 90% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.test.ts rename to src/plugins/saved_objects_management/public/lib/resolve_import_errors.test.ts index b94b0a9d1291f..86eebad7ae787 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.test.ts +++ b/src/plugins/saved_objects_management/public/lib/resolve_import_errors.test.ts @@ -17,14 +17,10 @@ * under the License. */ -jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() })); - import { SavedObjectsImportUnknownError } from 'src/core/public'; -import { kfetch } from 'ui/kfetch'; +import { httpServiceMock } from '../../../../core/public/mocks'; import { resolveImportErrors } from './resolve_import_errors'; -const kfetchMock = kfetch as jest.Mock; - function getFormData(form: Map<string, any>) { const formData: Record<string, any> = {}; for (const [key, val] of form.entries()) { @@ -39,13 +35,20 @@ function getFormData(form: Map<string, any>) { describe('resolveImportErrors', () => { const getConflictResolutions = jest.fn(); + let httpMock: ReturnType<typeof httpServiceMock.createSetupContract>; beforeEach(() => { + httpMock = httpServiceMock.createSetupContract(); jest.resetAllMocks(); }); + const extractBodyFromCall = (index: number): Map<string, any> => { + return (httpMock.post.mock.calls[index] as any)[1].body; + }; + test('works with empty import failures', async () => { const result = await resolveImportErrors({ + http: httpMock, getConflictResolutions, state: { importCount: 0, @@ -62,6 +65,7 @@ Object { test(`doesn't retry if only unknown failures are passed in`, async () => { const result = await resolveImportErrors({ + http: httpMock, getConflictResolutions, state: { importCount: 0, @@ -98,7 +102,7 @@ Object { }); test('resolves conflicts', async () => { - kfetchMock.mockResolvedValueOnce({ + httpMock.post.mockResolvedValueOnce({ success: true, successCount: 1, }); @@ -107,6 +111,7 @@ Object { 'a:2': false, }); const result = await resolveImportErrors({ + http: httpMock, getConflictResolutions, state: { importCount: 0, @@ -139,7 +144,8 @@ Object { "status": "success", } `); - const formData = getFormData(kfetchMock.mock.calls[0][0].body); + + const formData = getFormData(extractBodyFromCall(0)); expect(formData).toMatchInlineSnapshot(` Object { "file": "undefined", @@ -156,12 +162,13 @@ Object { }); test('resolves missing references', async () => { - kfetchMock.mockResolvedValueOnce({ + httpMock.post.mockResolvedValueOnce({ success: true, successCount: 2, }); getConflictResolutions.mockResolvedValueOnce({}); const result = await resolveImportErrors({ + http: httpMock, getConflictResolutions, state: { importCount: 0, @@ -203,7 +210,7 @@ Object { "status": "success", } `); - const formData = getFormData(kfetchMock.mock.calls[0][0].body); + const formData = getFormData(extractBodyFromCall(0)); expect(formData).toMatchInlineSnapshot(` Object { "file": "undefined", @@ -232,6 +239,7 @@ Object { test(`doesn't resolve missing references if newIndexPatternId isn't defined`, async () => { getConflictResolutions.mockResolvedValueOnce({}); const result = await resolveImportErrors({ + http: httpMock, getConflictResolutions, state: { importCount: 0, @@ -276,7 +284,7 @@ Object { }); test('handles missing references then conflicts on the same errored objects', async () => { - kfetchMock.mockResolvedValueOnce({ + httpMock.post.mockResolvedValueOnce({ success: false, successCount: 0, errors: [ @@ -289,7 +297,7 @@ Object { }, ], }); - kfetchMock.mockResolvedValueOnce({ + httpMock.post.mockResolvedValueOnce({ success: true, successCount: 1, }); @@ -298,6 +306,7 @@ Object { 'a:1': true, }); const result = await resolveImportErrors({ + http: httpMock, getConflictResolutions, state: { importCount: 0, @@ -334,7 +343,7 @@ Object { "status": "success", } `); - const formData1 = getFormData(kfetchMock.mock.calls[0][0].body); + const formData1 = getFormData(extractBodyFromCall(0)); expect(formData1).toMatchInlineSnapshot(` Object { "file": "undefined", @@ -354,7 +363,7 @@ Object { ], } `); - const formData2 = getFormData(kfetchMock.mock.calls[1][0].body); + const formData2 = getFormData(extractBodyFromCall(1)); expect(formData2).toMatchInlineSnapshot(` Object { "file": "undefined", diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.ts b/src/plugins/saved_objects_management/public/lib/resolve_import_errors.ts similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.ts rename to src/plugins/saved_objects_management/public/lib/resolve_import_errors.ts index dcc282402147d..0aea7114bad1c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_import_errors.ts +++ b/src/plugins/saved_objects_management/public/lib/resolve_import_errors.ts @@ -17,7 +17,7 @@ * under the License. */ -import { kfetch } from 'ui/kfetch'; +import { HttpStart } from 'src/core/public'; import { FailedImport } from './process_import_response'; interface RetryObject { @@ -27,13 +27,11 @@ interface RetryObject { replaceReferences?: any[]; } -async function callResolveImportErrorsApi(file: File, retries: any) { +async function callResolveImportErrorsApi(http: HttpStart, file: File, retries: any) { const formData = new FormData(); formData.append('file', file); formData.append('retries', JSON.stringify(retries)); - return await kfetch({ - method: 'POST', - pathname: '/api/saved_objects/_resolve_import_errors', + return http.post<any>('/api/saved_objects/_resolve_import_errors', { headers: { // Important to be undefined, it forces proper headers to be set for FormData 'Content-Type': undefined, @@ -100,9 +98,11 @@ function mapImportFailureToRetryObject({ } export async function resolveImportErrors({ + http, getConflictResolutions, state, }: { + http: HttpStart; getConflictResolutions: (objects: any[]) => Promise<Record<string, boolean>>; state: { importCount: number; failedImports?: FailedImport[] } & Record<string, any>; }) { @@ -170,7 +170,7 @@ export async function resolveImportErrors({ } // Call API - const response = await callResolveImportErrorsApi(file, retries); + const response = await callResolveImportErrorsApi(http, file, retries); successImportCount += response.successCount; importFailures = []; for (const { error, ...obj } of response.errors || []) { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.test.ts b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.test.ts similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.test.ts rename to src/plugins/saved_objects_management/public/lib/resolve_saved_objects.test.ts index dc6d2643145ff..23c2b75169555 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.test.ts +++ b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.test.ts @@ -23,11 +23,8 @@ import { saveObjects, saveObject, } from './resolve_saved_objects'; -import { - SavedObject, - SavedObjectLoader, -} from '../../../../../../../../plugins/saved_objects/public'; -import { IndexPatternsContract } from '../../../../../../../../plugins/data/public'; +import { SavedObject, SavedObjectLoader } from '../../../saved_objects/public'; +import { IndexPatternsContract } from '../../../data/public'; class SavedObjectNotFound extends Error { constructor(options: Record<string, any>) { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.ts b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts similarity index 94% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.ts rename to src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts index d9473367f7502..15e03ed39d88c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/lib/resolve_saved_objects.ts +++ b/src/plugins/saved_objects_management/public/lib/resolve_saved_objects.ts @@ -20,15 +20,8 @@ import { i18n } from '@kbn/i18n'; import { cloneDeep } from 'lodash'; import { OverlayStart, SavedObjectReference } from 'src/core/public'; -import { - SavedObject, - SavedObjectLoader, -} from '../../../../../../../../plugins/saved_objects/public'; -import { - IndexPatternsContract, - IIndexPattern, - createSearchSource, -} from '../../../../../../../../plugins/data/public'; +import { SavedObject, SavedObjectLoader } from '../../../saved_objects/public'; +import { IndexPatternsContract, IIndexPattern, createSearchSource } from '../../../data/public'; type SavedObjectsRawDoc = Record<string, any>; @@ -55,7 +48,7 @@ function addJsonFieldToIndexPattern( target[fieldName] = JSON.parse(sourceString); } catch (error) { throw new Error( - i18n.translate('kbn.management.objects.parsingFieldErrorMessage', { + i18n.translate('savedObjectsManagement.parsingFieldErrorMessage', { defaultMessage: 'Error encountered parsing {fieldName} for index pattern {indexName}: {errorMessage}', values: { @@ -103,18 +96,21 @@ async function importIndexPattern( if (!newId) { // We can override and we want to prompt for confirmation const isConfirmed = await openConfirm( - i18n.translate('kbn.management.indexPattern.confirmOverwriteLabel', { + i18n.translate('savedObjectsManagement.indexPattern.confirmOverwriteLabel', { values: { title }, defaultMessage: "Are you sure you want to overwrite '{title}'?", }), { - title: i18n.translate('kbn.management.indexPattern.confirmOverwriteTitle', { + title: i18n.translate('savedObjectsManagement.indexPattern.confirmOverwriteTitle', { defaultMessage: 'Overwrite {type}?', values: { type }, }), - confirmButtonText: i18n.translate('kbn.management.indexPattern.confirmOverwriteButton', { - defaultMessage: 'Overwrite', - }), + confirmButtonText: i18n.translate( + 'savedObjectsManagement.indexPattern.confirmOverwriteButton', + { + defaultMessage: 'Overwrite', + } + ), } ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/index.js b/src/plugins/saved_objects_management/public/management_section/index.ts similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/index.js rename to src/plugins/saved_objects_management/public/management_section/index.ts index 522b1ce83a6b6..1bccb2102f3b4 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/index.js +++ b/src/plugins/saved_objects_management/public/management_section/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { Relationships } from './relationships'; +export { mountManagementSection } from './mount_section'; diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx new file mode 100644 index 0000000000000..6f03f97079bb6 --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -0,0 +1,211 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect } from 'react'; +import ReactDOM from 'react-dom'; +import { HashRouter, Switch, Route, useParams, useLocation } from 'react-router-dom'; +import { parse } from 'query-string'; +import { get } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { I18nProvider } from '@kbn/i18n/react'; +import { CoreSetup, CoreStart, ChromeBreadcrumb, Capabilities } from 'src/core/public'; +import { ManagementAppMountParams } from '../../../management/public'; +import { DataPublicPluginStart } from '../../../data/public'; +import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin'; +import { + ISavedObjectsManagementServiceRegistry, + SavedObjectsManagementActionServiceStart, +} from '../services'; +import { SavedObjectsTable } from './objects_table'; +import { SavedObjectEdition } from './object_view'; +import { getAllowedTypes } from './../lib'; + +interface MountParams { + core: CoreSetup<StartDependencies, SavedObjectsManagementPluginStart>; + serviceRegistry: ISavedObjectsManagementServiceRegistry; + mountParams: ManagementAppMountParams; +} + +let allowedObjectTypes: string[] | undefined; + +export const mountManagementSection = async ({ + core, + mountParams, + serviceRegistry, +}: MountParams) => { + const [coreStart, { data }, pluginStart] = await core.getStartServices(); + const { element, basePath, setBreadcrumbs } = mountParams; + if (allowedObjectTypes === undefined) { + allowedObjectTypes = await getAllowedTypes(coreStart.http); + } + + const capabilities = coreStart.application.capabilities; + + ReactDOM.render( + <I18nProvider> + <HashRouter basename={basePath}> + <Switch> + <Route path={'/:service/:id'} exact={true}> + <RedirectToHomeIfUnauthorized capabilities={capabilities}> + <SavedObjectsEditionPage + coreStart={coreStart} + serviceRegistry={serviceRegistry} + setBreadcrumbs={setBreadcrumbs} + /> + </RedirectToHomeIfUnauthorized> + </Route> + <Route path={'/'} exact={false}> + <RedirectToHomeIfUnauthorized capabilities={capabilities}> + <SavedObjectsTablePage + coreStart={coreStart} + dataStart={data} + serviceRegistry={serviceRegistry} + actionRegistry={pluginStart.actions} + allowedTypes={allowedObjectTypes} + setBreadcrumbs={setBreadcrumbs} + /> + </RedirectToHomeIfUnauthorized> + </Route> + </Switch> + </HashRouter> + </I18nProvider>, + element + ); + + return () => { + ReactDOM.unmountComponentAtNode(element); + }; +}; + +const RedirectToHomeIfUnauthorized: React.FunctionComponent<{ + capabilities: Capabilities; +}> = ({ children, capabilities }) => { + const allowed = capabilities?.management?.kibana?.objects ?? false; + if (!allowed) { + window.location.hash = '/home'; + return null; + } + return children! as React.ReactElement; +}; + +const SavedObjectsEditionPage = ({ + coreStart, + serviceRegistry, + setBreadcrumbs, +}: { + coreStart: CoreStart; + serviceRegistry: ISavedObjectsManagementServiceRegistry; + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; +}) => { + const { service: serviceName, id } = useParams<{ service: string; id: string }>(); + const capabilities = coreStart.application.capabilities; + + const { search } = useLocation(); + const query = parse(search); + const service = serviceRegistry.get(serviceName); + + useEffect(() => { + setBreadcrumbs([ + { + text: i18n.translate('savedObjectsManagement.breadcrumb.index', { + defaultMessage: 'Saved objects', + }), + href: '#/management/kibana/objects', + }, + { + text: i18n.translate('savedObjectsManagement.breadcrumb.edit', { + defaultMessage: 'Edit {savedObjectType}', + values: { savedObjectType: service?.service.type ?? 'object' }, + }), + }, + ]); + }, [setBreadcrumbs, service]); + + return ( + <SavedObjectEdition + id={id} + serviceName={serviceName} + serviceRegistry={serviceRegistry} + savedObjectsClient={coreStart.savedObjects.client} + overlays={coreStart.overlays} + notifications={coreStart.notifications} + capabilities={capabilities} + notFoundType={query.notFound as string} + /> + ); +}; + +const SavedObjectsTablePage = ({ + coreStart, + dataStart, + allowedTypes, + serviceRegistry, + actionRegistry, + setBreadcrumbs, +}: { + coreStart: CoreStart; + dataStart: DataPublicPluginStart; + allowedTypes: string[]; + serviceRegistry: ISavedObjectsManagementServiceRegistry; + actionRegistry: SavedObjectsManagementActionServiceStart; + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; +}) => { + const capabilities = coreStart.application.capabilities; + const itemsPerPage = coreStart.uiSettings.get<number>('savedObjects:perPage', 50); + + useEffect(() => { + setBreadcrumbs([ + { + text: i18n.translate('savedObjectsManagement.breadcrumb.index', { + defaultMessage: 'Saved objects', + }), + href: '#/management/kibana/objects', + }, + ]); + }, [setBreadcrumbs]); + + return ( + <SavedObjectsTable + allowedTypes={allowedTypes} + serviceRegistry={serviceRegistry} + actionRegistry={actionRegistry} + savedObjectsClient={coreStart.savedObjects.client} + indexPatterns={dataStart.indexPatterns} + http={coreStart.http} + overlays={coreStart.overlays} + notifications={coreStart.notifications} + applications={coreStart.application} + perPageConfig={itemsPerPage} + goInspectObject={savedObject => { + const { editUrl } = savedObject.meta; + if (editUrl) { + // previously, kbnUrl.change(object.meta.editUrl); was used. + // using direct access to location.hash seems the only option for now, + // as using react-router-dom will prefix the url with the router's basename + // which should be ignored there. + window.location.hash = editUrl; + } + }} + canGoInApp={savedObject => { + const { inAppUrl } = savedObject.meta; + return inAppUrl ? get(capabilities, inAppUrl.uiCapabilitiesPath) : false; + }} + /> + ); +}; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/header.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/header.test.tsx.snap similarity index 96% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/header.test.tsx.snap rename to src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/header.test.tsx.snap index 7e1f7ea12b014..d56776c2be9d7 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/header.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/header.test.tsx.snap @@ -23,7 +23,7 @@ exports[`Intro component renders correctly 1`] = ` > <FormattedMessage defaultMessage="Edit {title}" - id="kbn.management.objects.view.editItemTitle" + id="savedObjectsManagement.view.editItemTitle" values={ Object { "title": "search", @@ -85,7 +85,7 @@ exports[`Intro component renders correctly 1`] = ` > <FormattedMessage defaultMessage="View {title}" - id="kbn.management.objects.view.viewItemButtonLabel" + id="savedObjectsManagement.view.viewItemButtonLabel" values={ Object { "title": "search", @@ -140,7 +140,7 @@ exports[`Intro component renders correctly 1`] = ` > <FormattedMessage defaultMessage="Delete {title}" - id="kbn.management.objects.view.deleteItemButtonLabel" + id="savedObjectsManagement.view.deleteItemButtonLabel" values={ Object { "title": "search", diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/intro.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/intro.test.tsx.snap similarity index 90% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/intro.test.tsx.snap rename to src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/intro.test.tsx.snap index 812031b4b363c..ff179401e6f71 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/intro.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/intro.test.tsx.snap @@ -8,7 +8,7 @@ exports[`Intro component renders correctly 1`] = ` title={ <FormattedMessage defaultMessage="Proceed with caution!" - id="kbn.management.objects.view.howToModifyObjectTitle" + id="savedObjectsManagement.view.howToModifyObjectTitle" values={Object {}} /> } @@ -37,7 +37,7 @@ exports[`Intro component renders correctly 1`] = ` > <FormattedMessage defaultMessage="Proceed with caution!" - id="kbn.management.objects.view.howToModifyObjectTitle" + id="savedObjectsManagement.view.howToModifyObjectTitle" values={Object {}} > Proceed with caution! @@ -53,7 +53,7 @@ exports[`Intro component renders correctly 1`] = ` <div> <FormattedMessage defaultMessage="Modifying objects is for advanced users only. Object properties are not validated and invalid objects could cause errors, data loss, or worse. Unless someone with intimate knowledge of the code told you to be in here, you probably shouldn’t be." - id="kbn.management.objects.view.howToModifyObjectDescription" + id="savedObjectsManagement.view.howToModifyObjectDescription" values={Object {}} > Modifying objects is for advanced users only. Object properties are not validated and invalid objects could cause errors, data loss, or worse. Unless someone with intimate knowledge of the code told you to be in here, you probably shouldn’t be. diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/not_found_errors.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/not_found_errors.test.tsx.snap similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/not_found_errors.test.tsx.snap rename to src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/not_found_errors.test.tsx.snap index ac565a000813e..d5372fd5b18d9 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/__snapshots__/not_found_errors.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/__snapshots__/not_found_errors.test.tsx.snap @@ -10,7 +10,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern type 1`] = title={ <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} /> } @@ -39,7 +39,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern type 1`] = > <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} > There is a problem with this saved object @@ -55,7 +55,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern type 1`] = <div> <FormattedMessage defaultMessage="The index pattern associated with this object no longer exists." - id="kbn.management.objects.view.indexPatternDoesNotExistErrorMessage" + id="savedObjectsManagement.view.indexPatternDoesNotExistErrorMessage" values={Object {}} > The index pattern associated with this object no longer exists. @@ -64,7 +64,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern type 1`] = <div> <FormattedMessage defaultMessage="If you know what this error means, go ahead and fix it — otherwise click the delete button above." - id="kbn.management.objects.view.howToFixErrorDescription" + id="savedObjectsManagement.view.howToFixErrorDescription" values={Object {}} > If you know what this error means, go ahead and fix it — otherwise click the delete button above. @@ -87,7 +87,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern-field type title={ <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} /> } @@ -116,7 +116,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern-field type > <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} > There is a problem with this saved object @@ -132,7 +132,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern-field type <div> <FormattedMessage defaultMessage="A field associated with this object no longer exists in the index pattern." - id="kbn.management.objects.view.fieldDoesNotExistErrorMessage" + id="savedObjectsManagement.view.fieldDoesNotExistErrorMessage" values={Object {}} > A field associated with this object no longer exists in the index pattern. @@ -141,7 +141,7 @@ exports[`NotFoundErrors component renders correctly for index-pattern-field type <div> <FormattedMessage defaultMessage="If you know what this error means, go ahead and fix it — otherwise click the delete button above." - id="kbn.management.objects.view.howToFixErrorDescription" + id="savedObjectsManagement.view.howToFixErrorDescription" values={Object {}} > If you know what this error means, go ahead and fix it — otherwise click the delete button above. @@ -164,7 +164,7 @@ exports[`NotFoundErrors component renders correctly for search type 1`] = ` title={ <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} /> } @@ -193,7 +193,7 @@ exports[`NotFoundErrors component renders correctly for search type 1`] = ` > <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} > There is a problem with this saved object @@ -209,7 +209,7 @@ exports[`NotFoundErrors component renders correctly for search type 1`] = ` <div> <FormattedMessage defaultMessage="The saved search associated with this object no longer exists." - id="kbn.management.objects.view.savedSearchDoesNotExistErrorMessage" + id="savedObjectsManagement.view.savedSearchDoesNotExistErrorMessage" values={Object {}} > The saved search associated with this object no longer exists. @@ -218,7 +218,7 @@ exports[`NotFoundErrors component renders correctly for search type 1`] = ` <div> <FormattedMessage defaultMessage="If you know what this error means, go ahead and fix it — otherwise click the delete button above." - id="kbn.management.objects.view.howToFixErrorDescription" + id="savedObjectsManagement.view.howToFixErrorDescription" values={Object {}} > If you know what this error means, go ahead and fix it — otherwise click the delete button above. @@ -241,7 +241,7 @@ exports[`NotFoundErrors component renders correctly for unknown type 1`] = ` title={ <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} /> } @@ -270,7 +270,7 @@ exports[`NotFoundErrors component renders correctly for unknown type 1`] = ` > <FormattedMessage defaultMessage="There is a problem with this saved object" - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" values={Object {}} > There is a problem with this saved object @@ -287,7 +287,7 @@ exports[`NotFoundErrors component renders correctly for unknown type 1`] = ` <div> <FormattedMessage defaultMessage="If you know what this error means, go ahead and fix it — otherwise click the delete button above." - id="kbn.management.objects.view.howToFixErrorDescription" + id="savedObjectsManagement.view.howToFixErrorDescription" values={Object {}} > If you know what this error means, go ahead and fix it — otherwise click the delete button above. diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.test.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.test.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/field.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx similarity index 97% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx index 1ed0b57e400b8..1b69eb4240d68 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/field.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/field.tsx @@ -104,9 +104,9 @@ export class Field extends PureComponent<FieldProps> { id={this.fieldId} label={ !!currentValue ? ( - <FormattedMessage id="kbn.management.objects.field.onLabel" defaultMessage="On" /> + <FormattedMessage id="savedObjectsManagement.field.onLabel" defaultMessage="On" /> ) : ( - <FormattedMessage id="kbn.management.objects.field.offLabel" defaultMessage="Off" /> + <FormattedMessage id="savedObjectsManagement.field.offLabel" defaultMessage="Off" /> ) } checked={!!currentValue} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/form.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/form.tsx similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/form.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/form.tsx index 7270d41eef529..04be7ee3ce207 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/form.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/form.tsx @@ -29,15 +29,11 @@ import { import { cloneDeep, set } from 'lodash'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - SimpleSavedObject, - SavedObjectsClientContract, -} from '../../../../../../../../../core/public'; - -import { SavedObjectLoader } from '../../../../../../../../../plugins/saved_objects/public'; +import { SimpleSavedObject, SavedObjectsClientContract } from '../../../../../../core/public'; +import { SavedObjectLoader } from '../../../../../saved_objects/public'; import { Field } from './field'; import { ObjectField, FieldState, SubmittedFormData } from '../../types'; -import { createFieldList } from '../../lib/create_field_list'; +import { createFieldList } from '../../../lib'; interface FormProps { object: SimpleSavedObject; @@ -96,7 +92,7 @@ export class Form extends Component<FormProps, FormState> { <EuiFlexItem grow={false}> <EuiButton fill={true} - aria-label={i18n.translate('kbn.management.objects.view.saveButtonAriaLabel', { + aria-label={i18n.translate('savedObjectsManagement.view.saveButtonAriaLabel', { defaultMessage: 'Save { title } object', values: { title: service.type, @@ -107,7 +103,7 @@ export class Form extends Component<FormProps, FormState> { data-test-subj="savedObjectEditSave" > <FormattedMessage - id="kbn.management.objects.view.saveButtonLabel" + id="savedObjectsManagement.view.saveButtonLabel" defaultMessage="Save { title } object" values={{ title: service.type }} /> @@ -117,14 +113,14 @@ export class Form extends Component<FormProps, FormState> { <EuiFlexItem grow={false}> <EuiButtonEmpty - aria-label={i18n.translate('kbn.management.objects.view.cancelButtonAriaLabel', { + aria-label={i18n.translate('savedObjectsManagement.view.cancelButtonAriaLabel', { defaultMessage: 'Cancel', })} onClick={this.onCancel} data-test-subj="savedObjectEditCancel" > <FormattedMessage - id="kbn.management.objects.view.cancelButtonLabel" + id="savedObjectsManagement.view.cancelButtonLabel" defaultMessage="Cancel" /> </EuiButtonEmpty> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.test.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/header.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.test.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/header.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/header.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/header.tsx index 641493e0cbaa8..305d953c4990b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/header.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/header.tsx @@ -52,7 +52,7 @@ export const Header = ({ {canEdit ? ( <h1> <FormattedMessage - id="kbn.management.objects.view.editItemTitle" + id="savedObjectsManagement.view.editItemTitle" defaultMessage="Edit {title}" values={{ title: type }} /> @@ -60,7 +60,7 @@ export const Header = ({ ) : ( <h1> <FormattedMessage - id="kbn.management.objects.view.viewItemTitle" + id="savedObjectsManagement.view.viewItemTitle" defaultMessage="View {title}" values={{ title: type }} /> @@ -79,7 +79,7 @@ export const Header = ({ data-test-subj="savedObjectEditViewInApp" > <FormattedMessage - id="kbn.management.objects.view.viewItemButtonLabel" + id="savedObjectsManagement.view.viewItemButtonLabel" defaultMessage="View {title}" values={{ title: type }} /> @@ -96,7 +96,7 @@ export const Header = ({ data-test-subj="savedObjectEditDelete" > <FormattedMessage - id="kbn.management.objects.view.deleteItemButtonLabel" + id="savedObjectsManagement.view.deleteItemButtonLabel" defaultMessage="Delete {title}" values={{ title: type }} /> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/index.ts b/src/plugins/saved_objects_management/public/management_section/object_view/components/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/index.ts rename to src/plugins/saved_objects_management/public/management_section/object_view/components/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.test.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/intro.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.test.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/intro.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/intro.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/intro.tsx index 098ad71345d49..920a5fcbcb02e 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/intro.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/intro.tsx @@ -26,7 +26,7 @@ export const Intro = () => { <EuiCallOut title={ <FormattedMessage - id="kbn.management.objects.view.howToModifyObjectTitle" + id="savedObjectsManagement.view.howToModifyObjectTitle" defaultMessage="Proceed with caution!" /> } @@ -35,7 +35,7 @@ export const Intro = () => { > <div> <FormattedMessage - id="kbn.management.objects.view.howToModifyObjectDescription" + id="savedObjectsManagement.view.howToModifyObjectDescription" defaultMessage="Modifying objects is for advanced users only. Object properties are not validated and invalid objects could cause errors, data loss, or worse. Unless someone with intimate knowledge of the code told you to be in here, you probably shouldn’t be." /> </div> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.test.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/not_found_errors.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.test.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/not_found_errors.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/components/not_found_errors.tsx similarity index 87% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/components/not_found_errors.tsx index c3d18855f6c9a..1a63f7eaf4819 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/object_view/not_found_errors.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/components/not_found_errors.tsx @@ -31,21 +31,21 @@ export const NotFoundErrors = ({ type }: NotFoundErrors) => { case 'search': return ( <FormattedMessage - id="kbn.management.objects.view.savedSearchDoesNotExistErrorMessage" + id="savedObjectsManagement.view.savedSearchDoesNotExistErrorMessage" defaultMessage="The saved search associated with this object no longer exists." /> ); case 'index-pattern': return ( <FormattedMessage - id="kbn.management.objects.view.indexPatternDoesNotExistErrorMessage" + id="savedObjectsManagement.view.indexPatternDoesNotExistErrorMessage" defaultMessage="The index pattern associated with this object no longer exists." /> ); case 'index-pattern-field': return ( <FormattedMessage - id="kbn.management.objects.view.fieldDoesNotExistErrorMessage" + id="savedObjectsManagement.view.fieldDoesNotExistErrorMessage" defaultMessage="A field associated with this object no longer exists in the index pattern." /> ); @@ -58,7 +58,7 @@ export const NotFoundErrors = ({ type }: NotFoundErrors) => { <EuiCallOut title={ <FormattedMessage - id="kbn.management.objects.view.savedObjectProblemErrorMessage" + id="savedObjectsManagement.view.savedObjectProblemErrorMessage" defaultMessage="There is a problem with this saved object" /> } @@ -68,7 +68,7 @@ export const NotFoundErrors = ({ type }: NotFoundErrors) => { <div>{getMessage()}</div> <div> <FormattedMessage - id="kbn.management.objects.view.howToFixErrorDescription" + id="savedObjectsManagement.view.howToFixErrorDescription" defaultMessage="If you know what this error means, go ahead and fix it — otherwise click the delete button above." /> </div> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/index.js b/src/plugins/saved_objects_management/public/management_section/object_view/index.ts similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/index.js rename to src/plugins/saved_objects_management/public/management_section/object_view/index.ts index cdeebdbf7b63a..a823923536d31 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/index.js +++ b/src/plugins/saved_objects_management/public/management_section/object_view/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { Flyout } from './flyout'; +export { SavedObjectEdition } from './saved_object_view'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/saved_object_view.tsx b/src/plugins/saved_objects_management/public/management_section/object_view/saved_object_view.tsx similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/saved_object_view.tsx rename to src/plugins/saved_objects_management/public/management_section/object_view/saved_object_view.tsx index 4984fe3e6d6b8..f714970a5cac3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/saved_object_view.tsx +++ b/src/plugins/saved_objects_management/public/management_section/object_view/saved_object_view.tsx @@ -26,16 +26,16 @@ import { OverlayStart, NotificationsStart, SimpleSavedObject, -} from '../../../../../../../core/public'; -import { ISavedObjectsManagementRegistry } from '../../saved_object_registry'; -import { Header, NotFoundErrors, Intro, Form } from './components/object_view'; -import { canViewInApp } from './lib/in_app_url'; -import { SubmittedFormData } from './types'; +} from '../../../../../core/public'; +import { ISavedObjectsManagementServiceRegistry } from '../../services'; +import { Header, NotFoundErrors, Intro, Form } from './components'; +import { canViewInApp } from '../../lib'; +import { SubmittedFormData } from '../types'; interface SavedObjectEditionProps { id: string; serviceName: string; - serviceRegistry: ISavedObjectsManagementRegistry; + serviceRegistry: ISavedObjectsManagementServiceRegistry; capabilities: Capabilities; overlays: OverlayStart; notifications: NotificationsStart; @@ -135,17 +135,17 @@ export class SavedObjectEdition extends Component< const { type, object } = this.state; const confirmed = await overlays.openConfirm( - i18n.translate('kbn.management.objects.confirmModalOptions.modalDescription', { + i18n.translate('savedObjectsManagement.deleteConfirm.modalDescription', { defaultMessage: 'This action permanently removes the object from Kibana.', }), { confirmButtonText: i18n.translate( - 'kbn.management.objects.confirmModalOptions.deleteButtonLabel', + 'savedObjectsManagement.deleteConfirm.modalDeleteButtonLabel', { defaultMessage: 'Delete', } ), - title: i18n.translate('kbn.management.objects.confirmModalOptions.modalTitle', { + title: i18n.translate('savedObjectsManagement.deleteConfirm.modalTitle', { defaultMessage: `Delete '{title}'?`, values: { title: object?.attributes?.title || 'saved Kibana object', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap similarity index 73% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap rename to src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 2c0a5d8f6b8f1..fe64df6ff51d1 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -1,19 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ObjectsTable delete should show a confirm modal 1`] = ` +exports[`SavedObjectsTable delete should show a confirm modal 1`] = ` <EuiConfirmModal buttonColor="danger" cancelButtonText={ <FormattedMessage defaultMessage="Cancel" - id="kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel" values={Object {}} /> } confirmButtonText={ <FormattedMessage defaultMessage="Delete" - id="kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel" + id="savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel" values={Object {}} /> } @@ -23,7 +23,7 @@ exports[`ObjectsTable delete should show a confirm modal 1`] = ` title={ <FormattedMessage defaultMessage="Delete saved objects" - id="kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModalTitle" + id="savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle" values={Object {}} /> } @@ -31,7 +31,7 @@ exports[`ObjectsTable delete should show a confirm modal 1`] = ` <p> <FormattedMessage defaultMessage="This action will delete the following saved objects:" - id="kbn.management.objects.deleteSavedObjectsConfirmModalDescription" + id="savedObjectsManagement.deleteSavedObjectsConfirmModalDescription" values={Object {}} /> </p> @@ -58,12 +58,10 @@ exports[`ObjectsTable delete should show a confirm modal 1`] = ` Array [ Object { "id": "1", - "title": "Title 1", "type": "index-pattern", }, Object { "id": "3", - "title": "Title 2", "type": "dashboard", }, ] @@ -76,7 +74,7 @@ exports[`ObjectsTable delete should show a confirm modal 1`] = ` </EuiConfirmModal> `; -exports[`ObjectsTable export should allow the user to choose when exporting all 1`] = ` +exports[`SavedObjectsTable export should allow the user to choose when exporting all 1`] = ` <EuiModal onClose={[Function]} > @@ -84,7 +82,7 @@ exports[`ObjectsTable export should allow the user to choose when exporting all <EuiModalHeaderTitle> <FormattedMessage defaultMessage="Export {filteredItemCount, plural, one{# object} other {# objects}}" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModalTitle" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModalTitle" values={ Object { "filteredItemCount": 4, @@ -103,7 +101,7 @@ exports[`ObjectsTable export should allow the user to choose when exporting all label={ <FormattedMessage defaultMessage="Select which types to export" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModalDescription" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription" values={Object {}} /> } @@ -149,7 +147,7 @@ exports[`ObjectsTable export should allow the user to choose when exporting all label={ <FormattedMessage defaultMessage="Include related objects" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" values={Object {}} /> } @@ -173,7 +171,7 @@ exports[`ObjectsTable export should allow the user to choose when exporting all > <FormattedMessage defaultMessage="Cancel" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.cancelButtonLabel" values={Object {}} /> </EuiButtonEmpty> @@ -187,7 +185,7 @@ exports[`ObjectsTable export should allow the user to choose when exporting all > <FormattedMessage defaultMessage="Export all" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel" values={Object {}} /> </EuiButton> @@ -199,23 +197,87 @@ exports[`ObjectsTable export should allow the user to choose when exporting all </EuiModal> `; -exports[`ObjectsTable import should show the flyout 1`] = ` +exports[`SavedObjectsTable import should show the flyout 1`] = ` <Flyout + allowedTypes={ + Array [ + "index-pattern", + "visualization", + "dashboard", + "search", + ] + } close={[Function]} - confirmModalPromise={[MockFunction]} done={[Function]} + http={ + Object { + "addLoadingCountSource": [MockFunction], + "anonymousPaths": Object { + "isAnonymous": [MockFunction], + "register": [MockFunction], + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + "serverBasePath": "", + }, + "delete": [MockFunction], + "fetch": [MockFunction], + "get": [MockFunction], + "getLoadingCount$": [MockFunction], + "head": [MockFunction], + "intercept": [MockFunction], + "options": [MockFunction], + "patch": [MockFunction], + "post": [MockFunction], + "put": [MockFunction], + } + } indexPatterns={ Object { "clearCache": [MockFunction], + "get": [MockFunction], + "make": [Function], + } + } + overlays={ + Object { + "banners": Object { + "add": [MockFunction], + "get$": [MockFunction], + "getComponent": [MockFunction], + "remove": [MockFunction], + "replace": [MockFunction], + }, + "openConfirm": [MockFunction], + "openFlyout": [MockFunction], + "openModal": [MockFunction], + } + } + serviceRegistry={ + Object { + "all": [MockFunction], + "get": [MockFunction], + "register": [MockFunction], } } - newIndexPatternUrl="" - services={Array []} /> `; -exports[`ObjectsTable relationships should show the flyout 1`] = ` +exports[`SavedObjectsTable relationships should show the flyout 1`] = ` <Relationships + basePath={ + BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + "serverBasePath": "", + } + } + canGoInApp={[Function]} close={[Function]} getRelationships={[Function]} goInspectObject={[Function]} @@ -237,7 +299,7 @@ exports[`ObjectsTable relationships should show the flyout 1`] = ` /> `; -exports[`ObjectsTable should render normally 1`] = ` +exports[`SavedObjectsTable should render normally 1`] = ` <EuiPageContent horizontalPosition="center" > @@ -251,7 +313,23 @@ exports[`ObjectsTable should render normally 1`] = ` size="xs" /> <Table + actionRegistry={ + Object { + "getAll": [MockFunction], + "has": [MockFunction], + } + } + basePath={ + BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + "serverBasePath": "", + } + } canDelete={false} + canGoInApp={[Function]} filterOptions={ Array [ Object { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap similarity index 85% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap index 34ce8394232ed..4721d166c65e5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap @@ -18,7 +18,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = ` <h2> <FormattedMessage defaultMessage="Import saved objects" - id="kbn.management.objects.objectsTable.flyout.importSavedObjectTitle" + id="savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle" values={Object {}} /> </h2> @@ -36,7 +36,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = ` title={ <FormattedMessage defaultMessage="Index Pattern Conflicts" - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsTitle" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle" values={Object {}} /> } @@ -44,7 +44,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = ` <p> <FormattedMessage defaultMessage="The following saved objects use index patterns that do not exist. Please select the index patterns you'd like re-associated with them. You can {indexPatternLink} if necessary." - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsDescription" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription" values={ Object { "indexPatternLink": <ForwardRef @@ -52,7 +52,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = ` > <FormattedMessage defaultMessage="create a new index pattern" - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsCalloutLinkText" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText" values={Object {}} /> </ForwardRef>, @@ -131,7 +131,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = ` > <FormattedMessage defaultMessage="Cancel" - id="kbn.management.objects.objectsTable.flyout.import.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel" values={Object {}} /> </EuiButtonEmpty> @@ -148,7 +148,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = ` > <FormattedMessage defaultMessage="Confirm all changes" - id="kbn.management.objects.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel" values={Object {}} /> </EuiButton> @@ -164,6 +164,30 @@ exports[`Flyout conflicts should allow conflict resolution 2`] = ` Array [ Object { "getConflictResolutions": [Function], + "http": Object { + "addLoadingCountSource": [MockFunction], + "anonymousPaths": Object { + "isAnonymous": [MockFunction], + "register": [MockFunction], + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + "serverBasePath": "", + }, + "delete": [MockFunction], + "fetch": [MockFunction], + "get": [MockFunction], + "getLoadingCount$": [MockFunction], + "head": [MockFunction], + "intercept": [MockFunction], + "options": [MockFunction], + "patch": [MockFunction], + "post": [MockFunction], + "put": [MockFunction], + }, "state": Object { "conflictedIndexPatterns": undefined, "conflictedSavedObjectsLinkedToSavedSearches": undefined, @@ -243,7 +267,7 @@ exports[`Flyout conflicts should handle errors 1`] = ` title={ <FormattedMessage defaultMessage="Import failed" - id="kbn.management.objects.objectsTable.flyout.importFailedTitle" + id="savedObjectsManagement.objectsTable.flyout.importFailedTitle" values={Object {}} /> } @@ -251,7 +275,7 @@ exports[`Flyout conflicts should handle errors 1`] = ` <p> <FormattedMessage defaultMessage="Failed to import {failedImportCount} of {totalImportCount} objects. Import failed" - id="kbn.management.objects.objectsTable.flyout.importFailedDescription" + id="savedObjectsManagement.objectsTable.flyout.importFailedDescription" values={ Object { "failedImportCount": 1, @@ -272,7 +296,7 @@ exports[`Flyout errors should display unsupported type errors properly 1`] = ` title={ <FormattedMessage defaultMessage="Import failed" - id="kbn.management.objects.objectsTable.flyout.importFailedTitle" + id="savedObjectsManagement.objectsTable.flyout.importFailedTitle" values={Object {}} /> } @@ -280,7 +304,7 @@ exports[`Flyout errors should display unsupported type errors properly 1`] = ` <p> <FormattedMessage defaultMessage="Failed to import {failedImportCount} of {totalImportCount} objects. Import failed" - id="kbn.management.objects.objectsTable.flyout.importFailedDescription" + id="savedObjectsManagement.objectsTable.flyout.importFailedDescription" values={ Object { "failedImportCount": 1, @@ -313,7 +337,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` <h2> <FormattedMessage defaultMessage="Import saved objects" - id="kbn.management.objects.objectsTable.flyout.importSavedObjectTitle" + id="savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle" values={Object {}} /> </h2> @@ -331,7 +355,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` title={ <FormattedMessage defaultMessage="Support for JSON files is going away" - id="kbn.management.objects.objectsTable.flyout.legacyFileUsedTitle" + id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle" values={Object {}} /> } @@ -339,7 +363,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` <p> <FormattedMessage defaultMessage="Use our updated export to generate NDJSON files, and you'll be all set." - id="kbn.management.objects.objectsTable.flyout.legacyFileUsedBody" + id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody" values={Object {}} /> </p> @@ -356,7 +380,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` title={ <FormattedMessage defaultMessage="Index Pattern Conflicts" - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsTitle" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle" values={Object {}} /> } @@ -364,7 +388,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` <p> <FormattedMessage defaultMessage="The following saved objects use index patterns that do not exist. Please select the index patterns you'd like re-associated with them. You can {indexPatternLink} if necessary." - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsDescription" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription" values={ Object { "indexPatternLink": <ForwardRef @@ -372,7 +396,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` > <FormattedMessage defaultMessage="create a new index pattern" - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsCalloutLinkText" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText" values={Object {}} /> </ForwardRef>, @@ -462,7 +486,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` > <FormattedMessage defaultMessage="Cancel" - id="kbn.management.objects.objectsTable.flyout.import.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel" values={Object {}} /> </EuiButtonEmpty> @@ -479,7 +503,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = ` > <FormattedMessage defaultMessage="Confirm all changes" - id="kbn.management.objects.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel" values={Object {}} /> </EuiButton> @@ -498,7 +522,7 @@ Array [ title={ <FormattedMessage defaultMessage="Support for JSON files is going away" - id="kbn.management.objects.objectsTable.flyout.legacyFileUsedTitle" + id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle" values={Object {}} /> } @@ -506,7 +530,7 @@ Array [ <p> <FormattedMessage defaultMessage="Use our updated export to generate NDJSON files, and you'll be all set." - id="kbn.management.objects.objectsTable.flyout.legacyFileUsedBody" + id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody" values={Object {}} /> </p> @@ -518,7 +542,7 @@ Array [ title={ <FormattedMessage defaultMessage="Index Pattern Conflicts" - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsTitle" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle" values={Object {}} /> } @@ -526,7 +550,7 @@ Array [ <p> <FormattedMessage defaultMessage="The following saved objects use index patterns that do not exist. Please select the index patterns you'd like re-associated with them. You can {indexPatternLink} if necessary." - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsDescription" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription" values={ Object { "indexPatternLink": <ForwardRef @@ -534,7 +558,7 @@ Array [ > <FormattedMessage defaultMessage="create a new index pattern" - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsCalloutLinkText" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText" values={Object {}} /> </ForwardRef>, @@ -548,7 +572,7 @@ Array [ title={ <FormattedMessage defaultMessage="Sorry, there was an error" - id="kbn.management.objects.objectsTable.flyout.errorCalloutTitle" + id="savedObjectsManagement.objectsTable.flyout.errorCalloutTitle" values={Object {}} /> } @@ -578,7 +602,7 @@ exports[`Flyout should render import step 1`] = ` <h2> <FormattedMessage defaultMessage="Import saved objects" - id="kbn.management.objects.objectsTable.flyout.importSavedObjectTitle" + id="savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle" values={Object {}} /> </h2> @@ -595,7 +619,7 @@ exports[`Flyout should render import step 1`] = ` label={ <FormattedMessage defaultMessage="Please select a file to import" - id="kbn.management.objects.objectsTable.flyout.selectFileToImportFormRowLabel" + id="savedObjectsManagement.objectsTable.flyout.selectFileToImportFormRowLabel" values={Object {}} /> } @@ -607,7 +631,7 @@ exports[`Flyout should render import step 1`] = ` initialPromptText={ <FormattedMessage defaultMessage="Import" - id="kbn.management.objects.objectsTable.flyout.importPromptText" + id="savedObjectsManagement.objectsTable.flyout.importPromptText" values={Object {}} /> } @@ -628,7 +652,7 @@ exports[`Flyout should render import step 1`] = ` label={ <FormattedMessage defaultMessage="Automatically overwrite all saved objects?" - id="kbn.management.objects.objectsTable.flyout.overwriteSavedObjectsLabel" + id="savedObjectsManagement.objectsTable.flyout.overwriteSavedObjectsLabel" values={Object {}} /> } @@ -651,7 +675,7 @@ exports[`Flyout should render import step 1`] = ` > <FormattedMessage defaultMessage="Cancel" - id="kbn.management.objects.objectsTable.flyout.import.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel" values={Object {}} /> </EuiButtonEmpty> @@ -668,7 +692,7 @@ exports[`Flyout should render import step 1`] = ` > <FormattedMessage defaultMessage="Import" - id="kbn.management.objects.objectsTable.flyout.import.confirmButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel" values={Object {}} /> </EuiButton> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap similarity index 88% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap index 51bd51a5e2e58..642a5030e4ec0 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/__snapshots__/header.test.js.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/header.test.tsx.snap @@ -13,7 +13,7 @@ exports[`Header should render normally 1`] = ` <h1> <FormattedMessage defaultMessage="Saved Objects" - id="kbn.management.objects.objectsTable.header.savedObjectsTitle" + id="savedObjectsManagement.objectsTable.header.savedObjectsTitle" values={Object {}} /> </h1> @@ -38,7 +38,7 @@ exports[`Header should render normally 1`] = ` > <FormattedMessage defaultMessage="Export {filteredCount, plural, one{# object} other {# objects}}" - id="kbn.management.objects.objectsTable.header.exportButtonLabel" + id="savedObjectsManagement.objectsTable.header.exportButtonLabel" values={ Object { "filteredCount": 2, @@ -58,7 +58,7 @@ exports[`Header should render normally 1`] = ` > <FormattedMessage defaultMessage="Import" - id="kbn.management.objects.objectsTable.header.importButtonLabel" + id="savedObjectsManagement.objectsTable.header.importButtonLabel" values={Object {}} /> </EuiButtonEmpty> @@ -73,7 +73,7 @@ exports[`Header should render normally 1`] = ` > <FormattedMessage defaultMessage="Refresh" - id="kbn.management.objects.objectsTable.header.refreshButtonLabel" + id="savedObjectsManagement.objectsTable.header.refreshButtonLabel" values={Object {}} /> </EuiButtonEmpty> @@ -93,7 +93,7 @@ exports[`Header should render normally 1`] = ` > <FormattedMessage defaultMessage="From here you can delete saved objects, such as saved searches. You can also edit the raw data of saved objects. Typically objects are only modified via their associated application, which is probably what you should use instead of this screen." - id="kbn.management.objects.objectsTable.howToDeleteSavedObjectsDescription" + id="savedObjectsManagement.objectsTable.howToDeleteSavedObjectsDescription" values={Object {}} /> </EuiTextColor> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap similarity index 99% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap index 728944f3ccbfe..a8bb691cd54e9 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/relationships.test.tsx.snap @@ -202,7 +202,7 @@ exports[`Relationships should render errors 1`] = ` title={ <FormattedMessage defaultMessage="Error" - id="kbn.management.objects.objectsTable.relationships.renderErrorMessage" + id="savedObjectsManagement.objectsTable.relationships.renderErrorMessage" values={Object {}} /> } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap index a4dcfb9c38184..d09dd6f8b868b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/table.test.tsx.snap @@ -36,7 +36,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` > <FormattedMessage defaultMessage="Delete" - id="kbn.management.objects.objectsTable.table.deleteButtonLabel" + id="savedObjectsManagement.objectsTable.table.deleteButtonLabel" values={Object {}} /> </EuiButton>, @@ -51,7 +51,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` > <FormattedMessage defaultMessage="Export" - id="kbn.management.objects.objectsTable.table.exportPopoverButtonLabel" + id="savedObjectsManagement.objectsTable.table.exportPopoverButtonLabel" values={Object {}} /> </EuiButton> @@ -72,7 +72,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` label={ <FormattedMessage defaultMessage="Options" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportOptionsLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel" values={Object {}} /> } @@ -83,7 +83,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` label={ <FormattedMessage defaultMessage="Include related objects" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" values={Object {}} /> } @@ -106,7 +106,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` > <FormattedMessage defaultMessage="Export" - id="kbn.management.objects.objectsTable.table.exportButtonLabel" + id="savedObjectsManagement.objectsTable.table.exportButtonLabel" values={Object {}} /> </EuiButton> @@ -171,6 +171,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` items={ Array [ Object { + "attributes": Object {}, "id": "1", "meta": Object { "editUrl": "#/management/kibana/index_patterns/1", @@ -181,6 +182,7 @@ exports[`Table prevents saved objects from being deleted 1`] = ` }, "title": "MyIndexPattern*", }, + "references": Array [], "type": "index-pattern", }, ] @@ -249,7 +251,7 @@ exports[`Table should render normally 1`] = ` > <FormattedMessage defaultMessage="Delete" - id="kbn.management.objects.objectsTable.table.deleteButtonLabel" + id="savedObjectsManagement.objectsTable.table.deleteButtonLabel" values={Object {}} /> </EuiButton>, @@ -264,7 +266,7 @@ exports[`Table should render normally 1`] = ` > <FormattedMessage defaultMessage="Export" - id="kbn.management.objects.objectsTable.table.exportPopoverButtonLabel" + id="savedObjectsManagement.objectsTable.table.exportPopoverButtonLabel" values={Object {}} /> </EuiButton> @@ -285,7 +287,7 @@ exports[`Table should render normally 1`] = ` label={ <FormattedMessage defaultMessage="Options" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportOptionsLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel" values={Object {}} /> } @@ -296,7 +298,7 @@ exports[`Table should render normally 1`] = ` label={ <FormattedMessage defaultMessage="Include related objects" - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" values={Object {}} /> } @@ -319,7 +321,7 @@ exports[`Table should render normally 1`] = ` > <FormattedMessage defaultMessage="Export" - id="kbn.management.objects.objectsTable.table.exportButtonLabel" + id="savedObjectsManagement.objectsTable.table.exportButtonLabel" values={Object {}} /> </EuiButton> @@ -384,6 +386,7 @@ exports[`Table should render normally 1`] = ` items={ Array [ Object { + "attributes": Object {}, "id": "1", "meta": Object { "editUrl": "#/management/kibana/index_patterns/1", @@ -394,6 +397,7 @@ exports[`Table should render normally 1`] = ` }, "title": "MyIndexPattern*", }, + "references": Array [], "type": "index-pattern", }, ] diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.mocks.ts b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.mocks.ts new file mode 100644 index 0000000000000..b5361d212954f --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.mocks.ts @@ -0,0 +1,44 @@ +/* + * 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 const importFileMock = jest.fn(); +jest.doMock('../../../lib/import_file', () => ({ + importFile: importFileMock, +})); + +export const resolveImportErrorsMock = jest.fn(); +jest.doMock('../../../lib/resolve_import_errors', () => ({ + resolveImportErrors: resolveImportErrorsMock, +})); + +export const importLegacyFileMock = jest.fn(); +jest.doMock('../../../lib/import_legacy_file', () => ({ + importLegacyFile: importLegacyFileMock, +})); + +export const resolveSavedObjectsMock = jest.fn(); +export const resolveSavedSearchesMock = jest.fn(); +export const resolveIndexPatternConflictsMock = jest.fn(); +export const saveObjectsMock = jest.fn(); +jest.doMock('../../../lib/resolve_saved_objects', () => ({ + resolveSavedObjects: resolveSavedObjectsMock, + resolveSavedSearches: resolveSavedSearchesMock, + resolveIndexPatternConflicts: resolveIndexPatternConflictsMock, + saveObjects: saveObjectsMock, +})); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx similarity index 75% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx index 0d16e0ae35dd6..5d713ff044f24 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/flyout.test.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.test.tsx @@ -17,68 +17,62 @@ * under the License. */ +import { + importFileMock, + importLegacyFileMock, + resolveImportErrorsMock, + resolveIndexPatternConflictsMock, + resolveSavedObjectsMock, + resolveSavedSearchesMock, + saveObjectsMock, +} from './flyout.test.mocks'; + import React from 'react'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; -import { mockManagementPlugin } from '../../../../../../../../../../../../plugins/index_pattern_management/public/mocks'; -import { Flyout } from '../flyout'; - -jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() })); - -jest.mock('../../../../../lib/import_file', () => ({ - importFile: jest.fn(), -})); - -jest.mock('../../../../../lib/resolve_import_errors', () => ({ - resolveImportErrors: jest.fn(), -})); - -jest.mock('ui/chrome', () => ({ - addBasePath: () => {}, - getInjected: () => ['index-pattern', 'visualization', 'dashboard', 'search'], -})); - -jest.mock('../../../../../lib/import_legacy_file', () => ({ - importLegacyFile: jest.fn(), -})); - -jest.mock('../../../../../lib/resolve_saved_objects', () => ({ - resolveSavedObjects: jest.fn(), - resolveSavedSearches: jest.fn(), - resolveIndexPatternConflicts: jest.fn(), - saveObjects: jest.fn(), -})); - -jest.mock('../../../../../../../../../../../../plugins/index_pattern_management/public', () => ({ - setup: mockManagementPlugin.createSetupContract(), - start: mockManagementPlugin.createStartContract(), -})); - -jest.mock('ui/notify', () => ({})); - -const defaultProps = { - close: jest.fn(), - done: jest.fn(), - services: [], - newIndexPatternUrl: '', - getConflictResolutions: jest.fn(), - confirmModalPromise: jest.fn(), - indexPatterns: { - getFields: jest.fn().mockImplementation(() => [{ id: '1' }, { id: '2' }]), - }, -}; - -const mockFile = { +import { coreMock } from '../../../../../../core/public/mocks'; +import { serviceRegistryMock } from '../../../services/service_registry.mock'; +import { Flyout, FlyoutProps, FlyoutState } from './flyout'; +import { ShallowWrapper } from 'enzyme'; + +const mockFile = ({ name: 'foo.ndjson', path: '/home/foo.ndjson', -}; -const legacyMockFile = { +} as unknown) as File; +const legacyMockFile = ({ name: 'foo.json', path: '/home/foo.json', -}; +} as unknown) as File; describe('Flyout', () => { + let defaultProps: FlyoutProps; + + const shallowRender = (props: FlyoutProps) => { + return (shallowWithI18nProvider(<Flyout {...props} />) as unknown) as ShallowWrapper< + FlyoutProps, + FlyoutState, + Flyout + >; + }; + + beforeEach(() => { + const { http, overlays } = coreMock.createStart(); + + defaultProps = { + close: jest.fn(), + done: jest.fn(), + newIndexPatternUrl: '', + indexPatterns: { + getFields: jest.fn().mockImplementation(() => [{ id: '1' }, { id: '2' }]), + } as any, + overlays, + http, + allowedTypes: ['search', 'index-pattern', 'visualization'], + serviceRegistry: serviceRegistryMock.create(), + }; + }); + it('should render import step', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -89,7 +83,7 @@ describe('Flyout', () => { }); it('should toggle the overwrite all control', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -102,7 +96,7 @@ describe('Flyout', () => { }); it('should allow picking a file', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -115,7 +109,7 @@ describe('Flyout', () => { }); it('should allow removing a file', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await Promise.resolve(); @@ -130,22 +124,21 @@ describe('Flyout', () => { }); it('should handle invalid files', async () => { - const { importLegacyFile } = require('../../../../../lib/import_legacy_file'); - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); // Ensure the state changes are reflected component.update(); - importLegacyFile.mockImplementation(() => { + importLegacyFileMock.mockImplementation(() => { throw new Error('foobar'); }); await component.instance().legacyImport(); expect(component.state('error')).toBe('The file could not be processed.'); - importLegacyFile.mockImplementation(() => ({ + importLegacyFileMock.mockImplementation(() => ({ invalid: true, })); @@ -156,11 +149,8 @@ describe('Flyout', () => { }); describe('conflicts', () => { - const { importFile } = require('../../../../../lib/import_file'); - const { resolveImportErrors } = require('../../../../../lib/resolve_import_errors'); - beforeEach(() => { - importFile.mockImplementation(() => ({ + importFileMock.mockImplementation(() => ({ success: false, successCount: 0, errors: [ @@ -180,7 +170,7 @@ describe('Flyout', () => { }, ], })); - resolveImportErrors.mockImplementation(() => ({ + resolveImportErrorsMock.mockImplementation(() => ({ status: 'success', importCount: 1, failedImports: [], @@ -188,7 +178,7 @@ describe('Flyout', () => { }); it('should figure out unmatchedReferences', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -198,7 +188,7 @@ describe('Flyout', () => { component.setState({ file: mockFile, isLegacyFile: false }); await component.instance().import(); - expect(importFile).toHaveBeenCalledWith(mockFile, true); + expect(importFileMock).toHaveBeenCalledWith(defaultProps.http, mockFile, true); expect(component.state()).toMatchObject({ conflictedIndexPatterns: undefined, conflictedSavedObjectsLinkedToSavedSearches: undefined, @@ -223,7 +213,7 @@ describe('Flyout', () => { }); it('should allow conflict resolution', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -239,7 +229,7 @@ describe('Flyout', () => { // Ensure we can change the resolution component.instance().onIndexChanged('MyIndexPattern*', { target: { value: '2' } }); - expect(component.state('unmatchedReferences')[0].newIndexPatternId).toBe('2'); + expect(component.state('unmatchedReferences')![0].newIndexPatternId).toBe('2'); // Let's resolve now await component @@ -247,18 +237,18 @@ describe('Flyout', () => { .simulate('click'); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); - expect(resolveImportErrors).toMatchSnapshot(); + expect(resolveImportErrorsMock).toMatchSnapshot(); }); it('should handle errors', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); // Ensure the state changes are reflected component.update(); - resolveImportErrors.mockImplementation(() => ({ + resolveImportErrorsMock.mockImplementation(() => ({ status: 'success', importCount: 0, failedImports: [ @@ -303,18 +293,15 @@ describe('Flyout', () => { }); describe('errors', () => { - const { importFile } = require('../../../../../lib/import_file'); - const { resolveImportErrors } = require('../../../../../lib/resolve_import_errors'); - it('should display unsupported type errors properly', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await Promise.resolve(); // Ensure the state changes are reflected component.update(); - importFile.mockImplementation(() => ({ + importFileMock.mockImplementation(() => ({ success: false, successCount: 0, errors: [ @@ -328,7 +315,7 @@ describe('Flyout', () => { }, ], })); - resolveImportErrors.mockImplementation(() => ({ + resolveImportErrorsMock.mockImplementation(() => ({ status: 'success', importCount: 0, failedImports: [ @@ -372,14 +359,6 @@ describe('Flyout', () => { }); describe('legacy conflicts', () => { - const { importLegacyFile } = require('../../../../../lib/import_legacy_file'); - const { - resolveSavedObjects, - resolveSavedSearches, - resolveIndexPatternConflicts, - saveObjects, - } = require('../../../../../lib/resolve_saved_objects'); - const mockData = [ { _id: '1', @@ -406,7 +385,7 @@ describe('Flyout', () => { }, obj: { searchSource: { - getOwnField: field => { + getOwnField: (field: string) => { if (field === 'index') { return 'MyIndexPattern*'; } @@ -426,8 +405,8 @@ describe('Flyout', () => { const mockConflictedSearchDocs = [3]; beforeEach(() => { - importLegacyFile.mockImplementation(() => mockData); - resolveSavedObjects.mockImplementation(() => ({ + importLegacyFileMock.mockImplementation(() => mockData); + resolveSavedObjectsMock.mockImplementation(() => ({ conflictedIndexPatterns: mockConflictedIndexPatterns, conflictedSavedObjectsLinkedToSavedSearches: mockConflictedSavedObjectsLinkedToSavedSearches, conflictedSearchDocs: mockConflictedSearchDocs, @@ -437,7 +416,7 @@ describe('Flyout', () => { }); it('should figure out unmatchedReferences', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -447,14 +426,14 @@ describe('Flyout', () => { component.setState({ file: legacyMockFile, isLegacyFile: true }); await component.instance().legacyImport(); - expect(importLegacyFile).toHaveBeenCalledWith(legacyMockFile); + expect(importLegacyFileMock).toHaveBeenCalledWith(legacyMockFile); // Remove the last element from data since it should be filtered out - expect(resolveSavedObjects).toHaveBeenCalledWith( + expect(resolveSavedObjectsMock).toHaveBeenCalledWith( mockData.slice(0, 2).map(doc => ({ ...doc, _migrationVersion: {} })), true, - defaultProps.services, + defaultProps.serviceRegistry.all().map(s => s.service), defaultProps.indexPatterns, - defaultProps.confirmModalPromise + defaultProps.overlays.openConfirm ); expect(component.state()).toMatchObject({ @@ -492,7 +471,7 @@ describe('Flyout', () => { }); it('should allow conflict resolution', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -508,7 +487,7 @@ describe('Flyout', () => { // Ensure we can change the resolution component.instance().onIndexChanged('MyIndexPattern*', { target: { value: '2' } }); - expect(component.state('unmatchedReferences')[0].newIndexPatternId).toBe('2'); + expect(component.state('unmatchedReferences')![0].newIndexPatternId).toBe('2'); // Let's resolve now await component @@ -516,33 +495,33 @@ describe('Flyout', () => { .simulate('click'); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); - expect(resolveIndexPatternConflicts).toHaveBeenCalledWith( + expect(resolveIndexPatternConflictsMock).toHaveBeenCalledWith( component.instance().resolutions, mockConflictedIndexPatterns, true, defaultProps.indexPatterns ); - expect(saveObjects).toHaveBeenCalledWith( + expect(saveObjectsMock).toHaveBeenCalledWith( mockConflictedSavedObjectsLinkedToSavedSearches, true ); - expect(resolveSavedSearches).toHaveBeenCalledWith( + expect(resolveSavedSearchesMock).toHaveBeenCalledWith( mockConflictedSearchDocs, - defaultProps.services, + defaultProps.serviceRegistry.all().map(s => s.service), defaultProps.indexPatterns, true ); }); it('should handle errors', async () => { - const component = shallowWithI18nProvider(<Flyout {...defaultProps} />); + const component = shallowRender(defaultProps); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); // Ensure the state changes are reflected component.update(); - resolveIndexPatternConflicts.mockImplementation(() => { + resolveIndexPatternConflictsMock.mockImplementation(() => { throw new Error('foobar'); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx similarity index 77% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx index da2221bb54203..45788dcb601ae 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/flyout.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx @@ -18,7 +18,6 @@ */ import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; import { take, get as getField } from 'lodash'; import { EuiFlyout, @@ -32,6 +31,7 @@ import { EuiForm, EuiFormRow, EuiSwitch, + // @ts-ignore EuiFilePicker, EuiInMemoryTable, EuiSelect, @@ -47,34 +47,62 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - +import { OverlayStart, HttpStart } from 'src/core/public'; +import { IndexPatternsContract, IIndexPattern } from '../../../../../data/public'; import { importFile, importLegacyFile, resolveImportErrors, logLegacyImport, getDefaultTitle, -} from '../../../../lib'; -import { processImportResponse } from '../../../../lib/process_import_response'; + processImportResponse, + ProcessedImportResponse, +} from '../../../lib'; import { resolveSavedObjects, resolveSavedSearches, resolveIndexPatternConflicts, saveObjects, -} from '../../../../lib/resolve_saved_objects'; -import { POSSIBLE_TYPES } from '../../objects_table'; - -export class Flyout extends Component { - static propTypes = { - close: PropTypes.func.isRequired, - done: PropTypes.func.isRequired, - services: PropTypes.array.isRequired, - newIndexPatternUrl: PropTypes.string.isRequired, - indexPatterns: PropTypes.object.isRequired, - confirmModalPromise: PropTypes.func.isRequired, - }; +} from '../../../lib/resolve_saved_objects'; +import { ISavedObjectsManagementServiceRegistry } from '../../../services'; + +export interface FlyoutProps { + serviceRegistry: ISavedObjectsManagementServiceRegistry; + allowedTypes: string[]; + close: () => void; + done: () => void; + newIndexPatternUrl: string; + indexPatterns: IndexPatternsContract; + overlays: OverlayStart; + http: HttpStart; +} + +export interface FlyoutState { + conflictedIndexPatterns?: any[]; + conflictedSavedObjectsLinkedToSavedSearches?: any[]; + conflictedSearchDocs?: any[]; + unmatchedReferences?: ProcessedImportResponse['unmatchedReferences']; + failedImports?: ProcessedImportResponse['failedImports']; + conflictingRecord?: ConflictingRecord; + error?: string; + file?: File; + importCount: number; + indexPatterns?: IIndexPattern[]; + isOverwriteAllChecked: boolean; + loadingMessage?: string; + isLegacyFile: boolean; + status: string; +} + +interface ConflictingRecord { + id: string; + type: string; + title: string; + done: (success: boolean) => void; +} - constructor(props) { +export class Flyout extends Component<FlyoutProps, FlyoutState> { + constructor(props: FlyoutProps) { super(props); this.state = { @@ -100,7 +128,7 @@ export class Flyout extends Component { fetchIndexPatterns = async () => { const indexPatterns = await this.props.indexPatterns.getFields(['id', 'title']); - this.setState({ indexPatterns }); + this.setState({ indexPatterns } as any); }; changeOverwriteAll = () => { @@ -109,11 +137,12 @@ export class Flyout extends Component { })); }; - setImportFile = ([file]) => { - if (!file) { + setImportFile = (files: FileList | null) => { + if (!files || !files[0]) { this.setState({ file: undefined, isLegacyFile: false }); return; } + const file = files[0]; this.setState({ file, isLegacyFile: /\.json$/i.test(file.name) || file.type === 'application/json', @@ -126,30 +155,29 @@ export class Flyout extends Component { * Does the initial import of a file, resolveImportErrors then handles errors and retries */ import = async () => { + const { http } = this.props; const { file, isOverwriteAllChecked } = this.state; this.setState({ status: 'loading', error: undefined }); // Import the file - let response; try { - response = await importFile(file, isOverwriteAllChecked); + const response = await importFile(http, file!, isOverwriteAllChecked); + this.setState(processImportResponse(response), () => { + // Resolve import errors right away if there's no index patterns to match + // This will ask about overwriting each object, etc + if (this.state.unmatchedReferences?.length === 0) { + this.resolveImportErrors(); + } + }); } catch (e) { this.setState({ status: 'error', - error: i18n.translate('kbn.management.objects.objectsTable.flyout.importFileErrorMessage', { + error: i18n.translate('savedObjectsManagement.objectsTable.flyout.importFileErrorMessage', { defaultMessage: 'The file could not be processed.', }), }); return; } - - this.setState(processImportResponse(response), () => { - // Resolve import errors right away if there's no index patterns to match - // This will ask about overwriting each object, etc - if (this.state.unmatchedReferences.length === 0) { - this.resolveImportErrors(); - } - }); }; /** @@ -160,10 +188,10 @@ export class Flyout extends Component { * @param {array} objects List of objects to request the user if they wish to overwrite it * @return {Promise<array>} An object with the key being "type:id" and value the resolution chosen by the user */ - getConflictResolutions = async objects => { - const resolutions = {}; + getConflictResolutions = async (objects: any[]) => { + const resolutions: Record<string, boolean> = {}; for (const { type, id, title } of objects) { - const overwrite = await new Promise(resolve => { + const overwrite = await new Promise<boolean>(resolve => { this.setState({ conflictingRecord: { id, @@ -193,6 +221,7 @@ export class Flyout extends Component { try { const updatedState = await resolveImportErrors({ + http: this.props.http, state: this.state, getConflictResolutions: this.getConflictResolutions, }); @@ -201,7 +230,7 @@ export class Flyout extends Component { this.setState({ status: 'error', error: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.resolveImportErrorsFileErrorMessage', + 'savedObjectsManagement.objectsTable.flyout.resolveImportErrorsFileErrorMessage', { defaultMessage: 'The file could not be processed.' } ), }); @@ -209,22 +238,22 @@ export class Flyout extends Component { }; legacyImport = async () => { - const { services, indexPatterns, confirmModalPromise } = this.props; + const { serviceRegistry, indexPatterns, overlays, http, allowedTypes } = this.props; const { file, isOverwriteAllChecked } = this.state; this.setState({ status: 'loading', error: undefined }); // Log warning on server, don't wait for response - logLegacyImport(); + logLegacyImport(http); let contents; try { - contents = await importLegacyFile(file); + contents = await importLegacyFile(file!); } catch (e) { this.setState({ status: 'error', error: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.importLegacyFileErrorMessage', + 'savedObjectsManagement.objectsTable.flyout.importLegacyFileErrorMessage', { defaultMessage: 'The file could not be processed.' } ), }); @@ -235,7 +264,7 @@ export class Flyout extends Component { this.setState({ status: 'error', error: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage', + 'savedObjectsManagement.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage', { defaultMessage: 'Saved objects file format is invalid and cannot be imported.' } ), }); @@ -243,7 +272,7 @@ export class Flyout extends Component { } contents = contents - .filter(content => POSSIBLE_TYPES.includes(content._type)) + .filter(content => allowedTypes.includes(content._type)) .map(doc => ({ ...doc, // The server assumes that documents with no migrationVersion are up to date. @@ -263,18 +292,18 @@ export class Flyout extends Component { } = await resolveSavedObjects( contents, isOverwriteAllChecked, - services, + serviceRegistry.all().map(e => e.service), indexPatterns, - confirmModalPromise + overlays.openConfirm ); - const byId = {}; + const byId: Record<string, any[]> = {}; conflictedIndexPatterns .map(({ doc, obj }) => { return { doc, obj: obj._serialize() }; }) .forEach(({ doc, obj }) => - obj.references.forEach(ref => { + obj.references.forEach((ref: Record<string, any>) => { byId[ref.id] = byId[ref.id] != null ? byId[ref.id].concat({ doc, obj }) : [{ doc, obj }]; }) ); @@ -291,7 +320,7 @@ export class Flyout extends Component { }); return accum; }, - [] + [] as any[] ); this.setState({ @@ -305,12 +334,12 @@ export class Flyout extends Component { }); }; - get hasUnmatchedReferences() { + public get hasUnmatchedReferences() { return this.state.unmatchedReferences && this.state.unmatchedReferences.length > 0; } - get resolutions() { - return this.state.unmatchedReferences.reduce( + public get resolutions() { + return this.state.unmatchedReferences!.reduce( (accum, { existingIndexPatternId, newIndexPatternId }) => { if (newIndexPatternId) { accum.push({ @@ -320,7 +349,7 @@ export class Flyout extends Component { } return accum; }, - [] + [] as Array<{ oldId: string; newId: string }> ); } @@ -333,7 +362,7 @@ export class Flyout extends Component { failedImports, } = this.state; - const { services, indexPatterns } = this.props; + const { serviceRegistry, indexPatterns } = this.props; this.setState({ error: undefined, @@ -350,48 +379,48 @@ export class Flyout extends Component { // Do not Promise.all these calls as the order matters this.setState({ loadingMessage: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage', + 'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage', { defaultMessage: 'Resolving conflicts…' } ), }); if (resolutions.length) { importCount += await resolveIndexPatternConflicts( resolutions, - conflictedIndexPatterns, + conflictedIndexPatterns!, isOverwriteAllChecked, - this.props.indexPatterns + indexPatterns ); } this.setState({ loadingMessage: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage', + 'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage', { defaultMessage: 'Saving conflicts…' } ), }); importCount += await saveObjects( - conflictedSavedObjectsLinkedToSavedSearches, + conflictedSavedObjectsLinkedToSavedSearches!, isOverwriteAllChecked ); this.setState({ loadingMessage: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage', + 'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage', { defaultMessage: 'Ensure saved searches are linked properly…' } ), }); importCount += await resolveSavedSearches( - conflictedSearchDocs, - services, + conflictedSearchDocs!, + serviceRegistry.all().map(e => e.service), indexPatterns, isOverwriteAllChecked ); this.setState({ loadingMessage: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage', + 'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage', { defaultMessage: 'Retrying failed objects…' } ), }); importCount += await saveObjects( - failedImports.map(({ obj }) => obj), + failedImports!.map(({ obj }) => obj) as any[], isOverwriteAllChecked ); } catch (e) { @@ -407,26 +436,26 @@ export class Flyout extends Component { this.setState({ status: 'success', importCount }); }; - onIndexChanged = (id, e) => { + onIndexChanged = (id: string, e: any) => { const value = e.target.value; this.setState(state => { - const conflictIndex = state.unmatchedReferences.findIndex( + const conflictIndex = state.unmatchedReferences?.findIndex( conflict => conflict.existingIndexPatternId === id ); - if (conflictIndex === -1) { + if (conflictIndex === undefined || conflictIndex === -1) { return state; } return { unmatchedReferences: [ - ...state.unmatchedReferences.slice(0, conflictIndex), + ...state.unmatchedReferences!.slice(0, conflictIndex), { - ...state.unmatchedReferences[conflictIndex], + ...state.unmatchedReferences![conflictIndex], newIndexPatternId: value, }, - ...state.unmatchedReferences.slice(conflictIndex + 1), + ...state.unmatchedReferences!.slice(conflictIndex + 1), ], - }; + } as any; }); }; @@ -441,11 +470,11 @@ export class Flyout extends Component { { field: 'existingIndexPatternId', name: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.renderConflicts.columnIdName', + 'savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdName', { defaultMessage: 'ID' } ), description: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.renderConflicts.columnIdDescription', + 'savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdDescription', { defaultMessage: 'ID of the index pattern' } ), sortable: true, @@ -453,28 +482,28 @@ export class Flyout extends Component { { field: 'list', name: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.renderConflicts.columnCountName', + 'savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountName', { defaultMessage: 'Count' } ), description: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.renderConflicts.columnCountDescription', + 'savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountDescription', { defaultMessage: 'How many affected objects' } ), - render: list => { + render: (list: any[]) => { return <Fragment>{list.length}</Fragment>; }, }, { field: 'list', name: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName', + 'savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName', { defaultMessage: 'Sample of affected objects' } ), description: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription', + 'savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription', { defaultMessage: 'Sample of affected objects' } ), - render: list => { + render: (list: any[]) => { return ( <ul style={{ listStyle: 'none' }}> {take(list, 3).map((obj, key) => ( @@ -487,15 +516,18 @@ export class Flyout extends Component { { field: 'existingIndexPatternId', name: i18n.translate( - 'kbn.management.objects.objectsTable.flyout.renderConflicts.columnNewIndexPatternName', + 'savedObjectsManagement.objectsTable.flyout.renderConflicts.columnNewIndexPatternName', { defaultMessage: 'New index pattern' } ), - render: id => { - const options = this.state.indexPatterns.map(indexPattern => ({ - text: indexPattern.title, - value: indexPattern.id, - ['data-test-subj']: `indexPatternOption-${indexPattern.title}`, - })); + render: (id: string) => { + const options = this.state.indexPatterns!.map( + indexPattern => + ({ + text: indexPattern.title, + value: indexPattern.id, + 'data-test-subj': `indexPatternOption-${indexPattern.title}`, + } as { text: string; value: string; 'data-test-subj'?: string }) + ); options.unshift({ text: '-- Skip Import --', @@ -518,7 +550,11 @@ export class Flyout extends Component { }; return ( - <EuiInMemoryTable items={unmatchedReferences} columns={columns} pagination={pagination} /> + <EuiInMemoryTable + items={unmatchedReferences as any[]} + columns={columns} + pagination={pagination} + /> ); } @@ -534,7 +570,7 @@ export class Flyout extends Component { <EuiCallOut title={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.errorCalloutTitle" + id="savedObjectsManagement.objectsTable.flyout.errorCalloutTitle" defaultMessage="Sorry, there was an error" /> } @@ -581,7 +617,7 @@ export class Flyout extends Component { data-test-subj="importSavedObjectsFailedWarning" title={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importFailedTitle" + id="savedObjectsManagement.objectsTable.flyout.importFailedTitle" defaultMessage="Import failed" /> } @@ -590,7 +626,7 @@ export class Flyout extends Component { > <p> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importFailedDescription" + id="savedObjectsManagement.objectsTable.flyout.importFailedDescription" defaultMessage="Failed to import {failedImportCount} of {totalImportCount} objects. Import failed" values={{ failedImportCount: failedImports.length, @@ -604,7 +640,7 @@ export class Flyout extends Component { if (error.type === 'missing_references') { return error.references.map(reference => { return i18n.translate( - 'kbn.management.objects.objectsTable.flyout.importFailedMissingReference', + 'savedObjectsManagement.objectsTable.flyout.importFailedMissingReference', { defaultMessage: '{type} [id={id}] could not locate {refType} [id={refId}]', values: { @@ -618,7 +654,7 @@ export class Flyout extends Component { }); } else if (error.type === 'unsupported_type') { return i18n.translate( - 'kbn.management.objects.objectsTable.flyout.importFailedUnsupportedType', + 'savedObjectsManagement.objectsTable.flyout.importFailedUnsupportedType', { defaultMessage: '{type} [id={id}] unsupported type', values: { @@ -628,7 +664,7 @@ export class Flyout extends Component { } ); } - return getField(error, 'body.message', error.message || ''); + return getField(error, 'body.message', (error as any).message ?? ''); }) .join(' ')} </p> @@ -643,7 +679,7 @@ export class Flyout extends Component { data-test-subj="importSavedObjectsSuccessNoneImported" title={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle" + id="savedObjectsManagement.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle" defaultMessage="No objects imported" /> } @@ -657,7 +693,7 @@ export class Flyout extends Component { data-test-subj="importSavedObjectsSuccess" title={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importSuccessfulTitle" + id="savedObjectsManagement.objectsTable.flyout.importSuccessfulTitle" defaultMessage="Import successful" /> } @@ -666,7 +702,7 @@ export class Flyout extends Component { > <p> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importSuccessfulDescription" + id="savedObjectsManagement.objectsTable.flyout.importSuccessfulDescription" defaultMessage="Successfully imported {importCount} objects." values={{ importCount }} /> @@ -684,7 +720,7 @@ export class Flyout extends Component { <EuiFormRow label={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.selectFileToImportFormRowLabel" + id="savedObjectsManagement.objectsTable.flyout.selectFileToImportFormRowLabel" defaultMessage="Please select a file to import" /> } @@ -692,7 +728,7 @@ export class Flyout extends Component { <EuiFilePicker initialPromptText={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importPromptText" + id="savedObjectsManagement.objectsTable.flyout.importPromptText" defaultMessage="Import" /> } @@ -704,7 +740,7 @@ export class Flyout extends Component { name="overwriteAll" label={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.overwriteSavedObjectsLabel" + id="savedObjectsManagement.objectsTable.flyout.overwriteSavedObjectsLabel" defaultMessage="Automatically overwrite all saved objects?" /> } @@ -727,7 +763,7 @@ export class Flyout extends Component { confirmButton = ( <EuiButton onClick={done} size="s" fill data-test-subj="importSavedObjectsDoneBtn"> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importSuccessful.confirmButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmButtonLabel" defaultMessage="Done" /> </EuiButton> @@ -742,7 +778,7 @@ export class Flyout extends Component { data-test-subj="importSavedObjectsConfirmBtn" > <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel" defaultMessage="Confirm all changes" /> </EuiButton> @@ -757,7 +793,7 @@ export class Flyout extends Component { data-test-subj="importSavedObjectsImportBtn" > <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.import.confirmButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel" defaultMessage="Import" /> </EuiButton> @@ -769,7 +805,7 @@ export class Flyout extends Component { <EuiFlexItem grow={false}> <EuiButtonEmpty onClick={close} size="s"> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.import.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel" defaultMessage="Cancel" /> </EuiButtonEmpty> @@ -791,7 +827,7 @@ export class Flyout extends Component { data-test-subj="importSavedObjectsLegacyWarning" title={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.legacyFileUsedTitle" + id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle" defaultMessage="Support for JSON files is going away" /> } @@ -800,7 +836,7 @@ export class Flyout extends Component { > <p> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.legacyFileUsedBody" + id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody" defaultMessage="Use our updated export to generate NDJSON files, and you'll be all set." /> </p> @@ -815,7 +851,7 @@ export class Flyout extends Component { data-test-subj="importSavedObjectsConflictsWarning" title={ <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsTitle" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle" defaultMessage="Index Pattern Conflicts" /> } @@ -824,7 +860,7 @@ export class Flyout extends Component { > <p> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsDescription" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription" defaultMessage="The following saved objects use index patterns that do not exist. Please select the index patterns you'd like re-associated with them. You can {indexPatternLink} if necessary." @@ -832,7 +868,7 @@ export class Flyout extends Component { indexPatternLink: ( <EuiLink href={this.props.newIndexPatternUrl}> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.indexPatternConflictsCalloutLinkText" + id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText" defaultMessage="create a new index pattern" /> </EuiLink> @@ -867,11 +903,11 @@ export class Flyout extends Component { } overwriteConfirmed() { - this.state.conflictingRecord.done(true); + this.state.conflictingRecord!.done(true); } overwriteSkipped() { - this.state.conflictingRecord.done(false); + this.state.conflictingRecord!.done(false); } render() { @@ -883,18 +919,18 @@ export class Flyout extends Component { <EuiOverlayMask> <EuiConfirmModal title={i18n.translate( - 'kbn.management.objects.objectsTable.flyout.confirmOverwriteTitle', + 'savedObjectsManagement.objectsTable.flyout.confirmOverwriteTitle', { defaultMessage: 'Overwrite {type}?', values: { type: this.state.conflictingRecord.type }, } )} cancelButtonText={i18n.translate( - 'kbn.management.objects.objectsTable.flyout.confirmOverwriteCancelButtonText', + 'savedObjectsManagement.objectsTable.flyout.confirmOverwriteCancelButtonText', { defaultMessage: 'Cancel' } )} confirmButtonText={i18n.translate( - 'kbn.management.objects.objectsTable.flyout.confirmOverwriteOverwriteButtonText', + 'savedObjectsManagement.objectsTable.flyout.confirmOverwriteOverwriteButtonText', { defaultMessage: 'Overwrite' } )} buttonColor="danger" @@ -904,7 +940,7 @@ export class Flyout extends Component { > <p> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.confirmOverwriteBody" + id="savedObjectsManagement.objectsTable.flyout.confirmOverwriteBody" defaultMessage="Are you sure you want to overwrite {title}?" values={{ title: @@ -924,7 +960,7 @@ export class Flyout extends Component { <EuiTitle size="m"> <h2> <FormattedMessage - id="kbn.management.objects.objectsTable.flyout.importSavedObjectTitle" + id="savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle" defaultMessage="Import saved objects" /> </h2> diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/header.test.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/header.test.tsx similarity index 96% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/header.test.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/header.test.tsx index 1f501b5751224..891190d0bb24b 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/__jest__/header.test.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/header.test.tsx @@ -19,8 +19,7 @@ import React from 'react'; import { shallow } from 'enzyme'; - -import { Header } from '../header'; +import { Header } from './header'; describe('Header', () => { it('should render normally', () => { diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/header.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/header.tsx similarity index 83% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/header.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/header.tsx index 0bec8a0cf2daf..7a9584f08d632 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/header/header.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/header.tsx @@ -18,8 +18,6 @@ */ import React, { Fragment } from 'react'; -import PropTypes from 'prop-types'; - import { EuiSpacer, EuiTitle, @@ -31,14 +29,24 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -export const Header = ({ onExportAll, onImport, onRefresh, filteredCount }) => ( +export const Header = ({ + onExportAll, + onImport, + onRefresh, + filteredCount, +}: { + onExportAll: () => void; + onImport: () => void; + onRefresh: () => void; + filteredCount: number; +}) => ( <Fragment> <EuiFlexGroup justifyContent="spaceBetween" alignItems="baseline"> <EuiFlexItem grow={false}> <EuiTitle> <h1> <FormattedMessage - id="kbn.management.objects.objectsTable.header.savedObjectsTitle" + id="savedObjectsManagement.objectsTable.header.savedObjectsTitle" defaultMessage="Saved Objects" /> </h1> @@ -55,7 +63,7 @@ export const Header = ({ onExportAll, onImport, onRefresh, filteredCount }) => ( onClick={onExportAll} > <FormattedMessage - id="kbn.management.objects.objectsTable.header.exportButtonLabel" + id="savedObjectsManagement.objectsTable.header.exportButtonLabel" defaultMessage="Export {filteredCount, plural, one{# object} other {# objects}}" values={{ filteredCount, @@ -71,7 +79,7 @@ export const Header = ({ onExportAll, onImport, onRefresh, filteredCount }) => ( onClick={onImport} > <FormattedMessage - id="kbn.management.objects.objectsTable.header.importButtonLabel" + id="savedObjectsManagement.objectsTable.header.importButtonLabel" defaultMessage="Import" /> </EuiButtonEmpty> @@ -79,7 +87,7 @@ export const Header = ({ onExportAll, onImport, onRefresh, filteredCount }) => ( <EuiFlexItem grow={false}> <EuiButtonEmpty size="s" iconType="refresh" onClick={onRefresh}> <FormattedMessage - id="kbn.management.objects.objectsTable.header.refreshButtonLabel" + id="savedObjectsManagement.objectsTable.header.refreshButtonLabel" defaultMessage="Refresh" /> </EuiButtonEmpty> @@ -92,7 +100,7 @@ export const Header = ({ onExportAll, onImport, onRefresh, filteredCount }) => ( <p> <EuiTextColor color="subdued"> <FormattedMessage - id="kbn.management.objects.objectsTable.howToDeleteSavedObjectsDescription" + id="savedObjectsManagement.objectsTable.howToDeleteSavedObjectsDescription" defaultMessage="From here you can delete saved objects, such as saved searches. You can also edit the raw data of saved objects. Typically objects are only modified via their associated application, @@ -104,10 +112,3 @@ export const Header = ({ onExportAll, onImport, onRefresh, filteredCount }) => ( <EuiSpacer size="m" /> </Fragment> ); - -Header.propTypes = { - onExportAll: PropTypes.func.isRequired, - onImport: PropTypes.func.isRequired, - onRefresh: PropTypes.func.isRequired, - filteredCount: PropTypes.number.isRequired, -}; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/index.ts b/src/plugins/saved_objects_management/public/management_section/objects_table/components/index.ts new file mode 100644 index 0000000000000..9c8736a9011eb --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/index.ts @@ -0,0 +1,23 @@ +/* + * 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 { Header } from './header'; +export { Table } from './table'; +export { Flyout } from './flyout'; +export { Relationships } from './relationships'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/relationships.test.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx similarity index 88% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/relationships.test.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx index 479726e8785d8..347f2d977015c 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/relationships.test.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.test.tsx @@ -19,27 +19,23 @@ import React from 'react'; import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; +import { httpServiceMock } from '../../../../../../core/public/mocks'; +import { Relationships, RelationshipsProps } from './relationships'; -jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() })); - -jest.mock('ui/chrome', () => ({ - addBasePath: () => '', -})); - -jest.mock('../../../../../lib/fetch_export_by_type_and_search', () => ({ +jest.mock('../../../lib/fetch_export_by_type_and_search', () => ({ fetchExportByTypeAndSearch: jest.fn(), })); -jest.mock('../../../../../lib/fetch_export_objects', () => ({ +jest.mock('../../../lib/fetch_export_objects', () => ({ fetchExportObjects: jest.fn(), })); -import { Relationships } from '../relationships'; - describe('Relationships', () => { it('should render index patterns normally', async () => { - const props = { + const props: RelationshipsProps = { goInspectObject: () => {}, + canGoInApp: () => true, + basePath: httpServiceMock.createSetupContract().basePath, getRelationships: jest.fn().mockImplementation(() => [ { type: 'search', @@ -73,6 +69,8 @@ describe('Relationships', () => { savedObject: { id: '1', type: 'index-pattern', + attributes: {}, + references: [], meta: { title: 'MyIndexPattern*', icon: 'indexPatternApp', @@ -101,8 +99,10 @@ describe('Relationships', () => { }); it('should render searches normally', async () => { - const props = { + const props: RelationshipsProps = { goInspectObject: () => {}, + canGoInApp: () => true, + basePath: httpServiceMock.createSetupContract().basePath, getRelationships: jest.fn().mockImplementation(() => [ { type: 'index-pattern', @@ -136,6 +136,8 @@ describe('Relationships', () => { savedObject: { id: '1', type: 'search', + attributes: {}, + references: [], meta: { title: 'MySearch', icon: 'search', @@ -164,8 +166,10 @@ describe('Relationships', () => { }); it('should render visualizations normally', async () => { - const props = { + const props: RelationshipsProps = { goInspectObject: () => {}, + canGoInApp: () => true, + basePath: httpServiceMock.createSetupContract().basePath, getRelationships: jest.fn().mockImplementation(() => [ { type: 'dashboard', @@ -199,6 +203,8 @@ describe('Relationships', () => { savedObject: { id: '1', type: 'visualization', + attributes: {}, + references: [], meta: { title: 'MyViz', icon: 'visualizeApp', @@ -227,8 +233,10 @@ describe('Relationships', () => { }); it('should render dashboards normally', async () => { - const props = { + const props: RelationshipsProps = { goInspectObject: () => {}, + canGoInApp: () => true, + basePath: httpServiceMock.createSetupContract().basePath, getRelationships: jest.fn().mockImplementation(() => [ { type: 'visualization', @@ -262,6 +270,8 @@ describe('Relationships', () => { savedObject: { id: '1', type: 'dashboard', + attributes: {}, + references: [], meta: { title: 'MyDashboard', icon: 'dashboardApp', @@ -290,14 +300,18 @@ describe('Relationships', () => { }); it('should render errors', async () => { - const props = { + const props: RelationshipsProps = { goInspectObject: () => {}, + canGoInApp: () => true, + basePath: httpServiceMock.createSetupContract().basePath, getRelationships: jest.fn().mockImplementation(() => { throw new Error('foo'); }), savedObject: { id: '1', type: 'dashboard', + attributes: {}, + references: [], meta: { title: 'MyDashboard', icon: 'dashboardApp', diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/relationships.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx similarity index 75% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/relationships.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx index ce3415ad2f0e7..ddb262138d565 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/relationships.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/relationships.tsx @@ -18,8 +18,6 @@ */ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - import { EuiTitle, EuiFlyout, @@ -34,25 +32,34 @@ import { EuiText, EuiSpacer, } from '@elastic/eui'; -import chrome from 'ui/chrome'; +import { FilterConfig } from '@elastic/eui/src/components/search_bar/filters/filters'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { getDefaultTitle, getSavedObjectLabel } from '../../../../lib'; +import { IBasePath } from 'src/core/public'; +import { getDefaultTitle, getSavedObjectLabel } from '../../../lib'; +import { SavedObjectWithMetadata, SavedObjectRelation } from '../../../types'; + +export interface RelationshipsProps { + basePath: IBasePath; + getRelationships: (type: string, id: string) => Promise<SavedObjectRelation[]>; + savedObject: SavedObjectWithMetadata; + close: () => void; + goInspectObject: (obj: SavedObjectWithMetadata) => void; + canGoInApp: (obj: SavedObjectWithMetadata) => boolean; +} -export class Relationships extends Component { - static propTypes = { - getRelationships: PropTypes.func.isRequired, - savedObject: PropTypes.object.isRequired, - close: PropTypes.func.isRequired, - goInspectObject: PropTypes.func.isRequired, - canGoInApp: PropTypes.func.isRequired, - }; +export interface RelationshipsState { + relationships: SavedObjectRelation[]; + isLoading: boolean; + error?: string; +} - constructor(props) { +export class Relationships extends Component<RelationshipsProps, RelationshipsState> { + constructor(props: RelationshipsProps) { super(props); this.state = { - relationships: undefined, + relationships: [], isLoading: false, error: undefined, }; @@ -62,7 +69,7 @@ export class Relationships extends Component { this.getRelationshipData(); } - UNSAFE_componentWillReceiveProps(nextProps) { + UNSAFE_componentWillReceiveProps(nextProps: RelationshipsProps) { if (nextProps.savedObject.id !== this.props.savedObject.id) { this.getRelationshipData(); } @@ -92,7 +99,7 @@ export class Relationships extends Component { <EuiCallOut title={ <FormattedMessage - id="kbn.management.objects.objectsTable.relationships.renderErrorMessage" + id="savedObjectsManagement.objectsTable.relationships.renderErrorMessage" defaultMessage="Error" /> } @@ -104,7 +111,7 @@ export class Relationships extends Component { } renderRelationships() { - const { goInspectObject, savedObject } = this.props; + const { goInspectObject, savedObject, basePath } = this.props; const { relationships, isLoading, error } = this.state; if (error) { @@ -118,17 +125,17 @@ export class Relationships extends Component { const columns = [ { field: 'type', - name: i18n.translate('kbn.management.objects.objectsTable.relationships.columnTypeName', { + name: i18n.translate('savedObjectsManagement.objectsTable.relationships.columnTypeName', { defaultMessage: 'Type', }), width: '50px', align: 'center', description: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.columnTypeDescription', + 'savedObjectsManagement.objectsTable.relationships.columnTypeDescription', { defaultMessage: 'Type of the saved object' } ), sortable: false, - render: (type, object) => { + render: (type: string, object: SavedObjectWithMetadata) => { return ( <EuiToolTip position="top" content={getSavedObjectLabel(type)}> <EuiIcon @@ -144,19 +151,19 @@ export class Relationships extends Component { { field: 'relationship', name: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.columnRelationshipName', + 'savedObjectsManagement.objectsTable.relationships.columnRelationshipName', { defaultMessage: 'Direct relationship' } ), dataType: 'string', sortable: false, width: '125px', 'data-test-subj': 'directRelationship', - render: relationship => { + render: (relationship: string) => { if (relationship === 'parent') { return ( <EuiText size="s"> <FormattedMessage - id="kbn.management.objects.objectsTable.relationships.columnRelationship.parentAsValue" + id="savedObjectsManagement.objectsTable.relationships.columnRelationship.parentAsValue" defaultMessage="Parent" /> </EuiText> @@ -166,7 +173,7 @@ export class Relationships extends Component { return ( <EuiText size="s"> <FormattedMessage - id="kbn.management.objects.objectsTable.relationships.columnRelationship.childAsValue" + id="savedObjectsManagement.objectsTable.relationships.columnRelationship.childAsValue" defaultMessage="Child" /> </EuiText> @@ -176,17 +183,17 @@ export class Relationships extends Component { }, { field: 'meta.title', - name: i18n.translate('kbn.management.objects.objectsTable.relationships.columnTitleName', { + name: i18n.translate('savedObjectsManagement.objectsTable.relationships.columnTitleName', { defaultMessage: 'Title', }), description: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.columnTitleDescription', + 'savedObjectsManagement.objectsTable.relationships.columnTitleDescription', { defaultMessage: 'Title of the saved object' } ), dataType: 'string', sortable: false, - render: (title, object) => { - const { path } = object.meta.inAppUrl || {}; + render: (title: string, object: SavedObjectWithMetadata) => { + const { path = '' } = object.meta.inAppUrl || {}; const canGoInApp = this.props.canGoInApp(object); if (!canGoInApp) { return ( @@ -196,7 +203,7 @@ export class Relationships extends Component { ); } return ( - <EuiLink href={chrome.addBasePath(path)} data-test-subj="relationshipsTitle"> + <EuiLink href={basePath.prepend(path)} data-test-subj="relationshipsTitle"> {title || getDefaultTitle(object)} </EuiLink> ); @@ -204,24 +211,24 @@ export class Relationships extends Component { }, { name: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.columnActionsName', + 'savedObjectsManagement.objectsTable.relationships.columnActionsName', { defaultMessage: 'Actions' } ), actions: [ { name: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.columnActions.inspectActionName', + 'savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionName', { defaultMessage: 'Inspect' } ), description: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.columnActions.inspectActionDescription', + 'savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionDescription', { defaultMessage: 'Inspect this saved object' } ), type: 'icon', icon: 'inspect', 'data-test-subj': 'relationshipsTableAction-inspect', - onClick: object => goInspectObject(object), - available: object => !!object.meta.editUrl, + onClick: (object: SavedObjectWithMetadata) => goInspectObject(object), + available: (object: SavedObjectWithMetadata) => !!object.meta.editUrl, }, ], }, @@ -244,7 +251,7 @@ export class Relationships extends Component { type: 'field_value_selection', field: 'relationship', name: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.search.filters.relationship.name', + 'savedObjectsManagement.objectsTable.relationships.search.filters.relationship.name', { defaultMessage: 'Direct relationship' } ), multiSelect: 'or', @@ -253,7 +260,7 @@ export class Relationships extends Component { value: 'parent', name: 'parent', view: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.search.filters.relationship.parentAsValue.view', + 'savedObjectsManagement.objectsTable.relationships.search.filters.relationship.parentAsValue.view', { defaultMessage: 'Parent' } ), }, @@ -261,7 +268,7 @@ export class Relationships extends Component { value: 'child', name: 'child', view: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.search.filters.relationship.childAsValue.view', + 'savedObjectsManagement.objectsTable.relationships.search.filters.relationship.childAsValue.view', { defaultMessage: 'Child' } ), }, @@ -271,13 +278,13 @@ export class Relationships extends Component { type: 'field_value_selection', field: 'type', name: i18n.translate( - 'kbn.management.objects.objectsTable.relationships.search.filters.type.name', + 'savedObjectsManagement.objectsTable.relationships.search.filters.type.name', { defaultMessage: 'Type' } ), multiSelect: 'or', options: [...filterTypesMap.values()], }, - ], + ] as FilterConfig[], }; return ( @@ -285,7 +292,7 @@ export class Relationships extends Component { <EuiCallOut> <p> {i18n.translate( - 'kbn.management.objects.objectsTable.relationships.relationshipsTitle', + 'savedObjectsManagement.objectsTable.relationships.relationshipsTitle', { defaultMessage: 'Here are the saved objects related to {title}. ' + @@ -301,7 +308,7 @@ export class Relationships extends Component { <EuiSpacer /> <EuiInMemoryTable items={relationships} - columns={columns} + columns={columns as any} pagination={true} search={search} rowProps={() => ({ diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx similarity index 87% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx index 9b3e2314c9f84..356f227773610 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/table.test.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.test.tsx @@ -19,27 +19,22 @@ import React from 'react'; import { shallowWithI18nProvider, mountWithI18nProvider } from 'test_utils/enzyme_helpers'; +// @ts-ignore import { findTestSubject } from '@elastic/eui/lib/test'; -import { keyCodes } from '@elastic/eui/lib/services'; -import { npSetup as mockNpSetup } from '../../../../../../../../../../../ui/public/new_platform/__mocks__'; +import { keyCodes } from '@elastic/eui'; +import { httpServiceMock } from '../../../../../../core/public/mocks'; +import { actionServiceMock } from '../../../services/action_service.mock'; +import { Table, TableProps } from './table'; -jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() })); - -jest.mock('ui/chrome', () => ({ - addBasePath: () => '', -})); - -jest.mock('ui/new_platform', () => ({ - npSetup: mockNpSetup, -})); - -import { Table } from '../table'; - -const defaultProps = { +const defaultProps: TableProps = { + basePath: httpServiceMock.createSetupContract().basePath, + actionRegistry: actionServiceMock.createStart(), selectedSavedObjects: [ { id: '1', type: 'index-pattern', + attributes: {}, + references: [], meta: { title: `MyIndexPattern*`, icon: 'indexPatternApp', @@ -58,13 +53,15 @@ const defaultProps = { onDelete: () => {}, onExport: () => {}, goInspectObject: () => {}, - canGoInApp: () => {}, + canGoInApp: () => true, pageIndex: 1, pageSize: 2, items: [ { id: '1', type: 'index-pattern', + attributes: {}, + references: [], meta: { title: `MyIndexPattern*`, icon: 'indexPatternApp', @@ -120,7 +117,7 @@ describe('Table', () => { { type: 'visualization' }, { type: 'search' }, { type: 'index-pattern' }, - ]; + ] as any; const customizedProps = { ...defaultProps, selectedSavedObjects, canDelete: false }; const component = shallowWithI18nProvider(<Table {...customizedProps} />); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx similarity index 71% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 132fa1e691c1c..5b574e4b3d331 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/table.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -17,12 +17,10 @@ * under the License. */ -import chrome from 'ui/chrome'; -import { npSetup } from 'ui/new_platform'; +import { IBasePath } from 'src/core/public'; import React, { PureComponent, Fragment } from 'react'; -import PropTypes from 'prop-types'; - import { + // @ts-ignore EuiSearchBar, EuiBasicTable, EuiButton, @@ -35,54 +33,64 @@ import { EuiSwitch, EuiFormRow, EuiText, + EuiTableFieldDataColumnType, + EuiTableActionsColumnType, } from '@elastic/eui'; -import { getDefaultTitle, getSavedObjectLabel } from '../../../../lib'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { getDefaultTitle, getSavedObjectLabel } from '../../../lib'; +import { SavedObjectWithMetadata } from '../../../types'; +import { + SavedObjectsManagementActionServiceStart, + SavedObjectsManagementAction, +} from '../../../services'; -export class Table extends PureComponent { - static propTypes = { - selectedSavedObjects: PropTypes.array.isRequired, - selectionConfig: PropTypes.shape({ - selectable: PropTypes.func, - selectableMessage: PropTypes.func, - onSelectionChange: PropTypes.func.isRequired, - }).isRequired, - filterOptions: PropTypes.array.isRequired, - canDelete: PropTypes.bool.isRequired, - onDelete: PropTypes.func.isRequired, - onExport: PropTypes.func.isRequired, - goInspectObject: PropTypes.func.isRequired, - - pageIndex: PropTypes.number.isRequired, - pageSize: PropTypes.number.isRequired, - items: PropTypes.array.isRequired, - itemId: PropTypes.oneOfType([ - PropTypes.string, // the name of the item id property - PropTypes.func, // (item) => string - ]), - totalItemCount: PropTypes.number.isRequired, - onQueryChange: PropTypes.func.isRequired, - onTableChange: PropTypes.func.isRequired, - isSearching: PropTypes.bool.isRequired, - - onShowRelationships: PropTypes.func.isRequired, +export interface TableProps { + basePath: IBasePath; + actionRegistry: SavedObjectsManagementActionServiceStart; + selectedSavedObjects: SavedObjectWithMetadata[]; + selectionConfig: { + onSelectionChange: (selection: SavedObjectWithMetadata[]) => void; }; + filterOptions: any[]; + canDelete: boolean; + onDelete: () => void; + onExport: (includeReferencesDeep: boolean) => void; + goInspectObject: (obj: SavedObjectWithMetadata) => void; + pageIndex: number; + pageSize: number; + items: SavedObjectWithMetadata[]; + itemId: string | (() => string); + totalItemCount: number; + onQueryChange: (query: any) => void; + onTableChange: (table: any) => void; + isSearching: boolean; + onShowRelationships: (object: SavedObjectWithMetadata) => void; + canGoInApp: (obj: SavedObjectWithMetadata) => boolean; +} + +interface TableState { + isSearchTextValid: boolean; + parseErrorMessage: any; + isExportPopoverOpen: boolean; + isIncludeReferencesDeepChecked: boolean; + activeAction?: SavedObjectsManagementAction; +} - state = { +export class Table extends PureComponent<TableProps, TableState> { + state: TableState = { isSearchTextValid: true, parseErrorMessage: null, isExportPopoverOpen: false, isIncludeReferencesDeepChecked: true, - activeAction: null, + activeAction: undefined, }; - constructor(props) { + constructor(props: TableProps) { super(props); - this.extraActions = npSetup.plugins.savedObjectsManagement.actionRegistry.getAll(); } - onChange = ({ query, error }) => { + onChange = ({ query, error }: any) => { if (error) { this.setState({ isSearchTextValid: false, @@ -136,12 +144,14 @@ export class Table extends PureComponent { onTableChange, goInspectObject, onShowRelationships, + basePath, + actionRegistry, } = this.props; const pagination = { - pageIndex: pageIndex, - pageSize: pageSize, - totalItemCount: totalItemCount, + pageIndex, + pageSize, + totalItemCount, pageSizeOptions: [5, 10, 20, 50], }; @@ -149,7 +159,7 @@ export class Table extends PureComponent { { type: 'field_value_selection', field: 'type', - name: i18n.translate('kbn.management.objects.objectsTable.table.typeFilterName', { + name: i18n.translate('savedObjectsManagement.objectsTable.table.typeFilterName', { defaultMessage: 'Type', }), multiSelect: 'or', @@ -168,18 +178,18 @@ export class Table extends PureComponent { const columns = [ { field: 'type', - name: i18n.translate('kbn.management.objects.objectsTable.table.columnTypeName', { + name: i18n.translate('savedObjectsManagement.objectsTable.table.columnTypeName', { defaultMessage: 'Type', }), width: '50px', align: 'center', description: i18n.translate( - 'kbn.management.objects.objectsTable.table.columnTypeDescription', + 'savedObjectsManagement.objectsTable.table.columnTypeDescription', { defaultMessage: 'Type of the saved object' } ), sortable: false, 'data-test-subj': 'savedObjectsTableRowType', - render: (type, object) => { + render: (type: string, object: SavedObjectWithMetadata) => { return ( <EuiToolTip position="top" content={getSavedObjectLabel(type)}> <EuiIcon @@ -191,42 +201,42 @@ export class Table extends PureComponent { </EuiToolTip> ); }, - }, + } as EuiTableFieldDataColumnType<SavedObjectWithMetadata<any>>, { field: 'meta.title', - name: i18n.translate('kbn.management.objects.objectsTable.table.columnTitleName', { + name: i18n.translate('savedObjectsManagement.objectsTable.table.columnTitleName', { defaultMessage: 'Title', }), description: i18n.translate( - 'kbn.management.objects.objectsTable.table.columnTitleDescription', + 'savedObjectsManagement.objectsTable.table.columnTitleDescription', { defaultMessage: 'Title of the saved object' } ), dataType: 'string', sortable: false, 'data-test-subj': 'savedObjectsTableRowTitle', - render: (title, object) => { - const { path } = object.meta.inAppUrl || {}; + render: (title: string, object: SavedObjectWithMetadata) => { + const { path = '' } = object.meta.inAppUrl || {}; const canGoInApp = this.props.canGoInApp(object); if (!canGoInApp) { return <EuiText size="s">{title || getDefaultTitle(object)}</EuiText>; } return ( - <EuiLink href={chrome.addBasePath(path)}>{title || getDefaultTitle(object)}</EuiLink> + <EuiLink href={basePath.prepend(path)}>{title || getDefaultTitle(object)}</EuiLink> ); }, - }, + } as EuiTableFieldDataColumnType<SavedObjectWithMetadata<any>>, { - name: i18n.translate('kbn.management.objects.objectsTable.table.columnActionsName', { + name: i18n.translate('savedObjectsManagement.objectsTable.table.columnActionsName', { defaultMessage: 'Actions', }), actions: [ { name: i18n.translate( - 'kbn.management.objects.objectsTable.table.columnActions.inspectActionName', + 'savedObjectsManagement.objectsTable.table.columnActions.inspectActionName', { defaultMessage: 'Inspect' } ), description: i18n.translate( - 'kbn.management.objects.objectsTable.table.columnActions.inspectActionDescription', + 'savedObjectsManagement.objectsTable.table.columnActions.inspectActionDescription', { defaultMessage: 'Inspect this saved object' } ), type: 'icon', @@ -237,11 +247,11 @@ export class Table extends PureComponent { }, { name: i18n.translate( - 'kbn.management.objects.objectsTable.table.columnActions.viewRelationshipsActionName', + 'savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionName', { defaultMessage: 'Relationships' } ), description: i18n.translate( - 'kbn.management.objects.objectsTable.table.columnActions.viewRelationshipsActionDescription', + 'savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionDescription', { defaultMessage: 'View the relationships this saved object has to other saved objects', @@ -252,33 +262,35 @@ export class Table extends PureComponent { onClick: object => onShowRelationships(object), 'data-test-subj': 'savedObjectsTableAction-relationships', }, - ...this.extraActions.map(action => { + ...actionRegistry.getAll().map(action => { return { ...action.euiAction, 'data-test-subj': `savedObjectsTableAction-${action.id}`, - onClick: object => { + onClick: (object: SavedObjectWithMetadata) => { this.setState({ activeAction: action, }); action.registerOnFinishCallback(() => { this.setState({ - activeAction: null, + activeAction: undefined, }); }); - action.euiAction.onClick(object); + if (action.euiAction.onClick) { + action.euiAction.onClick(object as any); + } }, }; }), ], - }, + } as EuiTableActionsColumnType<SavedObjectWithMetadata>, ]; let queryParseError; if (!this.state.isSearchTextValid) { const parseErrorMsg = i18n.translate( - 'kbn.management.objects.objectsTable.searchBar.unableToParseQueryErrorMessage', + 'savedObjectsManagement.objectsTable.searchBar.unableToParseQueryErrorMessage', { defaultMessage: 'Unable to parse query' } ); queryParseError = ( @@ -294,20 +306,20 @@ export class Table extends PureComponent { isDisabled={selectedSavedObjects.length === 0} > <FormattedMessage - id="kbn.management.objects.objectsTable.table.exportPopoverButtonLabel" + id="savedObjectsManagement.objectsTable.table.exportPopoverButtonLabel" defaultMessage="Export" /> </EuiButton> ); - const activeActionContents = this.state.activeAction ? this.state.activeAction.render() : null; + const activeActionContents = this.state.activeAction?.render() ?? null; return ( <Fragment> {activeActionContents} <EuiSearchBar box={{ 'data-test-subj': 'savedObjectSearchBar' }} - filters={filters} + filters={filters as any} onChange={this.onChange} toolsRight={[ <EuiButton @@ -319,14 +331,14 @@ export class Table extends PureComponent { title={ this.props.canDelete ? undefined - : i18n.translate('kbn.management.objects.objectsTable.table.deleteButtonTitle', { + : i18n.translate('savedObjectsManagement.objectsTable.table.deleteButtonTitle', { defaultMessage: 'Unable to delete saved objects', }) } data-test-subj="savedObjectsManagementDelete" > <FormattedMessage - id="kbn.management.objects.objectsTable.table.deleteButtonLabel" + id="savedObjectsManagement.objectsTable.table.deleteButtonLabel" defaultMessage="Delete" /> </EuiButton>, @@ -339,7 +351,7 @@ export class Table extends PureComponent { <EuiFormRow label={ <FormattedMessage - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportOptionsLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel" defaultMessage="Options" /> } @@ -348,7 +360,7 @@ export class Table extends PureComponent { name="includeReferencesDeep" label={ <FormattedMessage - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" defaultMessage="Include related objects" /> } @@ -359,7 +371,7 @@ export class Table extends PureComponent { <EuiFormRow> <EuiButton key="exportSO" iconType="exportAction" onClick={this.onExportClick} fill> <FormattedMessage - id="kbn.management.objects.objectsTable.table.exportButtonLabel" + id="savedObjectsManagement.objectsTable.table.exportButtonLabel" defaultMessage="Export" /> </EuiButton> @@ -374,7 +386,7 @@ export class Table extends PureComponent { loading={isSearching} itemId={itemId} items={items} - columns={columns} + columns={columns as any} pagination={pagination} selection={selection} onChange={onTableChange} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/index.js b/src/plugins/saved_objects_management/public/management_section/objects_table/index.ts similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/index.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/index.ts index e1195c6edfe31..8777b15389690 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/index.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { Table } from './table'; +export { SavedObjectsTable } from './saved_objects_table'; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.mocks.ts b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.mocks.ts new file mode 100644 index 0000000000000..6b4659a6b5a13 --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.mocks.ts @@ -0,0 +1,67 @@ +/* + * 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 const saveAsMock = jest.fn(); +jest.doMock('@elastic/filesaver', () => ({ + saveAs: saveAsMock, +})); + +jest.doMock('lodash', () => ({ + ...jest.requireActual('lodash'), + debounce: (func: Function) => { + function debounced(this: any, ...args: any[]) { + return func.apply(this, args); + } + return debounced; + }, +})); + +export const findObjectsMock = jest.fn(); +jest.doMock('../../lib/find_objects', () => ({ + findObjects: findObjectsMock, +})); + +export const fetchExportObjectsMock = jest.fn(); +jest.doMock('../../lib/fetch_export_objects', () => ({ + fetchExportObjects: fetchExportObjectsMock, +})); + +export const fetchExportByTypeAndSearchMock = jest.fn(); +jest.doMock('../../lib/fetch_export_by_type_and_search', () => ({ + fetchExportByTypeAndSearch: fetchExportByTypeAndSearchMock, +})); + +export const extractExportDetailsMock = jest.fn(); +jest.doMock('../../lib/extract_export_details', () => ({ + extractExportDetails: extractExportDetailsMock, +})); + +jest.doMock('./components/header', () => ({ + Header: () => 'Header', +})); + +export const getSavedObjectCountsMock = jest.fn(); +jest.doMock('../../lib/get_saved_object_counts', () => ({ + getSavedObjectCounts: getSavedObjectCountsMock, +})); + +export const getRelationshipsMock = jest.fn(); +jest.doMock('../../lib/get_relationships', () => ({ + getRelationships: getRelationshipsMock, +})); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx similarity index 58% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx index 7b9c17640a0f3..342fdc4784b09 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/objects_table.test.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.test.tsx @@ -17,69 +17,39 @@ * under the License. */ +import { + extractExportDetailsMock, + fetchExportByTypeAndSearchMock, + fetchExportObjectsMock, + findObjectsMock, + getRelationshipsMock, + getSavedObjectCountsMock, + saveAsMock, +} from './saved_objects_table.test.mocks'; + import React from 'react'; -import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; -import { mockManagementPlugin } from '../../../../../../../../../../plugins/index_pattern_management/public/mocks'; import { Query } from '@elastic/eui'; - -import { ObjectsTable, POSSIBLE_TYPES } from '../objects_table'; -import { Flyout } from '../components/flyout/'; -import { Relationships } from '../components/relationships/'; -import { findObjects } from '../../../lib'; -import { extractExportDetails } from '../../../lib/extract_export_details'; - -jest.mock('ui/kfetch', () => ({ kfetch: jest.fn() })); - -jest.mock('../../../../../../../../../../plugins/index_pattern_management/public', () => ({ - setup: mockManagementPlugin.createSetupContract(), - start: mockManagementPlugin.createStartContract(), -})); - -jest.mock('../../../lib/find_objects', () => ({ - findObjects: jest.fn(), -})); - -jest.mock('../components/header', () => ({ - Header: () => 'Header', -})); - -jest.mock('ui/chrome', () => ({ - addBasePath: () => '', - getInjected: () => ['index-pattern', 'visualization', 'dashboard', 'search'], -})); - -jest.mock('../../../lib/fetch_export_objects', () => ({ - fetchExportObjects: jest.fn(), -})); - -jest.mock('../../../lib/fetch_export_by_type_and_search', () => ({ - fetchExportByTypeAndSearch: jest.fn(), -})); - -jest.mock('../../../lib/extract_export_details', () => ({ - extractExportDetails: jest.fn(), -})); - -jest.mock('../../../lib/get_saved_object_counts', () => ({ - getSavedObjectCounts: jest.fn().mockImplementation(() => { - return { - 'index-pattern': 0, - visualization: 0, - dashboard: 0, - search: 0, - }; - }), -})); - -jest.mock('@elastic/filesaver', () => ({ - saveAs: jest.fn(), -})); - -jest.mock('../../../lib/get_relationships', () => ({ - getRelationships: jest.fn(), -})); - -jest.mock('ui/notify', () => ({})); +import { ShallowWrapper } from 'enzyme'; +import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; +import { + httpServiceMock, + overlayServiceMock, + notificationServiceMock, + savedObjectsServiceMock, + applicationServiceMock, +} from '../../../../../core/public/mocks'; +import { dataPluginMock } from '../../../../data/public/mocks'; +import { serviceRegistryMock } from '../../services/service_registry.mock'; +import { actionServiceMock } from '../../services/action_service.mock'; +import { + SavedObjectsTable, + SavedObjectsTableProps, + SavedObjectsTableState, +} from './saved_objects_table'; +import { Flyout, Relationships } from './components'; +import { SavedObjectWithMetadata } from '../../types'; + +const allowedTypes = ['index-pattern', 'visualization', 'dashboard', 'search']; const allSavedObjects = [ { @@ -112,122 +82,128 @@ const allSavedObjects = [ }, ]; -const $http = () => {}; -$http.post = jest.fn().mockImplementation(() => []); -const defaultProps = { - goInspectObject: () => {}, - confirmModalPromise: jest.fn(), - savedObjectsClient: { - find: jest.fn(), - bulkGet: jest.fn(), - }, - indexPatterns: { - clearCache: jest.fn(), - }, - $http, - basePath: '', - newIndexPatternUrl: '', - kbnIndex: '', - services: [], - uiCapabilities: { - savedObjectsManagement: { - read: true, - edit: false, - delete: false, - }, - }, - canDelete: true, -}; - -beforeEach(() => { - findObjects.mockImplementation(() => ({ - total: 4, - savedObjects: [ - { - id: '1', - type: 'index-pattern', - meta: { - title: `MyIndexPattern*`, - icon: 'indexPatternApp', - editUrl: '#/management/kibana/index_patterns/1', - inAppUrl: { - path: '/management/kibana/index_patterns/1', - uiCapabilitiesPath: 'management.kibana.index_patterns', +describe('SavedObjectsTable', () => { + let defaultProps: SavedObjectsTableProps; + let http: ReturnType<typeof httpServiceMock.createStartContract>; + let overlays: ReturnType<typeof overlayServiceMock.createStartContract>; + let notifications: ReturnType<typeof notificationServiceMock.createStartContract>; + let savedObjects: ReturnType<typeof savedObjectsServiceMock.createStartContract>; + + const shallowRender = (overrides: Partial<SavedObjectsTableProps> = {}) => { + return (shallowWithI18nProvider( + <SavedObjectsTable {...defaultProps} {...overrides} /> + ) as unknown) as ShallowWrapper< + SavedObjectsTableProps, + SavedObjectsTableState, + SavedObjectsTable + >; + }; + + beforeEach(() => { + extractExportDetailsMock.mockReset(); + + http = httpServiceMock.createStartContract(); + overlays = overlayServiceMock.createStartContract(); + notifications = notificationServiceMock.createStartContract(); + savedObjects = savedObjectsServiceMock.createStartContract(); + + const applications = applicationServiceMock.createStartContract(); + applications.capabilities = { + navLinks: {}, + management: {}, + catalogue: {}, + savedObjectsManagement: { + read: true, + edit: false, + delete: false, + }, + }; + + http.post.mockResolvedValue([]); + + getSavedObjectCountsMock.mockReturnValue({ + 'index-pattern': 0, + visualization: 0, + dashboard: 0, + search: 0, + }); + + defaultProps = { + allowedTypes, + serviceRegistry: serviceRegistryMock.create(), + actionRegistry: actionServiceMock.createStart(), + savedObjectsClient: savedObjects.client, + indexPatterns: dataPluginMock.createStartContract().indexPatterns, + http, + overlays, + notifications, + applications, + perPageConfig: 15, + goInspectObject: () => {}, + canGoInApp: () => true, + }; + + findObjectsMock.mockImplementation(() => ({ + total: 4, + savedObjects: [ + { + id: '1', + type: 'index-pattern', + meta: { + title: `MyIndexPattern*`, + icon: 'indexPatternApp', + editUrl: '#/management/kibana/index_patterns/1', + inAppUrl: { + path: '/management/kibana/index_patterns/1', + uiCapabilitiesPath: 'management.kibana.index_patterns', + }, }, }, - }, - { - id: '2', - type: 'search', - meta: { - title: `MySearch`, - icon: 'search', - editUrl: '#/management/kibana/objects/savedSearches/2', - inAppUrl: { - path: '/discover/2', - uiCapabilitiesPath: 'discover.show', + { + id: '2', + type: 'search', + meta: { + title: `MySearch`, + icon: 'search', + editUrl: '#/management/kibana/objects/savedSearches/2', + inAppUrl: { + path: '/discover/2', + uiCapabilitiesPath: 'discover.show', + }, }, }, - }, - { - id: '3', - type: 'dashboard', - meta: { - title: `MyDashboard`, - icon: 'dashboardApp', - editUrl: '#/management/kibana/objects/savedDashboards/3', - inAppUrl: { - path: '/dashboard/3', - uiCapabilitiesPath: 'dashboard.show', + { + id: '3', + type: 'dashboard', + meta: { + title: `MyDashboard`, + icon: 'dashboardApp', + editUrl: '#/management/kibana/objects/savedDashboards/3', + inAppUrl: { + path: '/dashboard/3', + uiCapabilitiesPath: 'dashboard.show', + }, }, }, - }, - { - id: '4', - type: 'visualization', - meta: { - title: `MyViz`, - icon: 'visualizeApp', - editUrl: '#/management/kibana/objects/savedVisualizations/4', - inAppUrl: { - path: '/visualize/edit/4', - uiCapabilitiesPath: 'visualize.show', + { + id: '4', + type: 'visualization', + meta: { + title: `MyViz`, + icon: 'visualizeApp', + editUrl: '#/management/kibana/objects/savedVisualizations/4', + inAppUrl: { + path: '/visualize/edit/4', + uiCapabilitiesPath: 'visualize.show', + }, }, }, - }, - ], - })); -}); - -let addDangerMock; -let addSuccessMock; -let addWarningMock; - -describe('ObjectsTable', () => { - beforeEach(() => { - defaultProps.savedObjectsClient.find.mockClear(); - extractExportDetails.mockReset(); - // mock _.debounce to fire immediately with no internal timer - require('lodash').debounce = func => { - function debounced(...args) { - return func.apply(this, args); - } - return debounced; - }; - addDangerMock = jest.fn(); - addSuccessMock = jest.fn(); - addWarningMock = jest.fn(); - require('ui/notify').toastNotifications = { - addDanger: addDangerMock, - addSuccess: addSuccessMock, - addWarning: addWarningMock, - }; + ], + })); }); it('should render normally', async () => { - const component = shallowWithI18nProvider( - <ObjectsTable {...defaultProps} perPageConfig={15} /> - ); + const component = shallowRender({ perPageConfig: 15 }); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -238,19 +214,17 @@ describe('ObjectsTable', () => { }); it('should add danger toast when find fails', async () => { - findObjects.mockImplementation(() => { + findObjectsMock.mockImplementation(() => { throw new Error('Simulated find error'); }); - const component = shallowWithI18nProvider( - <ObjectsTable {...defaultProps} perPageConfig={15} /> - ); + const component = shallowRender({ perPageConfig: 15 }); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); // Ensure the state changes are reflected component.update(); - expect(addDangerMock).toHaveBeenCalled(); + expect(notifications.toasts.addDanger).toHaveBeenCalled(); }); describe('export', () => { @@ -258,7 +232,7 @@ describe('ObjectsTable', () => { const mockSelectedSavedObjects = [ { id: '1', type: 'index-pattern' }, { id: '3', type: 'dashboard' }, - ]; + ] as SavedObjectWithMetadata[]; const mockSavedObjects = mockSelectedSavedObjects.map(obj => ({ _id: obj.id, @@ -272,11 +246,7 @@ describe('ObjectsTable', () => { })), }; - const { fetchExportObjects } = require('../../../lib/fetch_export_objects'); - - const component = shallowWithI18nProvider( - <ObjectsTable {...defaultProps} savedObjectsClient={mockSavedObjectsClient} /> - ); + const component = shallowRender({ savedObjectsClient: mockSavedObjectsClient }); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -288,8 +258,8 @@ describe('ObjectsTable', () => { await component.instance().onExport(true); - expect(fetchExportObjects).toHaveBeenCalledWith(mockSelectedSavedObjects, true); - expect(addSuccessMock).toHaveBeenCalledWith({ + expect(fetchExportObjectsMock).toHaveBeenCalledWith(http, mockSelectedSavedObjects, true); + expect(notifications.toasts.addSuccess).toHaveBeenCalledWith({ title: 'Your file is downloading in the background', }); }); @@ -298,7 +268,7 @@ describe('ObjectsTable', () => { const mockSelectedSavedObjects = [ { id: '1', type: 'index-pattern' }, { id: '3', type: 'dashboard' }, - ]; + ] as SavedObjectWithMetadata[]; const mockSavedObjects = mockSelectedSavedObjects.map(obj => ({ _id: obj.id, @@ -312,16 +282,13 @@ describe('ObjectsTable', () => { })), }; - const { fetchExportObjects } = require('../../../lib/fetch_export_objects'); - extractExportDetails.mockImplementation(() => ({ + extractExportDetailsMock.mockImplementation(() => ({ exportedCount: 2, missingRefCount: 1, missingReferences: [{ id: '7', type: 'visualisation' }], })); - const component = shallowWithI18nProvider( - <ObjectsTable {...defaultProps} savedObjectsClient={mockSavedObjectsClient} /> - ); + const component = shallowRender({ savedObjectsClient: mockSavedObjectsClient }); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -333,8 +300,8 @@ describe('ObjectsTable', () => { await component.instance().onExport(true); - expect(fetchExportObjects).toHaveBeenCalledWith(mockSelectedSavedObjects, true); - expect(addWarningMock).toHaveBeenCalledWith({ + expect(fetchExportObjectsMock).toHaveBeenCalledWith(http, mockSelectedSavedObjects, true); + expect(notifications.toasts.addWarning).toHaveBeenCalledWith({ title: 'Your file is downloading in the background. ' + 'Some related objects could not be found. ' + @@ -343,25 +310,21 @@ describe('ObjectsTable', () => { }); it('should allow the user to choose when exporting all', async () => { - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); // Ensure the state changes are reflected component.update(); - component.find('Header').prop('onExportAll')(); + (component.find('Header') as any).prop('onExportAll')(); component.update(); expect(component.find('EuiModal')).toMatchSnapshot(); }); it('should export all', async () => { - const { - fetchExportByTypeAndSearch, - } = require('../../../lib/fetch_export_by_type_and_search'); - const { saveAs } = require('@elastic/filesaver'); - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -370,23 +333,24 @@ describe('ObjectsTable', () => { // Set up mocks const blob = new Blob([JSON.stringify(allSavedObjects)], { type: 'application/ndjson' }); - fetchExportByTypeAndSearch.mockImplementation(() => blob); + fetchExportByTypeAndSearchMock.mockImplementation(() => blob); await component.instance().onExportAll(); - expect(fetchExportByTypeAndSearch).toHaveBeenCalledWith(POSSIBLE_TYPES, undefined, true); - expect(saveAs).toHaveBeenCalledWith(blob, 'export.ndjson'); - expect(addSuccessMock).toHaveBeenCalledWith({ + expect(fetchExportByTypeAndSearchMock).toHaveBeenCalledWith( + http, + allowedTypes, + undefined, + true + ); + expect(saveAsMock).toHaveBeenCalledWith(blob, 'export.ndjson'); + expect(notifications.toasts.addSuccess).toHaveBeenCalledWith({ title: 'Your file is downloading in the background', }); }); it('should export all, accounting for the current search criteria', async () => { - const { - fetchExportByTypeAndSearch, - } = require('../../../lib/fetch_export_by_type_and_search'); - const { saveAs } = require('@elastic/filesaver'); - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); component.instance().onQueryChange({ query: Query.parse('test'), @@ -399,13 +363,18 @@ describe('ObjectsTable', () => { // Set up mocks const blob = new Blob([JSON.stringify(allSavedObjects)], { type: 'application/ndjson' }); - fetchExportByTypeAndSearch.mockImplementation(() => blob); + fetchExportByTypeAndSearchMock.mockImplementation(() => blob); await component.instance().onExportAll(); - expect(fetchExportByTypeAndSearch).toHaveBeenCalledWith(POSSIBLE_TYPES, 'test*', true); - expect(saveAs).toHaveBeenCalledWith(blob, 'export.ndjson'); - expect(addSuccessMock).toHaveBeenCalledWith({ + expect(fetchExportByTypeAndSearchMock).toHaveBeenCalledWith( + http, + allowedTypes, + 'test*', + true + ); + expect(saveAsMock).toHaveBeenCalledWith(blob, 'export.ndjson'); + expect(notifications.toasts.addSuccess).toHaveBeenCalledWith({ title: 'Your file is downloading in the background', }); }); @@ -413,7 +382,7 @@ describe('ObjectsTable', () => { describe('import', () => { it('should show the flyout', async () => { - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -427,7 +396,7 @@ describe('ObjectsTable', () => { }); it('should hide the flyout', async () => { - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -443,9 +412,7 @@ describe('ObjectsTable', () => { describe('relationships', () => { it('should fetch relationships', async () => { - const { getRelationships } = require('../../../lib/get_relationships'); - - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -454,17 +421,11 @@ describe('ObjectsTable', () => { await component.instance().getRelationships('search', '1'); const savedObjectTypes = ['index-pattern', 'visualization', 'dashboard', 'search']; - expect(getRelationships).toHaveBeenCalledWith( - 'search', - '1', - savedObjectTypes, - defaultProps.$http, - defaultProps.basePath - ); + expect(getRelationshipsMock).toHaveBeenCalledWith(http, 'search', '1', savedObjectTypes); }); it('should show the flyout', async () => { - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -483,7 +444,7 @@ describe('ObjectsTable', () => { uiCapabilitiesPath: 'discover.show', }, }, - }); + } as SavedObjectWithMetadata); component.update(); expect(component.find(Relationships)).toMatchSnapshot(); @@ -503,7 +464,7 @@ describe('ObjectsTable', () => { }); it('should hide the flyout', async () => { - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -522,12 +483,12 @@ describe('ObjectsTable', () => { describe('delete', () => { it('should show a confirm modal', async () => { - const component = shallowWithI18nProvider(<ObjectsTable {...defaultProps} />); + const component = shallowRender(); const mockSelectedSavedObjects = [ - { id: '1', type: 'index-pattern', title: 'Title 1' }, - { id: '3', type: 'dashboard', title: 'Title 2' }, - ]; + { id: '1', type: 'index-pattern' }, + { id: '3', type: 'dashboard' }, + ] as SavedObjectWithMetadata[]; // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); @@ -546,7 +507,7 @@ describe('ObjectsTable', () => { const mockSelectedSavedObjects = [ { id: '1', type: 'index-pattern' }, { id: '3', type: 'dashboard' }, - ]; + ] as SavedObjectWithMetadata[]; const mockSavedObjects = mockSelectedSavedObjects.map(obj => ({ id: obj.id, @@ -562,9 +523,7 @@ describe('ObjectsTable', () => { delete: jest.fn(), }; - const component = shallowWithI18nProvider( - <ObjectsTable {...defaultProps} savedObjectsClient={mockSavedObjectsClient} /> - ); + const component = shallowRender({ savedObjectsClient: mockSavedObjectsClient }); // Ensure all promises resolve await new Promise(resolve => process.nextTick(resolve)); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/objects_table.js b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx similarity index 73% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/objects_table.js rename to src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 188762f165b24..c76fea5a0fb29 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/objects_table.js +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -17,17 +17,10 @@ * under the License. */ -import chrome from 'ui/chrome'; -import { saveAs } from '@elastic/filesaver'; import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import { debounce } from 'lodash'; -import { Header } from './components/header'; -import { Flyout } from './components/flyout'; -import { Relationships } from './components/relationships'; -import { Table } from './components/table'; -import { toastNotifications } from 'ui/notify'; - +// @ts-ignore +import { saveAs } from '@elastic/filesaver'; import { EuiSpacer, Query, @@ -54,7 +47,15 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - +import { + SavedObjectsClientContract, + SavedObjectsFindOptions, + HttpStart, + OverlayStart, + NotificationsStart, + ApplicationStart, +} from 'src/core/public'; +import { IndexPatternsContract } from '../../../../data/public'; import { parseQuery, getSavedObjectCounts, @@ -63,39 +64,72 @@ import { fetchExportObjects, fetchExportByTypeAndSearch, findObjects, + extractExportDetails, + SavedObjectsExportResultDetails, } from '../../lib'; -import { extractExportDetails } from '../../lib/extract_export_details'; - -export const POSSIBLE_TYPES = chrome.getInjected('importAndExportableTypes'); - -export class ObjectsTable extends Component { - static propTypes = { - savedObjectsClient: PropTypes.object.isRequired, - indexPatterns: PropTypes.object.isRequired, - $http: PropTypes.func.isRequired, - basePath: PropTypes.string.isRequired, - perPageConfig: PropTypes.number, - newIndexPatternUrl: PropTypes.string.isRequired, - confirmModalPromise: PropTypes.func.isRequired, - services: PropTypes.array.isRequired, - uiCapabilities: PropTypes.object.isRequired, - goInspectObject: PropTypes.func.isRequired, - canGoInApp: PropTypes.func.isRequired, - }; +import { SavedObjectWithMetadata } from '../../types'; +import { + ISavedObjectsManagementServiceRegistry, + SavedObjectsManagementActionServiceStart, +} from '../../services'; +import { Header, Table, Flyout, Relationships } from './components'; + +interface ExportAllOption { + id: string; + label: string; +} - constructor(props) { +export interface SavedObjectsTableProps { + allowedTypes: string[]; + serviceRegistry: ISavedObjectsManagementServiceRegistry; + actionRegistry: SavedObjectsManagementActionServiceStart; + savedObjectsClient: SavedObjectsClientContract; + indexPatterns: IndexPatternsContract; + http: HttpStart; + overlays: OverlayStart; + notifications: NotificationsStart; + applications: ApplicationStart; + perPageConfig: number; + goInspectObject: (obj: SavedObjectWithMetadata) => void; + canGoInApp: (obj: SavedObjectWithMetadata) => boolean; +} + +export interface SavedObjectsTableState { + totalCount: number; + page: number; + perPage: number; + savedObjects: SavedObjectWithMetadata[]; + savedObjectCounts: Record<string, number>; + activeQuery: Query; + selectedSavedObjects: SavedObjectWithMetadata[]; + isShowingImportFlyout: boolean; + isSearching: boolean; + filteredItemCount: number; + isShowingRelationships: boolean; + relationshipObject?: SavedObjectWithMetadata; + isShowingDeleteConfirmModal: boolean; + isShowingExportAllOptionsModal: boolean; + isDeleting: boolean; + exportAllOptions: ExportAllOption[]; + exportAllSelectedOptions: Record<string, boolean>; + isIncludeReferencesDeepChecked: boolean; +} + +export class SavedObjectsTable extends Component<SavedObjectsTableProps, SavedObjectsTableState> { + private _isMounted = false; + + constructor(props: SavedObjectsTableProps) { super(props); - this.savedObjectTypes = POSSIBLE_TYPES; this.state = { totalCount: 0, page: 0, perPage: props.perPageConfig || 50, savedObjects: [], - savedObjectCounts: this.savedObjectTypes.reduce((typeToCountMap, type) => { + savedObjectCounts: props.allowedTypes.reduce((typeToCountMap, type) => { typeToCountMap[type] = 0; return typeToCountMap; - }, {}), + }, {} as Record<string, number>), activeQuery: Query.parse(''), selectedSavedObjects: [], isShowingImportFlyout: false, @@ -124,21 +158,20 @@ export class ObjectsTable extends Component { } fetchCounts = async () => { + const { allowedTypes } = this.props; const { queryText, visibleTypes } = parseQuery(this.state.activeQuery); - const filteredTypes = this.savedObjectTypes.filter( - type => !visibleTypes || visibleTypes.includes(type) - ); + const filteredTypes = allowedTypes.filter(type => !visibleTypes || visibleTypes.includes(type)); // These are the saved objects visible in the table. const filteredSavedObjectCounts = await getSavedObjectCounts( - this.props.$http, + this.props.http, filteredTypes, queryText ); - const exportAllOptions = []; - const exportAllSelectedOptions = {}; + const exportAllOptions: ExportAllOption[] = []; + const exportAllSelectedOptions: Record<string, boolean> = {}; Object.keys(filteredSavedObjectCounts).forEach(id => { // Add this type as a bulk-export option. @@ -147,17 +180,13 @@ export class ObjectsTable extends Component { label: `${id} (${filteredSavedObjectCounts[id] || 0})`, }); - // Select it by defayult. + // Select it by default. exportAllSelectedOptions[id] = true; }); // Fetch all the saved objects that exist so we can accurately populate the counts within // the table filter dropdown. - const savedObjectCounts = await getSavedObjectCounts( - this.props.$http, - this.savedObjectTypes, - queryText - ); + const savedObjectCounts = await getSavedObjectCounts(this.props.http, allowedTypes, queryText); this.setState(state => ({ ...state, @@ -178,66 +207,64 @@ export class ObjectsTable extends Component { debouncedFetch = debounce(async () => { const { activeQuery: query, page, perPage } = this.state; + const { notifications, http, allowedTypes } = this.props; const { queryText, visibleTypes } = parseQuery(query); // "searchFields" is missing from the "findOptions" but gets injected via the API. // The API extracts the fields from each uiExports.savedObjectsManagement "defaultSearchField" attribute - const findOptions = { + const findOptions: SavedObjectsFindOptions = { search: queryText ? `${queryText}*` : undefined, perPage, page: page + 1, fields: ['id'], - type: this.savedObjectTypes.filter(type => !visibleTypes || visibleTypes.includes(type)), + type: allowedTypes.filter(type => !visibleTypes || visibleTypes.includes(type)), }; if (findOptions.type.length > 1) { findOptions.sortField = 'type'; } - let resp; try { - resp = await findObjects(findOptions); + const resp = await findObjects(http, findOptions); + if (!this._isMounted) { + return; + } + + this.setState(({ activeQuery }) => { + // ignore results for old requests + if (activeQuery.text !== query.text) { + return null; + } + + return { + savedObjects: resp.savedObjects, + filteredItemCount: resp.total, + isSearching: false, + }; + }); } catch (error) { if (this._isMounted) { this.setState({ isSearching: false, }); } - toastNotifications.addDanger({ + notifications.toasts.addDanger({ title: i18n.translate( - 'kbn.management.objects.objectsTable.unableFindSavedObjectsNotificationMessage', + 'savedObjectsManagement.objectsTable.unableFindSavedObjectsNotificationMessage', { defaultMessage: 'Unable find saved objects' } ), text: `${error}`, }); - return; - } - - if (!this._isMounted) { - return; } - - this.setState(({ activeQuery }) => { - // ignore results for old requests - if (activeQuery.text !== query.text) { - return {}; - } - - return { - savedObjects: resp.savedObjects, - filteredItemCount: resp.total, - isSearching: false, - }; - }); }, 300); refreshData = async () => { await Promise.all([this.fetchSavedObjects(), this.fetchCounts()]); }; - onSelectionChanged = selection => { + onSelectionChanged = (selection: SavedObjectWithMetadata[]) => { this.setState({ selectedSavedObjects: selection }); }; - onQueryChange = ({ query }) => { + onQueryChange = ({ query }: { query: Query }) => { // TODO: Use isSameQuery to compare new query with state.activeQuery to avoid re-fetching the // same data we already have. this.setState( @@ -253,7 +280,7 @@ export class ObjectsTable extends Component { ); }; - onTableChange = async table => { + onTableChange = async (table: any) => { const { index: page, size: perPage } = table.page || {}; this.setState( @@ -266,7 +293,7 @@ export class ObjectsTable extends Component { ); }; - onShowRelationships = object => { + onShowRelationships = (object: SavedObjectWithMetadata) => { this.setState({ isShowingRelationships: true, relationshipObject: object, @@ -280,16 +307,17 @@ export class ObjectsTable extends Component { }); }; - onExport = async includeReferencesDeep => { + onExport = async (includeReferencesDeep: boolean) => { const { selectedSavedObjects } = this.state; + const { notifications, http } = this.props; const objectsToExport = selectedSavedObjects.map(obj => ({ id: obj.id, type: obj.type })); let blob; try { - blob = await fetchExportObjects(objectsToExport, includeReferencesDeep); + blob = await fetchExportObjects(http, objectsToExport, includeReferencesDeep); } catch (e) { - toastNotifications.addDanger({ - title: i18n.translate('kbn.management.objects.objectsTable.export.dangerNotification', { + notifications.toasts.addDanger({ + title: i18n.translate('savedObjectsManagement.objectsTable.export.dangerNotification', { defaultMessage: 'Unable to generate export', }), }); @@ -304,24 +332,26 @@ export class ObjectsTable extends Component { onExportAll = async () => { const { exportAllSelectedOptions, isIncludeReferencesDeepChecked, activeQuery } = this.state; + const { notifications, http } = this.props; const { queryText } = parseQuery(activeQuery); const exportTypes = Object.entries(exportAllSelectedOptions).reduce((accum, [id, selected]) => { if (selected) { accum.push(id); } return accum; - }, []); + }, [] as string[]); let blob; try { blob = await fetchExportByTypeAndSearch( + http, exportTypes, queryText ? `${queryText}*` : undefined, isIncludeReferencesDeepChecked ); } catch (e) { - toastNotifications.addDanger({ - title: i18n.translate('kbn.management.objects.objectsTable.export.dangerNotification', { + notifications.toasts.addDanger({ + title: i18n.translate('savedObjectsManagement.objectsTable.export.dangerNotification', { defaultMessage: 'Unable to generate export', }), }); @@ -335,11 +365,12 @@ export class ObjectsTable extends Component { this.setState({ isShowingExportAllOptionsModal: false }); }; - showExportSuccessMessage = exportDetails => { + showExportSuccessMessage = (exportDetails: SavedObjectsExportResultDetails | undefined) => { + const { notifications } = this.props; if (exportDetails && exportDetails.missingReferences.length > 0) { - toastNotifications.addWarning({ + notifications.toasts.addWarning({ title: i18n.translate( - 'kbn.management.objects.objectsTable.export.successWithMissingRefsNotification', + 'savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification', { defaultMessage: 'Your file is downloading in the background. ' + @@ -349,8 +380,8 @@ export class ObjectsTable extends Component { ), }); } else { - toastNotifications.addSuccess({ - title: i18n.translate('kbn.management.objects.objectsTable.export.successNotification', { + notifications.toasts.addSuccess({ + title: i18n.translate('savedObjectsManagement.objectsTable.export.successNotification', { defaultMessage: 'Your file is downloading in the background', }), }); @@ -412,30 +443,30 @@ export class ObjectsTable extends Component { }); }; - getRelationships = async (type, id) => { - return await getRelationships( - type, - id, - this.savedObjectTypes, - this.props.$http, - this.props.basePath - ); + getRelationships = async (type: string, id: string) => { + const { allowedTypes, http } = this.props; + return await getRelationships(http, type, id, allowedTypes); }; renderFlyout() { if (!this.state.isShowingImportFlyout) { return null; } + const { applications } = this.props; + const newIndexPatternUrl = applications.getUrlForApp('kibana', { + path: '#/management/kibana/index_pattern', + }); return ( <Flyout close={this.hideImportFlyout} done={this.finishImport} - services={this.props.services} + http={this.props.http} + serviceRegistry={this.props.serviceRegistry} indexPatterns={this.props.indexPatterns} - newIndexPatternUrl={this.props.newIndexPatternUrl} - savedObjectTypes={this.props.savedObjectTypes} - confirmModalPromise={this.props.confirmModalPromise} + newIndexPatternUrl={newIndexPatternUrl} + allowedTypes={this.props.allowedTypes} + overlays={this.props.overlays} /> ); } @@ -447,10 +478,10 @@ export class ObjectsTable extends Component { return ( <Relationships - savedObject={this.state.relationshipObject} + basePath={this.props.http.basePath} + savedObject={this.state.relationshipObject!} getRelationships={this.getRelationships} close={this.onHideRelationships} - getDashboardUrl={this.props.getDashboardUrl} goInspectObject={this.props.goInspectObject} canGoInApp={this.props.canGoInApp} /> @@ -482,7 +513,7 @@ export class ObjectsTable extends Component { <EuiConfirmModal title={ <FormattedMessage - id="kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModalTitle" + id="savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle" defaultMessage="Delete saved objects" /> } @@ -491,19 +522,19 @@ export class ObjectsTable extends Component { buttonColor="danger" cancelButtonText={ <FormattedMessage - id="kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel" defaultMessage="Cancel" /> } confirmButtonText={ isDeleting ? ( <FormattedMessage - id="kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.deleteProcessButtonLabel" + id="savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteProcessButtonLabel" defaultMessage="Deleting…" /> ) : ( <FormattedMessage - id="kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel" + id="savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel" defaultMessage="Delete" /> ) @@ -512,7 +543,7 @@ export class ObjectsTable extends Component { > <p> <FormattedMessage - id="kbn.management.objects.deleteSavedObjectsConfirmModalDescription" + id="savedObjectsManagement.deleteSavedObjectsConfirmModalDescription" defaultMessage="This action will delete the following saved objects:" /> </p> @@ -522,7 +553,7 @@ export class ObjectsTable extends Component { { field: 'type', name: i18n.translate( - 'kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName', + 'savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName', { defaultMessage: 'Type' } ), width: '50px', @@ -535,14 +566,14 @@ export class ObjectsTable extends Component { { field: 'id', name: i18n.translate( - 'kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.idColumnName', + 'savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.idColumnName', { defaultMessage: 'Id' } ), }, { field: 'meta.title', name: i18n.translate( - 'kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName', + 'savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName', { defaultMessage: 'Title' } ), }, @@ -586,7 +617,7 @@ export class ObjectsTable extends Component { <EuiModalHeader> <EuiModalHeaderTitle> <FormattedMessage - id="kbn.management.objects.objectsTable.exportObjectsConfirmModalTitle" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModalTitle" defaultMessage="Export {filteredItemCount, plural, one{# object} other {# objects}}" values={{ filteredItemCount, @@ -598,7 +629,7 @@ export class ObjectsTable extends Component { <EuiFormRow label={ <FormattedMessage - id="kbn.management.objects.objectsTable.exportObjectsConfirmModalDescription" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription" defaultMessage="Select which types to export" /> } @@ -626,7 +657,7 @@ export class ObjectsTable extends Component { name="includeReferencesDeep" label={ <FormattedMessage - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel" defaultMessage="Include related objects" /> } @@ -641,7 +672,7 @@ export class ObjectsTable extends Component { <EuiFlexItem grow={false}> <EuiButtonEmpty onClick={this.closeExportAllModal}> <FormattedMessage - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.cancelButtonLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.cancelButtonLabel" defaultMessage="Cancel" /> </EuiButtonEmpty> @@ -649,7 +680,7 @@ export class ObjectsTable extends Component { <EuiFlexItem grow={false}> <EuiButton fill onClick={this.onExportAll}> <FormattedMessage - id="kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel" + id="savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel" defaultMessage="Export all" /> </EuiButton> @@ -673,12 +704,13 @@ export class ObjectsTable extends Component { isSearching, savedObjectCounts, } = this.state; + const { http, allowedTypes, applications } = this.props; const selectionConfig = { onSelectionChange: this.onSelectionChanged, }; - const filterOptions = this.savedObjectTypes.map(type => ({ + const filterOptions = allowedTypes.map(type => ({ value: type, name: type, view: `${type} (${savedObjectCounts[type] || 0})`, @@ -698,14 +730,16 @@ export class ObjectsTable extends Component { /> <EuiSpacer size="xs" /> <Table + basePath={http.basePath} itemId={'id'} + actionRegistry={this.props.actionRegistry} selectionConfig={selectionConfig} selectedSavedObjects={selectedSavedObjects} onQueryChange={this.onQueryChange} onTableChange={this.onTableChange} filterOptions={filterOptions} onExport={this.onExport} - canDelete={this.props.uiCapabilities.savedObjectsManagement.delete} + canDelete={applications.capabilities.savedObjectsManagement.delete as boolean} onDelete={this.onDelete} goInspectObject={this.props.goInspectObject} pageIndex={page} diff --git a/src/plugins/saved_objects_management/public/management_section/types.ts b/src/plugins/saved_objects_management/public/management_section/types.ts new file mode 100644 index 0000000000000..541746534b84a --- /dev/null +++ b/src/plugins/saved_objects_management/public/management_section/types.ts @@ -0,0 +1,38 @@ +/* + * 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 { SavedObjectReference } from '../../../../core/types'; + +export interface ObjectField { + type: FieldType; + name: string; + value: any; +} + +export type FieldType = 'text' | 'number' | 'boolean' | 'array' | 'json'; + +export interface FieldState { + value?: any; + invalid?: boolean; +} + +export interface SubmittedFormData { + attributes: any; + references: SavedObjectReference[]; +} diff --git a/src/plugins/saved_objects_management/public/mocks.ts b/src/plugins/saved_objects_management/public/mocks.ts index 8cf23afe87907..1de3de8e85302 100644 --- a/src/plugins/saved_objects_management/public/mocks.ts +++ b/src/plugins/saved_objects_management/public/mocks.ts @@ -17,23 +17,27 @@ * under the License. */ -import { actionRegistryMock } from './services/action_registry.mock'; +import { actionServiceMock } from './services/action_service.mock'; +import { serviceRegistryMock } from './services/service_registry.mock'; import { SavedObjectsManagementPluginSetup, SavedObjectsManagementPluginStart } from './plugin'; const createSetupContractMock = (): jest.Mocked<SavedObjectsManagementPluginSetup> => { const mock = { - actionRegistry: actionRegistryMock.create(), + actions: actionServiceMock.createSetup(), + serviceRegistry: serviceRegistryMock.create(), }; return mock; }; const createStartContractMock = (): jest.Mocked<SavedObjectsManagementPluginStart> => { - const mock = {}; + const mock = { + actions: actionServiceMock.createStart(), + }; return mock; }; export const savedObjectsManagementPluginMock = { - createActionRegistry: actionRegistryMock.create, + createServiceRegistry: serviceRegistryMock.create, createSetupContract: createSetupContractMock, createStartContract: createStartContractMock, }; diff --git a/src/plugins/saved_objects_management/public/plugin.test.ts b/src/plugins/saved_objects_management/public/plugin.test.ts index 1cafbb235ad5b..09080f46a6869 100644 --- a/src/plugins/saved_objects_management/public/plugin.test.ts +++ b/src/plugins/saved_objects_management/public/plugin.test.ts @@ -20,6 +20,9 @@ import { coreMock } from '../../../core/public/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { homePluginMock } from '../../home/public/mocks'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { managementPluginMock } from '../../management/public/mocks'; +import { dataPluginMock } from '../../data/public/mocks'; import { SavedObjectsManagementPlugin } from './plugin'; describe('SavedObjectsManagementPlugin', () => { @@ -31,10 +34,13 @@ describe('SavedObjectsManagementPlugin', () => { describe('#setup', () => { it('registers the saved_objects feature to the home plugin', async () => { - const coreSetup = coreMock.createSetup(); + const coreSetup = coreMock.createSetup({ + pluginStartDeps: { data: dataPluginMock.createStartContract() }, + }); const homeSetup = homePluginMock.createSetupContract(); + const managementSetup = managementPluginMock.createSetupContract(); - await plugin.setup(coreSetup, { home: homeSetup }); + await plugin.setup(coreSetup, { home: homeSetup, management: managementSetup }); expect(homeSetup.featureCatalogue.register).toHaveBeenCalledTimes(1); expect(homeSetup.featureCatalogue.register).toHaveBeenCalledWith( diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index 3f2e9c166058e..c8dede3da9263 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -19,37 +19,59 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { ManagementSetup } from '../../management/public'; +import { DataPublicPluginStart } from '../../data/public'; +import { DashboardStart } from '../../dashboard/public'; +import { DiscoverStart } from '../../discover/public'; import { HomePublicPluginSetup, FeatureCatalogueCategory } from '../../home/public'; +import { VisualizationsStart } from '../../visualizations/public'; import { - SavedObjectsManagementActionRegistry, - ISavedObjectsManagementActionRegistry, + SavedObjectsManagementActionService, + SavedObjectsManagementActionServiceSetup, + SavedObjectsManagementActionServiceStart, + SavedObjectsManagementServiceRegistry, + ISavedObjectsManagementServiceRegistry, } from './services'; +import { registerServices } from './register_services'; export interface SavedObjectsManagementPluginSetup { - actionRegistry: ISavedObjectsManagementActionRegistry; + actions: SavedObjectsManagementActionServiceSetup; + serviceRegistry: ISavedObjectsManagementServiceRegistry; } -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface SavedObjectsManagementPluginStart {} +export interface SavedObjectsManagementPluginStart { + actions: SavedObjectsManagementActionServiceStart; +} export interface SetupDependencies { + management: ManagementSetup; home: HomePublicPluginSetup; } +export interface StartDependencies { + data: DataPublicPluginStart; + dashboard?: DashboardStart; + visualizations?: VisualizationsStart; + discover?: DiscoverStart; +} + export class SavedObjectsManagementPlugin implements Plugin< SavedObjectsManagementPluginSetup, SavedObjectsManagementPluginStart, SetupDependencies, - {} + StartDependencies > { - private actionRegistry = new SavedObjectsManagementActionRegistry(); + private actionService = new SavedObjectsManagementActionService(); + private serviceRegistry = new SavedObjectsManagementServiceRegistry(); public setup( - core: CoreSetup<{}>, - { home }: SetupDependencies + core: CoreSetup<StartDependencies, SavedObjectsManagementPluginStart>, + { home, management }: SetupDependencies ): SavedObjectsManagementPluginSetup { + const actionSetup = this.actionService.setup(); + home.featureCatalogue.register({ id: 'saved_objects', title: i18n.translate('savedObjectsManagement.objects.savedObjectsTitle', { @@ -65,12 +87,39 @@ export class SavedObjectsManagementPlugin category: FeatureCatalogueCategory.ADMIN, }); + const kibanaSection = management.sections.getSection('kibana'); + if (!kibanaSection) { + throw new Error('`kibana` management section not found.'); + } + kibanaSection.registerApp({ + id: 'objects', + title: i18n.translate('savedObjectsManagement.managementSectionLabel', { + defaultMessage: 'Saved Objects', + }), + order: 10, + mount: async mountParams => { + const { mountManagementSection } = await import('./management_section'); + return mountManagementSection({ + core, + serviceRegistry: this.serviceRegistry, + mountParams, + }); + }, + }); + + // depends on `getStartServices`, should not be awaited + registerServices(this.serviceRegistry, core.getStartServices); + return { - actionRegistry: this.actionRegistry, + actions: actionSetup, + serviceRegistry: this.serviceRegistry, }; } public start(core: CoreStart) { - return {}; + const actionStart = this.actionService.start(); + return { + actions: actionStart, + }; } } diff --git a/src/plugins/saved_objects_management/public/register_services.ts b/src/plugins/saved_objects_management/public/register_services.ts new file mode 100644 index 0000000000000..a34b632b78f6c --- /dev/null +++ b/src/plugins/saved_objects_management/public/register_services.ts @@ -0,0 +1,59 @@ +/* + * 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 { StartServicesAccessor } from '../../../core/public'; +import { SavedObjectsManagementPluginStart, StartDependencies } from './plugin'; +import { ISavedObjectsManagementServiceRegistry } from './services'; + +export const registerServices = async ( + registry: ISavedObjectsManagementServiceRegistry, + getStartServices: StartServicesAccessor<StartDependencies, SavedObjectsManagementPluginStart> +) => { + const [coreStart, { dashboard, data, visualizations, discover }] = await getStartServices(); + + if (dashboard) { + registry.register({ + id: 'savedDashboards', + title: 'dashboards', + service: dashboard.getSavedDashboardLoader(), + }); + } + + if (visualizations) { + registry.register({ + id: 'savedVisualizations', + title: 'visualizations', + service: visualizations.savedVisualizationsLoader, + }); + } + + if (discover) { + registry.register({ + id: 'savedSearches', + title: 'searches', + service: discover.savedSearches.createLoader({ + savedObjectsClient: coreStart.savedObjects.client, + indexPatterns: data.indexPatterns, + search: data.search, + chrome: coreStart.chrome, + overlays: coreStart.overlays, + }), + }); + } +}; diff --git a/src/plugins/saved_objects_management/public/services/action_service.mock.ts b/src/plugins/saved_objects_management/public/services/action_service.mock.ts new file mode 100644 index 0000000000000..97c95a589b925 --- /dev/null +++ b/src/plugins/saved_objects_management/public/services/action_service.mock.ts @@ -0,0 +1,57 @@ +/* + * 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 { + SavedObjectsManagementActionService, + SavedObjectsManagementActionServiceSetup, + SavedObjectsManagementActionServiceStart, +} from './action_service'; + +const createSetupMock = (): jest.Mocked<SavedObjectsManagementActionServiceSetup> => { + const mock = { + register: jest.fn(), + }; + return mock; +}; + +const createStartMock = (): jest.Mocked<SavedObjectsManagementActionServiceStart> => { + const mock = { + has: jest.fn(), + getAll: jest.fn(), + }; + + mock.has.mockReturnValue(true); + mock.getAll.mockReturnValue([]); + + return mock; +}; + +const createServiceMock = (): jest.Mocked<PublicMethodsOf<SavedObjectsManagementActionService>> => { + const mock = { + setup: jest.fn().mockReturnValue(createSetupMock()), + start: jest.fn().mockReturnValue(createStartMock()), + }; + return mock; +}; + +export const actionServiceMock = { + create: createServiceMock, + createSetup: createSetupMock, + createStart: createStartMock, +}; diff --git a/src/plugins/saved_objects_management/public/services/action_registry.test.ts b/src/plugins/saved_objects_management/public/services/action_service.test.ts similarity index 69% rename from src/plugins/saved_objects_management/public/services/action_registry.test.ts rename to src/plugins/saved_objects_management/public/services/action_service.test.ts index eb3bda00f4196..107554589f83d 100644 --- a/src/plugins/saved_objects_management/public/services/action_registry.test.ts +++ b/src/plugins/saved_objects_management/public/services/action_service.test.ts @@ -17,8 +17,11 @@ * under the License. */ -import { SavedObjectsManagementActionRegistry } from './action_registry'; -import { SavedObjectsManagementAction } from './action_types'; +import { + SavedObjectsManagementActionService, + SavedObjectsManagementActionServiceSetup, +} from './action_service'; +import { SavedObjectsManagementAction } from './types'; class DummyAction extends SavedObjectsManagementAction { constructor(public id: string) { @@ -36,27 +39,30 @@ class DummyAction extends SavedObjectsManagementAction { } describe('SavedObjectsManagementActionRegistry', () => { - let registry: SavedObjectsManagementActionRegistry; + let service: SavedObjectsManagementActionService; + let setup: SavedObjectsManagementActionServiceSetup; const createAction = (id: string): SavedObjectsManagementAction => { return new DummyAction(id); }; beforeEach(() => { - registry = new SavedObjectsManagementActionRegistry(); + service = new SavedObjectsManagementActionService(); + setup = service.setup(); }); describe('#register', () => { it('allows actions to be registered and retrieved', () => { const action = createAction('foo'); - registry.register(action); - expect(registry.getAll()).toContain(action); + setup.register(action); + const start = service.start(); + expect(start.getAll()).toContain(action); }); it('does not allow actions with duplicate ids to be registered', () => { const action = createAction('my-action'); - registry.register(action); - expect(() => registry.register(action)).toThrowErrorMatchingInlineSnapshot( + setup.register(action); + expect(() => setup.register(action)).toThrowErrorMatchingInlineSnapshot( `"Saved Objects Management Action with id 'my-action' already exists"` ); }); @@ -65,12 +71,14 @@ describe('SavedObjectsManagementActionRegistry', () => { describe('#has', () => { it('returns true when an action with a matching ID exists', () => { const action = createAction('existing-action'); - registry.register(action); - expect(registry.has('existing-action')).toEqual(true); + setup.register(action); + const start = service.start(); + expect(start.has('existing-action')).toEqual(true); }); it(`returns false when an action doesn't exist`, () => { - expect(registry.has('missing-action')).toEqual(false); + const start = service.start(); + expect(start.has('missing-action')).toEqual(false); }); }); }); diff --git a/src/plugins/saved_objects_management/public/services/action_registry.ts b/src/plugins/saved_objects_management/public/services/action_service.ts similarity index 56% rename from src/plugins/saved_objects_management/public/services/action_registry.ts rename to src/plugins/saved_objects_management/public/services/action_service.ts index 8bf77231dd73f..2b0b4cf5431e5 100644 --- a/src/plugins/saved_objects_management/public/services/action_registry.ts +++ b/src/plugins/saved_objects_management/public/services/action_service.ts @@ -17,36 +17,44 @@ * under the License. */ -import { SavedObjectsManagementAction } from './action_types'; - -export type ISavedObjectsManagementActionRegistry = PublicMethodsOf< - SavedObjectsManagementActionRegistry ->; - -export class SavedObjectsManagementActionRegistry { - private readonly actions = new Map<string, SavedObjectsManagementAction>(); +import { SavedObjectsManagementAction } from './types'; +export interface SavedObjectsManagementActionServiceSetup { /** * register given action in the registry. */ - register(action: SavedObjectsManagementAction) { - if (this.actions.has(action.id)) { - throw new Error(`Saved Objects Management Action with id '${action.id}' already exists`); - } - this.actions.set(action.id, action); - } + register: (action: SavedObjectsManagementAction) => void; +} +export interface SavedObjectsManagementActionServiceStart { /** * return true if the registry contains given action, false otherwise. */ - has(actionId: string) { - return this.actions.has(actionId); - } - + has: (actionId: string) => boolean; /** * return all {@link SavedObjectsManagementAction | actions} currently registered. */ - getAll() { - return [...this.actions.values()]; + getAll: () => SavedObjectsManagementAction[]; +} + +export class SavedObjectsManagementActionService { + private readonly actions = new Map<string, SavedObjectsManagementAction>(); + + setup(): SavedObjectsManagementActionServiceSetup { + return { + register: action => { + if (this.actions.has(action.id)) { + throw new Error(`Saved Objects Management Action with id '${action.id}' already exists`); + } + this.actions.set(action.id, action); + }, + }; + } + + start(): SavedObjectsManagementActionServiceStart { + return { + has: actionId => this.actions.has(actionId), + getAll: () => [...this.actions.values()], + }; } } diff --git a/src/plugins/saved_objects_management/public/services/index.ts b/src/plugins/saved_objects_management/public/services/index.ts index d6353576b8e11..a59ad9012c402 100644 --- a/src/plugins/saved_objects_management/public/services/index.ts +++ b/src/plugins/saved_objects_management/public/services/index.ts @@ -18,7 +18,13 @@ */ export { - SavedObjectsManagementActionRegistry, - ISavedObjectsManagementActionRegistry, -} from './action_registry'; -export { SavedObjectsManagementAction, SavedObjectsManagementRecord } from './action_types'; + SavedObjectsManagementActionService, + SavedObjectsManagementActionServiceStart, + SavedObjectsManagementActionServiceSetup, +} from './action_service'; +export { + SavedObjectsManagementServiceRegistry, + ISavedObjectsManagementServiceRegistry, + SavedObjectsManagementServiceRegistryEntry, +} from './service_registry'; +export { SavedObjectsManagementAction, SavedObjectsManagementRecord } from './types'; diff --git a/src/plugins/saved_objects_management/public/services/action_registry.mock.ts b/src/plugins/saved_objects_management/public/services/service_registry.mock.ts similarity index 79% rename from src/plugins/saved_objects_management/public/services/action_registry.mock.ts rename to src/plugins/saved_objects_management/public/services/service_registry.mock.ts index a9093ad42d0ac..2e671c781928f 100644 --- a/src/plugins/saved_objects_management/public/services/action_registry.mock.ts +++ b/src/plugins/saved_objects_management/public/services/service_registry.mock.ts @@ -17,21 +17,20 @@ * under the License. */ -import { ISavedObjectsManagementActionRegistry } from './action_registry'; +import { ISavedObjectsManagementServiceRegistry } from './service_registry'; -const createRegistryMock = (): jest.Mocked<ISavedObjectsManagementActionRegistry> => { +const createRegistryMock = (): jest.Mocked<ISavedObjectsManagementServiceRegistry> => { const mock = { register: jest.fn(), - has: jest.fn(), - getAll: jest.fn(), + all: jest.fn(), + get: jest.fn(), }; - mock.has.mockReturnValue(true); - mock.getAll.mockReturnValue([]); + mock.all.mockReturnValue([]); return mock; }; -export const actionRegistryMock = { +export const serviceRegistryMock = { create: createRegistryMock, }; diff --git a/src/plugins/saved_objects_management/public/services/service_registry.ts b/src/plugins/saved_objects_management/public/services/service_registry.ts new file mode 100644 index 0000000000000..2d6ec0b92047a --- /dev/null +++ b/src/plugins/saved_objects_management/public/services/service_registry.ts @@ -0,0 +1,49 @@ +/* + * 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 { SavedObjectLoader } from '../../../saved_objects/public'; + +export interface SavedObjectsManagementServiceRegistryEntry { + id: string; + service: SavedObjectLoader; + title: string; +} + +export type ISavedObjectsManagementServiceRegistry = PublicMethodsOf< + SavedObjectsManagementServiceRegistry +>; + +export class SavedObjectsManagementServiceRegistry { + private readonly registry = new Map<string, SavedObjectsManagementServiceRegistryEntry>(); + + public register(entry: SavedObjectsManagementServiceRegistryEntry) { + if (this.registry.has(entry.id)) { + throw new Error(''); + } + this.registry.set(entry.id, entry); + } + + public all(): SavedObjectsManagementServiceRegistryEntry[] { + return [...this.registry.values()]; + } + + public get(id: string): SavedObjectsManagementServiceRegistryEntry | undefined { + return this.registry.get(id); + } +} diff --git a/src/plugins/saved_objects_management/public/services/action_types.ts b/src/plugins/saved_objects_management/public/services/types.ts similarity index 100% rename from src/plugins/saved_objects_management/public/services/action_types.ts rename to src/plugins/saved_objects_management/public/services/types.ts diff --git a/src/plugins/saved_objects_management/public/types.ts b/src/plugins/saved_objects_management/public/types.ts new file mode 100644 index 0000000000000..e91b5d253b55f --- /dev/null +++ b/src/plugins/saved_objects_management/public/types.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 { SavedObjectMetadata, SavedObjectWithMetadata, SavedObjectRelation } from '../common'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/index.js b/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts similarity index 61% rename from src/legacy/core_plugins/kibana/public/management/sections/objects/index.js rename to src/plugins/saved_objects_management/server/routes/get_allowed_types.ts index 3965c42ac088d..ab5bec6678946 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/objects/index.js +++ b/src/plugins/saved_objects_management/server/routes/get_allowed_types.ts @@ -17,20 +17,24 @@ * under the License. */ -import { i18n } from '@kbn/i18n'; -import { management } from 'ui/management'; -import './_view'; -import './_objects'; -import 'ace'; -import { uiModules } from 'ui/modules'; +import { IRouter } from 'src/core/server'; -// add the module deps to this module -uiModules.get('apps/management'); +export const registerGetAllowedTypesRoute = (router: IRouter) => { + router.get( + { + path: '/api/kibana/management/saved_objects/_allowed_types', + validate: false, + }, + async (context, req, res) => { + const allowedTypes = context.core.savedObjects.typeRegistry + .getImportableAndExportableTypes() + .map(type => type.name); -management.getSection('kibana').register('objects', { - display: i18n.translate('kbn.management.objects.savedObjectsSectionLabel', { - defaultMessage: 'Saved Objects', - }), - order: 10, - url: '#/management/kibana/objects', -}); + return res.ok({ + body: { + types: allowedTypes, + }, + }); + } + ); +}; diff --git a/src/plugins/saved_objects_management/server/routes/index.test.ts b/src/plugins/saved_objects_management/server/routes/index.test.ts index f183972953dce..237760444f04e 100644 --- a/src/plugins/saved_objects_management/server/routes/index.test.ts +++ b/src/plugins/saved_objects_management/server/routes/index.test.ts @@ -34,7 +34,7 @@ describe('registerRoutes', () => { }); expect(httpSetup.createRouter).toHaveBeenCalledTimes(1); - expect(router.get).toHaveBeenCalledTimes(2); + expect(router.get).toHaveBeenCalledTimes(3); expect(router.post).toHaveBeenCalledTimes(2); expect(router.get).toHaveBeenCalledWith( @@ -49,6 +49,12 @@ describe('registerRoutes', () => { }), expect.any(Function) ); + expect(router.get).toHaveBeenCalledWith( + expect.objectContaining({ + path: '/api/kibana/management/saved_objects/_allowed_types', + }), + expect.any(Function) + ); expect(router.post).toHaveBeenCalledWith( expect.objectContaining({ path: '/api/kibana/management/saved_objects/scroll/counts', diff --git a/src/plugins/saved_objects_management/server/routes/index.ts b/src/plugins/saved_objects_management/server/routes/index.ts index 2c6adb71ed3ce..0929de56b215e 100644 --- a/src/plugins/saved_objects_management/server/routes/index.ts +++ b/src/plugins/saved_objects_management/server/routes/index.ts @@ -23,6 +23,7 @@ import { registerFindRoute } from './find'; import { registerScrollForCountRoute } from './scroll_count'; import { registerScrollForExportRoute } from './scroll_export'; import { registerRelationshipsRoute } from './relationships'; +import { registerGetAllowedTypesRoute } from './get_allowed_types'; interface RegisterRouteOptions { http: HttpServiceSetup; @@ -35,4 +36,5 @@ export function registerRoutes({ http, managementServicePromise }: RegisterRoute registerScrollForCountRoute(router); registerScrollForExportRoute(router); registerRelationshipsRoute(router, managementServicePromise); + registerGetAllowedTypesRoute(router); } diff --git a/src/plugins/saved_objects_management/server/types.ts b/src/plugins/saved_objects_management/server/types.ts index 5c4763d357e87..bd17d6a19ae70 100644 --- a/src/plugins/saved_objects_management/server/types.ts +++ b/src/plugins/saved_objects_management/server/types.ts @@ -17,38 +17,10 @@ * under the License. */ -import { SavedObject } from 'src/core/server'; - // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SavedObjectsManagementPluginSetup {} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SavedObjectsManagementPluginStart {} -/** - * The metadata injected into a {@link SavedObject | saved object} when returning - * {@link SavedObjectWithMetadata | enhanced objects} from the plugin API endpoints. - */ -export interface SavedObjectMetadata { - icon?: string; - title?: string; - editUrl?: string; - inAppUrl?: { path: string; uiCapabilitiesPath: string }; -} - -/** - * A {@link SavedObject | saved object} enhanced with meta properties used by the client-side plugin. - */ -export type SavedObjectWithMetadata<T = unknown> = SavedObject<T> & { - meta: SavedObjectMetadata; -}; - -/** - * Represents a relation between two {@link SavedObject | saved object} - */ -export interface SavedObjectRelation { - id: string; - type: string; - relationship: 'child' | 'parent'; - meta: SavedObjectMetadata; -} +export { SavedObjectMetadata, SavedObjectWithMetadata, SavedObjectRelation } from '../common'; diff --git a/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.test.ts b/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.test.ts index 7d680f0ee0ed6..4e61756d933c9 100644 --- a/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.test.ts +++ b/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.test.ts @@ -22,8 +22,8 @@ describe('CopySavedObjectsToSpaceService', () => { const service = new CopySavedObjectsToSpaceService(); service.setup(deps); - expect(deps.savedObjectsManagementSetup.actionRegistry.register).toHaveBeenCalledTimes(1); - expect(deps.savedObjectsManagementSetup.actionRegistry.register).toHaveBeenCalledWith( + expect(deps.savedObjectsManagementSetup.actions.register).toHaveBeenCalledTimes(1); + expect(deps.savedObjectsManagementSetup.actions.register).toHaveBeenCalledWith( expect.any(CopyToSpaceSavedObjectsManagementAction) ); }); diff --git a/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.ts b/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.ts index d564514beebff..93d0f92744d41 100644 --- a/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.ts +++ b/x-pack/plugins/spaces/public/copy_saved_objects_to_space/copy_saved_objects_to_space_service.ts @@ -18,6 +18,6 @@ interface SetupDeps { export class CopySavedObjectsToSpaceService { public setup({ spacesManager, savedObjectsManagementSetup, notificationsSetup }: SetupDeps) { const action = new CopyToSpaceSavedObjectsManagementAction(spacesManager, notificationsSetup); - savedObjectsManagementSetup.actionRegistry.register(action); + savedObjectsManagementSetup.actions.register(action); } } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index fe0c58e83e544..e579830bad203 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2011,7 +2011,6 @@ "kbn.dashboard.listing.table.descriptionColumnName": "説明", "kbn.dashboard.panel.unableToMigratePanelDataForSixOneZeroErrorMessage": "「6.1.0」のダッシュボードの互換性のため、パネルデータを移行できませんでした。パネルには想定された列または行フィールドがありません", "kbn.dashboard.panel.unableToMigratePanelDataForSixThreeZeroErrorMessage": "「6.3.0」のダッシュボードの互換性のため、パネルデータを移行できませんでした。パネルに必要なフィールドがありません: {key}", - "kbn.dashboard.savedDashboardsTitle": "ダッシュボード", "kbn.dashboardTitle": "ダッシュボード", "kbn.devToolsTitle": "開発ツール", "kbn.discover.backToTopLinkText": "最上部へ戻る。", @@ -2281,9 +2280,6 @@ "kbn.management.editIndexPattern.timeFilterLabel.mappingAPILink": "マッピング API", "kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail": "このページは {indexPatternTitle} インデックス内のすべてのフィールドと、Elasticsearch に記録された各フィールドのコアタイプを一覧表示します。フィールドタイプを変更するには Elasticsearch を使用します", "kbn.management.editIndexPatternLiveRegionAriaLabel": "インデックスパターン", - "kbn.management.indexPattern.confirmOverwriteButton": "上書き", - "kbn.management.indexPattern.confirmOverwriteLabel": "「{title}」に上書きしてよろしいですか?", - "kbn.management.indexPattern.confirmOverwriteTitle": "{type} を上書きしますか?", "kbn.management.indexPattern.goToPatternButtonLabel": "既存のパターンに移動", "kbn.management.indexPattern.sectionsHeader": "インデックスパターン", "kbn.management.indexPattern.titleExistsLabel": "「{title}」というタイトルのインデックスパターンが既に存在します。", @@ -2306,125 +2302,128 @@ "kbn.management.indexPatternTable.title": "インデックスパターン", "kbn.management.landing.header": "Kibana {version} 管理", "kbn.management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibana の設定、その他を管理します。", - "kbn.management.landing.text": "アプリの一覧は左側のメニューにあります。", - "kbn.management.objects.confirmModalOptions.deleteButtonLabel": "削除", - "kbn.management.objects.confirmModalOptions.modalDescription": "このアクションはオブジェクトを Kibana から永久に削除します。", - "kbn.management.objects.confirmModalOptions.modalTitle": "「{title}」を削除しますか?", - "kbn.management.objects.deleteSavedObjectsConfirmModalDescription": "この操作は次の保存されたオブジェクトを削除します:", - "kbn.management.objects.field.offLabel": "オフ", - "kbn.management.objects.field.onLabel": "オン", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel": "キャンセル", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel": "削除", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.deleteProcessButtonLabel": "削除中…", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.idColumnName": "ID", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "タイトル", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "タイプ", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModalTitle": "保存されたオブジェクトの削除", - "kbn.management.objects.objectsTable.export.dangerNotification": "エクスポートを生成できません", - "kbn.management.objects.objectsTable.export.successNotification": "ファイルはバックグラウンドでダウンロード中です", - "kbn.management.objects.objectsTable.export.successWithMissingRefsNotification": "ファイルはバックグラウンドでダウンロード中です。一部の関連オブジェクトが見つかりませんでした。足りないオブジェクトの一覧は、エクスポートされたファイルの最後の行をご覧ください。", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.cancelButtonLabel": "キャンセル", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel": "すべてエクスポート:", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportOptionsLabel": "オプション", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "関連オブジェクトを含める", - "kbn.management.objects.objectsTable.exportObjectsConfirmModalDescription": "エクスポートするタイプを選択してください", - "kbn.management.objects.objectsTable.exportObjectsConfirmModalTitle": "{filteredItemCount, plural, one{# オブジェクト} other {# オブジェクト}}をエクスポート", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage": "矛盾を解決中…", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage": "失敗したオブジェクトを再試行中…", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage": "保存された検索が正しくリンクされていることを確認してください…", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage": "矛盾を保存中…", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteBody": "{title} を上書きしてよろしいですか?", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteCancelButtonText": "キャンセル", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteOverwriteButtonText": "上書き", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteTitle": "{type} を上書きしますか?", - "kbn.management.objects.objectsTable.flyout.errorCalloutTitle": "申し訳ございませんが、エラーが発生しました", - "kbn.management.objects.objectsTable.flyout.import.cancelButtonLabel": "キャンセル", - "kbn.management.objects.objectsTable.flyout.import.confirmButtonLabel": "インポート", - "kbn.management.objects.objectsTable.flyout.importFailedDescription": "{totalImportCount} 個中 {failedImportCount} 個のオブジェクトのインポートに失敗しました。インポート失敗", - "kbn.management.objects.objectsTable.flyout.importFailedMissingReference": "{type} [id={id}] は {refType} [id={refId}] を見つけられませんでした", - "kbn.management.objects.objectsTable.flyout.importFailedTitle": "インポート失敗", - "kbn.management.objects.objectsTable.flyout.importFailedUnsupportedType": "{type} [id={id}] サポートされていないタイプ", - "kbn.management.objects.objectsTable.flyout.importFileErrorMessage": "ファイルを処理できませんでした。", - "kbn.management.objects.objectsTable.flyout.importLegacyFileErrorMessage": "ファイルを処理できませんでした。", - "kbn.management.objects.objectsTable.flyout.importPromptText": "インポート", - "kbn.management.objects.objectsTable.flyout.importSavedObjectTitle": "保存されたオブジェクトのインポート", - "kbn.management.objects.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "すべての変更を確定", - "kbn.management.objects.objectsTable.flyout.importSuccessful.confirmButtonLabel": "完了", - "kbn.management.objects.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle": "オブジェクトがインポートされませんでした", - "kbn.management.objects.objectsTable.flyout.importSuccessfulDescription": "{importCount} 個のオブジェクトがインポートされました。", - "kbn.management.objects.objectsTable.flyout.importSuccessfulTitle": "インポート成功", - "kbn.management.objects.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "新規インデックスパターンを作成", - "kbn.management.objects.objectsTable.flyout.indexPatternConflictsDescription": "次の保存されたオブジェクトは、存在しないインデックスパターンを使用しています。別のデックスパターンを選択してください。必要に応じて {indexPatternLink} できます。", - "kbn.management.objects.objectsTable.flyout.indexPatternConflictsTitle": "インデックスパターンの矛盾", - "kbn.management.objects.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage": "保存されたオブジェクトのファイル形式が無効なため、インポートできません。", - "kbn.management.objects.objectsTable.flyout.legacyFileUsedBody": "最新のレポートで NDJSON ファイルを作成すれば完了です。", - "kbn.management.objects.objectsTable.flyout.legacyFileUsedTitle": "JSON ファイルのサポートが終了します", - "kbn.management.objects.objectsTable.flyout.overwriteSavedObjectsLabel": "すべての保存されたオブジェクトを自動的に上書きしますか?", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnCountDescription": "影響されるオブジェクトの数です", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnCountName": "カウント", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnIdDescription": "インデックスパターンの ID です", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnIdName": "ID", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnNewIndexPatternName": "新規インデックスパターン", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription": "影響されるオブジェクトのサンプルです", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName": "影響されるオブジェクトのサンプル", - "kbn.management.objects.objectsTable.flyout.resolveImportErrorsFileErrorMessage": "ファイルを処理できませんでした。", - "kbn.management.objects.objectsTable.flyout.selectFileToImportFormRowLabel": "インポートするファイルを選択してください", - "kbn.management.objects.objectsTable.header.exportButtonLabel": "{filteredCount, plural, one{# オブジェクト} other {# オブジェクト}}をエクスポート", - "kbn.management.objects.objectsTable.header.importButtonLabel": "インポート", - "kbn.management.objects.objectsTable.header.refreshButtonLabel": "更新", - "kbn.management.objects.objectsTable.header.savedObjectsTitle": "保存されたオブジェクト", - "kbn.management.objects.objectsTable.howToDeleteSavedObjectsDescription": "ここから保存された検索などの保存されたオブジェクトを削除できます。保存されたオブジェクトの生データを編集することもできます。通常、オブジェクトは関連アプリケーションでのみ編集され、こn画面で編集するよりもそちらのほうが賢明です。", - "kbn.management.objects.objectsTable.relationships.columnActions.inspectActionDescription": "この保存されたオブジェクトを確認してください", - "kbn.management.objects.objectsTable.relationships.columnActions.inspectActionName": "検査", - "kbn.management.objects.objectsTable.relationships.columnActionsName": "アクション", - "kbn.management.objects.objectsTable.relationships.columnRelationship.childAsValue": "子", - "kbn.management.objects.objectsTable.relationships.columnRelationship.parentAsValue": "ペアレント", - "kbn.management.objects.objectsTable.relationships.columnRelationshipName": "直接関係", - "kbn.management.objects.objectsTable.relationships.columnTitleDescription": "保存されたオブジェクトのタイトルです", - "kbn.management.objects.objectsTable.relationships.columnTitleName": "タイトル", - "kbn.management.objects.objectsTable.relationships.columnTypeDescription": "保存されたオブジェクトのタイプです", - "kbn.management.objects.objectsTable.relationships.columnTypeName": "タイプ", - "kbn.management.objects.objectsTable.relationships.relationshipsTitle": "{title} に関連する保存されたオブジェクトはこちらです。この {type} を削除すると、親オブジェクトに影響がありますが、子オブジェクトには影響はありません。", - "kbn.management.objects.objectsTable.relationships.renderErrorMessage": "エラー", - "kbn.management.objects.objectsTable.relationships.search.filters.relationship.childAsValue.view": "子", - "kbn.management.objects.objectsTable.relationships.search.filters.relationship.name": "直接関係", - "kbn.management.objects.objectsTable.relationships.search.filters.relationship.parentAsValue.view": "親", - "kbn.management.objects.objectsTable.relationships.search.filters.type.name": "タイプ", - "kbn.management.objects.objectsTable.searchBar.unableToParseQueryErrorMessage": "クエリをパースできません", - "kbn.management.objects.objectsTable.table.columnActions.inspectActionDescription": "この保存されたオブジェクトを確認してください", - "kbn.management.objects.objectsTable.table.columnActions.inspectActionName": "検査", - "kbn.management.objects.objectsTable.table.columnActions.viewRelationshipsActionDescription": "この保存されたオブジェクトと他の保存されたオブジェクトとの関係性を表示します", - "kbn.management.objects.objectsTable.table.columnActions.viewRelationshipsActionName": "関係性", - "kbn.management.objects.objectsTable.table.columnActionsName": "アクション", - "kbn.management.objects.objectsTable.table.columnTitleDescription": "保存されたオブジェクトのタイトルです", - "kbn.management.objects.objectsTable.table.columnTitleName": "タイトル", - "kbn.management.objects.objectsTable.table.columnTypeDescription": "保存されたオブジェクトのタイプです", - "kbn.management.objects.objectsTable.table.columnTypeName": "タイプ", - "kbn.management.objects.objectsTable.table.deleteButtonLabel": "削除", - "kbn.management.objects.objectsTable.table.deleteButtonTitle": "保存されたオブジェクトを削除できません", - "kbn.management.objects.objectsTable.table.exportButtonLabel": "エクスポート", - "kbn.management.objects.objectsTable.table.exportPopoverButtonLabel": "エクスポート", - "kbn.management.objects.objectsTable.table.typeFilterName": "タイプ", - "kbn.management.objects.objectsTable.unableFindSavedObjectsNotificationMessage": "保存されたオブジェクトが見つかりません", - "kbn.management.objects.parsingFieldErrorMessage": "{fieldName} をインデックスパターン {indexName} 用にパース中にエラーが発生しました: {errorMessage}", - "kbn.management.objects.savedObjectsSectionLabel": "保存されたオブジェクト", - "kbn.management.objects.view.cancelButtonAriaLabel": "キャンセル", - "kbn.management.objects.view.cancelButtonLabel": "キャンセル", - "kbn.management.objects.view.deleteItemButtonLabel": "{title} を削除", - "kbn.management.objects.view.editItemTitle": "{title} の編集", - "kbn.management.objects.view.fieldDoesNotExistErrorMessage": "このオブジェクトに関連付けられたフィールドは、現在このインデックスパターンに存在しません。", - "kbn.management.objects.view.howToFixErrorDescription": "このエラーの原因がわかる場合は修正してください。わからない場合は上の削除ボタンをクリックしてください。", - "kbn.management.objects.view.howToModifyObjectDescription": "オブジェクトの編集は上級ユーザー向けです。オブジェクトのプロパティが検証されておらず、無効なオブジェクトはエラー、データ損失、またはそれ以上の問題の原因となります。コードを熟知した人に指示されていない限り、この設定は変更しない方が無難です。", - "kbn.management.objects.view.howToModifyObjectTitle": "十分ご注意ください!", - "kbn.management.objects.view.indexPatternDoesNotExistErrorMessage": "このオブジェクトに関連付けられたインデックスパターンは現在存在しません。", - "kbn.management.objects.view.saveButtonAriaLabel": "{ title } オブジェクトを保存", - "kbn.management.objects.view.saveButtonLabel": "{ title } オブジェクトを保存", - "kbn.management.objects.view.savedObjectProblemErrorMessage": "この保存されたオブジェクトに問題があります", - "kbn.management.objects.view.savedSearchDoesNotExistErrorMessage": "このオブジェクトに関連付けられた保存された検索は現在存在しません。", - "kbn.management.objects.view.viewItemButtonLabel": "{title} を表示", - "kbn.management.objects.view.viewItemTitle": "{title} を表示", - "kbn.management.savedObjects.editBreadcrumb": "{savedObjectType} を編集", - "kbn.management.savedObjects.indexBreadcrumb": "保存されたオブジェクト", + "kbn.management.landing.text": "すべてのツールの一覧は、左のメニューにあります。", + "savedObjectsManagement.indexPattern.confirmOverwriteButton": "上書き", + "savedObjectsManagement.indexPattern.confirmOverwriteLabel": "「{title}」に上書きしてよろしいですか?", + "savedObjectsManagement.indexPattern.confirmOverwriteTitle": "{type} を上書きしますか?", + "savedObjectsManagement.deleteConfirm.modalDeleteButtonLabel": "削除", + "savedObjectsManagement.deleteConfirm.modalDescription": "このアクションはオブジェクトを Kibana から永久に削除します。", + "savedObjectsManagement.deleteConfirm.modalTitle": "「{title}」を削除しますか?", + "savedObjectsManagement.deleteSavedObjectsConfirmModalDescription": "この操作は次の保存されたオブジェクトを削除します:", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel": "キャンセル", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel": "削除", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteProcessButtonLabel": "削除中…", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.idColumnName": "ID", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "タイトル", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "タイプ", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle": "保存されたオブジェクトの削除", + "savedObjectsManagement.objectsTable.export.dangerNotification": "エクスポートを生成できません", + "savedObjectsManagement.objectsTable.export.successNotification": "ファイルはバックグラウンドでダウンロード中です", + "savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification": "ファイルはバックグラウンドでダウンロード中です。一部の関連オブジェクトが見つかりませんでした。足りないオブジェクトの一覧は、エクスポートされたファイルの最後の行をご覧ください。", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.cancelButtonLabel": "キャンセル", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel": "すべてエクスポート:", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel": "オプション", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "関連オブジェクトを含める", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription": "エクスポートするタイプを選択してください", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModalTitle": "{filteredItemCount, plural, one{# オブジェクト} other {# オブジェクト}}をエクスポート", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage": "矛盾を解決中…", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage": "失敗したオブジェクトを再試行中…", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage": "保存された検索が正しくリンクされていることを確認してください…", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage": "矛盾を保存中…", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteBody": "{title} を上書きしてよろしいですか?", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteCancelButtonText": "キャンセル", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteOverwriteButtonText": "上書き", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteTitle": "{type} を上書きしますか?", + "savedObjectsManagement.objectsTable.flyout.errorCalloutTitle": "申し訳ございませんが、エラーが発生しました", + "savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel": "キャンセル", + "savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel": "インポート", + "savedObjectsManagement.objectsTable.flyout.importFailedDescription": "{totalImportCount} 個中 {failedImportCount} 個のオブジェクトのインポートに失敗しました。インポート失敗", + "savedObjectsManagement.objectsTable.flyout.importFailedMissingReference": "{type} [id={id}] は {refType} [id={refId}] を見つけられませんでした", + "savedObjectsManagement.objectsTable.flyout.importFailedTitle": "インポート失敗", + "savedObjectsManagement.objectsTable.flyout.importFailedUnsupportedType": "{type} [id={id}] サポートされていないタイプ", + "savedObjectsManagement.objectsTable.flyout.importFileErrorMessage": "ファイルを処理できませんでした。", + "savedObjectsManagement.objectsTable.flyout.importLegacyFileErrorMessage": "ファイルを処理できませんでした。", + "savedObjectsManagement.objectsTable.flyout.importPromptText": "インポート", + "savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle": "保存されたオブジェクトのインポート", + "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "すべての変更を確定", + "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmButtonLabel": "完了", + "savedObjectsManagement.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle": "オブジェクトがインポートされませんでした", + "savedObjectsManagement.objectsTable.flyout.importSuccessfulDescription": "{importCount} 個のオブジェクトがインポートされました。", + "savedObjectsManagement.objectsTable.flyout.importSuccessfulTitle": "インポート成功", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "新規インデックスパターンを作成", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription": "次の保存されたオブジェクトは、存在しないインデックスパターンを使用しています。別のデックスパターンを選択してください。必要に応じて {indexPatternLink} できます。", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle": "インデックスパターンの矛盾", + "savedObjectsManagement.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage": "保存されたオブジェクトのファイル形式が無効なため、インポートできません。", + "savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody": "最新のレポートで NDJSON ファイルを作成すれば完了です。", + "savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle": "JSON ファイルのサポートが終了します", + "savedObjectsManagement.objectsTable.flyout.overwriteSavedObjectsLabel": "すべての保存されたオブジェクトを自動的に上書きしますか?", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountDescription": "影響されるオブジェクトの数です", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountName": "カウント", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdDescription": "インデックスパターンの ID です", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdName": "ID", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnNewIndexPatternName": "新規インデックスパターン", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription": "影響されるオブジェクトのサンプルです", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName": "影響されるオブジェクトのサンプル", + "savedObjectsManagement.objectsTable.flyout.resolveImportErrorsFileErrorMessage": "ファイルを処理できませんでした。", + "savedObjectsManagement.objectsTable.flyout.selectFileToImportFormRowLabel": "インポートするファイルを選択してください", + "savedObjectsManagement.objectsTable.header.exportButtonLabel": "{filteredCount, plural, one{# オブジェクト} other {# オブジェクト}}をエクスポート", + "savedObjectsManagement.objectsTable.header.importButtonLabel": "インポート", + "savedObjectsManagement.objectsTable.header.refreshButtonLabel": "更新", + "savedObjectsManagement.objectsTable.header.savedObjectsTitle": "保存されたオブジェクト", + "savedObjectsManagement.objectsTable.howToDeleteSavedObjectsDescription": "ここから保存された検索などの保存されたオブジェクトを削除できます。保存されたオブジェクトの生データを編集することもできます。通常、オブジェクトは関連アプリケーションでのみ編集され、こn画面で編集するよりもそちらのほうが賢明です。", + "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionDescription": "この保存されたオブジェクトを確認してください", + "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionName": "検査", + "savedObjectsManagement.objectsTable.relationships.columnActionsName": "アクション", + "savedObjectsManagement.objectsTable.relationships.columnRelationship.childAsValue": "子", + "savedObjectsManagement.objectsTable.relationships.columnRelationship.parentAsValue": "ペアレント", + "savedObjectsManagement.objectsTable.relationships.columnRelationshipName": "直接関係", + "savedObjectsManagement.objectsTable.relationships.columnTitleDescription": "保存されたオブジェクトのタイトルです", + "savedObjectsManagement.objectsTable.relationships.columnTitleName": "タイトル", + "savedObjectsManagement.objectsTable.relationships.columnTypeDescription": "保存されたオブジェクトのタイプです", + "savedObjectsManagement.objectsTable.relationships.columnTypeName": "タイプ", + "savedObjectsManagement.objectsTable.relationships.relationshipsTitle": "{title} に関連する保存されたオブジェクトはこちらです。この {type} を削除すると、親オブジェクトに影響がありますが、子オブジェクトには影響はありません。", + "savedObjectsManagement.objectsTable.relationships.renderErrorMessage": "エラー", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.childAsValue.view": "子", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.name": "直接関係", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.parentAsValue.view": "親", + "savedObjectsManagement.objectsTable.relationships.search.filters.type.name": "タイプ", + "savedObjectsManagement.objectsTable.searchBar.unableToParseQueryErrorMessage": "クエリをパースできません", + "savedObjectsManagement.objectsTable.table.columnActions.inspectActionDescription": "この保存されたオブジェクトを確認してください", + "savedObjectsManagement.objectsTable.table.columnActions.inspectActionName": "検査", + "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionDescription": "この保存されたオブジェクトと他の保存されたオブジェクトとの関係性を表示します", + "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionName": "関係性", + "savedObjectsManagement.objectsTable.table.columnActionsName": "アクション", + "savedObjectsManagement.objectsTable.table.columnTitleDescription": "保存されたオブジェクトのタイトルです", + "savedObjectsManagement.objectsTable.table.columnTitleName": "タイトル", + "savedObjectsManagement.objectsTable.table.columnTypeDescription": "保存されたオブジェクトのタイプです", + "savedObjectsManagement.objectsTable.table.columnTypeName": "タイプ", + "savedObjectsManagement.objectsTable.table.deleteButtonLabel": "削除", + "savedObjectsManagement.objectsTable.table.deleteButtonTitle": "保存されたオブジェクトを削除できません", + "savedObjectsManagement.objectsTable.table.exportButtonLabel": "エクスポート", + "savedObjectsManagement.objectsTable.table.exportPopoverButtonLabel": "エクスポート", + "savedObjectsManagement.objectsTable.table.typeFilterName": "タイプ", + "savedObjectsManagement.objectsTable.unableFindSavedObjectsNotificationMessage": "保存されたオブジェクトが見つかりません", + "savedObjectsManagement.parsingFieldErrorMessage": "{fieldName} をインデックスパターン {indexName} 用にパース中にエラーが発生しました: {errorMessage}", + "savedObjectsManagement.managementSectionLabel": "保存されたオブジェクト", + "savedObjectsManagement.view.cancelButtonAriaLabel": "キャンセル", + "savedObjectsManagement.view.cancelButtonLabel": "キャンセル", + "savedObjectsManagement.view.deleteItemButtonLabel": "{title} を削除", + "savedObjectsManagement.view.editItemTitle": "{title} の編集", + "savedObjectsManagement.view.fieldDoesNotExistErrorMessage": "このオブジェクトに関連付けられたフィールドは、現在このインデックスパターンに存在しません。", + "savedObjectsManagement.view.howToFixErrorDescription": "このエラーの原因がわかる場合は修正してください。わからない場合は上の削除ボタンをクリックしてください。", + "savedObjectsManagement.view.howToModifyObjectDescription": " オブジェクトの編集は上級ユーザー向けです。オブジェクトのプロパティが検証されておらず、無効なオブジェクトはエラー、データ損失、またはそれ以上の問題の原因となります。コードを熟知した人に指示されていない限り、この設定は変更しない方が無難です。", + "savedObjectsManagement.view.howToModifyObjectTitle": "十分ご注意ください!", + "savedObjectsManagement.view.indexPatternDoesNotExistErrorMessage": "このオブジェクトに関連付けられたインデックスパターンは現在存在しません。", + "savedObjectsManagement.view.saveButtonAriaLabel": "{ title } オブジェクトを保存", + "savedObjectsManagement.view.saveButtonLabel": "{ title } オブジェクトを保存", + "savedObjectsManagement.view.savedObjectProblemErrorMessage": "この保存されたオブジェクトに問題があります", + "savedObjectsManagement.view.savedSearchDoesNotExistErrorMessage": "このオブジェクトに関連付けられた保存された検索は現在存在しません。", + "savedObjectsManagement.view.viewItemButtonLabel": "{title} を表示", + "savedObjectsManagement.view.viewItemTitle": "{title} を表示", + "savedObjectsManagement.breadcrumb.edit": "{savedObjectType} を編集", + "savedObjectsManagement.breadcrumb.index": "保存されたオブジェクト", + "savedObjectsManagement.field.offLabel": "オフ", + "savedObjectsManagement.field.onLabel": "オン", "kbn.managementTitle": "管理", "kbn.topNavMenu.openInspectorButtonLabel": "検査", "kbn.topNavMenu.refreshButtonLabel": "更新", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index fd2a92c2c402f..75f48fb11823a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2012,7 +2012,6 @@ "kbn.dashboard.listing.table.descriptionColumnName": "描述", "kbn.dashboard.panel.unableToMigratePanelDataForSixOneZeroErrorMessage": "无法迁移用于“6.1.0”向后兼容的面板数据,面板不包含所需的列和/或行字段", "kbn.dashboard.panel.unableToMigratePanelDataForSixThreeZeroErrorMessage": "无法迁移用于“6.3.0”向后兼容的面板数据,面板不包含预期字段:{key}", - "kbn.dashboard.savedDashboardsTitle": "仪表板", "kbn.dashboardTitle": "仪表板", "kbn.devToolsTitle": "开发工具", "kbn.discover.backToTopLinkText": "返至顶部。", @@ -2282,9 +2281,6 @@ "kbn.management.editIndexPattern.timeFilterLabel.mappingAPILink": "映射 API", "kbn.management.editIndexPattern.timeFilterLabel.timeFilterDetail": "此页根据 Elasticsearch 的记录列出“{indexPatternTitle}”索引中的每个字段以及字段的关联核心类型。要更改字段类型,请使用 Elasticsearch", "kbn.management.editIndexPatternLiveRegionAriaLabel": "索引模式", - "kbn.management.indexPattern.confirmOverwriteButton": "覆盖", - "kbn.management.indexPattern.confirmOverwriteLabel": "确定要覆盖 “{title}”?", - "kbn.management.indexPattern.confirmOverwriteTitle": "覆盖“{type}”?", "kbn.management.indexPattern.goToPatternButtonLabel": "前往现有模式", "kbn.management.indexPattern.sectionsHeader": "索引模式", "kbn.management.indexPattern.titleExistsLabel": "具有标题 “{title}” 的索引模式已存在。", @@ -2308,124 +2304,127 @@ "kbn.management.landing.header": "Kibana {version} 管理", "kbn.management.landing.subhead": "管理您的索引、索引模式、已保存对象、Kibana 设置等等。", "kbn.management.landing.text": "应用的完整列表位于左侧菜单中。", - "kbn.management.objects.confirmModalOptions.deleteButtonLabel": "删除", - "kbn.management.objects.confirmModalOptions.modalDescription": "此操作会将对象从 Kibana 永久移除。", - "kbn.management.objects.confirmModalOptions.modalTitle": "删除“{title}”?", - "kbn.management.objects.deleteSavedObjectsConfirmModalDescription": "此操作将删除以下已保存对象:", - "kbn.management.objects.field.offLabel": "关闭", - "kbn.management.objects.field.onLabel": "开启", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel": "取消", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel": "删除", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.deleteProcessButtonLabel": "正在删除……", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.idColumnName": "ID", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "标题", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "类型", - "kbn.management.objects.objectsTable.deleteSavedObjectsConfirmModalTitle": "删除已保存对象", - "kbn.management.objects.objectsTable.export.dangerNotification": "无法生成报告", - "kbn.management.objects.objectsTable.export.successNotification": "您的文件正在后台下载", - "kbn.management.objects.objectsTable.export.successWithMissingRefsNotification": "您的文件正在后台下载。找不到某些相关对象。有关缺失对象列表,请查看导出文件的最后一行。", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.cancelButtonLabel": "取消", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel": "全部导出", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.exportOptionsLabel": "选项", - "kbn.management.objects.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "包括相关对象", - "kbn.management.objects.objectsTable.exportObjectsConfirmModalDescription": "选择要导出的类型。", - "kbn.management.objects.objectsTable.exportObjectsConfirmModalTitle": "导出 {filteredItemCount, plural, one{# 个对象} other {# 个对象}}", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage": "正在解决冲突……", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage": "正在重试失败的对象……", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage": "确保已保存搜索已正确链接……", - "kbn.management.objects.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage": "正在保存冲突……", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteBody": "确定要覆盖 “{title}”?", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteCancelButtonText": "取消", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteOverwriteButtonText": "覆盖", - "kbn.management.objects.objectsTable.flyout.confirmOverwriteTitle": "覆盖“{type}”?", - "kbn.management.objects.objectsTable.flyout.errorCalloutTitle": "抱歉,出现了错误", - "kbn.management.objects.objectsTable.flyout.import.cancelButtonLabel": "取消", - "kbn.management.objects.objectsTable.flyout.import.confirmButtonLabel": "导入", - "kbn.management.objects.objectsTable.flyout.importFailedDescription": "无法导入 {failedImportCount} 个对象,共 {totalImportCount} 个。导入失败", - "kbn.management.objects.objectsTable.flyout.importFailedMissingReference": "{type} [id={id}] 无法找到 {refType} [id={refId}]", - "kbn.management.objects.objectsTable.flyout.importFailedTitle": "导入失败", - "kbn.management.objects.objectsTable.flyout.importFailedUnsupportedType": "{type} [id={id}] 不受支持的类型", - "kbn.management.objects.objectsTable.flyout.importFileErrorMessage": "无法处理该文件。", - "kbn.management.objects.objectsTable.flyout.importLegacyFileErrorMessage": "无法处理该文件。", - "kbn.management.objects.objectsTable.flyout.importPromptText": "导入", - "kbn.management.objects.objectsTable.flyout.importSavedObjectTitle": "导入已保存对象", - "kbn.management.objects.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "确认所有更改", - "kbn.management.objects.objectsTable.flyout.importSuccessful.confirmButtonLabel": "完成", - "kbn.management.objects.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle": "未导入任何对象", - "kbn.management.objects.objectsTable.flyout.importSuccessfulDescription": "已成功导入 {importCount} 个对象。", - "kbn.management.objects.objectsTable.flyout.importSuccessfulTitle": "导入成功", - "kbn.management.objects.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "创建新的索引模式", - "kbn.management.objects.objectsTable.flyout.indexPatternConflictsDescription": "以下已保存对象使用不存在的索引模式。请选择要重新关联的索引模式。必要时,您可以{indexPatternLink}。", - "kbn.management.objects.objectsTable.flyout.indexPatternConflictsTitle": "索引模式冲突", - "kbn.management.objects.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage": "已保存对象文件格式无效,无法导入。", - "kbn.management.objects.objectsTable.flyout.legacyFileUsedBody": "只需使用更新的导出功能生成 NDJSON 文件,便万事俱备。", - "kbn.management.objects.objectsTable.flyout.legacyFileUsedTitle": "将不再支持 JSON 文件", - "kbn.management.objects.objectsTable.flyout.overwriteSavedObjectsLabel": "自动覆盖所有已保存对象?", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnCountDescription": "受影响对象数目", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnCountName": "计数", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnIdDescription": "索引模式的 ID", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnIdName": "ID", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnNewIndexPatternName": "新建索引模式", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription": "受影响对象样例", - "kbn.management.objects.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName": "受影响对象样例", - "kbn.management.objects.objectsTable.flyout.resolveImportErrorsFileErrorMessage": "无法处理该文件。", - "kbn.management.objects.objectsTable.flyout.selectFileToImportFormRowLabel": "请选择要导入的文件", - "kbn.management.objects.objectsTable.header.exportButtonLabel": "导出 {filteredCount, plural, one{# 个对象} other {# 个对象}}", - "kbn.management.objects.objectsTable.header.importButtonLabel": "导入", - "kbn.management.objects.objectsTable.header.refreshButtonLabel": "刷新", - "kbn.management.objects.objectsTable.header.savedObjectsTitle": "已保存对象", - "kbn.management.objects.objectsTable.howToDeleteSavedObjectsDescription": "从这里您可以删除已保存对象,如已保存搜索。还可以编辑已保存对象的原始数据。通常,对象只能通过其关联的应用程序进行修改;或许您应该遵循这一原则,而非使用此屏幕进行修改。", - "kbn.management.objects.objectsTable.relationships.columnActions.inspectActionDescription": "检查此已保存对象", - "kbn.management.objects.objectsTable.relationships.columnActions.inspectActionName": "检查", - "kbn.management.objects.objectsTable.relationships.columnActionsName": "操作", - "kbn.management.objects.objectsTable.relationships.columnRelationship.childAsValue": "子项", - "kbn.management.objects.objectsTable.relationships.columnRelationship.parentAsValue": "父项", - "kbn.management.objects.objectsTable.relationships.columnRelationshipName": "直接关系", - "kbn.management.objects.objectsTable.relationships.columnTitleDescription": "已保存对象的标题", - "kbn.management.objects.objectsTable.relationships.columnTitleName": "标题", - "kbn.management.objects.objectsTable.relationships.columnTypeDescription": "已保存对象的类型", - "kbn.management.objects.objectsTable.relationships.columnTypeName": "类型", - "kbn.management.objects.objectsTable.relationships.relationshipsTitle": "以下是与 {title} 相关的已保存对象。删除此{type}将影响其父级对象,但不会影响其子级对象。", - "kbn.management.objects.objectsTable.relationships.renderErrorMessage": "错误", - "kbn.management.objects.objectsTable.relationships.search.filters.relationship.childAsValue.view": "子项", - "kbn.management.objects.objectsTable.relationships.search.filters.relationship.name": "直接关系", - "kbn.management.objects.objectsTable.relationships.search.filters.relationship.parentAsValue.view": "父项", - "kbn.management.objects.objectsTable.relationships.search.filters.type.name": "类型", - "kbn.management.objects.objectsTable.searchBar.unableToParseQueryErrorMessage": "无法解析查询", - "kbn.management.objects.objectsTable.table.columnActions.inspectActionDescription": "检查此已保存对象", - "kbn.management.objects.objectsTable.table.columnActions.inspectActionName": "检查", - "kbn.management.objects.objectsTable.table.columnActions.viewRelationshipsActionDescription": "查看此已保存对象与其他已保存对象的关系", - "kbn.management.objects.objectsTable.table.columnActions.viewRelationshipsActionName": "关系", - "kbn.management.objects.objectsTable.table.columnActionsName": "操作", - "kbn.management.objects.objectsTable.table.columnTitleDescription": "已保存对象的标题", - "kbn.management.objects.objectsTable.table.columnTitleName": "标题", - "kbn.management.objects.objectsTable.table.columnTypeDescription": "已保存对象的类型", - "kbn.management.objects.objectsTable.table.columnTypeName": "类型", - "kbn.management.objects.objectsTable.table.deleteButtonLabel": "删除", - "kbn.management.objects.objectsTable.table.deleteButtonTitle": "无法删除已保存对象", - "kbn.management.objects.objectsTable.table.exportButtonLabel": "导出", - "kbn.management.objects.objectsTable.table.exportPopoverButtonLabel": "导出", - "kbn.management.objects.objectsTable.table.typeFilterName": "类型", - "kbn.management.objects.objectsTable.unableFindSavedObjectsNotificationMessage": "找不到已保存对象", - "kbn.management.objects.parsingFieldErrorMessage": "为索引模式 “{indexName}” 解析 “{fieldName}” 时发生错误:{errorMessage}", - "kbn.management.objects.savedObjectsSectionLabel": "已保存对象", - "kbn.management.objects.view.cancelButtonAriaLabel": "取消", - "kbn.management.objects.view.cancelButtonLabel": "取消", - "kbn.management.objects.view.deleteItemButtonLabel": "删除“{title}”", - "kbn.management.objects.view.editItemTitle": "编辑“{title}", - "kbn.management.objects.view.fieldDoesNotExistErrorMessage": "与此对象关联的字段在该索引模式中已不存在。", - "kbn.management.objects.view.howToFixErrorDescription": "如果您清楚此错误的含义,请修复该错误 — 否则单击上面的删除按钮。", - "kbn.management.objects.view.howToModifyObjectDescription": "修改对象仅适用于高级用户。对象属性未得到验证,无效的对象可能会导致错误、数据丢失或更坏的情况发生。除非熟悉该代码的人让您来这里,否则您可能不应该来这里。", - "kbn.management.objects.view.howToModifyObjectTitle": "谨慎操作!", - "kbn.management.objects.view.indexPatternDoesNotExistErrorMessage": "与此对象关联的索引模式已不存在。", - "kbn.management.objects.view.saveButtonAriaLabel": "保存 { title } 对象", - "kbn.management.objects.view.saveButtonLabel": "保存 { title } 对象", - "kbn.management.objects.view.savedObjectProblemErrorMessage": "此已保存对象有问题", - "kbn.management.objects.view.savedSearchDoesNotExistErrorMessage": "与此对象关联的已保存搜索已不存在。", - "kbn.management.objects.view.viewItemButtonLabel": "查看“{title}”", - "kbn.management.objects.view.viewItemTitle": "查看“{title}”", - "kbn.management.savedObjects.editBreadcrumb": "编辑 {savedObjectType}", - "kbn.management.savedObjects.indexBreadcrumb": "已保存对象", + "savedObjectsManagement.indexPattern.confirmOverwriteButton": "覆盖", + "savedObjectsManagement.indexPattern.confirmOverwriteLabel": "确定要覆盖 “{title}”?", + "savedObjectsManagement.indexPattern.confirmOverwriteTitle": "覆盖“{type}”?", + "savedObjectsManagement.deleteConfirm.modalDeleteButtonLabel": "删除", + "savedObjectsManagement.deleteConfirm.modalDescription": "此操作会将对象从 Kibana 永久移除。", + "savedObjectsManagement.deleteConfirm.modalTitle": "删除“{title}”?", + "savedObjectsManagement.deleteSavedObjectsConfirmModalDescription": "此操作将删除以下已保存对象:", + "savedObjectsManagement.field.offLabel": "关闭", + "savedObjectsManagement.field.onLabel": "开启", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel": "取消", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteButtonLabel": "删除", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.deleteProcessButtonLabel": "正在删除……", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.idColumnName": "ID", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "标题", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "类型", + "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle": "删除已保存对象", + "savedObjectsManagement.objectsTable.export.dangerNotification": "无法生成报告", + "savedObjectsManagement.objectsTable.export.successNotification": "您的文件正在后台下载", + "savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification": "您的文件正在后台下载。找不到某些相关对象。有关缺失对象列表,请查看导出文件的最后一行。", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.cancelButtonLabel": "取消", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel": "全部导出", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel": "选项", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "包括相关对象", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription": "选择要导出的类型。", + "savedObjectsManagement.objectsTable.exportObjectsConfirmModalTitle": "导出 {filteredItemCount, plural, one{# 个对象} other {# 个对象}}", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage": "正在解决冲突……", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage": "正在重试失败的对象……", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage": "确保已保存搜索已正确链接……", + "savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage": "正在保存冲突……", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteBody": "确定要覆盖 “{title}”?", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteCancelButtonText": "取消", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteOverwriteButtonText": "覆盖", + "savedObjectsManagement.objectsTable.flyout.confirmOverwriteTitle": "覆盖“{type}”?", + "savedObjectsManagement.objectsTable.flyout.errorCalloutTitle": "抱歉,出现了错误", + "savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel": "取消", + "savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel": "导入", + "savedObjectsManagement.objectsTable.flyout.importFailedDescription": "无法导入 {failedImportCount} 个对象,共 {totalImportCount} 个。导入失败", + "savedObjectsManagement.objectsTable.flyout.importFailedMissingReference": "{type} [id={id}] 无法找到 {refType} [id={refId}]", + "savedObjectsManagement.objectsTable.flyout.importFailedTitle": "导入失败", + "savedObjectsManagement.objectsTable.flyout.importFailedUnsupportedType": "{type} [id={id}] 不受支持的类型", + "savedObjectsManagement.objectsTable.flyout.importFileErrorMessage": "无法处理该文件。", + "savedObjectsManagement.objectsTable.flyout.importLegacyFileErrorMessage": "无法处理该文件。", + "savedObjectsManagement.objectsTable.flyout.importPromptText": "导入", + "savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle": "导入已保存对象", + "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "确认所有更改", + "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmButtonLabel": "完成", + "savedObjectsManagement.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle": "未导入任何对象", + "savedObjectsManagement.objectsTable.flyout.importSuccessfulDescription": "已成功导入 {importCount} 个对象。", + "savedObjectsManagement.objectsTable.flyout.importSuccessfulTitle": "导入成功", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "创建新的索引模式", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription": "以下已保存对象使用不存在的索引模式。请选择要重新关联的索引模式。必要时,您可以{indexPatternLink}。", + "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle": "索引模式冲突", + "savedObjectsManagement.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage": "已保存对象文件格式无效,无法导入。", + "savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody": "只需使用更新的导出功能生成 NDJSON 文件,便万事俱备。", + "savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle": "将不再支持 JSON 文件", + "savedObjectsManagement.objectsTable.flyout.overwriteSavedObjectsLabel": "自动覆盖所有已保存对象?", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountDescription": "受影响对象数目", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountName": "计数", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdDescription": "索引模式的 ID", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdName": "ID", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnNewIndexPatternName": "新建索引模式", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription": "受影响对象样例", + "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName": "受影响对象样例", + "savedObjectsManagement.objectsTable.flyout.resolveImportErrorsFileErrorMessage": "无法处理该文件。", + "savedObjectsManagement.objectsTable.flyout.selectFileToImportFormRowLabel": "请选择要导入的文件", + "savedObjectsManagement.objectsTable.header.exportButtonLabel": "导出 {filteredCount, plural, one{# 个对象} other {# 个对象}}", + "savedObjectsManagement.objectsTable.header.importButtonLabel": "导入", + "savedObjectsManagement.objectsTable.header.refreshButtonLabel": "刷新", + "savedObjectsManagement.objectsTable.header.savedObjectsTitle": "已保存对象", + "savedObjectsManagement.objectsTable.howToDeleteSavedObjectsDescription": "从这里您可以删除已保存对象,如已保存搜索。还可以编辑已保存对象的原始数据。通常,对象只能通过其关联的应用程序进行修改;或许您应该遵循这一原则,而非使用此屏幕进行修改。", + "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionDescription": "检查此已保存对象", + "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionName": "检查", + "savedObjectsManagement.objectsTable.relationships.columnActionsName": "操作", + "savedObjectsManagement.objectsTable.relationships.columnRelationship.childAsValue": "子项", + "savedObjectsManagement.objectsTable.relationships.columnRelationship.parentAsValue": "父项", + "savedObjectsManagement.objectsTable.relationships.columnRelationshipName": "直接关系", + "savedObjectsManagement.objectsTable.relationships.columnTitleDescription": "已保存对象的标题", + "savedObjectsManagement.objectsTable.relationships.columnTitleName": "标题", + "savedObjectsManagement.objectsTable.relationships.columnTypeDescription": "已保存对象的类型", + "savedObjectsManagement.objectsTable.relationships.columnTypeName": "类型", + "savedObjectsManagement.objectsTable.relationships.relationshipsTitle": "以下是与 {title} 相关的已保存对象。删除此{type}将影响其父级对象,但不会影响其子级对象。", + "savedObjectsManagement.objectsTable.relationships.renderErrorMessage": "错误", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.childAsValue.view": "子项", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.name": "直接关系", + "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.parentAsValue.view": "父项", + "savedObjectsManagement.objectsTable.relationships.search.filters.type.name": "类型", + "savedObjectsManagement.objectsTable.searchBar.unableToParseQueryErrorMessage": "无法解析查询", + "savedObjectsManagement.objectsTable.table.columnActions.inspectActionDescription": "检查此已保存对象", + "savedObjectsManagement.objectsTable.table.columnActions.inspectActionName": "检查", + "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionDescription": "查看此已保存对象与其他已保存对象的关系", + "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionName": "关系", + "savedObjectsManagement.objectsTable.table.columnActionsName": "操作", + "savedObjectsManagement.objectsTable.table.columnTitleDescription": "已保存对象的标题", + "savedObjectsManagement.objectsTable.table.columnTitleName": "标题", + "savedObjectsManagement.objectsTable.table.columnTypeDescription": "已保存对象的类型", + "savedObjectsManagement.objectsTable.table.columnTypeName": "类型", + "savedObjectsManagement.objectsTable.table.deleteButtonLabel": "删除", + "savedObjectsManagement.objectsTable.table.deleteButtonTitle": "无法删除已保存对象", + "savedObjectsManagement.objectsTable.table.exportButtonLabel": "导出", + "savedObjectsManagement.objectsTable.table.exportPopoverButtonLabel": "导出", + "savedObjectsManagement.objectsTable.table.typeFilterName": "类型", + "savedObjectsManagement.objectsTable.unableFindSavedObjectsNotificationMessage": "找不到已保存对象", + "savedObjectsManagement.parsingFieldErrorMessage": "为索引模式 “{indexName}” 解析 “{fieldName}” 时发生错误:{errorMessage}", + "savedObjectsManagement.managementSectionLabel": "已保存对象", + "savedObjectsManagement.view.cancelButtonAriaLabel": "取消", + "savedObjectsManagement.view.cancelButtonLabel": "取消", + "savedObjectsManagement.view.deleteItemButtonLabel": "删除“{title}”", + "savedObjectsManagement.view.editItemTitle": "编辑“{title}", + "savedObjectsManagement.view.fieldDoesNotExistErrorMessage": "与此对象关联的字段在该索引模式中已不存在。", + "savedObjectsManagement.view.howToFixErrorDescription": "如果您清楚此错误的含义,请修复该错误 — 否则单击上面的删除按钮。", + "savedObjectsManagement.view.howToModifyObjectDescription": " 修改对象仅适用于高级用户。对象属性未得到验证,无效的对象可能会导致错误、数据丢失或更坏的情况发生。除非熟悉该代码的人让您来这里,否则您可能不应该来这里。", + "savedObjectsManagement.view.howToModifyObjectTitle": "谨慎操作!", + "savedObjectsManagement.view.indexPatternDoesNotExistErrorMessage": "与此对象关联的索引模式已不存在。", + "savedObjectsManagement.view.saveButtonAriaLabel": "保存 { title } 对象", + "savedObjectsManagement.view.saveButtonLabel": "保存 { title } 对象", + "savedObjectsManagement.view.savedObjectProblemErrorMessage": "此已保存对象有问题", + "savedObjectsManagement.view.savedSearchDoesNotExistErrorMessage": "与此对象关联的已保存搜索已不存在。", + "savedObjectsManagement.view.viewItemButtonLabel": "查看“{title}”", + "savedObjectsManagement.view.viewItemTitle": "查看“{title}”", + "savedObjectsManagement.breadcrumb.edit": "编辑 {savedObjectType}", + "savedObjectsManagement.breadcrumb.index": "已保存对象", "kbn.managementTitle": "管理", "kbn.topNavMenu.openInspectorButtonLabel": "检查", "kbn.topNavMenu.refreshButtonLabel": "刷新", From 61271c0652a8393f9af6972a46b31759d8b81c7d Mon Sep 17 00:00:00 2001 From: Shahzad <shahzad.muhammad@elastic.co> Date: Mon, 13 Apr 2020 13:44:10 +0200 Subject: [PATCH 056/121] [Uptime] Simplify monitor param usage (#63121) * add useMonitorId hook * update url param hook * update type Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../connected/charts/monitor_duration.tsx | 5 ++-- .../connected/charts/ping_histogram.tsx | 5 ++-- .../connected/charts/snapshot_container.tsx | 5 ++-- .../monitor/list_drawer_container.tsx | 5 ++-- .../monitor/status_bar_container.tsx | 5 ++-- .../monitor/status_details_container.tsx | 5 ++-- .../monitor_list_drawer/most_recent_error.tsx | 5 ++-- .../monitor_details/ml/manage_ml_job.tsx | 10 +++---- .../ml/ml_flyout_container.tsx | 10 +++---- .../monitor_details/ml/ml_integeration.tsx | 6 ++--- .../contexts/uptime_settings_context.tsx | 6 ++--- .../hooks/__tests__/use_url_params.test.tsx | 3 ++- .../uptime/public/hooks/use_monitor.ts | 14 ++++++++++ .../uptime/public/hooks/use_telemetry.ts | 10 ++++--- .../uptime/public/hooks/use_url_params.ts | 27 +++++++++---------- .../plugins/uptime/public/pages/monitor.tsx | 6 ++--- .../plugins/uptime/public/pages/overview.tsx | 5 ++-- 17 files changed, 66 insertions(+), 66 deletions(-) create mode 100644 x-pack/legacy/plugins/uptime/public/hooks/use_monitor.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx index 7d1cb08cb8b1c..40480905350af 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx @@ -6,7 +6,7 @@ import React, { useContext, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; import { getAnomalyRecordsAction, getMLCapabilitiesAction, @@ -28,13 +28,12 @@ interface Props { } export const DurationChart: React.FC<Props> = ({ monitorId }: Props) => { - const [getUrlParams] = useUrlParams(); const { dateRangeStart, dateRangeEnd, absoluteDateRangeStart, absoluteDateRangeEnd, - } = getUrlParams(); + } = useGetUrlParams(); const { durationLines, loading } = useSelector(selectDurationLines); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx index 50f91be4ff09f..6428ddfd10f8c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx @@ -15,7 +15,7 @@ import { getPingHistogram } from '../../../state/actions'; import { selectPingHistogram } from '../../../state/selectors'; import { withResponsiveWrapper, ResponsiveWrapperProps } from '../../higher_order'; import { GetPingHistogramParams, HistogramResult } from '../../../../common/types'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; type Props = ResponsiveWrapperProps & Pick<PingHistogramComponentProps, 'height' | 'data' | 'loading'> & @@ -30,14 +30,13 @@ const PingHistogramContainer: React.FC<Props> = ({ loading, esKuery, }) => { - const [getUrlParams] = useUrlParams(); const { absoluteDateRangeStart, absoluteDateRangeEnd, dateRangeStart: dateStart, dateRangeEnd: dateEnd, statusFilter, - } = getUrlParams(); + } = useGetUrlParams(); useEffect(() => { loadData({ monitorId, dateStart, dateEnd, statusFilter, filters: esKuery }); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx index ac8ff13d1edce..39ead242527f8 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx @@ -6,7 +6,7 @@ import React, { useEffect } from 'react'; import { connect } from 'react-redux'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; import { AppState } from '../../../state'; import { getSnapshotCountAction } from '../../../state/actions'; import { SnapshotComponent } from '../../functional/snapshot'; @@ -54,8 +54,7 @@ export const Container: React.FC<Props> = ({ esKuery, loadSnapshotCount, }: Props) => { - const [getUrlParams] = useUrlParams(); - const { dateRangeStart, dateRangeEnd, statusFilter } = getUrlParams(); + const { dateRangeStart, dateRangeEnd, statusFilter } = useGetUrlParams(); useEffect(() => { loadSnapshotCount({ dateRangeStart, dateRangeEnd, filters: esKuery, statusFilter }); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx index ceeaa7026059f..70da62d5833af 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx @@ -11,7 +11,7 @@ import { monitorDetailsSelector } from '../../../state/selectors'; import { MonitorDetailsActionPayload } from '../../../state/actions/types'; import { getMonitorDetailsAction } from '../../../state/actions/monitor'; import { MonitorListDrawerComponent } from '../../functional/monitor_list/monitor_list_drawer/monitor_list_drawer'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; import { MonitorSummary } from '../../../../common/graphql/types'; import { MonitorDetails } from '../../../../common/runtime_types/monitor'; @@ -24,8 +24,7 @@ interface ContainerProps { const Container: React.FC<ContainerProps> = ({ summary, loadMonitorDetails, monitorDetails }) => { const monitorId = summary?.monitor_id; - const [getUrlParams] = useUrlParams(); - const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = getUrlParams(); + const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams(); useEffect(() => { loadMonitorDetails({ diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx index dd6f7a89cf9a3..00cfd02d8dc32 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx @@ -11,7 +11,7 @@ import { AppState } from '../../../state'; import { monitorLocationsSelector, monitorStatusSelector } from '../../../state/selectors'; import { MonitorStatusBarComponent } from '../../functional/monitor_status_details/monitor_status_bar'; import { getMonitorStatusAction } from '../../../state/actions'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; import { Ping } from '../../../../common/graphql/types'; import { MonitorLocations } from '../../../../common/runtime_types/monitor'; import { UptimeRefreshContext } from '../../../contexts'; @@ -39,8 +39,7 @@ const Container: React.FC<Props> = ({ }: Props) => { const { lastRefresh } = useContext(UptimeRefreshContext); - const [getUrlParams] = useUrlParams(); - const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = getUrlParams(); + const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams(); useEffect(() => { loadMonitorStatus({ dateStart, dateEnd, monitorId }); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx index 3ced251dfab8c..9d2e48830fbfe 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx @@ -7,7 +7,7 @@ import React, { useContext, useEffect } from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; import { AppState } from '../../../state'; import { monitorLocationsSelector } from '../../../state/selectors'; import { getMonitorLocationsAction, MonitorLocationsPayload } from '../../../state/actions/monitor'; @@ -36,8 +36,7 @@ export const Container: React.FC<Props> = ({ }: Props) => { const { lastRefresh } = useContext(UptimeRefreshContext); - const [getUrlParams] = useUrlParams(); - const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = getUrlParams(); + const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams(); useEffect(() => { loadMonitorLocations({ dateStart, dateEnd, monitorId }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx index 036882b49359f..1963a9c852b11 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx @@ -8,7 +8,7 @@ import { EuiText, EuiSpacer } from '@elastic/eui'; import moment from 'moment'; import { i18n } from '@kbn/i18n'; import { MonitorPageLink } from '../monitor_page_link'; -import { useUrlParams } from '../../../../hooks'; +import { useGetUrlParams } from '../../../../hooks'; import { stringifyUrlParams } from '../../../../lib/helper/stringify_url_params'; import { MonitorError } from '../../../../../common/runtime_types'; @@ -30,8 +30,7 @@ interface MostRecentErrorProps { } export const MostRecentError = ({ error, monitorId, timestamp }: MostRecentErrorProps) => { - const [getUrlParams] = useUrlParams(); - const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams(); + const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = useGetUrlParams(); params.selectedPingStatus = 'down'; const linkParameters = stringifyUrlParams(params, true); diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx index 29f003437f7cb..1abda87abf73a 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx @@ -7,13 +7,13 @@ import React, { useContext, useState } from 'react'; import { EuiButtonEmpty, EuiContextMenu, EuiIcon, EuiPopover } from '@elastic/eui'; -import { useParams } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { canDeleteMLJobSelector } from '../../../state/selectors'; import { UptimeSettingsContext } from '../../../contexts'; import * as labels from './translations'; import { getMLJobLinkHref } from './ml_job_link'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; +import { useMonitorId } from '../../../hooks/use_monitor'; interface Props { hasMLJob: boolean; @@ -28,11 +28,9 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro const canDeleteMLJob = useSelector(canDeleteMLJobSelector); - const [getUrlParams] = useUrlParams(); - const { dateRangeStart, dateRangeEnd } = getUrlParams(); + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); - let { monitorId } = useParams(); - monitorId = atob(monitorId || ''); + const monitorId = useMonitorId(); const button = ( <EuiButtonEmpty diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx index 9eed24e2810d8..6953618d92213 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx @@ -6,7 +6,6 @@ import React, { useContext, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useParams } from 'react-router-dom'; import { canCreateMLJobSelector, hasMLJobSelector, @@ -24,8 +23,9 @@ import { import { MLFlyoutView } from './ml_flyout'; import { ML_JOB_ID } from '../../../../common/constants'; import { UptimeRefreshContext, UptimeSettingsContext } from '../../../contexts'; -import { useUrlParams } from '../../../hooks'; +import { useGetUrlParams } from '../../../hooks'; import { getDynamicSettings } from '../../../state/actions/dynamic_settings'; +import { useMonitorId } from '../../../hooks/use_monitor'; interface Props { onClose: () => void; @@ -77,8 +77,7 @@ export const MachineLearningFlyout: React.FC<Props> = ({ onClose }) => { const { refreshApp } = useContext(UptimeRefreshContext); - let { monitorId } = useParams(); - monitorId = atob(monitorId || ''); + const monitorId = useMonitorId(); const canCreateMLJob = useSelector(canCreateMLJobSelector) && heartbeatIndices !== ''; @@ -93,8 +92,7 @@ export const MachineLearningFlyout: React.FC<Props> = ({ onClose }) => { const [isCreatingJob, setIsCreatingJob] = useState(false); - const [getUrlParams] = useUrlParams(); - const { dateRangeStart, dateRangeEnd } = getUrlParams(); + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); useEffect(() => { if (isCreatingJob && !isMLJobCreating) { diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx index a27796167091e..e65a2510ea6f2 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx @@ -5,8 +5,6 @@ */ import React, { useContext, useEffect, useState } from 'react'; - -import { useParams } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { MachineLearningFlyout } from './ml_flyout_container'; import { @@ -23,6 +21,7 @@ import * as labels from './translations'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { ManageMLJobComponent } from './manage_ml_job'; import { JobStat } from '../../../../../../../plugins/ml/common/types/data_recognizer'; +import { useMonitorId } from '../../../hooks/use_monitor'; export const MLIntegrationComponent = () => { const [isMlFlyoutOpen, setIsMlFlyoutOpen] = useState(false); @@ -32,8 +31,7 @@ export const MLIntegrationComponent = () => { const { notifications } = useKibana(); - let { monitorId } = useParams(); - monitorId = atob(monitorId || ''); + const monitorId = useMonitorId(); const dispatch = useDispatch(); diff --git a/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx b/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx index 44a87d310c9c7..c5a0ec4831798 100644 --- a/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx +++ b/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx @@ -8,7 +8,7 @@ import React, { createContext, useMemo } from 'react'; import { UptimeAppProps } from '../uptime_app'; import { CLIENT_DEFAULTS, CONTEXT_DEFAULTS } from '../../common/constants'; import { CommonlyUsedRange } from '../components/functional/uptime_date_picker'; -import { useUrlParams } from '../hooks'; +import { useGetUrlParams } from '../hooks'; import { ILicense } from '../../../../../plugins/licensing/common/types'; export interface UptimeSettingsContextValues { @@ -50,9 +50,7 @@ export const UptimeSettingsContextProvider: React.FC<UptimeAppProps> = ({ childr plugins, } = props; - const [getUrlParams] = useUrlParams(); - - const { dateRangeStart, dateRangeEnd } = getUrlParams(); + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); let license: ILicense | null = null; diff --git a/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_url_params.test.tsx b/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_url_params.test.tsx index a8999a50927d2..deb1f163c1326 100644 --- a/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_url_params.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_url_params.test.tsx @@ -19,6 +19,7 @@ interface MockUrlParamsComponentProps { const UseUrlParamsTestComponent = ({ hook, updateParams }: MockUrlParamsComponentProps) => { const [params, setParams] = useState({}); const [getUrlParams, updateUrlParams] = hook(); + const queryParams = getUrlParams(); return ( <Fragment> {Object.keys(params).length > 0 ? <div>{JSON.stringify(params)}</div> : null} @@ -30,7 +31,7 @@ const UseUrlParamsTestComponent = ({ hook, updateParams }: MockUrlParamsComponen > Set url params </button> - <button id="getUrlParams" onClick={() => setParams(getUrlParams())}> + <button id="getUrlParams" onClick={() => setParams(queryParams)}> Get url params </button> </Fragment> diff --git a/x-pack/legacy/plugins/uptime/public/hooks/use_monitor.ts b/x-pack/legacy/plugins/uptime/public/hooks/use_monitor.ts new file mode 100644 index 0000000000000..8080ce2696a3c --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/hooks/use_monitor.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useParams } from 'react-router-dom'; + +export const useMonitorId = (): string => { + const { monitorId } = useParams(); + + // decode 64 base string, it was decoded to make it a valid url, since monitor id can be a url + return atob(monitorId || ''); +}; diff --git a/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts b/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts index 13fe523332ae5..a2012b8ac5636 100644 --- a/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts +++ b/x-pack/legacy/plugins/uptime/public/hooks/use_telemetry.ts @@ -5,7 +5,7 @@ */ import { useEffect } from 'react'; -import { useUrlParams } from './use_url_params'; +import { useGetUrlParams } from './use_url_params'; import { apiService } from '../state/api/utils'; import { API_URLS } from '../../common/constants'; @@ -17,8 +17,12 @@ export enum UptimePage { } export const useUptimeTelemetry = (page?: UptimePage) => { - const [getUrlParams] = useUrlParams(); - const { dateRangeStart, dateRangeEnd, autorefreshInterval, autorefreshIsPaused } = getUrlParams(); + const { + dateRangeStart, + dateRangeEnd, + autorefreshInterval, + autorefreshIsPaused, + } = useGetUrlParams(); useEffect(() => { if (!apiService.http) throw new Error('Core http services are not defined'); diff --git a/x-pack/legacy/plugins/uptime/public/hooks/use_url_params.ts b/x-pack/legacy/plugins/uptime/public/hooks/use_url_params.ts index 20063b2c1bc93..8b13e9e480559 100644 --- a/x-pack/legacy/plugins/uptime/public/hooks/use_url_params.ts +++ b/x-pack/legacy/plugins/uptime/public/hooks/use_url_params.ts @@ -15,27 +15,26 @@ export type UpdateUrlParams = (updatedParams: { export type UptimeUrlParamsHook = () => [GetUrlParams, UpdateUrlParams]; -export const useUrlParams: UptimeUrlParamsHook = () => { +const getParsedParams = (search: string) => { + return search ? parse(search[0] === '?' ? search.slice(1) : search, { sort: false }) : {}; +}; + +export const useGetUrlParams: GetUrlParams = () => { const location = useLocation(); - const history = useHistory(); - const getUrlParams: GetUrlParams = () => { - let search: string | undefined; - if (location) { - search = location.search; - } + const params = getParsedParams(location?.search); - const params = search - ? parse(search[0] === '?' ? search.slice(1) : search, { sort: false }) - : {}; + return getSupportedUrlParams(params); +}; - return getSupportedUrlParams(params); - }; +export const useUrlParams: UptimeUrlParamsHook = () => { + const location = useLocation(); + const history = useHistory(); const updateUrlParams: UpdateUrlParams = updatedParams => { if (!history || !location) return; const { pathname, search } = location; - const currentParams = parse(search[0] === '?' ? search.slice(1) : search, { sort: false }); + const currentParams = getParsedParams(search); const mergedParams = { ...currentParams, ...updatedParams, @@ -60,5 +59,5 @@ export const useUrlParams: UptimeUrlParamsHook = () => { }); }; - return [getUrlParams, updateUrlParams]; + return [useGetUrlParams, updateUrlParams]; }; diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx index 21124b7323d68..5016ccebbab54 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx @@ -6,7 +6,6 @@ import { EuiSpacer } from '@elastic/eui'; import React, { useContext, useState } from 'react'; -import { useParams } from 'react-router-dom'; import { useSelector } from 'react-redux'; import { MonitorCharts, PingList } from '../components/functional'; import { UptimeRefreshContext } from '../contexts'; @@ -16,11 +15,10 @@ import { MonitorStatusDetails } from '../components/connected'; import { monitorStatusSelector } from '../state/selectors'; import { PageHeader } from './page_header'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; +import { useMonitorId } from '../hooks/use_monitor'; export const MonitorPage: React.FC = () => { - // decode 64 base string, it was decoded to make it a valid url, since monitor id can be a url - let { monitorId } = useParams(); - monitorId = atob(monitorId || ''); + const monitorId = useMonitorId(); const [pingListPageCount, setPingListPageCount] = useState<number>(10); const { refreshApp } = useContext(UptimeRefreshContext); diff --git a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx index 943dbd6bd57ba..5550facaf42e9 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx @@ -13,7 +13,7 @@ import { OverviewPageParsingErrorCallout, StatusPanel, } from '../components/functional'; -import { useUrlParams, useUptimeTelemetry, UptimePage } from '../hooks'; +import { useUptimeTelemetry, UptimePage, useGetUrlParams } from '../hooks'; import { stringifyUrlParams } from '../lib/helper/stringify_url_params'; import { useTrackPageview } from '../../../../../plugins/observability/public'; import { DataPublicPluginSetup, IIndexPattern } from '../../../../../../src/plugins/data/public'; @@ -55,12 +55,11 @@ const getMonitorListPageSizeValue = () => { export const OverviewPageComponent = ({ autocomplete, indexPattern, setEsKueryFilters }: Props) => { const { colors } = useContext(UptimeThemeContext); - const [getUrlParams] = useUrlParams(); // TODO: this is temporary until we migrate the monitor list to our Redux implementation const [monitorListPageSize, setMonitorListPageSize] = useState<number>( getMonitorListPageSizeValue() ); - const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams(); + const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = useGetUrlParams(); const { dateRangeStart, dateRangeEnd, From c7f61f956a581bf39be01f9e0c263577c2165b6b Mon Sep 17 00:00:00 2001 From: Shahzad <shahzad.muhammad@elastic.co> Date: Mon, 13 Apr 2020 13:49:46 +0200 Subject: [PATCH 057/121] [Uptime] Update Ml functional test (#62562) * update test * added test * updated type * updated test * updated test * update test Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../connected/empty_state/empty_state.tsx | 6 +- .../confirm_delete.test.tsx.snap | 2 + .../__snapshots__/license_info.test.tsx.snap | 2 + .../__snapshots__/ml_flyout.test.tsx.snap | 5 ++ .../ml_integerations.test.tsx.snap | 1 + .../__snapshots__/ml_manage_job.test.tsx.snap | 1 + .../monitor_details/ml/confirm_delete.tsx | 1 + .../monitor_details/ml/license_info.tsx | 1 + .../monitor_details/ml/manage_ml_job.tsx | 8 ++- .../monitor_details/ml/ml_flyout.tsx | 3 +- .../ml/ml_flyout_container.tsx | 6 +- .../monitor_details/ml/ml_integeration.tsx | 2 +- .../plugins/uptime/public/pages/settings.tsx | 2 +- x-pack/test/functional/apps/uptime/index.ts | 5 +- .../test/functional/apps/uptime/ml_anomaly.ts | 51 ++++++++++++++++ x-pack/test/functional/apps/uptime/monitor.ts | 7 +-- .../test/functional/apps/uptime/overview.ts | 24 ++++---- .../functional/page_objects/uptime_page.ts | 39 ++++++------ .../test/functional/services/uptime/common.ts | 15 +++++ .../functional/services/uptime/ml_anomaly.ts | 59 +++++++++++++++++++ .../functional/services/uptime/navigation.ts | 52 +++++++++++----- .../test/functional/services/uptime/uptime.ts | 3 + 22 files changed, 235 insertions(+), 60 deletions(-) create mode 100644 x-pack/test/functional/apps/uptime/ml_anomaly.ts create mode 100644 x-pack/test/functional/services/uptime/ml_anomaly.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/empty_state/empty_state.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/empty_state/empty_state.tsx index b383a696095a3..55c92e70b6066 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/empty_state/empty_state.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/empty_state/empty_state.tsx @@ -4,20 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useEffect } from 'react'; +import React, { useContext, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { indexStatusAction } from '../../../state/actions'; import { indexStatusSelector } from '../../../state/selectors'; import { EmptyStateComponent } from '../../functional/empty_state/empty_state'; +import { UptimeRefreshContext } from '../../../contexts'; export const EmptyState: React.FC = ({ children }) => { const { data, loading, error } = useSelector(indexStatusSelector); + const { lastRefresh } = useContext(UptimeRefreshContext); const dispatch = useDispatch(); useEffect(() => { dispatch(indexStatusAction.get()); - }, [dispatch]); + }, [dispatch, lastRefresh]); return ( <EmptyStateComponent diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap index 24ef7eda0d129..d83e45fea1aec 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap @@ -6,6 +6,7 @@ exports[`ML Confirm Job Delete shallow renders without errors 1`] = ` buttonColor="danger" cancelButtonText="Cancel" confirmButtonText="Delete" + data-test-subj="uptimeMLJobDeleteConfirmModel" defaultFocusedButton="confirm" onCancel={[MockFunction]} onConfirm={[MockFunction]} @@ -35,6 +36,7 @@ exports[`ML Confirm Job Delete shallow renders without errors while loading 1`] buttonColor="danger" cancelButtonText="Cancel" confirmButtonText="Delete" + data-test-subj="uptimeMLJobDeleteConfirmModel" defaultFocusedButton="confirm" onCancel={[MockFunction]} onConfirm={[MockFunction]} diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap index 2457488c4facc..fb40a42e47f75 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap @@ -4,6 +4,7 @@ exports[`ShowLicenseInfo renders without errors 1`] = ` Array [ <div class="euiCallOut euiCallOut--primary license-info-trial" + data-test-subj="uptimeMLLicenseInfo" > <div class="euiCallOutHeader" @@ -54,6 +55,7 @@ exports[`ShowLicenseInfo shallow renders without errors 1`] = ` <EuiCallOut className="license-info-trial" color="primary" + data-test-subj="uptimeMLLicenseInfo" iconType="help" title="Start free 14-day trial" > diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap index ead27425c26f3..a83a1d99d7bb0 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap @@ -3,6 +3,7 @@ exports[`ML Flyout component renders without errors 1`] = ` <EuiFlyout closeButtonAriaLabel="Closes this dialog" + data-test-subj="uptimeMLFlyout" hideCloseButton={false} maxWidth={false} onClose={[Function]} @@ -69,6 +70,7 @@ exports[`ML Flyout component renders without errors 1`] = ` grow={false} > <EuiButton + data-test-subj="uptimeMLCreateJobBtn" disabled={true} fill={true} isLoading={false} @@ -99,6 +101,7 @@ exports[`ML Flyout component shows license info if no ml available 1`] = ` > <div class="euiFlyout euiFlyout--small" + data-test-subj="uptimeMLFlyout" role="dialog" tabindex="0" > @@ -137,6 +140,7 @@ exports[`ML Flyout component shows license info if no ml available 1`] = ` > <div class="euiCallOut euiCallOut--primary license-info-trial" + data-test-subj="uptimeMLLicenseInfo" > <div class="euiCallOutHeader" @@ -240,6 +244,7 @@ exports[`ML Flyout component shows license info if no ml available 1`] = ` > <button class="euiButton euiButton--primary euiButton--fill" + data-test-subj="uptimeMLCreateJobBtn" disabled="" type="button" > diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap index ac4630f4e69a8..fa9b59e13c34e 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap @@ -9,6 +9,7 @@ exports[`ML Integrations renders without errors 1`] = ` > <button class="euiButtonEmpty euiButtonEmpty--primary" + data-test-subj="uptimeEnableAnomalyBtn" type="button" > <span diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap index 6eb2930c4875a..91bd9fa3d86b5 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap @@ -9,6 +9,7 @@ exports[`Manage ML Job renders without errors 1`] = ` > <button class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--iconRight" + data-test-subj="uptimeManageMLJobBtn" type="button" > <span diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx index 6754676765fb6..628f943ef2e08 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx @@ -25,6 +25,7 @@ export const ConfirmJobDeletion: React.FC<Props> = ({ loading, onConfirm, onCanc confirmButtonText="Delete" buttonColor="danger" defaultFocusedButton="confirm" + data-test-subj="uptimeMLJobDeleteConfirmModel" > {!loading ? ( <p> diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx index 92badb4043ed6..fae81177a728c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx @@ -13,6 +13,7 @@ export const ShowLicenseInfo = () => { return ( <> <EuiCallOut + data-test-subj="uptimeMLLicenseInfo" className="license-info-trial" title={labels.START_TRAIL} color="primary" diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx index 1abda87abf73a..ec3e8bb2b9f68 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx @@ -34,6 +34,7 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro const button = ( <EuiButtonEmpty + data-test-subj={hasMLJob ? 'uptimeManageMLJobBtn' : 'uptimeEnableAnomalyBtn'} iconType={hasMLJob ? 'arrowDown' : 'machineLearningApp'} iconSide={hasMLJob ? 'right' : 'left'} onClick={hasMLJob ? () => setIsPopOverOpen(true) : onEnableJob} @@ -60,6 +61,7 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro }, { name: labels.DISABLE_ANOMALY_DETECTION, + 'data-test-subj': 'uptimeDeleteMLJobBtn', icon: <EuiIcon type="trash" size="m" />, onClick: () => { setIsPopOverOpen(false); @@ -72,7 +74,11 @@ export const ManageMLJobComponent = ({ hasMLJob, onEnableJob, onJobDelete }: Pro return ( <EuiPopover button={button} isOpen={isPopOverOpen} closePopover={() => setIsPopOverOpen(false)}> - <EuiContextMenu initialPanelId={0} panels={panels} /> + <EuiContextMenu + initialPanelId={0} + panels={panels} + data-test-subj="uptimeManageMLContextMenu" + /> </EuiPopover> ); }; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx index fdecfbf20810c..8c3f814e841f7 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx @@ -39,7 +39,7 @@ export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateM const hasPlatinumLicense = license?.getFeature('ml')?.isAvailable; return ( - <EuiFlyout onClose={onClose} size="s"> + <EuiFlyout onClose={onClose} size="s" data-test-subj="uptimeMLFlyout"> <EuiFlyoutHeader> <EuiTitle> <h2>{labels.ENABLE_ANOMALY_DETECTION}</h2> @@ -76,6 +76,7 @@ export function MLFlyoutView({ isCreatingJob, onClickCreate, onClose, canCreateM </EuiFlexItem> <EuiFlexItem grow={false}> <EuiButton + data-test-subj="uptimeMLCreateJobBtn" onClick={() => onClickCreate()} fill isLoading={isCreatingJob} diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx index 6953618d92213..a13de192cc443 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx @@ -41,7 +41,9 @@ const showMLJobNotification = ( ) => { if (success) { notifications.toasts.success({ - title: <p>{labels.JOB_CREATED_SUCCESS_TITLE}</p>, + title: ( + <p data-test-subj="uptimeMLJobSuccessfullyCreated">{labels.JOB_CREATED_SUCCESS_TITLE}</p> + ), body: ( <p> {labels.JOB_CREATED_SUCCESS_MESSAGE} @@ -54,7 +56,7 @@ const showMLJobNotification = ( }); } else { notifications.toasts.danger({ - title: <p>{labels.JOB_CREATION_FAILED}</p>, + title: <p data-test-subj="uptimeMLJobCreationFailed">{labels.JOB_CREATION_FAILED}</p>, body: message ?? <p>{labels.JOB_CREATION_FAILED_MESSAGE}</p>, toastLifeTimeMs: 10000, }); diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx index e65a2510ea6f2..e053ca733cb8c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx @@ -57,7 +57,7 @@ export const MLIntegrationComponent = () => { if (isConfirmDeleteJobOpen && jobDeletionSuccess?.[getMLJobId(monitorId as string)]?.deleted) { setIsConfirmDeleteJobOpen(false); notifications.toasts.success({ - title: <p>{labels.JOB_DELETION}</p>, + title: <p data-test-subj="uptimeMLJobSuccessfullyDeleted">{labels.JOB_DELETION}</p>, body: <p>{labels.JOB_DELETION_SUCCESS}</p>, toastLifeTimeMs: 3000, }); diff --git a/x-pack/legacy/plugins/uptime/public/pages/settings.tsx b/x-pack/legacy/plugins/uptime/public/pages/settings.tsx index d3e17a15ee0e0..765b0e3c664bc 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/settings.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/settings.tsx @@ -112,7 +112,7 @@ export const SettingsPageComponent = ({ return ( <> - <Link to={OVERVIEW_ROUTE}> + <Link to={OVERVIEW_ROUTE} data-test-subj="uptimeSettingsToOverviewLink"> <EuiButtonEmpty size="s" color="primary" iconType="arrowLeft"> {i18n.translate('xpack.uptime.settings.returnToOverviewLinkLabel', { defaultMessage: 'Return to overview', diff --git a/x-pack/test/functional/apps/uptime/index.ts b/x-pack/test/functional/apps/uptime/index.ts index 3789351263b98..f47214dc2ad2f 100644 --- a/x-pack/test/functional/apps/uptime/index.ts +++ b/x-pack/test/functional/apps/uptime/index.ts @@ -16,6 +16,7 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const server = getService('kibanaServer'); + const uptime = getService('uptime'); describe('Uptime app', function() { this.tags('ciGroup6'); @@ -58,12 +59,14 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => { await esArchiver.unload(ARCHIVE); await esArchiver.load(ARCHIVE); await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC' }); + await uptime.navigation.goToUptime(); }); after(async () => await esArchiver.unload(ARCHIVE)); - loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./overview')); loadTestFile(require.resolve('./monitor')); + loadTestFile(require.resolve('./ml_anomaly')); + loadTestFile(require.resolve('./feature_controls')); }); }); }; diff --git a/x-pack/test/functional/apps/uptime/ml_anomaly.ts b/x-pack/test/functional/apps/uptime/ml_anomaly.ts new file mode 100644 index 0000000000000..bcd165cc1afb7 --- /dev/null +++ b/x-pack/test/functional/apps/uptime/ml_anomaly.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. + */ +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const uptime = getService('uptime'); + const log = getService('log'); + + describe('uptime ml anomaly', function() { + this.tags(['skipFirefox']); + const dateStart = 'Sep 10, 2019 @ 12:40:08.078'; + const dateEnd = 'Sep 11, 2019 @ 19:40:08.078'; + const monitorId = '0000-intermittent'; + + before(async () => { + if (!(await uptime.navigation.checkIfOnMonitorPage(monitorId))) { + await uptime.navigation.loadDataAndGoToMonitorPage(dateStart, dateEnd, monitorId); + } + if (await uptime.ml.alreadyHasJob()) { + log.info('Jon already exists so lets delete it to start fresh.'); + await uptime.ml.deleteMLJob(); + } + }); + + it('can open ml flyout', async () => { + await uptime.ml.openMLFlyout(); + }); + + it('has permission to create job', async () => { + expect(uptime.ml.canCreateJob()).to.eql(true); + expect(uptime.ml.hasNoLicenseInfo()).to.eql(false); + }); + + it('can create job successfully', async () => { + await uptime.ml.createMLJob(); + // await uptime.navigation.refreshApp(); + }); + + it('can open ML Manage Menu', async () => { + await uptime.ml.openMLManageMenu(); + }); + + it('can delete job successfully', async () => { + await uptime.ml.deleteMLJob(); + }); + }); +}; diff --git a/x-pack/test/functional/apps/uptime/monitor.ts b/x-pack/test/functional/apps/uptime/monitor.ts index e15750eb6157b..90ad1836c69d3 100644 --- a/x-pack/test/functional/apps/uptime/monitor.ts +++ b/x-pack/test/functional/apps/uptime/monitor.ts @@ -17,19 +17,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const dateStart = 'Sep 10, 2019 @ 12:40:08.078'; const dateEnd = 'Sep 11, 2019 @ 19:40:08.078'; const monitorId = '0000-intermittent'; - const monitorName = '0000-intermittent'; before(async () => { await esArchiver.loadIfNeeded(archive); await uptimeService.navigation.goToUptime(); }); - after(async () => { - await esArchiver.unload(archive); - }); - it('loads and displays uptime data based on date range', async () => { - await uptime.loadDataAndGoToMonitorPage(dateStart, dateEnd, monitorId, monitorName); + await uptime.loadDataAndGoToMonitorPage(dateStart, dateEnd, monitorId); }); }); }; diff --git a/x-pack/test/functional/apps/uptime/overview.ts b/x-pack/test/functional/apps/uptime/overview.ts index 8195e6bbb6035..d0dfca64634f6 100644 --- a/x-pack/test/functional/apps/uptime/overview.ts +++ b/x-pack/test/functional/apps/uptime/overview.ts @@ -14,6 +14,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('overview page', function() { const DEFAULT_DATE_START = 'Sep 10, 2019 @ 12:40:08.078'; const DEFAULT_DATE_END = 'Sep 11, 2019 @ 19:40:08.078'; + + beforeEach(async () => { + await uptime.goToRoot(); + await uptime.setDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); + await uptime.resetFilters(); + }); + it('loads and displays uptime data based on date range', async () => { await uptime.goToUptimeOverviewAndLoadData( DEFAULT_DATE_START, @@ -22,13 +29,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ); }); - it('runs filter query without issues', async () => { - await uptime.inputFilterQuery('monitor.status:up and monitor.id:"0000-intermittent"'); - await uptime.pageHasExpectedIds(['0000-intermittent']); - }); - it('applies filters for multiple fields', async () => { - await uptime.goToUptimePageAndSetDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); await uptime.selectFilterItems({ location: ['mpls'], port: ['5678'], @@ -49,7 +50,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('pagination is cleared when filter criteria changes', async () => { - await uptime.goToUptimePageAndSetDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); await uptime.changePage('next'); await uptime.pageHasExpectedIds([ '0010-down', @@ -83,7 +83,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('clears pagination parameters when size changes', async () => { - await uptime.goToUptimePageAndSetDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); await uptime.changePage('next'); await uptime.pageUrlContains('pagination'); await uptime.setMonitorListPageSize(50); @@ -92,7 +91,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('pagination size updates to reflect current selection', async () => { - await uptime.goToUptimePageAndSetDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); await uptime.pageHasExpectedIds([ '0000-intermittent', '0001-up', @@ -162,7 +160,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('snapshot counts', () => { it('updates the snapshot count when status filter is set to down', async () => { - await uptime.goToUptimePageAndSetDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); await uptime.setStatusFilter('down'); await retry.tryForTime(12000, async () => { @@ -172,13 +169,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('updates the snapshot count when status filter is set to up', async () => { - await uptime.goToUptimePageAndSetDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); await uptime.setStatusFilter('up'); await retry.tryForTime(12000, async () => { const counts = await uptime.getSnapshotCount(); expect(counts).to.eql({ up: '93', down: '0' }); }); }); + + it('runs filter query without issues', async () => { + await uptime.inputFilterQuery('monitor.status:up and monitor.id:"0000-intermittent"'); + await uptime.pageHasExpectedIds(['0000-intermittent']); + await uptime.resetFilters(); + }); }); }); }; diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index 39c3c46adddbb..7157bbfb3811b 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -14,37 +14,33 @@ export function UptimePageProvider({ getPageObjects, getService }: FtrProviderCo return new (class UptimePage { public async goToRoot() { - await pageObjects.common.navigateToApp('uptime'); + await navigation.goToUptime(); } - public async goToUptimePageAndSetDateRange( - datePickerStartValue: string, - datePickerEndValue: string - ) { - await pageObjects.common.navigateToApp('uptime'); - await pageObjects.timePicker.setAbsoluteRange(datePickerStartValue, datePickerEndValue); + public async setDateRange(start: string, end: string) { + const { start: prevStart, end: prevEnd } = await pageObjects.timePicker.getTimeConfig(); + if (start !== prevStart || prevEnd !== end) { + await pageObjects.timePicker.setAbsoluteRange(start, end); + } else { + await navigation.refreshApp(); + } } public async goToUptimeOverviewAndLoadData( - datePickerStartValue: string, - datePickerEndValue: string, + dateStart: string, + dateEnd: string, monitorIdToCheck?: string ) { - await pageObjects.common.navigateToApp('uptime'); - await pageObjects.timePicker.setAbsoluteRange(datePickerStartValue, datePickerEndValue); + await navigation.goToUptime(); + await this.setDateRange(dateStart, dateEnd); if (monitorIdToCheck) { await commonService.monitorIdExists(monitorIdToCheck); } } - public async loadDataAndGoToMonitorPage( - datePickerStartValue: string, - datePickerEndValue: string, - monitorId: string, - monitorName?: string - ) { - await pageObjects.timePicker.setAbsoluteRange(datePickerStartValue, datePickerEndValue); - await navigation.goToMonitor(monitorId, monitorName); + public async loadDataAndGoToMonitorPage(dateStart: string, dateEnd: string, monitorId: string) { + await this.setDateRange(dateStart, dateEnd); + await navigation.goToMonitor(monitorId); } public async inputFilterQuery(filterQuery: string) { @@ -140,5 +136,10 @@ export function UptimePageProvider({ getPageObjects, getService }: FtrProviderCo await commonService.openPageSizeSelectPopover(); return commonService.clickPageSizeSelectPopoverItem(size); } + + public async resetFilters() { + await this.inputFilterQuery(''); + await commonService.resetStatusFilter(); + } })(); } diff --git a/x-pack/test/functional/services/uptime/common.ts b/x-pack/test/functional/services/uptime/common.ts index ed465eee343f9..b5be1e29a0e8c 100644 --- a/x-pack/test/functional/services/uptime/common.ts +++ b/x-pack/test/functional/services/uptime/common.ts @@ -10,6 +10,7 @@ export function UptimeCommonProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const browser = getService('browser'); const retry = getService('retry'); + const find = getService('find'); return { async assertExists(key: string) { @@ -52,6 +53,20 @@ export function UptimeCommonProvider({ getService }: FtrProviderContext) { async setStatusFilterDown() { await testSubjects.click('xpack.uptime.filterBar.filterStatusDown'); }, + async resetStatusFilter() { + const upFilter = await find.byCssSelector( + '[data-test-subj="xpack.uptime.filterBar.filterStatusUp"]' + ); + if (await upFilter.elementHasClass('euiFilterButton-hasActiveFilters')) { + this.setStatusFilterUp(); + } + const downFilter = await find.byCssSelector( + '[data-test-subj="xpack.uptime.filterBar.filterStatusDown"]' + ); + if (await downFilter.elementHasClass('euiFilterButton-hasActiveFilters')) { + this.setStatusFilterDown(); + } + }, async selectFilterItem(filterType: string, option: string) { const popoverId = `filter-popover_${filterType}`; const optionId = `filter-popover-item_${option}`; diff --git a/x-pack/test/functional/services/uptime/ml_anomaly.ts b/x-pack/test/functional/services/uptime/ml_anomaly.ts new file mode 100644 index 0000000000000..e15f47ddd9709 --- /dev/null +++ b/x-pack/test/functional/services/uptime/ml_anomaly.ts @@ -0,0 +1,59 @@ +/* + * 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 UptimeMLAnomalyProvider({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const log = getService('log'); + + return { + async openMLFlyout() { + return retry.tryForTime(15000, async () => { + await testSubjects.click('uptimeEnableAnomalyBtn'); + await testSubjects.existOrFail('uptimeMLFlyout'); + }); + }, + + async openMLManageMenu() { + return retry.tryForTime(30000, async () => { + await testSubjects.click('uptimeManageMLJobBtn'); + await testSubjects.existOrFail('uptimeManageMLContextMenu'); + }); + }, + + async alreadyHasJob() { + return await testSubjects.exists('uptimeManageMLJobBtn'); + }, + + async createMLJob() { + await testSubjects.click('uptimeMLCreateJobBtn'); + return retry.tryForTime(10000, async () => { + await testSubjects.existOrFail('uptimeMLJobSuccessfullyCreated'); + log.info('Job successfully created'); + }); + }, + + async deleteMLJob() { + await testSubjects.click('uptimeDeleteMLJobBtn'); + return retry.tryForTime(10000, async () => { + await testSubjects.click('uptimeMLJobDeleteConfirmModel > confirmModalConfirmButton'); + await testSubjects.existOrFail('uptimeMLJobSuccessfullyDeleted'); + log.info('Job successfully deleted'); + }); + }, + + async canCreateJob() { + const createJobBtn = await testSubjects.find('uptimeMLCreateJobBtn'); + return !!(await createJobBtn.getAttribute('disabled')); + }, + + async hasNoLicenseInfo() { + return await testSubjects.missingOrFail('uptimeMLLicenseInfo', { timeout: 1000 }); + }, + }; +} diff --git a/x-pack/test/functional/services/uptime/navigation.ts b/x-pack/test/functional/services/uptime/navigation.ts index 15ee869da1e6a..36a5d7c9702f8 100644 --- a/x-pack/test/functional/services/uptime/navigation.ts +++ b/x-pack/test/functional/services/uptime/navigation.ts @@ -9,17 +9,27 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export function UptimeNavigationProvider({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'header']); + const PageObjects = getPageObjects(['common', 'timePicker', 'header']); const goToUptimeRoot = async () => { - await retry.tryForTime(30 * 1000, async () => { - await PageObjects.common.navigateToApp('uptime'); - await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('uptimeOverviewPage', { timeout: 2000 }); + // Check if are already on overview uptime page, we don't need to repeat the step + await retry.tryForTime(60 * 1000, async () => { + if (await testSubjects.exists('uptimeSettingsToOverviewLink', { timeout: 0 })) { + await testSubjects.click('uptimeSettingsToOverviewLink'); + await testSubjects.existOrFail('uptimeOverviewPage', { timeout: 2000 }); + } else if (!(await testSubjects.exists('uptimeOverviewPage', { timeout: 0 }))) { + await PageObjects.common.navigateToApp('uptime'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('uptimeOverviewPage', { timeout: 2000 }); + } }); }; return { + async refreshApp() { + await testSubjects.click('superDatePickerApplyTimeButton'); + }, + async goToUptime() { await goToUptimeRoot(); }, @@ -30,17 +40,29 @@ export function UptimeNavigationProvider({ getService, getPageObjects }: FtrProv await testSubjects.existOrFail('uptimeSettingsPage', { timeout: 2000 }); }, - goToMonitor: async (monitorId: string, monitorName?: string) => { - await testSubjects.click(`monitor-page-link-${monitorId}`, 5000); - if ( - monitorName && - (await testSubjects.getVisibleText('monitor-page-title')) !== monitorName - ) { - throw new Error('Expected monitor name not found'); + checkIfOnMonitorPage: async (monitorId: string) => { + const monitorPage = await testSubjects.exists('uptimeMonitorPage', { timeout: 1000 }); + if (monitorId && monitorPage) { + const thisMonitorPage = + (await testSubjects.getVisibleText('monitor-page-title')) === monitorId; + return monitorPage && thisMonitorPage; + } else { + return monitorPage; + } + }, + + goToMonitor: async (monitorId: string) => { + if (!(await testSubjects.exists('uptimeMonitorPage', { timeout: 0 }))) { + await testSubjects.click(`monitor-page-link-${monitorId}`); + await testSubjects.existOrFail('uptimeMonitorPage', { + timeout: 30000, + }); } - await testSubjects.existOrFail('uptimeMonitorPage', { - timeout: 30000, - }); + }, + + async loadDataAndGoToMonitorPage(dateStart: string, dateEnd: string, monitorId: string) { + await PageObjects.timePicker.setAbsoluteRange(dateStart, dateEnd); + await this.goToMonitor(monitorId); }, }; } diff --git a/x-pack/test/functional/services/uptime/uptime.ts b/x-pack/test/functional/services/uptime/uptime.ts index c96bd0e0c4675..601feb6b0646e 100644 --- a/x-pack/test/functional/services/uptime/uptime.ts +++ b/x-pack/test/functional/services/uptime/uptime.ts @@ -11,6 +11,7 @@ import { UptimeCommonProvider } from './common'; import { UptimeMonitorProvider } from './monitor'; import { UptimeNavigationProvider } from './navigation'; import { UptimeAlertsProvider } from './alerts'; +import { UptimeMLAnomalyProvider } from './ml_anomaly'; export function UptimeProvider(context: FtrProviderContext) { const common = UptimeCommonProvider(context); @@ -18,6 +19,7 @@ export function UptimeProvider(context: FtrProviderContext) { const monitor = UptimeMonitorProvider(context); const navigation = UptimeNavigationProvider(context); const alerts = UptimeAlertsProvider(context); + const ml = UptimeMLAnomalyProvider(context); return { common, @@ -25,5 +27,6 @@ export function UptimeProvider(context: FtrProviderContext) { monitor, navigation, alerts, + ml, }; } From 36b4ad98883442c329f455d0d6ddd54ebf5e1b86 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar <dario.gieselaar@elastic.co> Date: Mon, 13 Apr 2020 14:06:20 +0200 Subject: [PATCH 058/121] [APM] Separate count/retainment telemetry requests (#63225) Separate count/retainment telemetry requests to make them less prone to timing out. Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../collect_data_telemetry/tasks.ts | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts index 85f233de2086d..e9801272cd57b 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts @@ -61,10 +61,10 @@ export const tasks: TelemetryTask[] = [ return prevJob.then(async data => { const { processorEvent, timeRange } = current; - const response = await search({ + const totalHitsResponse = await search({ index: indicesByProcessorEvent[processorEvent], body: { - size: 1, + size: 0, query: { bool: { filter: [ @@ -83,25 +83,43 @@ export const tasks: TelemetryTask[] = [ ] } }, - sort: { - '@timestamp': 'asc' - }, - _source: ['@timestamp'], track_total_hits: true } }); - const event = response.hits.hits[0]?._source as { - '@timestamp': number; - }; + const retainmentResponse = + timeRange === 'all' + ? await search({ + index: indicesByProcessorEvent[processorEvent], + body: { + query: { + bool: { + filter: [ + { term: { [PROCESSOR_EVENT]: processorEvent } } + ] + } + }, + sort: { + '@timestamp': 'asc' + }, + _source: ['@timestamp'] + } + }) + : null; + + const event = retainmentResponse?.hits.hits[0]?._source as + | { + '@timestamp': number; + } + | undefined; return merge({}, data, { counts: { [processorEvent]: { - [timeRange]: response.hits.total.value + [timeRange]: totalHitsResponse.hits.total.value } }, - ...(timeRange === 'all' && event + ...(event ? { retainment: { [processorEvent]: { From bbd501ea517225c551decd2f649255e7ff098c00 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck <thomas@elastic.co> Date: Mon, 13 Apr 2020 09:24:16 -0400 Subject: [PATCH 059/121] [Maps] Cleanup sources (#63175) - Introduces additional TS typing for sources - Organizes sources in sub-directories by type - migrates XYZTMSSource to TS --- .../server/maps_telemetry/maps_telemetry.ts | 2 + .../descriptor_types/descriptor_types.d.ts | 26 ++- .../public/layers/blended_vector_layer.ts | 6 +- x-pack/plugins/maps/public/layers/layer.d.ts | 1 + .../public/layers/layer_wizard_registry.ts | 20 +- .../{ => es_agg_source}/es_agg_source.d.ts | 10 +- .../{ => es_agg_source}/es_agg_source.js | 6 +- .../{ => es_agg_source}/es_agg_source.test.ts | 10 +- .../layers/sources/es_agg_source/index.ts | 7 + .../sources/{ => es_source}/es_source.d.ts | 8 +- .../sources/{ => es_source}/es_source.js | 14 +- .../public/layers/sources/es_source/index.ts | 7 + .../{ => es_term_source}/es_term_source.d.ts | 4 +- .../{ => es_term_source}/es_term_source.js | 8 +- .../es_term_source.test.js | 2 +- .../layers/sources/es_term_source/index.ts | 7 + .../maps/public/layers/sources/source.d.ts | 22 ++- .../public/layers/sources/source_registry.ts | 3 +- .../public/layers/sources/tms_source/index.ts | 7 + .../sources/{ => tms_source}/tms_source.d.ts | 3 +- .../sources/{ => tms_source}/tms_source.js | 2 +- .../layers/sources/vector_source/index.ts | 7 + .../{ => vector_source}/vector_source.d.ts | 6 +- .../{ => vector_source}/vector_source.js | 10 +- .../public/layers/sources/xyz_tms_source.d.ts | 11 -- .../public/layers/sources/xyz_tms_source.js | 187 ------------------ .../layers/sources/xyz_tms_source/index.ts | 8 + .../sources/xyz_tms_source/layer_wizard.tsx | 27 +++ .../sources/xyz_tms_source/xyz_tms_editor.tsx | 122 ++++++++++++ .../xyz_tms_source.test.ts | 12 +- .../sources/xyz_tms_source/xyz_tms_source.ts | 87 ++++++++ .../plugins/maps/public/layers/tile_layer.js | 4 +- .../maps/public/layers/tile_layer.test.ts | 2 +- .../maps/public/layers/vector_layer.d.ts | 4 +- 34 files changed, 392 insertions(+), 270 deletions(-) rename x-pack/plugins/maps/public/layers/sources/{ => es_agg_source}/es_agg_source.d.ts (73%) rename x-pack/plugins/maps/public/layers/sources/{ => es_agg_source}/es_agg_source.js (95%) rename x-pack/plugins/maps/public/layers/sources/{ => es_agg_source}/es_agg_source.test.ts (89%) create mode 100644 x-pack/plugins/maps/public/layers/sources/es_agg_source/index.ts rename x-pack/plugins/maps/public/layers/sources/{ => es_source}/es_source.d.ts (78%) rename x-pack/plugins/maps/public/layers/sources/{ => es_source}/es_source.js (95%) create mode 100644 x-pack/plugins/maps/public/layers/sources/es_source/index.ts rename x-pack/plugins/maps/public/layers/sources/{ => es_term_source}/es_term_source.d.ts (77%) rename x-pack/plugins/maps/public/layers/sources/{ => es_term_source}/es_term_source.js (95%) rename x-pack/plugins/maps/public/layers/sources/{ => es_term_source}/es_term_source.test.js (98%) create mode 100644 x-pack/plugins/maps/public/layers/sources/es_term_source/index.ts create mode 100644 x-pack/plugins/maps/public/layers/sources/tms_source/index.ts rename x-pack/plugins/maps/public/layers/sources/{ => tms_source}/tms_source.d.ts (80%) rename x-pack/plugins/maps/public/layers/sources/{ => tms_source}/tms_source.js (94%) create mode 100644 x-pack/plugins/maps/public/layers/sources/vector_source/index.ts rename x-pack/plugins/maps/public/layers/sources/{ => vector_source}/vector_source.d.ts (91%) rename x-pack/plugins/maps/public/layers/sources/{ => vector_source}/vector_source.js (93%) delete mode 100644 x-pack/plugins/maps/public/layers/sources/xyz_tms_source.d.ts delete mode 100644 x-pack/plugins/maps/public/layers/sources/xyz_tms_source.js create mode 100644 x-pack/plugins/maps/public/layers/sources/xyz_tms_source/index.ts create mode 100644 x-pack/plugins/maps/public/layers/sources/xyz_tms_source/layer_wizard.tsx create mode 100644 x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_editor.tsx rename x-pack/plugins/maps/public/layers/sources/{ => xyz_tms_source}/xyz_tms_source.test.ts (71%) create mode 100644 x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts index 5657e14622e9b..0300f22eeeb82 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts @@ -87,6 +87,8 @@ export function buildMapsTelemetry({ const mapsCount = layerLists.length; const dataSourcesCount = layerLists.map(lList => { + // todo: not every source-descriptor has an id + // @ts-ignore const sourceIdList = lList.map((layer: LayerDescriptor) => layer.sourceDescriptor.id); return _.uniq(sourceIdList).length; }); diff --git a/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts b/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts index fb49e1aaebe1c..ff285877750c5 100644 --- a/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts +++ b/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts @@ -9,6 +9,11 @@ import { AGG_TYPE, GRID_RESOLUTION, RENDER_AS, SORT_ORDER, SCALING_TYPES } from import { VectorStyleDescriptor } from './style_property_descriptor_types'; import { DataRequestDescriptor } from './data_request_descriptor_types'; +export type AttributionDescriptor = { + attributionText?: string; + attributionUrl?: string; +}; + export type AbstractSourceDescriptor = { id?: string; type: string; @@ -84,17 +89,26 @@ export type WMSSourceDescriptor = { attributionUrl: string; }; -export type XYZTMSSourceDescriptor = { - id: string; - type: string; - urlTemplate: string; -}; +export type XYZTMSSourceDescriptor = AbstractSourceDescriptor & + AttributionDescriptor & { + urlTemplate: string; + }; export type JoinDescriptor = { leftField: string; right: ESTermSourceDescriptor; }; +export type SourceDescriptor = + | XYZTMSSourceDescriptor + | WMSSourceDescriptor + | KibanaTilemapSourceDescriptor + | KibanaRegionmapSourceDescriptor + | ESTermSourceDescriptor + | ESSearchSourceDescriptor + | ESGeoGridSourceDescriptor + | EMSFileSourceDescriptor; + export type LayerDescriptor = { __dataRequests?: DataRequestDescriptor[]; __isInErrorState?: boolean; @@ -104,7 +118,7 @@ export type LayerDescriptor = { label?: string; minZoom?: number; maxZoom?: number; - sourceDescriptor: AbstractSourceDescriptor; + sourceDescriptor: SourceDescriptor; type?: string; visible?: boolean; }; diff --git a/x-pack/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/plugins/maps/public/layers/blended_vector_layer.ts index f5526ad703dd2..80bf0299380d9 100644 --- a/x-pack/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/layers/blended_vector_layer.ts @@ -34,6 +34,7 @@ import { VectorStyleDescriptor, SizeDynamicOptions, DynamicStylePropertyOptions, + VectorLayerDescriptor, } from '../../common/descriptor_types'; const ACTIVE_COUNT_DATA_ID = 'ACTIVE_COUNT_DATA_ID'; @@ -147,7 +148,10 @@ function getClusterStyleDescriptor( export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { static type = LAYER_TYPE.BLENDED_VECTOR; - static createDescriptor(options: VectorLayerArguments, mapColors: string[]) { + static createDescriptor( + options: VectorLayerDescriptor, + mapColors: string[] + ): VectorLayerDescriptor { const layerDescriptor = VectorLayer.createDescriptor(options, mapColors); layerDescriptor.type = BlendedVectorLayer.type; return layerDescriptor; diff --git a/x-pack/plugins/maps/public/layers/layer.d.ts b/x-pack/plugins/maps/public/layers/layer.d.ts index de59642ede8ab..8fb69734d3d06 100644 --- a/x-pack/plugins/maps/public/layers/layer.d.ts +++ b/x-pack/plugins/maps/public/layers/layer.d.ts @@ -25,6 +25,7 @@ export interface ILayerArguments { } export class AbstractLayer implements ILayer { + static createDescriptor(options: Partial<LayerDescriptor>, mapColors?: string[]): LayerDescriptor; constructor(layerArguments: ILayerArguments); getBounds(mapFilters: MapFilters): Promise<MapExtent>; getDataRequest(id: string): DataRequest | undefined; diff --git a/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts b/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts index 3ef4701269994..cb87aeaa9da3f 100644 --- a/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts +++ b/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts @@ -5,17 +5,21 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -type LayerWizard = { +import { ReactElement } from 'react'; +import { ISource } from './sources/source'; + +export type PreviewSourceHandler = (source: ISource | null) => void; + +export type RenderWizardArguments = { + onPreviewSource: PreviewSourceHandler; + inspectorAdapters: object; +}; + +export type LayerWizard = { description: string; icon: string; isIndexingSource?: boolean; - renderWizard({ - onPreviewSource, - inspectorAdapters, - }: { - onPreviewSource: () => void; - inspectorAdapters: unknown; - }): unknown; + renderWizard(renderWizardArguments: RenderWizardArguments): ReactElement<any>; title: string; }; diff --git a/x-pack/plugins/maps/public/layers/sources/es_agg_source.d.ts b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.d.ts similarity index 73% rename from x-pack/plugins/maps/public/layers/sources/es_agg_source.d.ts rename to x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.d.ts index 99ee1ec652b54..a93f9121d1e62 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_agg_source.d.ts +++ b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.d.ts @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IESSource } from './es_source'; -import { AbstractESSource } from './es_source'; -import { AGG_TYPE } from '../../../common/constants'; -import { IESAggField } from '../fields/es_agg_field'; -import { AbstractESAggSourceDescriptor } from '../../../common/descriptor_types'; +import { IESSource } from '../es_source'; +import { AbstractESSource } from '../es_source'; +import { AGG_TYPE } from '../../../../common/constants'; +import { IESAggField } from '../../fields/es_agg_field'; +import { AbstractESAggSourceDescriptor } from '../../../../common/descriptor_types'; export interface IESAggSource extends IESSource { getAggKey(aggType: AGG_TYPE, fieldName: string): string; diff --git a/x-pack/plugins/maps/public/layers/sources/es_agg_source.js b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js similarity index 95% rename from x-pack/plugins/maps/public/layers/sources/es_agg_source.js rename to x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js index 9f4b89cadc777..c6197f137f212 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_agg_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js @@ -5,15 +5,15 @@ */ import { i18n } from '@kbn/i18n'; -import { AbstractESSource } from './es_source'; -import { esAggFieldsFactory } from '../fields/es_agg_field'; +import { AbstractESSource } from '../es_source'; +import { esAggFieldsFactory } from '../../fields/es_agg_field'; import { AGG_TYPE, COUNT_PROP_LABEL, COUNT_PROP_NAME, FIELD_ORIGIN, -} from '../../../common/constants'; +} from '../../../../common/constants'; export const AGG_DELIMITER = '_of_'; diff --git a/x-pack/plugins/maps/public/layers/sources/es_agg_source.test.ts b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.test.ts similarity index 89% rename from x-pack/plugins/maps/public/layers/sources/es_agg_source.test.ts rename to x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.test.ts index 848091586eb9c..87abbedfdf50e 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_agg_source.test.ts +++ b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.test.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AbstractESAggSource } from './es_agg_source'; -import { IField } from '../fields/field'; -import { IESAggField } from '../fields/es_agg_field'; +import { AbstractESAggSource } from '../es_agg_source'; +import { IField } from '../../fields/field'; +import { IESAggField } from '../../fields/es_agg_field'; import _ from 'lodash'; -import { AGG_TYPE } from '../../../common/constants'; -import { AggDescriptor } from '../../../common/descriptor_types'; +import { AGG_TYPE } from '../../../../common/constants'; +import { AggDescriptor } from '../../../../common/descriptor_types'; jest.mock('ui/new_platform'); diff --git a/x-pack/plugins/maps/public/layers/sources/es_agg_source/index.ts b/x-pack/plugins/maps/public/layers/sources/es_agg_source/index.ts new file mode 100644 index 0000000000000..cbf4eceefd432 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/es_agg_source/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 * from './es_agg_source'; diff --git a/x-pack/plugins/maps/public/layers/sources/es_source.d.ts b/x-pack/plugins/maps/public/layers/sources/es_source/es_source.d.ts similarity index 78% rename from x-pack/plugins/maps/public/layers/sources/es_source.d.ts rename to x-pack/plugins/maps/public/layers/sources/es_source/es_source.d.ts index 65851d0e7bd38..092dc3bf0d5a8 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_source.d.ts +++ b/x-pack/plugins/maps/public/layers/sources/es_source/es_source.d.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AbstractVectorSource } from './vector_source'; -import { IVectorSource } from './vector_source'; -import { IndexPattern, SearchSource } from '../../../../../../src/plugins/data/public'; -import { VectorSourceRequestMeta } from '../../../common/descriptor_types'; +import { AbstractVectorSource } from '../vector_source'; +import { IVectorSource } from '../vector_source'; +import { IndexPattern, SearchSource } from '../../../../../../../src/plugins/data/public'; +import { VectorSourceRequestMeta } from '../../../../common/descriptor_types'; export interface IESSource extends IVectorSource { getId(): string; diff --git a/x-pack/plugins/maps/public/layers/sources/es_source.js b/x-pack/plugins/maps/public/layers/sources/es_source/es_source.js similarity index 95% rename from x-pack/plugins/maps/public/layers/sources/es_source.js rename to x-pack/plugins/maps/public/layers/sources/es_source/es_source.js index d90a802a38344..3402e367cbd73 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_source/es_source.js @@ -4,23 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AbstractVectorSource } from './vector_source'; +import { AbstractVectorSource } from '../vector_source'; import { getAutocompleteService, fetchSearchSourceAndRecordWithInspector, getIndexPatternService, SearchSource, getTimeFilter, -} from '../../kibana_services'; -import { createExtentFilter } from '../../elasticsearch_geo_utils'; +} from '../../../kibana_services'; +import { createExtentFilter } from '../../../elasticsearch_geo_utils'; import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { copyPersistentState } from '../../reducers/util'; -import { ES_GEO_FIELD_TYPE } from '../../../common/constants'; -import { DataRequestAbortError } from '../util/data_request'; -import { expandToTileBoundaries } from './es_geo_grid_source/geo_tile_utils'; +import { copyPersistentState } from '../../../reducers/util'; +import { ES_GEO_FIELD_TYPE } from '../../../../common/constants'; +import { DataRequestAbortError } from '../../util/data_request'; +import { expandToTileBoundaries } from '../es_geo_grid_source/geo_tile_utils'; export class AbstractESSource extends AbstractVectorSource { constructor(descriptor, inspectorAdapters) { diff --git a/x-pack/plugins/maps/public/layers/sources/es_source/index.ts b/x-pack/plugins/maps/public/layers/sources/es_source/index.ts new file mode 100644 index 0000000000000..227a4dd634457 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/es_source/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 * from './es_source'; diff --git a/x-pack/plugins/maps/public/layers/sources/es_term_source.d.ts b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.d.ts similarity index 77% rename from x-pack/plugins/maps/public/layers/sources/es_term_source.d.ts rename to x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.d.ts index 44cdc851b4fc7..701bd5e2c8b5e 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_term_source.d.ts +++ b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.d.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IField } from '../fields/field'; -import { IESAggSource } from './es_agg_source'; +import { IField } from '../../fields/field'; +import { IESAggSource } from '../es_agg_source'; export interface IESTermSource extends IESAggSource { getTermField(): IField; diff --git a/x-pack/plugins/maps/public/layers/sources/es_term_source.js b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js similarity index 95% rename from x-pack/plugins/maps/public/layers/sources/es_term_source.js rename to x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js index 3ce0fb58aba19..826197cc4fec7 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_term_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js @@ -7,10 +7,10 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN, AGG_TYPE } from '../../../common/constants'; -import { ESDocField } from '../fields/es_doc_field'; -import { AbstractESAggSource, AGG_DELIMITER } from './es_agg_source'; -import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../util/es_agg_utils'; +import { DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN, AGG_TYPE } from '../../../../common/constants'; +import { ESDocField } from '../../fields/es_doc_field'; +import { AbstractESAggSource, AGG_DELIMITER } from '../es_agg_source'; +import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../../util/es_agg_utils'; const TERMS_AGG_NAME = 'join'; diff --git a/x-pack/plugins/maps/public/layers/sources/es_term_source.test.js b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.test.js similarity index 98% rename from x-pack/plugins/maps/public/layers/sources/es_term_source.test.js rename to x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.test.js index 14ffd068df465..b6cd3b670d3ce 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_term_source.test.js +++ b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.test.js @@ -7,7 +7,7 @@ import { ESTermSource, extractPropertiesMap } from './es_term_source'; jest.mock('ui/new_platform'); -jest.mock('../vector_layer', () => {}); +jest.mock('../../vector_layer', () => {}); const indexPatternTitle = 'myIndex'; const termFieldName = 'myTermField'; diff --git a/x-pack/plugins/maps/public/layers/sources/es_term_source/index.ts b/x-pack/plugins/maps/public/layers/sources/es_term_source/index.ts new file mode 100644 index 0000000000000..6fad8384c690d --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/es_term_source/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 * from './es_term_source'; diff --git a/x-pack/plugins/maps/public/layers/sources/source.d.ts b/x-pack/plugins/maps/public/layers/sources/source.d.ts index e1706ad7b7d77..a1581b826d9a6 100644 --- a/x-pack/plugins/maps/public/layers/sources/source.d.ts +++ b/x-pack/plugins/maps/public/layers/sources/source.d.ts @@ -3,10 +3,21 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ -import { AbstractSourceDescriptor } from '../../../common/descriptor_types'; +import { AbstractSourceDescriptor, LayerDescriptor } from '../../../common/descriptor_types'; import { ILayer } from '../layer'; +export type ImmutableSourceProperty = { + label: string; + value: string; +}; + +export type Attribution = { + url: string; + label: string; +}; + export interface ISource { createDefaultLayer(): ILayer; destroy(): void; @@ -18,13 +29,16 @@ export interface ISource { isQueryAware(): boolean; isRefreshTimerAware(): Promise<boolean>; isTimeAware(): Promise<boolean>; + getImmutableProperties(): Promise<ImmutableSourceProperty[]>; + getAttributions(): Promise<Attribution[]>; } export class AbstractSource implements ISource { - constructor(sourceDescriptor: AbstractSourceDescriptor, inspectorAdapters: object); + readonly _descriptor: AbstractSourceDescriptor; + constructor(sourceDescriptor: AbstractSourceDescriptor, inspectorAdapters?: object); destroy(): void; - createDefaultLayer(): ILayer; + createDefaultLayer(options?: LayerDescriptor, mapColors?: string[]): ILayer; getDisplayName(): Promise<string>; getInspectorAdapters(): object; isFieldAware(): boolean; @@ -33,4 +47,6 @@ export class AbstractSource implements ISource { isQueryAware(): boolean; isRefreshTimerAware(): Promise<boolean>; isTimeAware(): Promise<boolean>; + getImmutableProperties(): Promise<ImmutableSourceProperty[]>; + getAttributions(): Promise<Attribution[]>; } diff --git a/x-pack/plugins/maps/public/layers/sources/source_registry.ts b/x-pack/plugins/maps/public/layers/sources/source_registry.ts index 518cab68b601b..d16b16af74e9d 100644 --- a/x-pack/plugins/maps/public/layers/sources/source_registry.ts +++ b/x-pack/plugins/maps/public/layers/sources/source_registry.ts @@ -5,12 +5,11 @@ */ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import { AbstractSourceDescriptor } from '../../../common/descriptor_types'; import { ISource } from './source'; type SourceRegistryEntry = { ConstructorFunction: new ( - sourceDescriptor: AbstractSourceDescriptor, + sourceDescriptor: any, // this is the source-descriptor that corresponds specifically to the particular ISource instance inspectorAdapters: unknown ) => ISource; type: string; diff --git a/x-pack/plugins/maps/public/layers/sources/tms_source/index.ts b/x-pack/plugins/maps/public/layers/sources/tms_source/index.ts new file mode 100644 index 0000000000000..f6bb1c6bc34ec --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/tms_source/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 * from './tms_source'; diff --git a/x-pack/plugins/maps/public/layers/sources/tms_source.d.ts b/x-pack/plugins/maps/public/layers/sources/tms_source/tms_source.d.ts similarity index 80% rename from x-pack/plugins/maps/public/layers/sources/tms_source.d.ts rename to x-pack/plugins/maps/public/layers/sources/tms_source/tms_source.d.ts index 90b6f28e050fd..b31138f4cdb86 100644 --- a/x-pack/plugins/maps/public/layers/sources/tms_source.d.ts +++ b/x-pack/plugins/maps/public/layers/sources/tms_source/tms_source.d.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AbstractSource, ISource } from './source'; +import { AbstractSource, Attribution, ISource } from '../source'; export interface ITMSSource extends ISource { getUrlTemplate(): Promise<string>; @@ -12,4 +12,5 @@ export interface ITMSSource extends ISource { export class AbstractTMSSource extends AbstractSource implements ITMSSource { getUrlTemplate(): Promise<string>; + getAttributions(): Promise<Attribution[]>; } diff --git a/x-pack/plugins/maps/public/layers/sources/tms_source.js b/x-pack/plugins/maps/public/layers/sources/tms_source/tms_source.js similarity index 94% rename from x-pack/plugins/maps/public/layers/sources/tms_source.js rename to x-pack/plugins/maps/public/layers/sources/tms_source/tms_source.js index f2ec9f2a29378..13b8da11633bc 100644 --- a/x-pack/plugins/maps/public/layers/sources/tms_source.js +++ b/x-pack/plugins/maps/public/layers/sources/tms_source/tms_source.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AbstractSource } from './source'; +import { AbstractSource } from '../source'; export class AbstractTMSSource extends AbstractSource { async getUrlTemplate() { diff --git a/x-pack/plugins/maps/public/layers/sources/vector_source/index.ts b/x-pack/plugins/maps/public/layers/sources/vector_source/index.ts new file mode 100644 index 0000000000000..62e801d027634 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/vector_source/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 * from './vector_source'; diff --git a/x-pack/plugins/maps/public/layers/sources/vector_source.d.ts b/x-pack/plugins/maps/public/layers/sources/vector_source/vector_source.d.ts similarity index 91% rename from x-pack/plugins/maps/public/layers/sources/vector_source.d.ts rename to x-pack/plugins/maps/public/layers/sources/vector_source/vector_source.d.ts index d597e64277186..63429830d9f4f 100644 --- a/x-pack/plugins/maps/public/layers/sources/vector_source.d.ts +++ b/x-pack/plugins/maps/public/layers/sources/vector_source/vector_source.d.ts @@ -6,14 +6,14 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ import { FeatureCollection } from 'geojson'; -import { AbstractSource, ISource } from './source'; -import { IField } from '../fields/field'; +import { AbstractSource, ISource } from '../source'; +import { IField } from '../../fields/field'; import { ESSearchSourceResponseMeta, MapExtent, VectorSourceRequestMeta, VectorSourceSyncMeta, -} from '../../../common/descriptor_types'; +} from '../../../../common/descriptor_types'; export type GeoJsonFetchMeta = ESSearchSourceResponseMeta; diff --git a/x-pack/plugins/maps/public/layers/sources/vector_source.js b/x-pack/plugins/maps/public/layers/sources/vector_source/vector_source.js similarity index 93% rename from x-pack/plugins/maps/public/layers/sources/vector_source.js rename to x-pack/plugins/maps/public/layers/sources/vector_source/vector_source.js index 7f97b1b21d189..bb37175b48655 100644 --- a/x-pack/plugins/maps/public/layers/sources/vector_source.js +++ b/x-pack/plugins/maps/public/layers/sources/vector_source/vector_source.js @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { VectorLayer } from '../vector_layer'; -import { TooltipProperty } from '../tooltips/tooltip_property'; -import { VectorStyle } from '../styles/vector/vector_style'; -import { AbstractSource } from './source'; +import { VectorLayer } from '../../vector_layer'; +import { TooltipProperty } from '../../tooltips/tooltip_property'; +import { VectorStyle } from '../../styles/vector/vector_style'; +import { AbstractSource } from './../source'; import * as topojson from 'topojson-client'; import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { VECTOR_SHAPE_TYPES } from './vector_feature_types'; +import { VECTOR_SHAPE_TYPES } from './../vector_feature_types'; export class AbstractVectorSource extends AbstractSource { static async getGeoJson({ format, featureCollectionPath, fetchUrl }) { diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.d.ts b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.d.ts deleted file mode 100644 index 579c9debeab3e..0000000000000 --- a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.d.ts +++ /dev/null @@ -1,11 +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 { AbstractTMSSource } from './tms_source'; -import { XYZTMSSourceDescriptor } from '../../../common/descriptor_types'; - -export class XYZTMSSource extends AbstractTMSSource { - constructor(sourceDescriptor: XYZTMSSourceDescriptor, inspectorAdapters: unknown); -} diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.js b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.js deleted file mode 100644 index d53fbffd21512..0000000000000 --- a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.js +++ /dev/null @@ -1,187 +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 } from 'react'; -import { EuiFieldText, EuiFormRow } from '@elastic/eui'; - -import { AbstractTMSSource } from './tms_source'; -import { TileLayer } from '../tile_layer'; -import { i18n } from '@kbn/i18n'; -import { getDataSourceLabel, getUrlLabel } from '../../../common/i18n_getters'; -import _ from 'lodash'; -import { EMS_XYZ } from '../../../common/constants'; -import { registerSource } from './source_registry'; - -const sourceTitle = i18n.translate('xpack.maps.source.ems_xyzTitle', { - defaultMessage: 'Tile Map Service', -}); - -export class XYZTMSSource extends AbstractTMSSource { - static type = EMS_XYZ; - - static createDescriptor({ urlTemplate, attributionText, attributionUrl }) { - return { - type: XYZTMSSource.type, - urlTemplate, - attributionText, - attributionUrl, - }; - } - - async getImmutableProperties() { - return [ - { label: getDataSourceLabel(), value: sourceTitle }, - { label: getUrlLabel(), value: this._descriptor.urlTemplate }, - ]; - } - - _createDefaultLayerDescriptor(options) { - return TileLayer.createDescriptor({ - sourceDescriptor: this._descriptor, - ...options, - }); - } - - createDefaultLayer(options) { - return new TileLayer({ - layerDescriptor: this._createDefaultLayerDescriptor(options), - source: this, - }); - } - - async getDisplayName() { - return this._descriptor.urlTemplate; - } - - getAttributions() { - const { attributionText, attributionUrl } = this._descriptor; - const attributionComplete = !!attributionText && !!attributionUrl; - - return attributionComplete - ? [ - { - url: attributionUrl, - label: attributionText, - }, - ] - : []; - } - - getUrlTemplate() { - return this._descriptor.urlTemplate; - } -} - -class XYZTMSEditor extends React.Component { - state = { - tmsInput: '', - tmsCanPreview: false, - attributionText: '', - attributionUrl: '', - }; - - _sourceConfigChange = _.debounce(updatedSourceConfig => { - if (this.state.tmsCanPreview) { - this.props.onSourceConfigChange(updatedSourceConfig); - } - }, 2000); - - _handleTMSInputChange(e) { - const url = e.target.value; - - const canPreview = - url.indexOf('{x}') >= 0 && url.indexOf('{y}') >= 0 && url.indexOf('{z}') >= 0; - this.setState( - { - tmsInput: url, - tmsCanPreview: canPreview, - }, - () => this._sourceConfigChange({ urlTemplate: url }) - ); - } - - _handleTMSAttributionChange(attributionUpdate) { - this.setState(attributionUpdate, () => { - const { attributionText, attributionUrl, tmsInput } = this.state; - - if (tmsInput && attributionText && attributionUrl) { - this._sourceConfigChange({ - urlTemplate: tmsInput, - attributionText, - attributionUrl, - }); - } - }); - } - - render() { - const { attributionText, attributionUrl } = this.state; - - return ( - <Fragment> - <EuiFormRow label="Url"> - <EuiFieldText - placeholder={'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'} - onChange={e => this._handleTMSInputChange(e)} - /> - </EuiFormRow> - <EuiFormRow - label="Attribution text" - isInvalid={attributionUrl !== '' && attributionText === ''} - error={[ - i18n.translate('xpack.maps.xyztmssource.attributionText', { - defaultMessage: 'Attribution url must have accompanying text', - }), - ]} - > - <EuiFieldText - placeholder={'© OpenStreetMap contributors'} - onChange={({ target }) => - this._handleTMSAttributionChange({ attributionText: target.value }) - } - /> - </EuiFormRow> - <EuiFormRow - label="Attribution link" - isInvalid={attributionText !== '' && attributionUrl === ''} - error={[ - i18n.translate('xpack.maps.xyztmssource.attributionLink', { - defaultMessage: 'Attribution text must have an accompanying link', - }), - ]} - > - <EuiFieldText - placeholder={'https://www.openstreetmap.org/copyright'} - onChange={({ target }) => - this._handleTMSAttributionChange({ attributionUrl: target.value }) - } - /> - </EuiFormRow> - </Fragment> - ); - } -} - -registerSource({ - ConstructorFunction: XYZTMSSource, - type: EMS_XYZ, -}); - -export const tmsLayerWizardConfig = { - description: i18n.translate('xpack.maps.source.ems_xyzDescription', { - defaultMessage: 'Tile map service configured in interface', - }), - icon: 'grid', - renderWizard: ({ onPreviewSource, inspectorAdapters }) => { - const onSourceConfigChange = sourceConfig => { - const sourceDescriptor = XYZTMSSource.createDescriptor(sourceConfig); - const source = new XYZTMSSource(sourceDescriptor, inspectorAdapters); - onPreviewSource(source); - }; - return <XYZTMSEditor onSourceConfigChange={onSourceConfigChange} />; - }, - title: sourceTitle, -}; diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/index.ts b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/index.ts new file mode 100644 index 0000000000000..c1116ad47a375 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './xyz_tms_source'; +export * from './layer_wizard'; diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/layer_wizard.tsx b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/layer_wizard.tsx new file mode 100644 index 0000000000000..8b1ed588c8dd1 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/layer_wizard.tsx @@ -0,0 +1,27 @@ +/* + * 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 { XYZTMSEditor, XYZTMSSourceConfig } from './xyz_tms_editor'; +import { XYZTMSSource, sourceTitle } from './xyz_tms_source'; +import { LayerWizard, RenderWizardArguments } from '../../layer_wizard_registry'; + +export const tmsLayerWizardConfig: LayerWizard = { + description: i18n.translate('xpack.maps.source.ems_xyzDescription', { + defaultMessage: 'Tile map service configured in interface', + }), + icon: 'grid', + renderWizard: ({ onPreviewSource }: RenderWizardArguments) => { + const onSourceConfigChange = (sourceConfig: XYZTMSSourceConfig) => { + const sourceDescriptor = XYZTMSSource.createDescriptor(sourceConfig); + const source = new XYZTMSSource(sourceDescriptor); + onPreviewSource(source); + }; + return <XYZTMSEditor onSourceConfigChange={onSourceConfigChange} />; + }, + title: sourceTitle, +}; diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_editor.tsx b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_editor.tsx new file mode 100644 index 0000000000000..0ee0fbb23bcff --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_editor.tsx @@ -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. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import React, { Fragment, Component, ChangeEvent } from 'react'; +import _ from 'lodash'; +import { EuiFormRow, EuiFieldText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { AttributionDescriptor } from '../../../../common/descriptor_types'; + +export type XYZTMSSourceConfig = AttributionDescriptor & { + urlTemplate: string; +}; + +export interface Props { + onSourceConfigChange: (sourceConfig: XYZTMSSourceConfig) => void; +} + +interface State { + tmsInput: string; + tmsCanPreview: boolean; + attributionText: string; + attributionUrl: string; +} + +export class XYZTMSEditor extends Component<Props, State> { + state = { + tmsInput: '', + tmsCanPreview: false, + attributionText: '', + attributionUrl: '', + }; + + _sourceConfigChange = _.debounce((updatedSourceConfig: XYZTMSSourceConfig) => { + if (this.state.tmsCanPreview) { + this.props.onSourceConfigChange(updatedSourceConfig); + } + }, 2000); + + _handleTMSInputChange(e: ChangeEvent<HTMLInputElement>) { + const url = e.target.value; + + const canPreview = + url.indexOf('{x}') >= 0 && url.indexOf('{y}') >= 0 && url.indexOf('{z}') >= 0; + this.setState( + { + tmsInput: url, + tmsCanPreview: canPreview, + }, + () => this._sourceConfigChange({ urlTemplate: url }) + ); + } + + _handleTMSAttributionChange(attributionUpdate: AttributionDescriptor) { + this.setState( + { + attributionUrl: attributionUpdate.attributionUrl || '', + attributionText: attributionUpdate.attributionText || '', + }, + () => { + const { attributionText, attributionUrl, tmsInput } = this.state; + + if (tmsInput && attributionText && attributionUrl) { + this._sourceConfigChange({ + urlTemplate: tmsInput, + attributionText, + attributionUrl, + }); + } + } + ); + } + + render() { + const { attributionText, attributionUrl } = this.state; + return ( + <Fragment> + <EuiFormRow label="Url"> + <EuiFieldText + placeholder={'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'} + onChange={e => this._handleTMSInputChange(e)} + /> + </EuiFormRow> + <EuiFormRow + label="Attribution text" + isInvalid={attributionUrl !== '' && attributionText === ''} + error={[ + i18n.translate('xpack.maps.xyztmssource.attributionText', { + defaultMessage: 'Attribution url must have accompanying text', + }), + ]} + > + <EuiFieldText + placeholder={'© OpenStreetMap contributors'} + onChange={({ target }: ChangeEvent<HTMLInputElement>) => + this._handleTMSAttributionChange({ attributionText: target.value }) + } + /> + </EuiFormRow> + <EuiFormRow + label="Attribution link" + isInvalid={attributionText !== '' && attributionUrl === ''} + error={[ + i18n.translate('xpack.maps.xyztmssource.attributionLink', { + defaultMessage: 'Attribution text must have an accompanying link', + }), + ]} + > + <EuiFieldText + placeholder={'https://www.openstreetmap.org/copyright'} + onChange={({ target }: ChangeEvent<HTMLInputElement>) => + this._handleTMSAttributionChange({ attributionUrl: target.value }) + } + /> + </EuiFormRow> + </Fragment> + ); + } +} diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.test.ts b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.test.ts similarity index 71% rename from x-pack/plugins/maps/public/layers/sources/xyz_tms_source.test.ts rename to x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.test.ts index e5ab5e57122ba..8a5cfb01e5821 100644 --- a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source.test.ts +++ b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.test.ts @@ -5,10 +5,10 @@ */ import { XYZTMSSource } from './xyz_tms_source'; -import { ILayer } from '../layer'; -import { TileLayer } from '../tile_layer'; -import { EMS_XYZ } from '../../../common/constants'; -import { XYZTMSSourceDescriptor } from '../../../common/descriptor_types'; +import { ILayer } from '../../layer'; +import { TileLayer } from '../../tile_layer'; +import { EMS_XYZ } from '../../../../common/constants'; +import { XYZTMSSourceDescriptor } from '../../../../common/descriptor_types'; const descriptor: XYZTMSSourceDescriptor = { type: EMS_XYZ, @@ -17,13 +17,13 @@ const descriptor: XYZTMSSourceDescriptor = { }; describe('xyz Tilemap Source', () => { it('should create a tile-layer', () => { - const source = new XYZTMSSource(descriptor, null); + const source = new XYZTMSSource(descriptor); const layer: ILayer = source.createDefaultLayer(); expect(layer instanceof TileLayer).toEqual(true); }); it('should echo url template for url template', async () => { - const source = new XYZTMSSource(descriptor, null); + const source = new XYZTMSSource(descriptor); const template = await source.getUrlTemplate(); expect(template).toEqual(descriptor.urlTemplate); }); diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts new file mode 100644 index 0000000000000..dd96c31573316 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts @@ -0,0 +1,87 @@ +/* + * 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 { TileLayer } from '../../tile_layer'; +import { getDataSourceLabel, getUrlLabel } from '../../../../common/i18n_getters'; +import { EMS_XYZ } from '../../../../common/constants'; +import { registerSource } from '../source_registry'; +import { AbstractTMSSource } from '../tms_source'; +import { LayerDescriptor, XYZTMSSourceDescriptor } from '../../../../common/descriptor_types'; +import { Attribution, ImmutableSourceProperty } from '../source'; +import { XYZTMSSourceConfig } from './xyz_tms_editor'; + +export const sourceTitle = i18n.translate('xpack.maps.source.ems_xyzTitle', { + defaultMessage: 'Tile Map Service', +}); + +export class XYZTMSSource extends AbstractTMSSource { + static type = EMS_XYZ; + + readonly _descriptor: XYZTMSSourceDescriptor; + + static createDescriptor({ + urlTemplate, + attributionText, + attributionUrl, + }: XYZTMSSourceConfig): XYZTMSSourceDescriptor { + return { + type: XYZTMSSource.type, + urlTemplate, + attributionText, + attributionUrl, + }; + } + + constructor(sourceDescriptor: XYZTMSSourceDescriptor) { + super(sourceDescriptor); + this._descriptor = sourceDescriptor; + } + + async getImmutableProperties(): Promise<ImmutableSourceProperty[]> { + return [ + { label: getDataSourceLabel(), value: sourceTitle }, + { label: getUrlLabel(), value: this._descriptor.urlTemplate }, + ]; + } + + createDefaultLayer(options?: LayerDescriptor): TileLayer { + const layerDescriptor: LayerDescriptor = TileLayer.createDescriptor({ + sourceDescriptor: this._descriptor, + ...options, + }); + return new TileLayer({ + layerDescriptor, + source: this, + }); + } + + async getDisplayName(): Promise<string> { + return this._descriptor.urlTemplate; + } + + async getAttributions(): Promise<Attribution[]> { + const { attributionText, attributionUrl } = this._descriptor; + const attributionComplete = !!attributionText && !!attributionUrl; + return attributionComplete + ? [ + { + url: attributionUrl as string, + label: attributionText as string, + }, + ] + : []; + } + + async getUrlTemplate(): Promise<string> { + return this._descriptor.urlTemplate; + } +} + +registerSource({ + ConstructorFunction: XYZTMSSource, + type: EMS_XYZ, +}); diff --git a/x-pack/plugins/maps/public/layers/tile_layer.js b/x-pack/plugins/maps/public/layers/tile_layer.js index aa2619e96f834..2ac60e12d137a 100644 --- a/x-pack/plugins/maps/public/layers/tile_layer.js +++ b/x-pack/plugins/maps/public/layers/tile_layer.js @@ -11,8 +11,8 @@ import { SOURCE_DATA_ID_ORIGIN, LAYER_TYPE } from '../../common/constants'; export class TileLayer extends AbstractLayer { static type = LAYER_TYPE.TILE; - static createDescriptor(options) { - const tileLayerDescriptor = super.createDescriptor(options); + static createDescriptor(options, mapColors) { + const tileLayerDescriptor = super.createDescriptor(options, mapColors); tileLayerDescriptor.type = TileLayer.type; tileLayerDescriptor.alpha = _.get(options, 'alpha', 1); return tileLayerDescriptor; diff --git a/x-pack/plugins/maps/public/layers/tile_layer.test.ts b/x-pack/plugins/maps/public/layers/tile_layer.test.ts index 1cb99dcbc1a70..43465eac7f3ce 100644 --- a/x-pack/plugins/maps/public/layers/tile_layer.test.ts +++ b/x-pack/plugins/maps/public/layers/tile_layer.test.ts @@ -17,7 +17,7 @@ const sourceDescriptor: XYZTMSSourceDescriptor = { }; class MockTileSource extends AbstractTMSSource implements ITMSSource { - private readonly _descriptor: XYZTMSSourceDescriptor; + readonly _descriptor: XYZTMSSourceDescriptor; constructor(descriptor: XYZTMSSourceDescriptor) { super(descriptor, {}); this._descriptor = descriptor; diff --git a/x-pack/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/plugins/maps/public/layers/vector_layer.d.ts index 70fd9927b7732..88b1a1ce8535e 100644 --- a/x-pack/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/plugins/maps/public/layers/vector_layer.d.ts @@ -32,8 +32,8 @@ export interface IVectorLayer extends ILayer { export class VectorLayer extends AbstractLayer implements IVectorLayer { static createDescriptor( - options: VectorLayerArguments, - mapColors: string[] + options: Partial<VectorLayerDescriptor>, + mapColors?: string[] ): VectorLayerDescriptor; protected readonly _source: IVectorSource; From e74d360adb1acfa2b4316d75d9ca5da56c9437e4 Mon Sep 17 00:00:00 2001 From: MadameSheema <snootchie.boochies@gmail.com> Date: Mon, 13 Apr 2020 15:38:32 +0200 Subject: [PATCH 060/121] fixes test flakiness (#63331) --- .../signal_detection_rules.spec.ts | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules.spec.ts index 2d2db9e70255b..ce6a49b675ef1 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/signal_detection_rules.spec.ts @@ -7,11 +7,16 @@ import { FIFTH_RULE, FIRST_RULE, RULE_NAME, + RULE_SWITCH, SECOND_RULE, SEVENTH_RULE, } from '../screens/signal_detection_rules'; -import { goToManageSignalDetectionRules } from '../tasks/detections'; +import { + goToManageSignalDetectionRules, + waitForSignalsPanelToBeLoaded, + waitForSignalsIndexToBeCreated, +} from '../tasks/detections'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { @@ -32,8 +37,10 @@ describe('Signal detection rules', () => { esArchiverUnload('prebuilt_rules_loaded'); }); - it.skip('Sorts by activated rules', () => { + it('Sorts by activated rules', () => { loginAndWaitForPageWithoutDateRange(DETECTIONS); + waitForSignalsPanelToBeLoaded(); + waitForSignalsIndexToBeCreated(); goToManageSignalDetectionRules(); waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); cy.get(RULE_NAME) @@ -52,10 +59,24 @@ describe('Signal detection rules', () => { cy.get(RULE_NAME) .eq(FIRST_RULE) - .should('have.text', fifthRuleName); - cy.get(RULE_NAME) + .invoke('text') + .then(firstRuleName => { + cy.get(RULE_NAME) + .eq(SECOND_RULE) + .invoke('text') + .then(secondRuleName => { + const expectedRulesNames = `${firstRuleName} ${secondRuleName}`; + cy.wrap(expectedRulesNames).should('include', fifthRuleName); + cy.wrap(expectedRulesNames).should('include', seventhRuleName); + }); + }); + + cy.get(RULE_SWITCH) + .eq(FIRST_RULE) + .should('have.attr', 'role', 'switch'); + cy.get(RULE_SWITCH) .eq(SECOND_RULE) - .should('have.text', seventhRuleName); + .should('have.attr', 'role', 'switch'); }); }); }); From c604eb9e63dcb7fe89b25bb4bc3b4a1b23e221d2 Mon Sep 17 00:00:00 2001 From: Nathan Reese <reese.nathan@gmail.com> Date: Mon, 13 Apr 2020 08:00:15 -0600 Subject: [PATCH 061/121] [Maps] fix regression in loading left join fields (#63325) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../maps/public/connected_components/layer_panel/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js index b3ad3d1df68ce..256f52112ba97 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/index.js @@ -12,7 +12,7 @@ import { fitToLayerExtent, updateSourceProp } from '../../actions/map_actions'; function mapStateToProps(state = {}) { const selectedLayer = getSelectedLayer(state); return { - key: selectedLayer ? selectedLayer.getId() : '', + key: selectedLayer ? `${selectedLayer.getId()}${selectedLayer.isJoinable()}` : '', selectedLayer, }; } From 8cef9457c1f4d07bdf19fbc4679768f261699311 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet <nicolas.chaulet@elastic.co> Date: Mon, 13 Apr 2020 10:39:40 -0400 Subject: [PATCH 062/121] [Ingest] Update Create datasource UI to fit in one page (#62858) --- .../enrollment_instructions/shell/index.tsx | 2 +- .../ingest_manager/components/header.tsx | 37 +- .../components/confirm_modal.tsx | 72 ++++ .../components/index.ts | 1 + .../components/layout.tsx | 175 +++++---- .../components/navigation.tsx | 85 ----- .../create_datasource_page/constants.ts | 7 - .../create_datasource_page/index.tsx | 348 +++++++++--------- .../step_configure_datasource.tsx | 188 +--------- .../step_define_datasource.tsx | 165 +++++++++ .../create_datasource_page/step_review.tsx | 202 ---------- .../step_select_config.tsx | 78 +--- .../step_select_package.tsx | 54 +-- .../agent_enrollment_flyout/instructions.tsx | 2 +- .../sections/fleet/agent_list_page/index.tsx | 4 +- .../translations/translations/ja-JP.json | 20 - .../translations/translations/zh-CN.json | 20 - 17 files changed, 550 insertions(+), 910 deletions(-) create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/confirm_modal.tsx delete mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_define_datasource.tsx delete mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_review.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/shell/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/shell/index.tsx index e6990927b926e..cb65e31fb74b5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/shell/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/shell/index.tsx @@ -43,7 +43,7 @@ export const ShellEnrollmentInstructions: React.FunctionComponent<Props> = ({ // apiKey.api_key // } sh -c "$(curl ${kibanaUrl}/api/ingest_manager/fleet/install/${currentPlatform})"`; - const quickInstallInstructions = `./agent enroll ${kibanaUrl} ${apiKey.api_key}`; + const quickInstallInstructions = `./elastic-agent enroll ${kibanaUrl} ${apiKey.api_key}`; return ( <> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/header.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/header.tsx index e1f29fdbeb323..1aab6d901a992 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/header.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/header.tsx @@ -7,14 +7,15 @@ import React, { memo } from 'react'; import styled from 'styled-components'; import { EuiFlexGroup, EuiFlexItem, EuiTabs, EuiTab, EuiSpacer } from '@elastic/eui'; import { Props as EuiTabProps } from '@elastic/eui/src/components/tabs/tab'; +import { EuiFlexItemProps } from '@elastic/eui/src/components/flex/flex_item'; const Container = styled.div` border-bottom: ${props => props.theme.eui.euiBorderThin}; background-color: ${props => props.theme.eui.euiPageBackgroundColor}; `; -const Wrapper = styled.div` - max-width: 1200px; +const Wrapper = styled.div<{ maxWidth?: number }>` + max-width: ${props => props.maxWidth || 1200}px; margin-left: auto; margin-right: auto; padding-top: ${props => props.theme.eui.paddingSizes.xl}; @@ -30,22 +31,36 @@ const Tabs = styled(EuiTabs)` `; export interface HeaderProps { + restrictHeaderWidth?: number; leftColumn?: JSX.Element; rightColumn?: JSX.Element; + rightColumnGrow?: EuiFlexItemProps['grow']; tabs?: EuiTabProps[]; } -const HeaderColumns: React.FC<Omit<HeaderProps, 'tabs'>> = memo(({ leftColumn, rightColumn }) => ( - <EuiFlexGroup alignItems="center"> - {leftColumn ? <EuiFlexItem>{leftColumn}</EuiFlexItem> : null} - {rightColumn ? <EuiFlexItem>{rightColumn}</EuiFlexItem> : null} - </EuiFlexGroup> -)); +const HeaderColumns: React.FC<Omit<HeaderProps, 'tabs'>> = memo( + ({ leftColumn, rightColumn, rightColumnGrow }) => ( + <EuiFlexGroup alignItems="center"> + {leftColumn ? <EuiFlexItem>{leftColumn}</EuiFlexItem> : null} + {rightColumn ? <EuiFlexItem grow={rightColumnGrow}>{rightColumn}</EuiFlexItem> : null} + </EuiFlexGroup> + ) +); -export const Header: React.FC<HeaderProps> = ({ leftColumn, rightColumn, tabs }) => ( +export const Header: React.FC<HeaderProps> = ({ + leftColumn, + rightColumn, + rightColumnGrow, + tabs, + restrictHeaderWidth, +}) => ( <Container> - <Wrapper> - <HeaderColumns leftColumn={leftColumn} rightColumn={rightColumn} /> + <Wrapper maxWidth={restrictHeaderWidth}> + <HeaderColumns + leftColumn={leftColumn} + rightColumn={rightColumn} + rightColumnGrow={rightColumnGrow} + /> <EuiFlexGroup> {tabs ? ( <EuiFlexItem> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/confirm_modal.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/confirm_modal.tsx new file mode 100644 index 0000000000000..aa7eab8f5be8d --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/confirm_modal.tsx @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiCallOut, EuiOverlayMask, EuiConfirmModal, EuiSpacer } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { AgentConfig } from '../../../../types'; + +export const ConfirmCreateDatasourceModal: React.FunctionComponent<{ + onConfirm: () => void; + onCancel: () => void; + agentCount: number; + agentConfig: AgentConfig; +}> = ({ onConfirm, onCancel, agentCount, agentConfig }) => { + return ( + <EuiOverlayMask> + <EuiConfirmModal + title={ + <FormattedMessage + id="xpack.ingestManager.createDatasource.confirmModalTitle" + defaultMessage="Save and deploy changes" + /> + } + onCancel={onCancel} + onConfirm={onConfirm} + cancelButtonText={ + <FormattedMessage + id="xpack.ingestManager.deleteApiKeys.confirmModal.cancelButtonLabel" + defaultMessage="Cancel" + /> + } + confirmButtonText={ + <FormattedMessage + id="xpack.ingestManager.createDatasource.confirmModalConfirmButtonLabel" + defaultMessage="Save and deploy changes" + /> + } + buttonColor="primary" + > + <EuiCallOut + iconType="iInCircle" + title={i18n.translate('xpack.ingestManager.createDatasource.confirmModalCalloutTitle', { + defaultMessage: + 'This action will update {agentCount, plural, one {# agent} other {# agents}}', + values: { + agentCount, + }, + })} + > + <FormattedMessage + id="xpack.ingestManager.createDatasource.confirmModalCalloutDescription" + defaultMessage="Fleet has detected that the selected agent configuration, {configName}, is already in use by + some of your agents. As a result of this action, Fleet will deploy updates to all agents + that use this configuration." + values={{ + configName: <b>{agentConfig.name}</b>, + }} + /> + </EuiCallOut> + <EuiSpacer size="l" /> + <FormattedMessage + id="xpack.ingestManager.createDatasource.confirmModalDescription" + defaultMessage="This action can not be undone. Are you sure you wish to continue?" + /> + </EuiConfirmModal> + </EuiOverlayMask> + ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts index 3bfca75668911..aa564690a6092 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/index.ts @@ -5,4 +5,5 @@ */ export { CreateDatasourcePageLayout } from './layout'; export { DatasourceInputPanel } from './datasource_input_panel'; +export { ConfirmCreateDatasourceModal } from './confirm_modal'; export { DatasourceInputVarField } from './datasource_input_var_field'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx index dd242f366e8c0..73a7ba8ec119d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/layout.tsx @@ -19,108 +19,107 @@ import { WithHeaderLayout } from '../../../../layouts'; import { AgentConfig, PackageInfo } from '../../../../types'; import { PackageIcon } from '../../../../components/package_icon'; import { CreateDatasourceFrom, CreateDatasourceStep } from '../types'; -import { CreateDatasourceStepsNavigation } from './navigation'; export const CreateDatasourcePageLayout: React.FunctionComponent<{ from: CreateDatasourceFrom; basePath: string; cancelUrl: string; maxStep: CreateDatasourceStep | ''; - currentStep: CreateDatasourceStep; agentConfig?: AgentConfig; packageInfo?: PackageInfo; - restrictWidth?: number; -}> = ({ - from, - basePath, - cancelUrl, - maxStep, - currentStep, - agentConfig, - packageInfo, - restrictWidth, - children, -}) => { - return ( - <WithHeaderLayout - restrictWidth={restrictWidth} - leftColumn={ - <EuiFlexGroup direction="column" gutterSize="s" alignItems="flexStart"> - <EuiFlexItem> - <EuiButtonEmpty size="s" iconType="cross" flush="left" href={cancelUrl}> +}> = ({ from, basePath, cancelUrl, maxStep, agentConfig, packageInfo, children }) => { + const leftColumn = ( + <EuiFlexGroup direction="column" gutterSize="s" alignItems="flexStart"> + <EuiFlexItem> + <EuiButtonEmpty size="s" iconType="arrowLeft" flush="left" href={cancelUrl}> + <FormattedMessage + id="xpack.ingestManager.createDatasource.cancelLinkText" + defaultMessage="Cancel" + /> + </EuiButtonEmpty> + </EuiFlexItem> + <EuiFlexItem> + <EuiText> + <h1> + <FormattedMessage + id="xpack.ingestManager.createDatasource.pageTitle" + defaultMessage="Add data source" + /> + </h1> + </EuiText> + </EuiFlexItem> + <EuiFlexItem> + <EuiSpacer size="s" /> + <EuiText color="subdued" size="s"> + {from === 'config' ? ( + <FormattedMessage + id="xpack.ingestManager.createDatasource.pageDescriptionfromConfig" + defaultMessage="Follow the instructions below to add an integration to this agent configuration." + /> + ) : ( + <FormattedMessage + id="xpack.ingestManager.createDatasource.pageDescriptionfromPackage" + defaultMessage="Follow the instructions below to add this integration to an agent configuration." + /> + )} + </EuiText> + </EuiFlexItem> + </EuiFlexGroup> + ); + const rightColumn = ( + <EuiFlexGroup justifyContent="flexEnd" direction={'row'} gutterSize="xl"> + <EuiFlexItem grow={false}> + <EuiSpacer size="s" /> + {agentConfig && from === 'config' ? ( + <EuiDescriptionList style={{ textAlign: 'right' }} textStyle="reverse"> + <EuiDescriptionListTitle> + <FormattedMessage + id="xpack.ingestManager.createDatasource.agentConfigurationNameLabel" + defaultMessage="Configuration" + /> + </EuiDescriptionListTitle> + <EuiDescriptionListDescription> + {agentConfig?.name || '-'} + </EuiDescriptionListDescription> + </EuiDescriptionList> + ) : null} + {packageInfo && from === 'package' ? ( + <EuiDescriptionList style={{ textAlign: 'right' }} textStyle="reverse"> + <EuiDescriptionListTitle> <FormattedMessage - id="xpack.ingestManager.createDatasource.cancelLinkText" - defaultMessage="Cancel" + id="xpack.ingestManager.createDatasource.packageNameLabel" + defaultMessage="Integration" /> - </EuiButtonEmpty> - </EuiFlexItem> - <EuiFlexItem> - <EuiText> - <h1> - <FormattedMessage - id="xpack.ingestManager.createDatasource.pageTitle" - defaultMessage="Create data source" - /> - </h1> - </EuiText> - </EuiFlexItem> - <EuiFlexItem> - <EuiSpacer size="s" /> - <EuiFlexGroup direction={from === 'config' ? 'row' : 'rowReverse'} gutterSize="xl"> - {agentConfig || from === 'config' ? ( + </EuiDescriptionListTitle> + <EuiDescriptionListDescription> + <EuiFlexGroup justifyContent="flexEnd" alignItems="center" gutterSize="s"> <EuiFlexItem grow={false}> - <EuiDescriptionList textStyle="reverse"> - <EuiDescriptionListTitle> - <FormattedMessage - id="xpack.ingestManager.createDatasource.agentConfigurationNameLabel" - defaultMessage="Configuration" - /> - </EuiDescriptionListTitle> - <EuiDescriptionListDescription> - {agentConfig?.name || '-'} - </EuiDescriptionListDescription> - </EuiDescriptionList> + <PackageIcon + packageName={packageInfo?.name || ''} + version={packageInfo?.version || ''} + icons={packageInfo?.icons} + size="m" + /> </EuiFlexItem> - ) : null} - {packageInfo || from === 'package' ? ( <EuiFlexItem grow={false}> - <EuiDescriptionList textStyle="reverse"> - <EuiDescriptionListTitle> - <FormattedMessage - id="xpack.ingestManager.createDatasource.packageNameLabel" - defaultMessage="Integration" - /> - </EuiDescriptionListTitle> - <EuiDescriptionListDescription> - <EuiFlexGroup alignItems="center" gutterSize="s"> - <EuiFlexItem grow={false}> - <PackageIcon - packageName={packageInfo?.name || ''} - version={packageInfo?.version || ''} - icons={packageInfo?.icons} - size="m" - /> - </EuiFlexItem> - <EuiFlexItem grow={false}> - {packageInfo?.title || packageInfo?.name || '-'} - </EuiFlexItem> - </EuiFlexGroup> - </EuiDescriptionListDescription> - </EuiDescriptionList> + {packageInfo?.title || packageInfo?.name || '-'} </EuiFlexItem> - ) : null} - </EuiFlexGroup> - </EuiFlexItem> - </EuiFlexGroup> - } - rightColumn={ - <CreateDatasourceStepsNavigation - from={from} - basePath={basePath} - maxStep={maxStep} - currentStep={currentStep} - /> - } + </EuiFlexGroup> + </EuiDescriptionListDescription> + </EuiDescriptionList> + ) : null} + </EuiFlexItem> + </EuiFlexGroup> + ); + + const maxWidth = 770; + return ( + <WithHeaderLayout + restrictHeaderWidth={maxWidth} + restrictWidth={maxWidth} + leftColumn={leftColumn} + rightColumn={rightColumn} + rightColumnGrow={false} > {children} </WithHeaderLayout> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx deleted file mode 100644 index 7dae981e65c30..0000000000000 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/components/navigation.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React from 'react'; -import styled from 'styled-components'; -import { useHistory } from 'react-router-dom'; -import { i18n } from '@kbn/i18n'; -import { EuiStepsHorizontal } from '@elastic/eui'; -import { CreateDatasourceFrom, CreateDatasourceStep } from '../types'; -import { WeightedCreateDatasourceSteps, CREATE_DATASOURCE_STEP_PATHS } from '../constants'; - -const StepsHorizontal = styled(EuiStepsHorizontal)` - background: none; -`; - -export const CreateDatasourceStepsNavigation: React.FunctionComponent<{ - from: CreateDatasourceFrom; - basePath: string; - maxStep: CreateDatasourceStep | ''; - currentStep: CreateDatasourceStep; -}> = ({ from, basePath, maxStep, currentStep }) => { - const history = useHistory(); - - const steps = [ - from === 'config' - ? { - title: i18n.translate('xpack.ingestManager.createDatasource.stepSelectPackageLabel', { - defaultMessage: 'Select integration', - }), - isSelected: currentStep === 'selectPackage', - isComplete: - WeightedCreateDatasourceSteps.indexOf('selectPackage') <= - WeightedCreateDatasourceSteps.indexOf(maxStep), - onClick: () => { - history.push(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.selectPackage}`); - }, - } - : { - title: i18n.translate('xpack.ingestManager.createDatasource.stepSelectConfigLabel', { - defaultMessage: 'Select configuration', - }), - isSelected: currentStep === 'selectConfig', - isComplete: - WeightedCreateDatasourceSteps.indexOf('selectConfig') <= - WeightedCreateDatasourceSteps.indexOf(maxStep), - onClick: () => { - history.push(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.selectConfig}`); - }, - }, - { - title: i18n.translate('xpack.ingestManager.createDatasource.stepConfigureDatasourceLabel', { - defaultMessage: 'Configure data source', - }), - isSelected: currentStep === 'configure', - isComplete: - WeightedCreateDatasourceSteps.indexOf('configure') <= - WeightedCreateDatasourceSteps.indexOf(maxStep), - disabled: - WeightedCreateDatasourceSteps.indexOf(maxStep) < - WeightedCreateDatasourceSteps.indexOf('configure') - 1, - onClick: () => { - history.push(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.configure}`); - }, - }, - { - title: i18n.translate('xpack.ingestManager.createDatasource.stepReviewLabel', { - defaultMessage: 'Review', - }), - isSelected: currentStep === 'review', - isComplete: - WeightedCreateDatasourceSteps.indexOf('review') <= - WeightedCreateDatasourceSteps.indexOf(maxStep), - disabled: - WeightedCreateDatasourceSteps.indexOf(maxStep) < - WeightedCreateDatasourceSteps.indexOf('review') - 1, - onClick: () => { - history.push(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.review}`); - }, - }, - ]; - - return <StepsHorizontal steps={steps} />; -}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/constants.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/constants.ts index eea18179560a1..49223a8eb4531 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/constants.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/constants.ts @@ -9,10 +9,3 @@ export const WeightedCreateDatasourceSteps = [ 'configure', 'review', ]; - -export const CREATE_DATASOURCE_STEP_PATHS = { - selectConfig: '/select-config', - selectPackage: '/select-package', - configure: '/configure', - review: '/review', -}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx index 461bb750ca6f5..1ad579d591b21 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/index.tsx @@ -3,45 +3,74 @@ * 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 } from 'react'; -import { - useRouteMatch, - HashRouter as Router, - Switch, - Route, - Redirect, - useHistory, -} from 'react-router-dom'; +import React, { useState, useEffect } from 'react'; +import { useRouteMatch, useHistory } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiButtonEmpty } from '@elastic/eui'; +import { + EuiButtonEmpty, + EuiButton, + EuiSteps, + EuiBottomBar, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, +} from '@elastic/eui'; +import { EuiStepProps } from '@elastic/eui/src/components/steps/step'; import { AGENT_CONFIG_DETAILS_PATH } from '../../../constants'; import { AgentConfig, PackageInfo, NewDatasource } from '../../../types'; -import { useLink, sendCreateDatasource } from '../../../hooks'; +import { + useLink, + sendCreateDatasource, + useCore, + useConfig, + sendGetAgentStatus, +} from '../../../hooks'; import { useLinks as useEPMLinks } from '../../epm/hooks'; -import { CreateDatasourcePageLayout } from './components'; +import { CreateDatasourcePageLayout, ConfirmCreateDatasourceModal } from './components'; import { CreateDatasourceFrom, CreateDatasourceStep } from './types'; -import { CREATE_DATASOURCE_STEP_PATHS } from './constants'; -import { DatasourceValidationResults, validateDatasource } from './services'; +import { DatasourceValidationResults, validateDatasource, validationHasErrors } from './services'; import { StepSelectPackage } from './step_select_package'; import { StepSelectConfig } from './step_select_config'; import { StepConfigureDatasource } from './step_configure_datasource'; -import { StepReviewDatasource } from './step_review'; + +import { StepDefineDatasource } from './step_define_datasource'; export const CreateDatasourcePage: React.FunctionComponent = () => { + const { notifications } = useCore(); + const { + fleet: { enabled: isFleetEnabled }, + } = useConfig(); const { params: { configId, pkgkey }, - path: matchPath, url: basePath, } = useRouteMatch(); const history = useHistory(); const from: CreateDatasourceFrom = configId ? 'config' : 'package'; const [maxStep, setMaxStep] = useState<CreateDatasourceStep | ''>(''); - const [isSaving, setIsSaving] = useState<boolean>(false); // Agent config and package info states const [agentConfig, setAgentConfig] = useState<AgentConfig>(); const [packageInfo, setPackageInfo] = useState<PackageInfo>(); + const agentConfigId = agentConfig?.id; + // Retrieve agent count + useEffect(() => { + const getAgentCount = async () => { + if (agentConfigId) { + const { data } = await sendGetAgentStatus({ configId: agentConfigId }); + if (data?.results.total) { + setAgentCount(data.results.total); + } + } + }; + + if (isFleetEnabled && agentConfigId) { + getAgentCount(); + } + }, [agentConfigId, isFleetEnabled]); + const [agentCount, setAgentCount] = useState<number>(0); + // New datasource state const [datasource, setDatasource] = useState<NewDatasource>({ name: '', @@ -60,6 +89,7 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { if (updatedPackageInfo) { setPackageInfo(updatedPackageInfo); } else { + setFormState('INVALID'); setPackageInfo(undefined); setMaxStep(''); } @@ -73,6 +103,7 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { if (updatedAgentConfig) { setAgentConfig(updatedAgentConfig); } else { + setFormState('INVALID'); setAgentConfig(undefined); setMaxStep(''); } @@ -81,6 +112,8 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { console.debug('Agent config updated', updatedAgentConfig); }; + const hasErrors = validationResults ? validationHasErrors(validationResults) : false; + // Update datasource method const updateDatasource = (updatedFields: Partial<NewDatasource>) => { const newDatasource = { @@ -88,9 +121,18 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { ...updatedFields, }; setDatasource(newDatasource); + // eslint-disable-next-line no-console console.debug('Datasource updated', newDatasource); - updateDatasourceValidation(newDatasource); + const newValidationResults = updateDatasourceValidation(newDatasource); + const hasPackage = newDatasource.package; + const hasValidationErrors = newValidationResults + ? validationHasErrors(newValidationResults) + : false; + const hasAgentConfig = newDatasource.config_id && newDatasource.config_id !== ''; + if (hasPackage && hasAgentConfig && !hasValidationErrors) { + setFormState('VALID'); + } }; const updateDatasourceValidation = (newDatasource?: NewDatasource) => { @@ -99,6 +141,8 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { setValidationResults(newValidationResult); // eslint-disable-next-line no-console console.debug('Datasource validation results', newValidationResult); + + return newValidationResult; } }; @@ -112,34 +156,37 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { }); const cancelUrl = from === 'config' ? CONFIG_URL : PACKAGE_URL; - // Redirect to first step - const redirectToFirstStep = - from === 'config' ? ( - <Redirect to={`${basePath}${CREATE_DATASOURCE_STEP_PATHS.selectPackage}`} /> - ) : ( - <Redirect to={`${basePath}${CREATE_DATASOURCE_STEP_PATHS.selectConfig}`} /> - ); - - // Url to first and second steps - const SELECT_PACKAGE_URL = useLink(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.selectPackage}`); - const SELECT_CONFIG_URL = useLink(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.selectConfig}`); - const CONFIGURE_DATASOURCE_URL = useLink(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.configure}`); - const firstStepUrl = from === 'config' ? SELECT_PACKAGE_URL : SELECT_CONFIG_URL; - const secondStepUrl = CONFIGURE_DATASOURCE_URL; - - // Redirect to second step - const redirectToSecondStep = ( - <Redirect to={`${basePath}${CREATE_DATASOURCE_STEP_PATHS.configure}`} /> - ); - // Save datasource + const [formState, setFormState] = useState< + 'VALID' | 'INVALID' | 'CONFIRM' | 'LOADING' | 'SUBMITTED' + >('INVALID'); const saveDatasource = async () => { - setIsSaving(true); + setFormState('LOADING'); const result = await sendCreateDatasource(datasource); - setIsSaving(false); + setFormState('SUBMITTED'); return result; }; + const onSubmit = async () => { + if (formState === 'VALID' && hasErrors) { + setFormState('INVALID'); + return; + } + if (agentCount !== 0 && formState !== 'CONFIRM') { + setFormState('CONFIRM'); + return; + } + const { error } = await saveDatasource(); + if (!error) { + history.push(`${AGENT_CONFIG_DETAILS_PATH}${agentConfig ? agentConfig.id : configId}`); + } else { + notifications.toasts.addError(error, { + title: 'Error', + }); + setFormState('VALID'); + } + }; + const layoutProps = { from, basePath, @@ -147,135 +194,108 @@ export const CreateDatasourcePage: React.FunctionComponent = () => { maxStep, agentConfig, packageInfo, - restrictWidth: 770, }; - return ( - <Router> - <Switch> - {/* Redirect to first step from `/` */} - {from === 'config' ? ( - <Redirect - exact - from={`${matchPath}`} - to={`${matchPath}${CREATE_DATASOURCE_STEP_PATHS.selectPackage}`} + const steps: EuiStepProps[] = [ + from === 'package' + ? { + title: i18n.translate('xpack.ingestManager.createDatasource.stepSelectAgentConfigTitle', { + defaultMessage: 'Select an agent configuration', + }), + children: ( + <StepSelectConfig + pkgkey={pkgkey} + updatePackageInfo={updatePackageInfo} + agentConfig={agentConfig} + updateAgentConfig={updateAgentConfig} + /> + ), + } + : { + title: i18n.translate('xpack.ingestManager.createDatasource.stepSelectPackageTitle', { + defaultMessage: 'Select an integration', + }), + children: ( + <StepSelectPackage + agentConfigId={configId} + updateAgentConfig={updateAgentConfig} + packageInfo={packageInfo} + updatePackageInfo={updatePackageInfo} + /> + ), + }, + { + title: i18n.translate('xpack.ingestManager.createDatasource.stepDefineDatasourceTitle', { + defaultMessage: 'Define your data source', + }), + status: !packageInfo || !agentConfig ? 'disabled' : undefined, + children: + agentConfig && packageInfo ? ( + <StepDefineDatasource + agentConfig={agentConfig} + packageInfo={packageInfo} + datasource={datasource} + updateDatasource={updateDatasource} /> - ) : ( - <Redirect - exact - from={`${matchPath}`} - to={`${matchPath}${CREATE_DATASOURCE_STEP_PATHS.selectConfig}`} + ) : null, + }, + { + title: i18n.translate('xpack.ingestManager.createDatasource.stepConfgiureDatasourceTitle', { + defaultMessage: 'Select the data you want to collect', + }), + status: !packageInfo || !agentConfig ? 'disabled' : undefined, + children: + agentConfig && packageInfo ? ( + <StepConfigureDatasource + agentConfig={agentConfig} + packageInfo={packageInfo} + datasource={datasource} + updateDatasource={updateDatasource} + validationResults={validationResults!} + submitAttempted={formState === 'INVALID'} /> - )} - - {/* First step, either render select package or select config depending on entry */} - {from === 'config' ? ( - <Route path={`${matchPath}${CREATE_DATASOURCE_STEP_PATHS.selectPackage}`}> - <CreateDatasourcePageLayout {...layoutProps} currentStep="selectPackage"> - <StepSelectPackage - agentConfigId={configId} - updateAgentConfig={updateAgentConfig} - packageInfo={packageInfo} - updatePackageInfo={updatePackageInfo} - cancelUrl={cancelUrl} - onNext={() => { - setMaxStep('selectPackage'); - history.push(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.configure}`); - }} - /> - </CreateDatasourcePageLayout> - </Route> - ) : ( - <Route path={`${matchPath}${CREATE_DATASOURCE_STEP_PATHS.selectConfig}`}> - <CreateDatasourcePageLayout {...layoutProps} currentStep="selectConfig"> - <StepSelectConfig - pkgkey={pkgkey} - updatePackageInfo={updatePackageInfo} - agentConfig={agentConfig} - updateAgentConfig={updateAgentConfig} - cancelUrl={cancelUrl} - onNext={() => { - setMaxStep('selectConfig'); - history.push(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.configure}`); - }} - /> - </CreateDatasourcePageLayout> - </Route> - )} - - {/* Second step to configure data source, redirect to first step if agent config */} - {/* or package info isn't defined (i.e. after full page reload) */} - <Route path={`${matchPath}${CREATE_DATASOURCE_STEP_PATHS.configure}`}> - <CreateDatasourcePageLayout {...layoutProps} currentStep="configure"> - {!agentConfig || !packageInfo ? ( - redirectToFirstStep - ) : ( - <StepConfigureDatasource - agentConfig={agentConfig} - packageInfo={packageInfo} - datasource={datasource} - updateDatasource={updateDatasource} - validationResults={validationResults!} - backLink={ - <EuiButtonEmpty href={firstStepUrl} iconType="arrowLeft" iconSide="left"> - {from === 'config' ? ( - <FormattedMessage - id="xpack.ingestManager.createDatasource.changePackageLinkText" - defaultMessage="Change integration" - /> - ) : ( - <FormattedMessage - id="xpack.ingestManager.createDatasource.changeConfigLinkText" - defaultMessage="Change configuration" - /> - )} - </EuiButtonEmpty> - } - cancelUrl={cancelUrl} - onNext={() => { - setMaxStep('configure'); - history.push(`${basePath}${CREATE_DATASOURCE_STEP_PATHS.review}`); - }} + ) : null, + }, + ]; + return ( + <CreateDatasourcePageLayout {...layoutProps}> + {formState === 'CONFIRM' && agentConfig && ( + <ConfirmCreateDatasourceModal + agentCount={agentCount} + agentConfig={agentConfig} + onConfirm={onSubmit} + onCancel={() => setFormState('VALID')} + /> + )} + <EuiSteps steps={steps} /> + <EuiSpacer size="l" /> + <EuiBottomBar css={{ zIndex: 5 }} paddingSize="s"> + <EuiFlexGroup gutterSize="s" justifyContent="flexEnd"> + <EuiFlexItem grow={false}> + <EuiButtonEmpty color="ghost" href={cancelUrl}> + <FormattedMessage + id="xpack.ingestManager.createDatasource.cancelButton" + defaultMessage="Cancel" /> - )} - </CreateDatasourcePageLayout> - </Route> - - {/* Third step to review, redirect to second step if data source name is missing */} - {/* (i.e. after full page reload) */} - <Route path={`${matchPath}${CREATE_DATASOURCE_STEP_PATHS.review}`}> - <CreateDatasourcePageLayout {...layoutProps} currentStep="review"> - {!agentConfig || !datasource.name ? ( - redirectToSecondStep - ) : ( - <StepReviewDatasource - agentConfig={agentConfig} - datasource={datasource} - cancelUrl={cancelUrl} - isSubmitLoading={isSaving} - backLink={ - <EuiButtonEmpty href={secondStepUrl} iconType="arrowLeft" iconSide="left"> - <FormattedMessage - id="xpack.ingestManager.createDatasource.editDatasourceLinkText" - defaultMessage="Edit data source" - /> - </EuiButtonEmpty> - } - onSubmit={async () => { - const { error } = await saveDatasource(); - if (!error) { - history.push( - `${AGENT_CONFIG_DETAILS_PATH}${agentConfig ? agentConfig.id : configId}` - ); - } else { - // TODO: Handle save datasource error - } - }} + </EuiButtonEmpty> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <EuiButton + onClick={onSubmit} + isLoading={formState === 'LOADING'} + disabled={formState !== 'VALID'} + iconType="save" + color="primary" + fill + > + <FormattedMessage + id="xpack.ingestManager.createDatasource.saveButton" + defaultMessage="Save data source" /> - )} - </CreateDatasourcePageLayout> - </Route> - </Switch> - </Router> + </EuiButton> + </EuiFlexItem> + </EuiFlexGroup> + </EuiBottomBar> + </CreateDatasourcePageLayout> ); }; 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 105d6c66a5704..843891b63ca01 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 @@ -3,23 +3,18 @@ * 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, { useEffect, useState, Fragment } from 'react'; -import { i18n } from '@kbn/i18n'; +import React, { useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { - EuiSteps, EuiPanel, EuiFlexGroup, EuiFlexItem, - EuiFormRow, - EuiButtonEmpty, EuiSpacer, EuiEmptyPrompt, EuiText, - EuiButton, - EuiComboBox, EuiCallOut, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { AgentConfig, PackageInfo, @@ -30,7 +25,7 @@ import { import { Loading } from '../../../components'; import { packageToConfigDatasourceInputs } from '../../../services'; import { DatasourceValidationResults, validationHasErrors } from './services'; -import { DatasourceInputPanel, DatasourceInputVarField } from './components'; +import { DatasourceInputPanel } from './components'; export const StepConfigureDatasource: React.FunctionComponent<{ agentConfig: AgentConfig; @@ -38,24 +33,17 @@ export const StepConfigureDatasource: React.FunctionComponent<{ datasource: NewDatasource; updateDatasource: (fields: Partial<NewDatasource>) => void; validationResults: DatasourceValidationResults; - backLink: JSX.Element; - cancelUrl: string; - onNext: () => void; + submitAttempted: boolean; }> = ({ agentConfig, packageInfo, datasource, updateDatasource, validationResults, - backLink, - cancelUrl, - onNext, + submitAttempted, }) => { // Form show/hide states - const [isShowingAdvancedDefine, setIsShowingAdvancedDefine] = useState<boolean>(false); - // Form submit state - const [submitAttempted, setSubmitAttempted] = useState<boolean>(false); const hasErrors = validationResults ? validationHasErrors(validationResults) : false; // Update datasource's package and config info @@ -95,107 +83,6 @@ export const StepConfigureDatasource: React.FunctionComponent<{ } }, [datasource.package, datasource.config_id, agentConfig, packageInfo, updateDatasource]); - // Step A, define datasource - const renderDefineDatasource = () => ( - <EuiPanel> - <EuiFlexGroup> - <EuiFlexItem grow={1}> - <DatasourceInputVarField - varDef={{ - name: 'name', - title: i18n.translate( - 'xpack.ingestManager.createDatasource.stepConfigure.datasourceNameInputLabel', - { - defaultMessage: 'Data source name', - } - ), - type: 'text', - required: true, - }} - value={datasource.name} - onChange={(newValue: any) => { - updateDatasource({ - name: newValue, - }); - }} - errors={validationResults!.name} - forceShowErrors={submitAttempted} - /> - </EuiFlexItem> - <EuiFlexItem grow={1}> - <DatasourceInputVarField - varDef={{ - name: 'description', - title: i18n.translate( - 'xpack.ingestManager.createDatasource.stepConfigure.datasourceDescriptionInputLabel', - { - defaultMessage: 'Description', - } - ), - type: 'text', - required: false, - }} - value={datasource.description} - onChange={(newValue: any) => { - updateDatasource({ - description: newValue, - }); - }} - errors={validationResults!.description} - forceShowErrors={submitAttempted} - /> - </EuiFlexItem> - </EuiFlexGroup> - <EuiSpacer size="m" /> - <EuiButtonEmpty - flush="left" - size="xs" - iconType={isShowingAdvancedDefine ? 'arrowUp' : 'arrowDown'} - onClick={() => setIsShowingAdvancedDefine(!isShowingAdvancedDefine)} - > - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepConfigure.advancedOptionsToggleLinkText" - defaultMessage="Advanced options" - /> - </EuiButtonEmpty> - {/* Todo: Populate list of existing namespaces */} - {isShowingAdvancedDefine ? ( - <Fragment> - <EuiSpacer size="m" /> - <EuiFlexGroup> - <EuiFlexItem grow={1}> - <EuiFormRow - label={ - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepConfigure.datasourceNamespaceInputLabel" - defaultMessage="Namespace" - /> - } - > - <EuiComboBox - noSuggestions - singleSelection={true} - selectedOptions={datasource.namespace ? [{ label: datasource.namespace }] : []} - onCreateOption={(newNamespace: string) => { - updateDatasource({ - namespace: newNamespace, - }); - }} - onChange={(newNamespaces: Array<{ label: string }>) => { - updateDatasource({ - namespace: newNamespaces.length ? newNamespaces[0].label : '', - }); - }} - /> - </EuiFormRow> - </EuiFlexItem> - <EuiFlexItem grow={1} /> - </EuiFlexGroup> - </Fragment> - ) : null} - </EuiPanel> - ); - // Step B, configure inputs (and their streams) // Assume packages only export one datasource for now const renderConfigureInputs = () => @@ -252,41 +139,10 @@ export const StepConfigureDatasource: React.FunctionComponent<{ return validationResults ? ( <EuiFlexGroup direction="column" gutterSize="none"> - <EuiFlexItem> - <EuiFlexGroup direction="column" gutterSize="none"> - <EuiFlexItem> - <EuiFlexGroup justifyContent="flexEnd"> - <EuiFlexItem grow={false}>{backLink}</EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - <EuiFlexItem> - <EuiSteps - steps={[ - { - title: i18n.translate( - 'xpack.ingestManager.createDatasource.stepConfigure.defineDatasourceTitle', - { - defaultMessage: 'Define your datasource', - } - ), - children: renderDefineDatasource(), - }, - { - title: i18n.translate( - 'xpack.ingestManager.createDatasource.stepConfigure.chooseDataTitle', - { - defaultMessage: 'Choose the data you want to collect', - } - ), - children: renderConfigureInputs(), - }, - ]} - /> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> + <EuiFlexItem>{renderConfigureInputs()}</EuiFlexItem> {hasErrors && submitAttempted ? ( <EuiFlexItem> + <EuiSpacer size="m" /> <EuiCallOut title={i18n.translate( 'xpack.ingestManager.createDatasource.stepConfigure.validationErrorTitle', @@ -306,36 +162,6 @@ export const StepConfigureDatasource: React.FunctionComponent<{ <EuiSpacer size="m" /> </EuiFlexItem> ) : null} - <EuiFlexItem> - <EuiFlexGroup justifyContent="flexEnd"> - <EuiFlexItem grow={false}> - <EuiButtonEmpty href={cancelUrl}> - <FormattedMessage - id="xpack.ingestManager.createDatasource.cancelLinkText" - defaultMessage="Cancel" - /> - </EuiButtonEmpty> - </EuiFlexItem> - <EuiFlexItem grow={false}> - <EuiButton - fill - iconType="arrowRight" - iconSide="right" - onClick={() => { - setSubmitAttempted(true); - if (!hasErrors) { - onNext(); - } - }} - > - <FormattedMessage - id="xpack.ingestManager.createDatasource.continueButtonText" - defaultMessage="Continue" - /> - </EuiButton> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> </EuiFlexGroup> ) : ( <Loading /> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_define_datasource.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_define_datasource.tsx new file mode 100644 index 0000000000000..792389381eaf0 --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_define_datasource.tsx @@ -0,0 +1,165 @@ +/* + * 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, { useEffect, useState, Fragment } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiFlexGrid, + EuiFlexItem, + EuiFormRow, + EuiFieldText, + EuiButtonEmpty, + EuiSpacer, + EuiText, + EuiComboBox, +} from '@elastic/eui'; +import { AgentConfig, PackageInfo, Datasource, NewDatasource } from '../../../types'; +import { packageToConfigDatasourceInputs } from '../../../services'; + +export const StepDefineDatasource: React.FunctionComponent<{ + agentConfig: AgentConfig; + packageInfo: PackageInfo; + datasource: NewDatasource; + updateDatasource: (fields: Partial<NewDatasource>) => void; +}> = ({ agentConfig, packageInfo, datasource, updateDatasource }) => { + // Form show/hide states + const [isShowingAdvancedDefine, setIsShowingAdvancedDefine] = useState<boolean>(false); + + // Update datasource's package and config info + useEffect(() => { + const dsPackage = datasource.package; + const currentPkgKey = dsPackage ? `${dsPackage.name}-${dsPackage.version}` : ''; + const pkgKey = `${packageInfo.name}-${packageInfo.version}`; + + // If package has changed, create shell datasource with input&stream values based on package info + if (currentPkgKey !== pkgKey) { + // Existing datasources on the agent config using the package name, retrieve highest number appended to datasource name + const dsPackageNamePattern = new RegExp(`${packageInfo.name}-(\\d+)`); + const dsWithMatchingNames = (agentConfig.datasources as Datasource[]) + .filter(ds => Boolean(ds.name.match(dsPackageNamePattern))) + .map(ds => parseInt(ds.name.match(dsPackageNamePattern)![1], 10)) + .sort(); + + updateDatasource({ + name: `${packageInfo.name}-${ + dsWithMatchingNames.length ? dsWithMatchingNames[dsWithMatchingNames.length - 1] + 1 : 1 + }`, + package: { + name: packageInfo.name, + title: packageInfo.title, + version: packageInfo.version, + }, + inputs: packageToConfigDatasourceInputs(packageInfo), + }); + } + + // If agent config has changed, update datasource's config ID and namespace + if (datasource.config_id !== agentConfig.id) { + updateDatasource({ + config_id: agentConfig.id, + namespace: agentConfig.namespace, + }); + } + }, [datasource.package, datasource.config_id, agentConfig, packageInfo, updateDatasource]); + + return ( + <> + <EuiFlexGrid columns={2}> + <EuiFlexItem> + <EuiFormRow + label={ + <FormattedMessage + id="xpack.ingestManager.createDatasource.stepConfigure.datasourceNameInputLabel" + defaultMessage="Data source name" + /> + } + > + <EuiFieldText + value={datasource.name} + onChange={e => + updateDatasource({ + name: e.target.value, + }) + } + /> + </EuiFormRow> + </EuiFlexItem> + <EuiFlexItem> + <EuiFormRow + label={ + <FormattedMessage + id="xpack.ingestManager.createDatasource.stepConfigure.datasourceDescriptionInputLabel" + defaultMessage="Description" + /> + } + labelAppend={ + <EuiText size="xs" color="subdued"> + <FormattedMessage + id="xpack.ingestManager.createDatasource.stepConfigure.inputVarFieldOptionalLabel" + defaultMessage="Optional" + /> + </EuiText> + } + > + <EuiFieldText + value={datasource.description} + onChange={e => + updateDatasource({ + description: e.target.value, + }) + } + /> + </EuiFormRow> + </EuiFlexItem> + </EuiFlexGrid> + <EuiSpacer size="m" /> + <EuiButtonEmpty + flush="left" + size="xs" + iconType={isShowingAdvancedDefine ? 'arrowUp' : 'arrowDown'} + onClick={() => setIsShowingAdvancedDefine(!isShowingAdvancedDefine)} + > + <FormattedMessage + id="xpack.ingestManager.createDatasource.stepConfigure.advancedOptionsToggleLinkText" + defaultMessage="Advanced options" + /> + </EuiButtonEmpty> + {/* Todo: Populate list of existing namespaces */} + {isShowingAdvancedDefine ? ( + <Fragment> + <EuiSpacer size="m" /> + <EuiFlexGrid columns={2}> + <EuiFlexItem> + <EuiFormRow + label={ + <FormattedMessage + id="xpack.ingestManager.createDatasource.stepConfigure.datasourceNamespaceInputLabel" + defaultMessage="Namespace" + /> + } + > + <EuiComboBox + noSuggestions + singleSelection={true} + selectedOptions={datasource.namespace ? [{ label: datasource.namespace }] : []} + onCreateOption={(newNamespace: string) => { + updateDatasource({ + namespace: newNamespace, + }); + }} + onChange={(newNamespaces: Array<{ label: string }>) => { + updateDatasource({ + namespace: newNamespaces.length ? newNamespaces[0].label : '', + }); + }} + /> + </EuiFormRow> + </EuiFlexItem> + </EuiFlexGrid> + </Fragment> + ) : null} + </> + ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_review.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_review.tsx deleted file mode 100644 index 20af5954c1436..0000000000000 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_review.tsx +++ /dev/null @@ -1,202 +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, useState, useEffect } from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiButtonEmpty, - EuiButton, - EuiTitle, - EuiCallOut, - EuiText, - EuiCheckbox, - EuiTabbedContent, - EuiCodeBlock, - EuiSpacer, -} from '@elastic/eui'; -import { dump } from 'js-yaml'; -import { NewDatasource, AgentConfig } from '../../../types'; -import { useConfig, sendGetAgentStatus } from '../../../hooks'; -import { storedDatasourceToAgentDatasource } from '../../../services'; - -const KEYS_TO_SINK = ['inputs', 'streams']; - -export const StepReviewDatasource: React.FunctionComponent<{ - agentConfig: AgentConfig; - datasource: NewDatasource; - backLink: JSX.Element; - cancelUrl: string; - onSubmit: () => void; - isSubmitLoading: boolean; -}> = ({ agentConfig, datasource, backLink, cancelUrl, onSubmit, isSubmitLoading }) => { - // Agent count info states - const [agentCount, setAgentCount] = useState<number>(0); - const [agentCountChecked, setAgentCountChecked] = useState<boolean>(false); - - // Config information - const { - fleet: { enabled: isFleetEnabled }, - } = useConfig(); - - // Retrieve agent count - useEffect(() => { - const getAgentCount = async () => { - const { data } = await sendGetAgentStatus({ configId: agentConfig.id }); - if (data?.results.total) { - setAgentCount(data.results.total); - } - }; - - if (isFleetEnabled) { - getAgentCount(); - } - }, [agentConfig.id, isFleetEnabled]); - - const showAgentDisclaimer = isFleetEnabled && agentCount; - const fullAgentDatasource = storedDatasourceToAgentDatasource(datasource); - - return ( - <EuiFlexGroup direction="column"> - <EuiFlexItem> - <EuiFlexGroup justifyContent="spaceBetween"> - <EuiFlexItem grow={false}> - <EuiTitle size="s"> - <h3> - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepReview.reviewTitle" - defaultMessage="Review changes" - /> - </h3> - </EuiTitle> - </EuiFlexItem> - <EuiFlexItem grow={false}>{backLink}</EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - - {/* Agents affected warning */} - {showAgentDisclaimer ? ( - <EuiFlexItem> - <EuiCallOut - title={ - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepReview.agentsAffectedCalloutTitle" - defaultMessage="This action will affect {count, plural, one {# agent} other {# agents}}" - values={{ - count: agentCount, - }} - /> - } - > - <EuiText> - <p> - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepReview.agentsAffectedCalloutText" - defaultMessage="Fleet has detected that the selected agent configuration, {configName} is already in use by some your agents. As a result of this action, Fleet will update all agents that are enrolled with this configuration." - values={{ - configName: <strong>{agentConfig.name}</strong>, - }} - /> - </p> - </EuiText> - </EuiCallOut> - </EuiFlexItem> - ) : null} - - {/* Preview and YAML view */} - {/* TODO: Implement preview tab */} - <EuiFlexItem> - <EuiTabbedContent - tabs={[ - { - id: 'yaml', - name: i18n.translate('xpack.ingestManager.agentConfigInfo.yamlTabName', { - defaultMessage: 'YAML', - }), - content: ( - <Fragment> - <EuiSpacer size="s" /> - <EuiCodeBlock language="yaml" isCopyable overflowHeight={450}> - {dump(fullAgentDatasource, { - sortKeys: (a: string, b: string) => { - // Make YAML output prettier by sinking certain fields - if (KEYS_TO_SINK.indexOf(a) > -1) { - return 1; - } - if (KEYS_TO_SINK.indexOf(b) > -1) { - return -1; - } - return 0; - }, - })} - </EuiCodeBlock> - </Fragment> - ), - }, - ]} - /> - </EuiFlexItem> - - {/* Confirm agents affected */} - {showAgentDisclaimer ? ( - <EuiFlexItem> - <EuiFlexGroup direction="column" gutterSize="s"> - <EuiFlexItem> - <EuiTitle size="xs"> - <h4> - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepReview.confirmAgentDisclaimerTitle" - defaultMessage="Confirm your decision" - /> - </h4> - </EuiTitle> - </EuiFlexItem> - <EuiFlexItem> - <EuiCheckbox - id="CreateDatasourceAgentDisclaimer" - label={ - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepReview.confirmAgentDisclaimerText" - defaultMessage="I understand that this action will update all agents that are enrolled with this configuration." - /> - } - checked={agentCountChecked} - onChange={e => setAgentCountChecked(e.target.checked)} - /> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - ) : null} - - <EuiFlexItem> - <EuiFlexGroup justifyContent="flexEnd"> - <EuiFlexItem grow={false}> - <EuiButtonEmpty href={cancelUrl}> - <FormattedMessage - id="xpack.ingestManager.createDatasource.cancelLinkText" - defaultMessage="Cancel" - /> - </EuiButtonEmpty> - </EuiFlexItem> - <EuiFlexItem grow={false}> - <EuiButton - fill - onClick={() => onSubmit()} - isLoading={isSubmitLoading} - disabled={isSubmitLoading || Boolean(showAgentDisclaimer && !agentCountChecked)} - > - <FormattedMessage - id="xpack.ingestManager.createDatasource.addDatasourceButtonText" - defaultMessage="Add datasource to configuration" - /> - </EuiButton> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - </EuiFlexGroup> - ); -}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_config.tsx index 2ddfc170069a1..6cbe56e628903 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_config.tsx @@ -6,19 +6,8 @@ import React, { useEffect, useState, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiButtonEmpty, - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiTitle, - EuiSelectable, - EuiSpacer, - EuiTextColor, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSelectable, EuiSpacer, EuiTextColor } from '@elastic/eui'; import { Error } from '../../../components'; -import { AGENT_CONFIG_PATH } from '../../../constants'; -import { useCapabilities, useLink } from '../../../hooks'; import { AgentConfig, PackageInfo, GetAgentConfigsResponseItem } from '../../../types'; import { useGetPackageInfoByKey, useGetAgentConfigs, sendGetOneAgentConfig } from '../../../hooks'; @@ -27,20 +16,13 @@ export const StepSelectConfig: React.FunctionComponent<{ updatePackageInfo: (packageInfo: PackageInfo | undefined) => void; agentConfig: AgentConfig | undefined; updateAgentConfig: (config: AgentConfig | undefined) => void; - cancelUrl: string; - onNext: () => void; -}> = ({ pkgkey, updatePackageInfo, agentConfig, updateAgentConfig, cancelUrl, onNext }) => { - const hasWriteCapabilites = useCapabilities().write; +}> = ({ pkgkey, updatePackageInfo, agentConfig, updateAgentConfig }) => { // Selected config state const [selectedConfigId, setSelectedConfigId] = useState<string | undefined>( agentConfig ? agentConfig.id : undefined ); - const [selectedConfigLoading, setSelectedConfigLoading] = useState<boolean>(false); const [selectedConfigError, setSelectedConfigError] = useState<Error>(); - // Todo: replace with create agent config flyout - const CREATE_NEW_CONFIG_URI = useLink(AGENT_CONFIG_PATH); - // Fetch package info const { data: packageInfoData, error: packageInfoError } = useGetPackageInfoByKey(pkgkey); @@ -70,9 +52,7 @@ export const StepSelectConfig: React.FunctionComponent<{ useEffect(() => { const fetchAgentConfigInfo = async () => { if (selectedConfigId) { - setSelectedConfigLoading(true); const { data, error } = await sendGetOneAgentConfig(selectedConfigId); - setSelectedConfigLoading(false); if (error) { setSelectedConfigError(error); updateAgentConfig(undefined); @@ -122,33 +102,6 @@ export const StepSelectConfig: React.FunctionComponent<{ return ( <EuiFlexGroup direction="column"> - <EuiFlexItem> - <EuiFlexGroup justifyContent="spaceBetween" alignItems="center"> - <EuiFlexItem grow={false}> - <EuiTitle size="s"> - <h3> - <FormattedMessage - id="xpack.ingestManager.createDatasource.StepSelectConfig.selectAgentConfigTitle" - defaultMessage="Select an agent configuration" - /> - </h3> - </EuiTitle> - </EuiFlexItem> - <EuiFlexItem grow={false}> - <EuiButtonEmpty - isDisabled={!hasWriteCapabilites} - iconType="plusInCircle" - href={CREATE_NEW_CONFIG_URI} - size="s" - > - <FormattedMessage - id="xpack.ingestManager.createDatasource.StepSelectConfig.createNewConfigButtonText" - defaultMessage="Create new configuration" - /> - </EuiButtonEmpty> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> <EuiFlexItem> <EuiSelectable searchable @@ -227,33 +180,6 @@ export const StepSelectConfig: React.FunctionComponent<{ /> </EuiFlexItem> ) : null} - <EuiFlexItem> - <EuiFlexGroup justifyContent="flexEnd"> - <EuiFlexItem grow={false}> - <EuiButtonEmpty href={cancelUrl}> - <FormattedMessage - id="xpack.ingestManager.createDatasource.cancelLinkText" - defaultMessage="Cancel" - /> - </EuiButtonEmpty> - </EuiFlexItem> - <EuiFlexItem grow={false}> - <EuiButton - fill - iconType="arrowRight" - iconSide="right" - isLoading={selectedConfigLoading} - disabled={!selectedConfigId || !!selectedConfigError || selectedConfigLoading} - onClick={() => onNext()} - > - <FormattedMessage - id="xpack.ingestManager.createDatasource.continueButtonText" - defaultMessage="Continue" - /> - </EuiButton> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> </EuiFlexGroup> ); }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_package.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_package.tsx index 496e1d3c0fd7b..8dabb3bc98110 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_package.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_config/create_datasource_page/step_select_package.tsx @@ -6,15 +6,7 @@ import React, { useEffect, useState, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiButtonEmpty, - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiTitle, - EuiSelectable, - EuiSpacer, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSelectable, EuiSpacer } from '@elastic/eui'; import { Error } from '../../../components'; import { AgentConfig, PackageInfo } from '../../../types'; import { useGetOneAgentConfig, useGetPackages, sendGetPackageInfoByKey } from '../../../hooks'; @@ -25,14 +17,11 @@ export const StepSelectPackage: React.FunctionComponent<{ updateAgentConfig: (config: AgentConfig | undefined) => void; packageInfo?: PackageInfo; updatePackageInfo: (packageInfo: PackageInfo | undefined) => void; - cancelUrl: string; - onNext: () => void; -}> = ({ agentConfigId, updateAgentConfig, packageInfo, updatePackageInfo, cancelUrl, onNext }) => { +}> = ({ agentConfigId, updateAgentConfig, packageInfo, updatePackageInfo }) => { // Selected package state const [selectedPkgKey, setSelectedPkgKey] = useState<string | undefined>( packageInfo ? `${packageInfo.name}-${packageInfo.version}` : undefined ); - const [selectedPkgLoading, setSelectedPkgLoading] = useState<boolean>(false); const [selectedPkgError, setSelectedPkgError] = useState<Error>(); // Fetch agent config info @@ -57,9 +46,7 @@ export const StepSelectPackage: React.FunctionComponent<{ useEffect(() => { const fetchPackageInfo = async () => { if (selectedPkgKey) { - setSelectedPkgLoading(true); const { data, error } = await sendGetPackageInfoByKey(selectedPkgKey); - setSelectedPkgLoading(false); if (error) { setSelectedPkgError(error); updatePackageInfo(undefined); @@ -109,16 +96,6 @@ export const StepSelectPackage: React.FunctionComponent<{ return ( <EuiFlexGroup direction="column"> - <EuiFlexItem> - <EuiTitle size="s"> - <h3> - <FormattedMessage - id="xpack.ingestManager.createDatasource.stepSelectPackage.selectPackageTitle" - defaultMessage="Select integration" - /> - </h3> - </EuiTitle> - </EuiFlexItem> <EuiFlexItem> <EuiSelectable searchable @@ -186,33 +163,6 @@ export const StepSelectPackage: React.FunctionComponent<{ /> </EuiFlexItem> ) : null} - <EuiFlexItem> - <EuiFlexGroup justifyContent="flexEnd"> - <EuiFlexItem grow={false}> - <EuiButtonEmpty href={cancelUrl}> - <FormattedMessage - id="xpack.ingestManager.createDatasource.cancelLinkText" - defaultMessage="Cancel" - /> - </EuiButtonEmpty> - </EuiFlexItem> - <EuiFlexItem grow={false}> - <EuiButton - fill - iconType="arrowRight" - iconSide="right" - isLoading={selectedPkgLoading} - disabled={!selectedPkgKey || !!selectedPkgError || selectedPkgLoading} - onClick={() => onNext()} - > - <FormattedMessage - id="xpack.ingestManager.createDatasource.continueButtonText" - defaultMessage="Continue" - /> - </EuiButton> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> </EuiFlexGroup> ); }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/agent_enrollment_flyout/instructions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/agent_enrollment_flyout/instructions.tsx index 1bc20c2baf660..a0244c601cd96 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/agent_enrollment_flyout/instructions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/agent_enrollment_flyout/instructions.tsx @@ -86,7 +86,7 @@ export const EnrollmentInstructions: React.FunctionComponent<Props> = ({ selecte steps={[ { title: i18n.translate('xpack.ingestManager.agentEnrollment.stepSetupAgents', { - defaultMessage: 'Setup Beats agent', + defaultMessage: 'Setup Elastic agent', }), children: ( <ShellEnrollmentInstructions diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx index 22314b6231d1e..d363c472f2305 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx @@ -364,7 +364,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { <h2> <FormattedMessage id="xpack.ingestManager.agentList.noAgentsPrompt" - defaultMessage="No agents installed" + defaultMessage="No agents enrolled" /> </h2> } @@ -373,7 +373,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { <EuiButton fill iconType="plusInCircle" onClick={() => setIsEnrollmentFlyoutOpen(true)}> <FormattedMessage id="xpack.ingestManager.agentList.addButton" - defaultMessage="Install new agent" + defaultMessage="Enroll new agent" /> </EuiButton> ) : null diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e579830bad203..3cebde793a085 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8283,7 +8283,6 @@ "xpack.ingestManager.agentConfigForm.systemMonitoringFieldLabel": "オプション", "xpack.ingestManager.agentConfigForm.systemMonitoringText": "システムメトリックを収集", "xpack.ingestManager.agentConfigForm.systemMonitoringTooltipText": "このオプションを有効にすると、システムメトリックと情報を収集するデータソースで構成をブートストラップできます。", - "xpack.ingestManager.agentConfigInfo.yamlTabName": "YAML", "xpack.ingestManager.agentConfigList.actionsColumnTitle": "アクション", "xpack.ingestManager.agentConfigList.actionsMenuText": "開く", "xpack.ingestManager.agentConfigList.addButton": "エージェント構成を作成", @@ -8421,21 +8420,14 @@ "xpack.ingestManager.createAgentConfig.flyoutTitleDescription": "エージェント構成は、エージェントのグループ全体にわたる設定を管理する目的で使用されます。エージェント構成にデータソースを追加すると、エージェントで収集するデータを指定できます。エージェント構成の編集時には、フリートを使用して、指定したエージェントのグループに更新をデプロイできます。", "xpack.ingestManager.createAgentConfig.submitButtonLabel": "エージェント構成を作成", "xpack.ingestManager.createAgentConfig.successNotificationTitle": "エージェント構成「{name}」を作成しました", - "xpack.ingestManager.createDatasource.addDatasourceButtonText": "データソースに構成を追加", "xpack.ingestManager.createDatasource.agentConfigurationNameLabel": "構成", "xpack.ingestManager.createDatasource.cancelLinkText": "キャンセル", - "xpack.ingestManager.createDatasource.changeConfigLinkText": "構成を変更", - "xpack.ingestManager.createDatasource.changePackageLinkText": "パッケージを変更", - "xpack.ingestManager.createDatasource.continueButtonText": "続行", - "xpack.ingestManager.createDatasource.editDatasourceLinkText": "データソースを編集", "xpack.ingestManager.createDatasource.packageNameLabel": "パッケージ", "xpack.ingestManager.createDatasource.pageTitle": "データソースを作成", "xpack.ingestManager.createDatasource.stepConfigure.advancedOptionsToggleLinkText": "高度なオプション", - "xpack.ingestManager.createDatasource.stepConfigure.chooseDataTitle": "収集したいデータを選択してください", "xpack.ingestManager.createDatasource.stepConfigure.datasourceDescriptionInputLabel": "説明", "xpack.ingestManager.createDatasource.stepConfigure.datasourceNameInputLabel": "データソース名", "xpack.ingestManager.createDatasource.stepConfigure.datasourceNamespaceInputLabel": "名前空間", - "xpack.ingestManager.createDatasource.stepConfigure.defineDatasourceTitle": "データソースを定義する", "xpack.ingestManager.createDatasource.stepConfigure.hideStreamsAriaLabel": "{type} ストリームを隠す", "xpack.ingestManager.createDatasource.stepConfigure.inputSettingsDescription": "次の設定はすべてのストリームに適用されます。", "xpack.ingestManager.createDatasource.stepConfigure.inputSettingsTitle": "設定", @@ -8444,27 +8436,15 @@ "xpack.ingestManager.createDatasource.stepConfigure.showStreamsAriaLabel": "{type} ストリームを表示", "xpack.ingestManager.createDatasource.stepConfigure.streamsEnabledCountText": "{count} / {total, plural, one {# ストリーム} other {# ストリーム}}が有効です", "xpack.ingestManager.createDatasource.stepConfigure.toggleAdvancedOptionsButtonText": "高度なオプション", - "xpack.ingestManager.createDatasource.stepConfigureDatasourceLabel": "構成データソース", - "xpack.ingestManager.createDatasource.stepReview.agentsAffectedCalloutText": "選択されたエージェント構成 {configName} が一部のエージェントで既に使用されていることをフリートが検出しました。このアクションの結果として、フリートはこの構成に登録されているすべてのエージェントを更新します。", - "xpack.ingestManager.createDatasource.stepReview.agentsAffectedCalloutTitle": "このアクションは {count, plural, one {# エージェント} other {# エージェント}}に影響します", - "xpack.ingestManager.createDatasource.stepReview.confirmAgentDisclaimerText": "このアクションによって、この構成に登録されているすべてのエージェントが更新されることを理解しています。", - "xpack.ingestManager.createDatasource.stepReview.confirmAgentDisclaimerTitle": "意思決定を確認", - "xpack.ingestManager.createDatasource.stepReview.reviewTitle": "変更の見直し", - "xpack.ingestManager.createDatasource.stepReviewLabel": "見直し", "xpack.ingestManager.createDatasource.StepSelectConfig.agentConfigAgentsCountText": "{count, plural, one {# エージェント} other {# エージェント}}", - "xpack.ingestManager.createDatasource.StepSelectConfig.createNewConfigButtonText": "新しい構成を作成", "xpack.ingestManager.createDatasource.StepSelectConfig.errorLoadingAgentConfigsTitle": "エージェント構成の読み込みエラー", "xpack.ingestManager.createDatasource.StepSelectConfig.errorLoadingPackageTitle": "パッケージ情報の読み込みエラー", "xpack.ingestManager.createDatasource.StepSelectConfig.errorLoadingSelectedAgentConfigTitle": "選択したエージェント構成の読み込みエラー", "xpack.ingestManager.createDatasource.StepSelectConfig.filterAgentConfigsInputPlaceholder": "エージェント構成の検索", - "xpack.ingestManager.createDatasource.StepSelectConfig.selectAgentConfigTitle": "エージェント構成を選択する", - "xpack.ingestManager.createDatasource.stepSelectConfigLabel": "構成を選択", "xpack.ingestManager.createDatasource.stepSelectPackage.errorLoadingConfigTitle": "エージェント構成情報の読み込みエラー", "xpack.ingestManager.createDatasource.stepSelectPackage.errorLoadingPackagesTitle": "パッケージの読み込みエラー", "xpack.ingestManager.createDatasource.stepSelectPackage.errorLoadingSelectedPackageTitle": "選択したパッケージの読み込みエラー", "xpack.ingestManager.createDatasource.stepSelectPackage.filterPackagesInputPlaceholder": "パッケージの検索", - "xpack.ingestManager.createDatasource.stepSelectPackage.selectPackageTitle": "パッケージを選択する", - "xpack.ingestManager.createDatasource.stepSelectPackageLabel": "パッケージを選択", "xpack.ingestManager.deleteAgentConfigs.confirmModal.affectedAgentsMessage": "{agentsCount, plural, one {# エージェントを} other {# エージェントを}}{agentConfigsCount, plural, one {このエージェント構成に} other {これらのエージェント構成に}}割り当てました。 {agentsCount, plural, one {このエージェント} other {これらのエージェント}}の登録が解除されます。", "xpack.ingestManager.deleteAgentConfigs.confirmModal.cancelButtonLabel": "キャンセル", "xpack.ingestManager.deleteAgentConfigs.confirmModal.confirmAndReassignButtonLabel": "{agentConfigsCount, plural, one {エージェント構成} other {エージェント構成}} and unenroll {agentsCount, plural, one {エージェント} other {エージェント}} を削除", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 75f48fb11823a..1daf66117e948 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8286,7 +8286,6 @@ "xpack.ingestManager.agentConfigForm.systemMonitoringFieldLabel": "可选", "xpack.ingestManager.agentConfigForm.systemMonitoringText": "收集系统指标", "xpack.ingestManager.agentConfigForm.systemMonitoringTooltipText": "启用此选项可使用收集系统指标和信息的数据源启动您的配置。", - "xpack.ingestManager.agentConfigInfo.yamlTabName": "YAML", "xpack.ingestManager.agentConfigList.actionsColumnTitle": "操作", "xpack.ingestManager.agentConfigList.actionsMenuText": "打开", "xpack.ingestManager.agentConfigList.addButton": "创建代理配置", @@ -8424,21 +8423,14 @@ "xpack.ingestManager.createAgentConfig.flyoutTitleDescription": "代理配置用于管理整个代理组的设置。您可以将数据源添加到代理配置以指定代理收集的数据。编辑代理配置时,可以使用 Fleet 将更新部署到指定的代理组。", "xpack.ingestManager.createAgentConfig.submitButtonLabel": "创建代理配置", "xpack.ingestManager.createAgentConfig.successNotificationTitle": "代理配置“{name}”已创建", - "xpack.ingestManager.createDatasource.addDatasourceButtonText": "将数据源添加到配置", "xpack.ingestManager.createDatasource.agentConfigurationNameLabel": "配置", "xpack.ingestManager.createDatasource.cancelLinkText": "取消", - "xpack.ingestManager.createDatasource.changeConfigLinkText": "更改配置", - "xpack.ingestManager.createDatasource.changePackageLinkText": "更改软件包", - "xpack.ingestManager.createDatasource.continueButtonText": "继续", - "xpack.ingestManager.createDatasource.editDatasourceLinkText": "编辑数据源", "xpack.ingestManager.createDatasource.packageNameLabel": "软件包", "xpack.ingestManager.createDatasource.pageTitle": "创建数据源", "xpack.ingestManager.createDatasource.stepConfigure.advancedOptionsToggleLinkText": "高级选项", - "xpack.ingestManager.createDatasource.stepConfigure.chooseDataTitle": "选择要收集的数据", "xpack.ingestManager.createDatasource.stepConfigure.datasourceDescriptionInputLabel": "描述", "xpack.ingestManager.createDatasource.stepConfigure.datasourceNameInputLabel": "数据源名称", "xpack.ingestManager.createDatasource.stepConfigure.datasourceNamespaceInputLabel": "命名空间", - "xpack.ingestManager.createDatasource.stepConfigure.defineDatasourceTitle": "定义您的数据源", "xpack.ingestManager.createDatasource.stepConfigure.hideStreamsAriaLabel": "隐藏 {type} 流", "xpack.ingestManager.createDatasource.stepConfigure.inputSettingsDescription": "以下设置适用于所有流。", "xpack.ingestManager.createDatasource.stepConfigure.inputSettingsTitle": "设置", @@ -8447,27 +8439,15 @@ "xpack.ingestManager.createDatasource.stepConfigure.showStreamsAriaLabel": "显示 {type} 流", "xpack.ingestManager.createDatasource.stepConfigure.streamsEnabledCountText": "{count} / {total, plural, one {# 个流} other {# 个流}}已启用", "xpack.ingestManager.createDatasource.stepConfigure.toggleAdvancedOptionsButtonText": "高级选项", - "xpack.ingestManager.createDatasource.stepConfigureDatasourceLabel": "配置数据源", - "xpack.ingestManager.createDatasource.stepReview.agentsAffectedCalloutText": "Fleet 检测到所选代理配置 {configName} 已由您的部分代理使用。此操作的结果是,Fleet 将更新用此配置进行注册的所有代理。", - "xpack.ingestManager.createDatasource.stepReview.agentsAffectedCalloutTitle": "此操作将影响 {count, plural, one {# 个代理} other {# 个代理}}", - "xpack.ingestManager.createDatasource.stepReview.confirmAgentDisclaimerText": "我理解此操作将更新注册到此配置的所有代理。", - "xpack.ingestManager.createDatasource.stepReview.confirmAgentDisclaimerTitle": "确认您的决定", - "xpack.ingestManager.createDatasource.stepReview.reviewTitle": "复查更改", - "xpack.ingestManager.createDatasource.stepReviewLabel": "复查", "xpack.ingestManager.createDatasource.StepSelectConfig.agentConfigAgentsCountText": "{count, plural, one {# 个代理} other {# 个代理}}", - "xpack.ingestManager.createDatasource.StepSelectConfig.createNewConfigButtonText": "创建新配置", "xpack.ingestManager.createDatasource.StepSelectConfig.errorLoadingAgentConfigsTitle": "加载代理配置时出错", "xpack.ingestManager.createDatasource.StepSelectConfig.errorLoadingPackageTitle": "加载软件包信息时出错", "xpack.ingestManager.createDatasource.StepSelectConfig.errorLoadingSelectedAgentConfigTitle": "加载选定代理配置时出错", "xpack.ingestManager.createDatasource.StepSelectConfig.filterAgentConfigsInputPlaceholder": "搜索代理配置", - "xpack.ingestManager.createDatasource.StepSelectConfig.selectAgentConfigTitle": "选择代理配置", - "xpack.ingestManager.createDatasource.stepSelectConfigLabel": "选择配置", "xpack.ingestManager.createDatasource.stepSelectPackage.errorLoadingConfigTitle": "加载代理配置信息时出错", "xpack.ingestManager.createDatasource.stepSelectPackage.errorLoadingPackagesTitle": "加载软件包时出错", "xpack.ingestManager.createDatasource.stepSelectPackage.errorLoadingSelectedPackageTitle": "加载选定软件包时出错", "xpack.ingestManager.createDatasource.stepSelectPackage.filterPackagesInputPlaceholder": "搜索软件包", - "xpack.ingestManager.createDatasource.stepSelectPackage.selectPackageTitle": "选择软件包", - "xpack.ingestManager.createDatasource.stepSelectPackageLabel": "选择软件包", "xpack.ingestManager.deleteAgentConfigs.confirmModal.affectedAgentsMessage": "{agentsCount, plural, one {# 个代理} other {# 个代理}}已分配{agentConfigsCount, plural, one {给此代理配置} other {给这些代理配置}}。将取消注册{agentsCount, plural, one {此代理} other {这些代理}}。", "xpack.ingestManager.deleteAgentConfigs.confirmModal.cancelButtonLabel": "取消", "xpack.ingestManager.deleteAgentConfigs.confirmModal.confirmAndReassignButtonLabel": "删除{agentConfigsCount, plural, one {代理配置} other {代理配置}}并取消注册{agentsCount, plural, one {代理} other {代理}}", From d00c90510d11e4575a3453b3437221b341a7478f Mon Sep 17 00:00:00 2001 From: Robert Austin <robert.austin@elastic.co> Date: Mon, 13 Apr 2020 11:33:14 -0400 Subject: [PATCH 063/121] Endpoint: Move files, add README, replace implicit `any` with stricter types. Reorganize types. (#63262) * Removed `FIXME` comments and references to private repos. Please use Github issues to track work * Added a README describing the modules in `applications/endpoint` * Removed dead code * Moved `AppRoot` component to its own module * Moved `applications/endpoint/services` under `store` * Moved some exported types to `applications/endpoint/types` * Moved all React code to `view` * Added types in some places that were implicitly `any` * Moved `PageId` type from common directory (where it could be shared with the server) to the public directory --- .../plugins/endpoint/common/generate_data.ts | 1 - x-pack/plugins/endpoint/common/types.ts | 5 -- .../public/applications/endpoint/README.md | 28 +++++++++ .../endpoint/components/truncate_text.ts | 13 ---- .../public/applications/endpoint/index.tsx | 51 +--------------- .../endpoint/store/alerts/index.ts | 1 - .../store/policy_details/middleware.ts | 14 +++-- .../endpoint/store/policy_list/middleware.ts | 4 +- .../policy_list}/services/ingest.test.ts | 2 +- .../policy_list}/services/ingest.ts | 32 +++------- .../endpoint/store/routing/action.ts | 4 +- .../public/applications/endpoint/types.ts | 27 ++++++++- .../applications/endpoint/view/app_root.tsx | 59 +++++++++++++++++++ .../__snapshots__/link_to_app.test.tsx.snap | 0 .../__snapshots__/page_view.test.tsx.snap | 0 .../components/header_navigation.tsx} | 7 ++- .../components/link_to_app.test.tsx | 17 ++++-- .../{ => view}/components/link_to_app.tsx | 2 +- .../{ => view}/components/page_view.test.tsx | 2 +- .../{ => view}/components/page_view.tsx | 0 .../use_navigate_to_app_event_handler.ts | 2 +- .../endpoint/view/hosts/details.tsx | 2 +- .../endpoint/view/hosts/index.test.tsx | 1 - .../endpoint/view/policy/policy_details.tsx | 5 +- .../endpoint/view/policy/policy_list.tsx | 4 +- .../applications/endpoint/view/use_page_id.ts | 2 +- 26 files changed, 161 insertions(+), 124 deletions(-) create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/README.md delete mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.ts rename x-pack/plugins/endpoint/public/applications/endpoint/{ => store/policy_list}/services/ingest.test.ts (95%) rename x-pack/plugins/endpoint/public/applications/endpoint/{ => store/policy_list}/services/ingest.ts (77%) create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/app_root.tsx rename x-pack/plugins/endpoint/public/applications/endpoint/{ => view}/components/__snapshots__/link_to_app.test.tsx.snap (100%) rename x-pack/plugins/endpoint/public/applications/endpoint/{ => view}/components/__snapshots__/page_view.test.tsx.snap (100%) rename x-pack/plugins/endpoint/public/applications/endpoint/{components/header_nav.tsx => view/components/header_navigation.tsx} (90%) rename x-pack/plugins/endpoint/public/applications/endpoint/{ => view}/components/link_to_app.test.tsx (86%) rename x-pack/plugins/endpoint/public/applications/endpoint/{ => view}/components/link_to_app.tsx (96%) rename x-pack/plugins/endpoint/public/applications/endpoint/{ => view}/components/page_view.test.tsx (96%) rename x-pack/plugins/endpoint/public/applications/endpoint/{ => view}/components/page_view.tsx (100%) rename x-pack/plugins/endpoint/public/applications/endpoint/{ => view}/hooks/use_navigate_to_app_event_handler.ts (96%) diff --git a/x-pack/plugins/endpoint/common/generate_data.ts b/x-pack/plugins/endpoint/common/generate_data.ts index 7c24bd9d77148..3f783d90e577d 100644 --- a/x-pack/plugins/endpoint/common/generate_data.ts +++ b/x-pack/plugins/endpoint/common/generate_data.ts @@ -7,7 +7,6 @@ import uuid from 'uuid'; import seedrandom from 'seedrandom'; import { AlertEvent, EndpointEvent, HostMetadata, OSFields, HostFields } from './types'; -// FIXME: move types/model to top-level // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { PolicyData } from '../public/applications/endpoint/types'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths diff --git a/x-pack/plugins/endpoint/common/types.ts b/x-pack/plugins/endpoint/common/types.ts index a614526d92a3f..403ca9832e191 100644 --- a/x-pack/plugins/endpoint/common/types.ts +++ b/x-pack/plugins/endpoint/common/types.ts @@ -375,11 +375,6 @@ export interface EndpointEvent { export type ResolverEvent = EndpointEvent | LegacyEndpointEvent; -/** - * The PageId type is used for the payload when firing userNavigatedToPage actions - */ -export type PageId = 'alertsPage' | 'managementPage' | 'policyListPage'; - /** * Takes a @kbn/config-schema 'schema' type and returns a type that represents valid inputs. * Similar to `TypeOf`, but allows strings as input for `schema.number()` (which is inline diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/README.md b/x-pack/plugins/endpoint/public/applications/endpoint/README.md new file mode 100644 index 0000000000000..25bfd615d1d2c --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/README.md @@ -0,0 +1,28 @@ +# Endpoint application +This application provides the user interface for the Elastic Endpoint + +# Architecture +The application consists of a _view_ written in React and a _model_ written in Redux. + +# Modules +We structure the modules to match the architecture. `view` contains the _view_ (all React) code. `store` contains the _model_. + +This section covers the conventions of each top level module. + +# `mocks` +This contains helper code for unit tests. + +## `models` +This contains domain models. By convention, each submodule here contains methods for a single type. Domain model classes would also live here. + +## `store` +This contains the _model_ of the application. All Redux and Redux middleware code (including API interactions) happen here. This module also contains the types and interfaces defining Redux actions. Each action type or interface should be commented and if it has fields, each field should be commented. Comments should be of `tsdoc` style. + +## `view` +This contains the code which renders elements to the DOM. All React code goes here. + +## `index.tsx` +This exports `renderApp` which instantiates the React view with the _model_. + +## `types.ts` +This contains the types and interfaces. All `export`ed types or interfaces (except ones defining Redux actions, which live in `store`) should be here. Each type or interface should have a `tsdoc` style comment. Interfaces should have `tsdoc` comments on each field and types which have fields should do the same. diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.ts b/x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.ts deleted file mode 100644 index 83f4bc1e79317..0000000000000 --- a/x-pack/plugins/endpoint/public/applications/endpoint/components/truncate_text.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 styled from 'styled-components'; - -export const TruncateText = styled.div` - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -`; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx index 82ac95160519c..a1999c056bf59 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/index.tsx @@ -6,19 +6,10 @@ import * as React from 'react'; import ReactDOM from 'react-dom'; -import { CoreStart, AppMountParameters, ScopedHistory } from 'kibana/public'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { Route, Switch } from 'react-router-dom'; -import { Store } from 'redux'; +import { CoreStart, AppMountParameters } from 'kibana/public'; import { EndpointPluginStartDependencies } from '../../plugin'; import { appStoreFactory } from './store'; -import { AlertIndex } from './view/alerts'; -import { HostList } from './view/hosts'; -import { PolicyList } from './view/policy'; -import { PolicyDetails } from './view/policy'; -import { HeaderNavigation } from './components/header_nav'; -import { AppRootProvider } from './view/app_root_provider'; -import { Setup } from './view/setup'; +import { AppRoot } from './view/app_root'; /** * This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle. @@ -37,41 +28,3 @@ export function renderApp( ReactDOM.unmountComponentAtNode(element); }; } - -interface RouterProps { - history: ScopedHistory; - store: Store; - coreStart: CoreStart; - depsStart: EndpointPluginStartDependencies; -} - -const AppRoot: React.FunctionComponent<RouterProps> = React.memo( - ({ history, store, coreStart, depsStart }) => { - return ( - <AppRootProvider store={store} history={history} coreStart={coreStart} depsStart={depsStart}> - <Setup ingestManager={depsStart.ingestManager} notifications={coreStart.notifications} /> - <HeaderNavigation /> - <Switch> - <Route - exact - path="/" - render={() => ( - <h1 data-test-subj="welcomeTitle"> - <FormattedMessage id="xpack.endpoint.welcomeTitle" defaultMessage="Hello World" /> - </h1> - )} - /> - <Route path="/hosts" component={HostList} /> - <Route path="/alerts" component={AlertIndex} /> - <Route path="/policy" exact component={PolicyList} /> - <Route path="/policy/:id" exact component={PolicyDetails} /> - <Route - render={() => ( - <FormattedMessage id="xpack.endpoint.notFound" defaultMessage="Page Not Found" /> - )} - /> - </Switch> - </AppRootProvider> - ); - } -); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/index.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/index.ts index f63910a1c305e..5545218d9abd6 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/index.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/alerts/index.ts @@ -6,4 +6,3 @@ export { alertListReducer } from './reducer'; export { AlertAction } from './action'; -export * from '../../types'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts index 18248e272aada..a00ce255cbac4 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts @@ -4,15 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { MiddlewareFactory, PolicyData, PolicyDetailsState } from '../../types'; +import { + MiddlewareFactory, + PolicyData, + PolicyDetailsState, + UpdateDatasourceResponse, +} from '../../types'; import { policyIdFromParams, isOnPolicyDetailsPage, policyDetails } from './selectors'; +import { generatePolicy } from '../../models/policy'; import { sendGetDatasource, sendGetFleetAgentStatusForConfig, sendPutDatasource, - UpdateDatasourceResponse, -} from '../../services/ingest'; -import { generatePolicy } from '../../models/policy'; +} from '../policy_list/services/ingest'; export const policyDetailsMiddlewareFactory: MiddlewareFactory<PolicyDetailsState> = coreStart => { const http = coreStart.http; @@ -35,7 +39,6 @@ export const policyDetailsMiddlewareFactory: MiddlewareFactory<PolicyDetailsStat return; } - // FIXME: remove this code once the Default Policy is available in the endpoint package - see: https://github.com/elastic/endpoint-app-team/issues/295 // Until we get the Default configuration into the Endpoint package so that the datasource has // the expected data structure, we will add it here manually. if (!policyItem.inputs.length) { @@ -62,7 +65,6 @@ export const policyDetailsMiddlewareFactory: MiddlewareFactory<PolicyDetailsStat // Agent summary is secondary data, so its ok for it to come after the details // page is populated with the main content - // FIXME: need to only do this IF fleet is enabled - see: https://github.com/elastic/endpoint-app-team/issues/296 if (policyItem.config_id) { const { results } = await sendGetFleetAgentStatusForConfig(http, policyItem.config_id); dispatch({ diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts index ebfee5dbe6a7e..adc176740fb4b 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { MiddlewareFactory, PolicyListState } from '../../types'; -import { GetDatasourcesResponse, sendGetEndpointSpecificDatasources } from '../../services/ingest'; +import { MiddlewareFactory, PolicyListState, GetDatasourcesResponse } from '../../types'; +import { sendGetEndpointSpecificDatasources } from './services/ingest'; export const policyListMiddlewareFactory: MiddlewareFactory<PolicyListState> = coreStart => { const http = coreStart.http; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/services/ingest.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.test.ts similarity index 95% rename from x-pack/plugins/endpoint/public/applications/endpoint/services/ingest.test.ts rename to x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.test.ts index a2c1dfbe09a48..c2865d36c95f2 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/services/ingest.test.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.test.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { httpServiceMock } from '../../../../../../../src/core/public/mocks'; import { sendGetDatasource, sendGetEndpointSpecificDatasources } from './ingest'; +import { httpServiceMock } from '../../../../../../../../../src/core/public/mocks'; describe('ingest service', () => { let http: ReturnType<typeof httpServiceMock.createStartContract>; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/services/ingest.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts similarity index 77% rename from x-pack/plugins/endpoint/public/applications/endpoint/services/ingest.ts rename to x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts index 583ebc55d896b..16c885f26f0a4 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/services/ingest.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts @@ -6,37 +6,21 @@ import { HttpFetchOptions, HttpStart } from 'kibana/public'; import { - CreateDatasourceResponse, - GetAgentStatusResponse, GetDatasourcesRequest, -} from '../../../../../ingest_manager/common/types/rest_spec'; -import { NewPolicyData, PolicyData } from '../types'; + GetAgentStatusResponse, +} from '../../../../../../../ingest_manager/common'; +import { + NewPolicyData, + GetDatasourcesResponse, + GetDatasourceResponse, + UpdateDatasourceResponse, +} from '../../../types'; const INGEST_API_ROOT = `/api/ingest_manager`; const INGEST_API_DATASOURCES = `${INGEST_API_ROOT}/datasources`; const INGEST_API_FLEET = `${INGEST_API_ROOT}/fleet`; const INGEST_API_FLEET_AGENT_STATUS = `${INGEST_API_FLEET}/agent-status`; -// FIXME: Import from ingest after - https://github.com/elastic/kibana/issues/60677 -export interface GetDatasourcesResponse { - items: PolicyData[]; - total: number; - page: number; - perPage: number; - success: boolean; -} - -// FIXME: Import from Ingest after - https://github.com/elastic/kibana/issues/60677 -export interface GetDatasourceResponse { - item: PolicyData; - success: boolean; -} - -// FIXME: Import from Ingest after - https://github.com/elastic/kibana/issues/60677 -export type UpdateDatasourceResponse = CreateDatasourceResponse & { - item: PolicyData; -}; - /** * Retrieves a list of endpoint specific datasources (those created with a `package.name` of * `endpoint`) from Ingest diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts index c7e9970e58c30..f22272bc68233 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PageId, Immutable } from '../../../../../common/types'; -import { EndpointAppLocation } from '../alerts'; +import { Immutable } from '../../../../../common/types'; +import { EndpointAppLocation, PageId } from '../../types'; interface UserNavigatedToPage { readonly type: 'userNavigatedToPage'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index dda50847169e7..f9ad8f6708f6b 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -18,7 +18,10 @@ import { EndpointPluginStartDependencies } from '../../plugin'; import { AppAction } from './store/action'; import { CoreStart } from '../../../../../../src/core/public'; import { Datasource, NewDatasource } from '../../../../ingest_manager/common/types/models'; -import { GetAgentStatusResponse } from '../../../../ingest_manager/common/types/rest_spec'; +import { + GetAgentStatusResponse, + CreateDatasourceResponse, +} from '../../../../ingest_manager/common/types/rest_spec'; export { AppAction }; export type MiddlewareFactory<S = GlobalState> = ( @@ -317,3 +320,25 @@ export interface AlertingIndexUIQueryParams { date_range?: string; filters?: string; } + +export interface GetDatasourcesResponse { + items: PolicyData[]; + total: number; + page: number; + perPage: number; + success: boolean; +} + +export interface GetDatasourceResponse { + item: PolicyData; + success: boolean; +} + +export type UpdateDatasourceResponse = CreateDatasourceResponse & { + item: PolicyData; +}; + +/** + * The PageId type is used for the payload when firing userNavigatedToPage actions + */ +export type PageId = 'alertsPage' | 'managementPage' | 'policyListPage'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/app_root.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/app_root.tsx new file mode 100644 index 0000000000000..f9634c63deefb --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/app_root.tsx @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import * as React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { Route, Switch } from 'react-router-dom'; +import { Store } from 'redux'; +import { AlertIndex } from './alerts'; +import { HostList } from './hosts'; +import { PolicyList } from './policy'; +import { PolicyDetails } from './policy'; +import { HeaderNavigation } from './components/header_navigation'; +import { AppRootProvider } from './app_root_provider'; +import { Setup } from './setup'; +import { EndpointPluginStartDependencies } from '../../../plugin'; +import { ScopedHistory, CoreStart } from '../../../../../../../src/core/public'; + +interface RouterProps { + history: ScopedHistory; + store: Store; + coreStart: CoreStart; + depsStart: EndpointPluginStartDependencies; +} + +/** + * The root of the Endpoint application react view. + */ +export const AppRoot: React.FunctionComponent<RouterProps> = React.memo( + ({ history, store, coreStart, depsStart }) => { + return ( + <AppRootProvider store={store} history={history} coreStart={coreStart} depsStart={depsStart}> + <Setup ingestManager={depsStart.ingestManager} notifications={coreStart.notifications} /> + <HeaderNavigation /> + <Switch> + <Route + exact + path="/" + render={() => ( + <h1 data-test-subj="welcomeTitle"> + <FormattedMessage id="xpack.endpoint.welcomeTitle" defaultMessage="Hello World" /> + </h1> + )} + /> + <Route path="/hosts" component={HostList} /> + <Route path="/alerts" component={AlertIndex} /> + <Route path="/policy" exact component={PolicyList} /> + <Route path="/policy/:id" exact component={PolicyDetails} /> + <Route + render={() => ( + <FormattedMessage id="xpack.endpoint.notFound" defaultMessage="Page Not Found" /> + )} + /> + </Switch> + </AppRootProvider> + ); + } +); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/link_to_app.test.tsx.snap b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/__snapshots__/link_to_app.test.tsx.snap similarity index 100% rename from x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/link_to_app.test.tsx.snap rename to x-pack/plugins/endpoint/public/applications/endpoint/view/components/__snapshots__/link_to_app.test.tsx.snap diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/page_view.test.tsx.snap b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/__snapshots__/page_view.test.tsx.snap similarity index 100% rename from x-pack/plugins/endpoint/public/applications/endpoint/components/__snapshots__/page_view.test.tsx.snap rename to x-pack/plugins/endpoint/public/applications/endpoint/view/components/__snapshots__/page_view.test.tsx.snap diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/header_navigation.tsx similarity index 90% rename from x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx rename to x-pack/plugins/endpoint/public/applications/endpoint/view/components/header_navigation.tsx index 3fb06d6b4a56e..6c294d9c86548 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/components/header_nav.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/header_navigation.tsx @@ -8,15 +8,16 @@ import React, { MouseEvent, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiTabs, EuiTab } from '@elastic/eui'; import { useHistory, useLocation } from 'react-router-dom'; -import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; +import { Immutable } from '../../../../../common/types'; -export interface NavTabs { +interface NavTabs { name: string; id: string; href: string; } -export const navTabs: NavTabs[] = [ +const navTabs: Immutable<NavTabs[]> = [ { id: 'home', name: i18n.translate('xpack.endpoint.headerNav.home', { diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/link_to_app.test.tsx similarity index 86% rename from x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.test.tsx rename to x-pack/plugins/endpoint/public/applications/endpoint/view/components/link_to_app.test.tsx index 902c215434aac..d0a8f9690dafb 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.test.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/link_to_app.test.tsx @@ -7,9 +7,14 @@ import React from 'react'; import { mount } from 'enzyme'; import { LinkToApp } from './link_to_app'; -import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public'; -import { coreMock } from '../../../../../../../src/core/public/mocks'; import { CoreStart } from 'kibana/public'; +import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public'; +import { coreMock } from '../../../../../../../../src/core/public/mocks'; + +type LinkToAppOnClickMock<Return = void> = jest.Mock< + Return, + [React.MouseEvent<HTMLAnchorElement, MouseEvent>] +>; describe('LinkToApp component', () => { let fakeCoreStart: jest.Mocked<CoreStart>; @@ -38,7 +43,8 @@ describe('LinkToApp component', () => { ).toMatchSnapshot(); }); it('should support onClick prop', () => { - const spyOnClickHandler = jest.fn(); + // Take `_event` (even though it is not used) so that `jest.fn` will have a type that expects to be called with an event + const spyOnClickHandler: LinkToAppOnClickMock = jest.fn(_event => {}); const renderResult = render( <LinkToApp appId="ingestManager" href="/app/ingest" onClick={spyOnClickHandler}> link @@ -91,7 +97,8 @@ describe('LinkToApp component', () => { }); }); it('should still preventDefault if onClick callback throws', () => { - const spyOnClickHandler = jest.fn(ev => { + // Take `_event` (even though it is not used) so that `jest.fn` will have a type that expects to be called with an event + const spyOnClickHandler: LinkToAppOnClickMock<never> = jest.fn(_event => { throw new Error('test'); }); const renderResult = render( @@ -104,7 +111,7 @@ describe('LinkToApp component', () => { expect(clickEventArg.isDefaultPrevented()).toBe(true); }); it('should not navigate if onClick callback prevents defalut', () => { - const spyOnClickHandler = jest.fn(ev => { + const spyOnClickHandler: LinkToAppOnClickMock = jest.fn(ev => { ev.preventDefault(); }); const renderResult = render( diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/link_to_app.tsx similarity index 96% rename from x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx rename to x-pack/plugins/endpoint/public/applications/endpoint/view/components/link_to_app.tsx index 858dac864b58a..6a3cf5e78f4bf 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/link_to_app.tsx @@ -9,7 +9,7 @@ import { EuiLink } from '@elastic/eui'; import { EuiLinkProps } from '@elastic/eui'; import { useNavigateToAppEventHandler } from '../hooks/use_navigate_to_app_event_handler'; -export type LinkToAppProps = EuiLinkProps & { +type LinkToAppProps = EuiLinkProps & { /** the app id - normally the value of the `id` in that plugin's `kibana.json` */ appId: string; /** Any app specific path (route) */ diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/page_view.test.tsx similarity index 96% rename from x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.test.tsx rename to x-pack/plugins/endpoint/public/applications/endpoint/view/components/page_view.test.tsx index 0d4d26737d355..4007477a088fa 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.test.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/page_view.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { mount } from 'enzyme'; import { PageView } from './page_view'; -import { EuiThemeProvider } from '../../../../../../legacy/common/eui_styled_components'; +import { EuiThemeProvider } from '../../../../../../../legacy/common/eui_styled_components'; describe('PageView component', () => { const render = (ui: Parameters<typeof mount>[0]) => diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/components/page_view.tsx similarity index 100% rename from x-pack/plugins/endpoint/public/applications/endpoint/components/page_view.tsx rename to x-pack/plugins/endpoint/public/applications/endpoint/view/components/page_view.tsx diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/hooks/use_navigate_to_app_event_handler.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/hooks/use_navigate_to_app_event_handler.ts similarity index 96% rename from x-pack/plugins/endpoint/public/applications/endpoint/hooks/use_navigate_to_app_event_handler.ts rename to x-pack/plugins/endpoint/public/applications/endpoint/view/hooks/use_navigate_to_app_event_handler.ts index 5fbfa5e0e58a8..ec9a8691c481e 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/hooks/use_navigate_to_app_event_handler.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/hooks/use_navigate_to_app_event_handler.ts @@ -6,7 +6,7 @@ import { MouseEventHandler, useCallback } from 'react'; import { ApplicationStart } from 'kibana/public'; -import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; type NavigateToAppHandlerProps = Parameters<ApplicationStart['navigateToApp']>; type EventHandlerCallback = MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx index 90829f7ad4cbe..f51349b24933a 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx @@ -28,7 +28,7 @@ import { useHostListSelector } from './hooks'; import { urlFromQueryParams } from './url_from_query_params'; import { FormattedDateAndTime } from '../formatted_date_time'; import { uiQueryParams, detailsData, detailsError } from './../../store/hosts/selectors'; -import { LinkToApp } from '../../components/link_to_app'; +import { LinkToApp } from '../components/link_to_app'; const HostIds = styled(EuiListGroupItem)` margin-top: 0; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx index c3ff41268e3db..d2d0ad40b025f 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/index.test.tsx @@ -151,7 +151,6 @@ describe('when on the hosts page', () => { }); it('should navigate to logs without full page refresh', async () => { - // FIXME: this is not working :( expect(coreStart.application.navigateToApp.mock.calls).toHaveLength(1); }); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx index 1e723e32615eb..267077da6598c 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx @@ -29,7 +29,7 @@ import { isLoading, apiError, } from '../../store/policy_details/selectors'; -import { PageView, PageViewHeaderTitle } from '../../components/page_view'; +import { PageView, PageViewHeaderTitle } from '../components/page_view'; import { AppAction } from '../../types'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { AgentsSummary } from './agents_summary'; @@ -82,7 +82,7 @@ export const PolicyDetails = React.memo(() => { } }, [notifications.toasts, policyItem, policyName, policyUpdateStatus]); - const handleBackToListOnClick = useCallback( + const handleBackToListOnClick: React.MouseEventHandler = useCallback( ev => { ev.preventDefault(); history.push(`/policy`); @@ -161,7 +161,6 @@ export const PolicyDetails = React.memo(() => { fill={true} iconType="save" data-test-subj="policyDetailsSaveButton" - // FIXME: need to disable if User has no write permissions to ingest - see: https://github.com/elastic/endpoint-app-team/issues/296 onClick={handleSaveOnClick} isLoading={isPolicyLoading} > diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx index 5ee1539ce9788..06ba74aa46732 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx @@ -23,8 +23,8 @@ import { usePolicyListSelector } from './policy_hooks'; import { PolicyListAction } from '../../store/policy_list'; import { PolicyData } from '../../types'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; -import { PageView } from '../../components/page_view'; -import { LinkToApp } from '../../components/link_to_app'; +import { PageView } from '../components/page_view'; +import { LinkToApp } from '../components/link_to_app'; interface TableChangeCallbackArguments { page: { index: number; size: number }; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts index 49c39064c8d9a..85ed8a39fb386 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts @@ -6,8 +6,8 @@ import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; -import { PageId } from '../../../../common/types'; import { RoutingAction } from '../store/routing'; +import { PageId } from '../types'; /** * Dispatches a 'userNavigatedToPage' action with the given 'pageId' as the action payload. From d5fc944b4bccdd987f05e5fcdcc5d8289eecfd92 Mon Sep 17 00:00:00 2001 From: Alexey Antonov <alexwizp@gmail.com> Date: Mon, 13 Apr 2020 18:59:48 +0300 Subject: [PATCH 064/121] Index pattern management UI -> TypeScript (source_filters_table) (#62925) * [WIP] Index pattern management UI -> TypeScript (source_filters_table) --- .../source_filters_table.test.tsx.snap} | 73 ++------ .../add_filter.test.tsx.snap} | 0 .../components/add_filter/add_filter.js | 73 -------- ...add_filter.test.js => add_filter.test.tsx} | 21 +-- .../components/add_filter/add_filter.tsx | 63 +++++++ .../add_filter/{index.js => index.ts} | 0 .../confirmation_modal.test.tsx.snap | 37 ++++ .../confirmation_modal.test.tsx | 37 ++++ .../confirmation_modal/confirmation_modal.tsx | 76 ++++++++ .../components/confirmation_modal/index.ts | 20 +++ .../header.test.tsx.snap} | 4 +- .../header.test.js => header.test.tsx} | 2 +- .../header/{header.js => header.tsx} | 5 +- .../components/header/{index.js => index.ts} | 0 .../source_filters_table/components/index.ts | 23 +++ .../table.test.tsx.snap} | 37 ++-- .../components/table/{index.js => index.ts} | 0 .../table.test.js => table.test.tsx} | 146 ++++++++------- .../components/table/{table.js => table.tsx} | 169 ++++++++++-------- .../{index.js => index.ts} | 0 ....test.js => source_filters_table.test.tsx} | 82 +++++---- ...ters_table.js => source_filters_table.tsx} | 138 ++++++-------- .../source_filters_table/types.ts | 24 +++ 23 files changed, 617 insertions(+), 413 deletions(-) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/{__jest__/__snapshots__/source_filters_table.test.js.snap => __snapshots__/source_filters_table.test.tsx.snap} (82%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/{__jest__/__snapshots__/add_filter.test.js.snap => __snapshots__/add_filter.test.tsx.snap} (100%) delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.js rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/{__jest__/add_filter.test.js => add_filter.test.tsx} (66%) create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/{index.js => index.ts} (100%) create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.test.tsx create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.tsx create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/index.ts rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/{__jest__/__snapshots__/header.test.js.snap => __snapshots__/header.test.tsx.snap} (98%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/{__jest__/header.test.js => header.test.tsx} (95%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/{header.js => header.tsx} (99%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/{index.js => index.ts} (100%) create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/index.ts rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/{__jest__/__snapshots__/table.test.js.snap => __snapshots__/table.test.tsx.snap} (77%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/{index.js => index.ts} (100%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/{__jest__/table.test.js => table.test.tsx} (69%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/{table.js => table.tsx} (54%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/{index.js => index.ts} (100%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/{__jest__/source_filters_table.test.js => source_filters_table.test.tsx} (64%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/{source_filters_table.js => source_filters_table.tsx} (56%) create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/types.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__jest__/__snapshots__/source_filters_table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__snapshots__/source_filters_table.test.tsx.snap similarity index 82% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__jest__/__snapshots__/source_filters_table.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__snapshots__/source_filters_table.test.tsx.snap index 52fccb8607a83..a7b73624c4665 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__jest__/__snapshots__/source_filters_table.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__snapshots__/source_filters_table.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`SourceFiltersTable should add a filter 1`] = ` -<div> +<Fragment> <header /> <AddFilter onAddFilter={[Function]} @@ -50,11 +50,11 @@ exports[`SourceFiltersTable should add a filter 1`] = ` } saveFilter={[Function]} /> -</div> +</Fragment> `; exports[`SourceFiltersTable should filter based on the query bar 1`] = ` -<div> +<Fragment> <header /> <AddFilter onAddFilter={[Function]} @@ -91,11 +91,11 @@ exports[`SourceFiltersTable should filter based on the query bar 1`] = ` } saveFilter={[Function]} /> -</div> +</Fragment> `; exports[`SourceFiltersTable should remove a filter 1`] = ` -<div> +<Fragment> <header /> <AddFilter onAddFilter={[Function]} @@ -120,10 +120,6 @@ exports[`SourceFiltersTable should remove a filter 1`] = ` ], }, "sourceFilters": Array [ - Object { - "clientId": 1, - "value": "tim*", - }, Object { "clientId": 2, "value": "na*", @@ -136,21 +132,17 @@ exports[`SourceFiltersTable should remove a filter 1`] = ` Array [ Object { "clientId": 3, - "value": "tim*", - }, - Object { - "clientId": 4, "value": "na*", }, ] } saveFilter={[Function]} /> -</div> +</Fragment> `; exports[`SourceFiltersTable should render normally 1`] = ` -<div> +<Fragment> <header /> <AddFilter onAddFilter={[Function]} @@ -195,11 +187,11 @@ exports[`SourceFiltersTable should render normally 1`] = ` } saveFilter={[Function]} /> -</div> +</Fragment> `; exports[`SourceFiltersTable should should a loading indicator when saving 1`] = ` -<div> +<Fragment> <header /> <AddFilter onAddFilter={[Function]} @@ -230,11 +222,11 @@ exports[`SourceFiltersTable should should a loading indicator when saving 1`] = } saveFilter={[Function]} /> -</div> +</Fragment> `; exports[`SourceFiltersTable should show a delete modal 1`] = ` -<div> +<Fragment> <header /> <AddFilter onAddFilter={[Function]} @@ -265,43 +257,16 @@ exports[`SourceFiltersTable should show a delete modal 1`] = ` } saveFilter={[Function]} /> - <eui-overlay-mask> - <eui-confirm-modal - buttonColor="danger" - cancelButtonText={ - <FormattedMessage - defaultMessage="Cancel" - id="kbn.management.editIndexPattern.source.deleteFilter.cancelButtonLabel" - values={Object {}} - /> - } - confirmButtonText={ - <FormattedMessage - defaultMessage="Delete" - id="kbn.management.editIndexPattern.source.deleteFilter.deleteButtonLabel" - values={Object {}} - /> - } - onCancel={[Function]} - onConfirm={[Function]} - title={ - <FormattedMessage - defaultMessage="Delete source filter '{value}'?" - id="kbn.management.editIndexPattern.source.deleteSourceFilterLabel" - values={ - Object { - "value": "tim*", - } - } - /> - } - /> - </eui-overlay-mask> -</div> + <DeleteFilterConfirmationModal + filterToDeleteValue="tim*" + onCancelConfirmationModal={[Function]} + onDeleteFilter={[Function]} + /> +</Fragment> `; exports[`SourceFiltersTable should update a filter 1`] = ` -<div> +<Fragment> <header /> <AddFilter onAddFilter={[Function]} @@ -344,5 +309,5 @@ exports[`SourceFiltersTable should update a filter 1`] = ` } saveFilter={[Function]} /> -</div> +</Fragment> `; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/__snapshots__/add_filter.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/__snapshots__/add_filter.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__snapshots__/add_filter.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.js deleted file mode 100644 index 2124b76b3a915..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; - -import { EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButton } from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -export class AddFilter extends Component { - static propTypes = { - onAddFilter: PropTypes.func.isRequired, - }; - - constructor(props) { - super(props); - this.state = { - filter: '', - }; - } - - onAddFilter = () => { - this.props.onAddFilter(this.state.filter); - this.setState({ filter: '' }); - }; - - render() { - const { filter } = this.state; - const placeholder = i18n.translate('kbn.management.editIndexPattern.sourcePlaceholder', { - defaultMessage: - "source filter, accepts wildcards (e.g., `user*` to filter fields starting with 'user')", - }); - - return ( - <EuiFlexGroup> - <EuiFlexItem grow={10}> - <EuiFieldText - fullWidth - value={filter} - onChange={e => this.setState({ filter: e.target.value.trim() })} - placeholder={placeholder} - /> - </EuiFlexItem> - <EuiFlexItem> - <EuiButton isDisabled={filter.length === 0} onClick={this.onAddFilter}> - <FormattedMessage - id="kbn.management.editIndexPattern.source.addButtonLabel" - defaultMessage="Add" - /> - </EuiButton> - </EuiFlexItem> - </EuiFlexGroup> - ); - } -} diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/add_filter.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.test.tsx similarity index 66% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/add_filter.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.test.tsx index 915d9490db045..1ebaa3eaf89f8 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/add_filter.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.test.tsx @@ -18,33 +18,30 @@ */ import React from 'react'; -import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; +import { shallow } from 'enzyme'; -import { AddFilter } from '../add_filter'; +import { AddFilter } from './add_filter'; describe('AddFilter', () => { - it('should render normally', async () => { - const component = shallowWithI18nProvider(<AddFilter onAddFilter={() => {}} />); + test('should render normally', () => { + const component = shallow(<AddFilter onAddFilter={() => {}} />); expect(component).toMatchSnapshot(); }); - it('should allow adding a filter', async () => { + test('should allow adding a filter', async () => { const onAddFilter = jest.fn(); - const component = shallowWithI18nProvider(<AddFilter onAddFilter={onAddFilter} />); + const component = shallow(<AddFilter onAddFilter={onAddFilter} />); - // Set a value in the input field - component.setState({ filter: 'tim*' }); - - // Click the button + component.find('EuiFieldText').simulate('change', { target: { value: 'tim*' } }); component.find('EuiButton').simulate('click'); component.update(); expect(onAddFilter).toBeCalledWith('tim*'); }); - it('should ignore strings with just spaces', async () => { - const component = shallowWithI18nProvider(<AddFilter onAddFilter={() => {}} />); + test('should ignore strings with just spaces', () => { + const component = shallow(<AddFilter onAddFilter={() => {}} />); // Set a value in the input field component.find('EuiFieldText').simulate('keypress', ' '); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx new file mode 100644 index 0000000000000..d0f397637de33 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/add_filter.tsx @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useState, useCallback } from 'react'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButton } from '@elastic/eui'; + +interface AddFilterProps { + onAddFilter: (filter: string) => void; +} + +const sourcePlaceholder = i18n.translate('kbn.management.editIndexPattern.sourcePlaceholder', { + defaultMessage: + "source filter, accepts wildcards (e.g., `user*` to filter fields starting with 'user')", +}); + +export const AddFilter = ({ onAddFilter }: AddFilterProps) => { + const [filter, setFilter] = useState<string>(''); + + const onAddButtonClick = useCallback(() => { + onAddFilter(filter); + setFilter(''); + }, [filter, onAddFilter]); + + return ( + <EuiFlexGroup> + <EuiFlexItem grow={10}> + <EuiFieldText + fullWidth + value={filter} + onChange={e => setFilter(e.target.value.trim())} + placeholder={sourcePlaceholder} + /> + </EuiFlexItem> + <EuiFlexItem> + <EuiButton isDisabled={filter.length === 0} onClick={onAddButtonClick}> + <FormattedMessage + id="kbn.management.editIndexPattern.source.addButtonLabel" + defaultMessage="Add" + /> + </EuiButton> + </EuiFlexItem> + </EuiFlexGroup> + ); +}; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap new file mode 100644 index 0000000000000..62376b498d887 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Header should render normally 1`] = ` +<EuiOverlayMask> + <EuiConfirmModal + buttonColor="danger" + cancelButtonText={ + <FormattedMessage + defaultMessage="Cancel" + id="kbn.management.editIndexPattern.source.deleteFilter.cancelButtonLabel" + values={Object {}} + /> + } + confirmButtonText={ + <FormattedMessage + defaultMessage="Delete" + id="kbn.management.editIndexPattern.source.deleteFilter.deleteButtonLabel" + values={Object {}} + /> + } + defaultFocusedButton="confirm" + onCancel={[Function]} + onConfirm={[Function]} + title={ + <FormattedMessage + defaultMessage="Delete source filter '{value}'?" + id="kbn.management.editIndexPattern.source.deleteSourceFilterLabel" + values={ + Object { + "value": "test", + } + } + /> + } + /> +</EuiOverlayMask> +`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.test.tsx new file mode 100644 index 0000000000000..ac7237095e4b3 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.test.tsx @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { DeleteFilterConfirmationModal } from './confirmation_modal'; + +describe('Header', () => { + test('should render normally', () => { + const component = shallow( + <DeleteFilterConfirmationModal + filterToDeleteValue={'test'} + onCancelConfirmationModal={() => {}} + onDeleteFilter={() => {}} + /> + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.tsx new file mode 100644 index 0000000000000..dabfb6d8f275a --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/confirmation_modal.tsx @@ -0,0 +1,76 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import PropTypes from 'prop-types'; + +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiOverlayMask, EuiConfirmModal, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui'; + +interface DeleteFilterConfirmationModalProps { + filterToDeleteValue: string; + onCancelConfirmationModal: ( + event?: React.KeyboardEvent<HTMLDivElement> | React.MouseEvent<HTMLButtonElement> + ) => void; + onDeleteFilter: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void; +} + +export const DeleteFilterConfirmationModal = ({ + filterToDeleteValue, + onCancelConfirmationModal, + onDeleteFilter, +}: DeleteFilterConfirmationModalProps) => { + return ( + <EuiOverlayMask> + <EuiConfirmModal + title={ + <FormattedMessage + id="kbn.management.editIndexPattern.source.deleteSourceFilterLabel" + defaultMessage="Delete source filter '{value}'?" + values={{ + value: filterToDeleteValue, + }} + /> + } + onCancel={onCancelConfirmationModal} + onConfirm={onDeleteFilter} + cancelButtonText={ + <FormattedMessage + id="kbn.management.editIndexPattern.source.deleteFilter.cancelButtonLabel" + defaultMessage="Cancel" + /> + } + buttonColor="danger" + confirmButtonText={ + <FormattedMessage + id="kbn.management.editIndexPattern.source.deleteFilter.deleteButtonLabel" + defaultMessage="Delete" + /> + } + defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON} + /> + </EuiOverlayMask> + ); +}; + +DeleteFilterConfirmationModal.propTypes = { + filterToDeleteValue: PropTypes.string.isRequired, + onCancelConfirmationModal: PropTypes.func.isRequired, + onDeleteFilter: PropTypes.func.isRequired, +}; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/index.ts b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/index.ts new file mode 100644 index 0000000000000..e48e38b7c3dcb --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/confirmation_modal/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 { DeleteFilterConfirmationModal } from './confirmation_modal'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__jest__/__snapshots__/header.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__jest__/__snapshots__/header.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap index a5be141a18c89..cde0de79caacd 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__jest__/__snapshots__/header.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__snapshots__/header.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Header should render normally 1`] = ` -<div> +<Fragment> <EuiTitle size="s" > @@ -32,5 +32,5 @@ exports[`Header should render normally 1`] = ` <EuiSpacer size="s" /> -</div> +</Fragment> `; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__jest__/header.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.test.tsx similarity index 95% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__jest__/header.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.test.tsx index 058bf99fe26fa..869bdeb55cf02 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/__jest__/header.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.test.tsx @@ -23,7 +23,7 @@ import { shallow } from 'enzyme'; import { Header } from '../header'; describe('Header', () => { - it('should render normally', async () => { + test('should render normally', () => { const component = shallow(<Header />); expect(component).toMatchSnapshot(); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.tsx similarity index 99% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.tsx index 8822ca6236250..7b37f75043dd5 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/header.tsx @@ -20,11 +20,10 @@ import React from 'react'; import { EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; - import { FormattedMessage } from '@kbn/i18n/react'; export const Header = () => ( - <div> + <> <EuiTitle size="s"> <h3> <FormattedMessage @@ -52,5 +51,5 @@ export const Header = () => ( </p> </EuiText> <EuiSpacer size="s" /> - </div> + </> ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/index.ts b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/index.ts new file mode 100644 index 0000000000000..87ac13ad15f50 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/index.ts @@ -0,0 +1,23 @@ +/* + * 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 { AddFilter } from './add_filter'; +export { DeleteFilterConfirmationModal } from './confirmation_modal'; +export { Header } from './header'; +export { Table } from './table'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__jest__/__snapshots__/table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap similarity index 77% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__jest__/__snapshots__/table.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap index a0853b8628cc9..c70d0871bb854 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__jest__/__snapshots__/table.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__snapshots__/table.test.tsx.snap @@ -3,14 +3,15 @@ exports[`Table editing should show a save button 1`] = ` <div> <EuiButtonIcon - aria-label="Save" - iconType="checkInCircleFilled" + aria-label="Edit" + iconType="pencil" onClick={[Function]} size="s" /> <EuiButtonIcon - aria-label="Cancel" - iconType="cross" + aria-label="Delete" + color="danger" + iconType="trash" onClick={[Function]} size="s" /> @@ -18,27 +19,20 @@ exports[`Table editing should show a save button 1`] = ` `; exports[`Table editing should show an input field 1`] = ` -<EuiFormControlLayout - fullWidth={false} -> - <EuiValidatableControl> - <input - autoFocus={true} - className="euiFieldText" - onChange={[Function]} - onKeyDown={[Function]} - type="text" - value="tim*" - /> - </EuiValidatableControl> -</EuiFormControlLayout> +<span> + tim* +</span> `; exports[`Table editing should update the matches dynamically as input value is changed 1`] = ` <div> - <span> - time, value - </span> + <em> + <FormattedMessage + defaultMessage="The source filter doesn't match any known fields." + id="kbn.management.editIndexPattern.source.table.notMatchedLabel" + values={Object {}} + /> + </em> </div> `; @@ -79,6 +73,7 @@ exports[`Table should render normally 1`] = ` items={ Array [ Object { + "clientId": "", "value": "tim*", }, ] diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__jest__/table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.test.tsx similarity index 69% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__jest__/table.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.test.tsx index 7fba1fcfe4876..4705ecd2d1685 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/__jest__/table.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.test.tsx @@ -17,25 +17,40 @@ * under the License. */ -import React from 'react'; -import { shallow } from 'enzyme'; -import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; - -import { Table } from '../table'; -import { keyCodes } from '@elastic/eui'; - -const indexPattern = {}; -const items = [{ value: 'tim*' }]; +import React, { ReactElement } from 'react'; +import { shallow, ShallowWrapper } from 'enzyme'; + +import { Table, TableProps, TableState } from './table'; +import { EuiTableFieldDataColumnType, keyCodes } from '@elastic/eui'; +import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; +import { SourceFiltersTableFilter } from '../../types'; + +const indexPattern = {} as IIndexPattern; +const items: SourceFiltersTableFilter[] = [{ value: 'tim*', clientId: '' }]; + +const getIndexPatternMock = (mockedFields: any = {}) => ({ ...mockedFields } as IIndexPattern); + +const getTableColumnRender = ( + component: ShallowWrapper<TableProps, TableState, Table>, + index: number = 0 +) => { + const columns = component.prop<Array<EuiTableFieldDataColumnType<SourceFiltersTableFilter>>>( + 'columns' + ); + return { + render: columns[index].render as (...args: any) => ReactElement, + }; +}; describe('Table', () => { - it('should render normally', async () => { - const component = shallowWithI18nProvider( + test('should render normally', () => { + const component = shallow( <Table indexPattern={indexPattern} items={items} deleteFilter={() => {}} fieldWildcardMatcher={() => {}} - saveFilter={() => {}} + saveFilter={() => undefined} isSaving={true} /> ); @@ -43,31 +58,33 @@ describe('Table', () => { expect(component).toMatchSnapshot(); }); - it('should render filter matches', async () => { - const component = shallowWithI18nProvider( + test('should render filter matches', () => { + const component = shallow<Table>( <Table - indexPattern={{ + indexPattern={getIndexPatternMock({ getNonScriptedFields: () => [{ name: 'time' }, { name: 'value' }], - }} + })} items={items} deleteFilter={() => {}} - fieldWildcardMatcher={filter => field => field.includes(filter[0])} - saveFilter={() => {}} + fieldWildcardMatcher={(filter: string) => (field: string) => field.includes(filter[0])} + saveFilter={() => undefined} isSaving={false} /> ); - const matchesTableCell = shallow(component.prop('columns')[1].render('tim', { clientId: 1 })); + const matchesTableCell = shallow( + getTableColumnRender(component, 1).render('tim', { clientId: 1 }) + ); expect(matchesTableCell).toMatchSnapshot(); }); describe('editing', () => { const saveFilter = jest.fn(); - const clientId = 1; - let component; + const clientId = '1'; + let component: ShallowWrapper<TableProps, TableState, Table>; beforeEach(() => { - component = shallowWithI18nProvider( + component = shallow<Table>( <Table indexPattern={indexPattern} items={items} @@ -79,11 +96,12 @@ describe('Table', () => { ); }); - it('should show an input field', () => { + test('should show an input field', () => { // Start the editing process + const editingComponent = shallow( // Wrap in a div because: https://github.com/airbnb/enzyme/issues/1213 - <div>{component.prop('columns')[2].render({ clientId, value: 'tim*' })}</div> + <div>{getTableColumnRender(component, 2).render({ clientId, value: 'tim*' })}</div> ); editingComponent .find('EuiButtonIcon') @@ -92,19 +110,19 @@ describe('Table', () => { // Ensure the state change propagates component.update(); - // Ensure the table cell switches to an input - const filterNameTableCell = shallow( - component.prop('columns')[0].render('tim*', { clientId }) - ); + const cell = getTableColumnRender(component).render('tim*', { clientId }); + const filterNameTableCell = shallow(cell); + expect(filterNameTableCell).toMatchSnapshot(); }); - it('should show a save button', () => { + test('should show a save button', () => { // Start the editing process const editingComponent = shallow( // Fixes: Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. - <div>{component.prop('columns')[2].render({ clientId, value: 'tim*' })}</div> + <div>{getTableColumnRender(component, 2).render({ clientId, value: 'tim*' })}</div> ); + editingComponent .find('EuiButtonIcon') .at(1) @@ -116,22 +134,20 @@ describe('Table', () => { // Verify save button const saveTableCell = shallow( // Fixes Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. - <div>{component.prop('columns')[2].render({ clientId, value: 'tim*' })}</div> + <div>{getTableColumnRender(component, 2).render({ clientId, value: 'tim*' })}</div> ); expect(saveTableCell).toMatchSnapshot(); }); - it('should update the matches dynamically as input value is changed', () => { - const localComponent = shallowWithI18nProvider( + test('should update the matches dynamically as input value is changed', () => { + const localComponent = shallow( <Table - indexPattern={{ + indexPattern={getIndexPatternMock({ getNonScriptedFields: () => [{ name: 'time' }, { name: 'value' }], - }} + })} items={items} deleteFilter={() => {}} - fieldWildcardMatcher={query => () => { - return query.includes('time*'); - }} + fieldWildcardMatcher={(query: string) => () => query.includes('time*')} saveFilter={saveFilter} isSaving={false} /> @@ -142,6 +158,7 @@ describe('Table', () => { // Fixes: Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. <div>{localComponent.prop('columns')[2].render({ clientId, value: 'tim*' })}</div> ); + editingComponent .find('EuiButtonIcon') .at(1) @@ -161,7 +178,7 @@ describe('Table', () => { expect(matchesTableCell).toMatchSnapshot(); }); - it('should exit on save', () => { + test('should exit on save', () => { // Change the value to something else component.setState({ editingFilterId: clientId, @@ -171,34 +188,37 @@ describe('Table', () => { // Click the save button const editingComponent = shallow( // Fixes Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. - <div>{component.prop('columns')[2].render({ clientId, value: 'tim*' })}</div> + <div>{getTableColumnRender(component, 2).render({ clientId, value: 'tim*' })}</div> ); + editingComponent .find('EuiButtonIcon') .at(0) .simulate('click'); + editingComponent.update(); + // Ensure we call saveFilter properly expect(saveFilter).toBeCalledWith({ - filterId: clientId, - newFilterValue: 'ti*', + clientId, + value: 'ti*', }); // Ensure the state is properly reset - expect(component.state('editingFilterId')).toBe(null); + expect(component.state('editingFilterId')).toBe(''); }); }); - it('should allow deletes', () => { + test('should allow deletes', () => { const deleteFilter = jest.fn(); - const component = shallowWithI18nProvider( + const component = shallow( <Table indexPattern={indexPattern} items={items} deleteFilter={deleteFilter} fieldWildcardMatcher={() => {}} - saveFilter={() => {}} + saveFilter={() => undefined} isSaving={false} /> ); @@ -210,16 +230,15 @@ describe('Table', () => { ); deleteCellComponent .find('EuiButtonIcon') - .at(0) + .at(1) .simulate('click'); expect(deleteFilter).toBeCalled(); }); - it('should save when in edit mode and the enter key is pressed', () => { + test('should save when in edit mode and the enter key is pressed', () => { const saveFilter = jest.fn(); - const clientId = 1; - const component = shallowWithI18nProvider( + const component = shallow( <Table indexPattern={indexPattern} items={items} @@ -233,19 +252,19 @@ describe('Table', () => { // Start the editing process const editingComponent = shallow( // Fixes Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. - <div>{component.prop('columns')[2].render({ clientId, value: 'tim*' })}</div> + <div>{component.prop('columns')[2].render({ clientId: 1, value: 'tim*' })}</div> ); editingComponent .find('EuiButtonIcon') - .at(1) + .at(0) .simulate('click'); - // Ensure the state change propagates + component.update(); // Get the rendered input cell const filterNameTableCell = shallow( // Fixes Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. - <div>{component.prop('columns')[0].render('tim*', { clientId })}</div> + <div>{component.prop('columns')[0].render('tim*', { clientId: 1 })}</div> ); // Press the enter key @@ -253,14 +272,13 @@ describe('Table', () => { expect(saveFilter).toBeCalled(); // It should reset - expect(component.state('editingFilterId')).toBe(null); + expect(component.state('editingFilterId')).toBe(''); }); - it('should cancel when in edit mode and the esc key is pressed', () => { + test('should cancel when in edit mode and the esc key is pressed', () => { const saveFilter = jest.fn(); - const clientId = 1; - const component = shallowWithI18nProvider( + const component = shallow( <Table indexPattern={indexPattern} items={items} @@ -274,26 +292,28 @@ describe('Table', () => { // Start the editing process const editingComponent = shallow( // Fixes Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. - <div>{component.prop('columns')[2].render({ clientId, value: 'tim*' })}</div> + <div>{component.prop('columns')[2].render({ clientId: 1, value: 'tim*' })}</div> ); + editingComponent .find('EuiButtonIcon') - .at(1) + .at(0) .simulate('click'); + // Ensure the state change propagates component.update(); // Get the rendered input cell const filterNameTableCell = shallow( // Fixes Invariant Violation: ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `symbol`. - <div>{component.prop('columns')[0].render('tim*', { clientId })}</div> + <div>{component.prop('columns')[0].render('tim*', { clientId: 1 })}</div> ); - // Press the enter key + // Press the ESCAPE key filterNameTableCell.find('EuiFieldText').simulate('keydown', { keyCode: keyCodes.ESCAPE }); expect(saveFilter).not.toBeCalled(); // It should reset - expect(component.state('editingFilterId')).toBe(null); + expect(component.state('editingFilterId')).toBe(''); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.tsx similarity index 54% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.tsx index f16663e1cd41a..db2b74bbc9824 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/table/table.tsx @@ -17,48 +17,94 @@ * under the License. */ -import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from 'react'; import { + keyCodes, + EuiBasicTableColumn, EuiInMemoryTable, EuiFieldText, EuiButtonIcon, - keyCodes, RIGHT_ALIGNMENT, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { SourceFiltersTableFilter } from '../../types'; -export class Table extends Component { - static propTypes = { - indexPattern: PropTypes.object.isRequired, - items: PropTypes.array.isRequired, - deleteFilter: PropTypes.func.isRequired, - fieldWildcardMatcher: PropTypes.func.isRequired, - saveFilter: PropTypes.func.isRequired, - isSaving: PropTypes.bool.isRequired, - }; +import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; + +const filterHeader = i18n.translate('kbn.management.editIndexPattern.source.table.filterHeader', { + defaultMessage: 'Filter', +}); + +const filterDescription = i18n.translate( + 'kbn.management.editIndexPattern.source.table.filterDescription', + { defaultMessage: 'Filter name' } +); + +const matchesHeader = i18n.translate('kbn.management.editIndexPattern.source.table.matchesHeader', { + defaultMessage: 'Matches', +}); + +const matchesDescription = i18n.translate( + 'kbn.management.editIndexPattern.source.table.matchesDescription', + { defaultMessage: 'Language used for the field' } +); + +const editAria = i18n.translate('kbn.management.editIndexPattern.source.table.editAria', { + defaultMessage: 'Edit', +}); + +const saveAria = i18n.translate('kbn.management.editIndexPattern.source.table.saveAria', { + defaultMessage: 'Save', +}); + +const deleteAria = i18n.translate('kbn.management.editIndexPattern.source.table.deleteAria', { + defaultMessage: 'Delete', +}); + +const cancelAria = i18n.translate('kbn.management.editIndexPattern.source.table.cancelAria', { + defaultMessage: 'Cancel', +}); + +export interface TableProps { + indexPattern: IIndexPattern; + items: SourceFiltersTableFilter[]; + deleteFilter: Function; + fieldWildcardMatcher: Function; + saveFilter: (filter: SourceFiltersTableFilter) => any; + isSaving: boolean; +} + +export interface TableState { + editingFilterId: string | number; + editingFilterValue: string; +} - constructor(props) { +export class Table extends Component<TableProps, TableState> { + constructor(props: TableProps) { super(props); this.state = { - editingFilterId: null, - editingFilterValue: null, + editingFilterId: '', + editingFilterValue: '', }; } - startEditingFilter = (id, value) => - this.setState({ editingFilterId: id, editingFilterValue: value }); - stopEditingFilter = () => this.setState({ editingFilterId: null }); - onEditingFilterChange = e => this.setState({ editingFilterValue: e.target.value }); + startEditingFilter = ( + editingFilterId: TableState['editingFilterId'], + editingFilterValue: TableState['editingFilterValue'] + ) => this.setState({ editingFilterId, editingFilterValue }); + + stopEditingFilter = () => this.setState({ editingFilterId: '' }); + onEditingFilterChange = (e: React.ChangeEvent<HTMLInputElement>) => + this.setState({ editingFilterValue: e.target.value }); - onEditFieldKeyDown = ({ keyCode }) => { - if (keyCodes.ENTER === keyCode) { + onEditFieldKeyDown = ({ keyCode }: React.KeyboardEvent<HTMLInputElement>) => { + if (keyCodes.ENTER === keyCode && this.state.editingFilterId && this.state.editingFilterValue) { this.props.saveFilter({ - filterId: this.state.editingFilterId, - newFilterValue: this.state.editingFilterValue, + clientId: this.state.editingFilterId, + value: this.state.editingFilterValue, }); this.stopEditingFilter(); } @@ -67,23 +113,18 @@ export class Table extends Component { } }; - getColumns() { + getColumns(): Array<EuiBasicTableColumn<SourceFiltersTableFilter>> { const { deleteFilter, fieldWildcardMatcher, indexPattern, saveFilter } = this.props; return [ { field: 'value', - name: i18n.translate('kbn.management.editIndexPattern.source.table.filterHeader', { - defaultMessage: 'Filter', - }), - description: i18n.translate( - 'kbn.management.editIndexPattern.source.table.filterDescription', - { defaultMessage: 'Filter name' } - ), + name: filterHeader, + description: filterDescription, dataType: 'string', sortable: true, render: (value, filter) => { - if (this.state.editingFilterId === filter.clientId) { + if (this.state.editingFilterId && this.state.editingFilterId === filter.clientId) { return ( <EuiFieldText autoFocus @@ -99,24 +140,20 @@ export class Table extends Component { }, { field: 'value', - name: i18n.translate('kbn.management.editIndexPattern.source.table.matchesHeader', { - defaultMessage: 'Matches', - }), - description: i18n.translate( - 'kbn.management.editIndexPattern.source.table.matchesDescription', - { defaultMessage: 'Language used for the field' } - ), + name: matchesHeader, + description: matchesDescription, dataType: 'string', sortable: true, render: (value, filter) => { - const realtimeValue = - this.state.editingFilterId === filter.clientId ? this.state.editingFilterValue : value; - const matcher = fieldWildcardMatcher([realtimeValue]); + const wildcardMatcher = fieldWildcardMatcher([ + this.state.editingFilterId === filter.clientId ? this.state.editingFilterValue : value, + ]); const matches = indexPattern .getNonScriptedFields() - .map(f => f.name) - .filter(matcher) + .map((currentFilter: any) => currentFilter.name) + .filter(wildcardMatcher) .sort(); + if (matches.length) { return <span>{matches.join(', ')}</span>; } @@ -135,24 +172,21 @@ export class Table extends Component { name: '', align: RIGHT_ALIGNMENT, width: '100', - render: filter => { + render: (filter: SourceFiltersTableFilter) => { if (this.state.editingFilterId === filter.clientId) { return ( - <Fragment> + <> <EuiButtonIcon size="s" onClick={() => { saveFilter({ - filterId: this.state.editingFilterId, - newFilterValue: this.state.editingFilterValue, + clientId: this.state.editingFilterId, + value: this.state.editingFilterValue, }); this.stopEditingFilter(); }} iconType="checkInCircleFilled" - aria-label={i18n.translate( - 'kbn.management.editIndexPattern.source.table.saveAria', - { defaultMessage: 'Save' } - )} + aria-label={saveAria} /> <EuiButtonIcon size="s" @@ -160,37 +194,28 @@ export class Table extends Component { this.stopEditingFilter(); }} iconType="cross" - aria-label={i18n.translate( - 'kbn.management.editIndexPattern.source.table.cancelAria', - { defaultMessage: 'Cancel' } - )} + aria-label={cancelAria} /> - </Fragment> + </> ); } return ( - <Fragment> + <> <EuiButtonIcon size="s" - color="danger" - onClick={() => deleteFilter(filter)} - iconType="trash" - aria-label={i18n.translate( - 'kbn.management.editIndexPattern.source.table.deleteAria', - { defaultMessage: 'Delete' } - )} + onClick={() => this.startEditingFilter(filter.clientId, filter.value)} + iconType="pencil" + aria-label={editAria} /> <EuiButtonIcon size="s" - onClick={() => this.startEditingFilter(filter.clientId, filter.value)} - iconType="pencil" - aria-label={i18n.translate( - 'kbn.management.editIndexPattern.source.table.editAria', - { defaultMessage: 'Edit' } - )} + color="danger" + onClick={() => deleteFilter(filter)} + iconType="trash" + aria-label={deleteAria} /> - </Fragment> + </> ); }, }, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__jest__/source_filters_table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.test.tsx similarity index 64% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__jest__/source_filters_table.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.test.tsx index a39958a77abbf..1b68dd13566d3 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/__jest__/source_filters_table.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.test.tsx @@ -20,13 +20,13 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { SourceFiltersTable } from '../source_filters_table'; +import { SourceFiltersTable } from './source_filters_table'; +import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; jest.mock('@elastic/eui', () => ({ EuiButton: 'eui-button', EuiTitle: 'eui-title', EuiText: 'eui-text', - EuiButton: 'eui-button', EuiHorizontalRule: 'eui-horizontal-rule', EuiSpacer: 'eui-spacer', EuiCallOut: 'eui-call-out', @@ -39,42 +39,54 @@ jest.mock('@elastic/eui', () => ({ default: () => {}, }, })); -jest.mock('../components/header', () => ({ Header: 'header' })); -jest.mock('../components/table', () => ({ + +jest.mock('./components/header', () => ({ Header: 'header' })); +jest.mock('./components/table', () => ({ // Note: this seems to fix React complaining about non lowercase attributes Table: () => { return 'table'; }, })); -const indexPattern = { - sourceFilters: [{ value: 'time*' }, { value: 'nam*' }, { value: 'age*' }], -}; +const getIndexPatternMock = (mockedFields: any = {}) => + ({ + sourceFilters: [{ value: 'time*' }, { value: 'nam*' }, { value: 'age*' }], + ...mockedFields, + } as IIndexPattern); describe('SourceFiltersTable', () => { - it('should render normally', async () => { + test('should render normally', () => { const component = shallow( - <SourceFiltersTable indexPattern={indexPattern} fieldWildcardMatcher={() => {}} /> + <SourceFiltersTable + indexPattern={getIndexPatternMock()} + fieldWildcardMatcher={() => {}} + filterFilter={''} + /> ); expect(component).toMatchSnapshot(); }); - it('should filter based on the query bar', async () => { + test('should filter based on the query bar', () => { const component = shallow( - <SourceFiltersTable indexPattern={indexPattern} fieldWildcardMatcher={() => {}} /> + <SourceFiltersTable + indexPattern={getIndexPatternMock()} + fieldWildcardMatcher={() => {}} + filterFilter={''} + /> ); component.setProps({ filterFilter: 'ti' }); expect(component).toMatchSnapshot(); }); - it('should should a loading indicator when saving', async () => { + test('should should a loading indicator when saving', () => { const component = shallow( <SourceFiltersTable - indexPattern={{ + indexPattern={getIndexPatternMock({ sourceFilters: [{ value: 'tim*' }], - }} + })} + filterFilter={''} fieldWildcardMatcher={() => {}} /> ); @@ -83,34 +95,36 @@ describe('SourceFiltersTable', () => { expect(component).toMatchSnapshot(); }); - it('should show a delete modal', async () => { - const component = shallow( + test('should show a delete modal', () => { + const component = shallow<SourceFiltersTable>( <SourceFiltersTable - indexPattern={{ + indexPattern={getIndexPatternMock({ sourceFilters: [{ value: 'tim*' }], - }} + })} + filterFilter={''} fieldWildcardMatcher={() => {}} /> ); - component.instance().startDeleteFilter({ value: 'tim*' }); + component.instance().startDeleteFilter({ value: 'tim*', clientId: 1 }); component.update(); // We are not calling `.setState` directly so we need to re-render expect(component).toMatchSnapshot(); }); - it('should remove a filter', async () => { + test('should remove a filter', async () => { const save = jest.fn(); - const component = shallow( + const component = shallow<SourceFiltersTable>( <SourceFiltersTable - indexPattern={{ + indexPattern={getIndexPatternMock({ save, sourceFilters: [{ value: 'tim*' }, { value: 'na*' }], - }} + })} + filterFilter={''} fieldWildcardMatcher={() => {}} /> ); - component.instance().startDeleteFilter({ value: 'tim*' }); + component.instance().startDeleteFilter({ value: 'tim*', clientId: 1 }); component.update(); // We are not calling `.setState` directly so we need to re-render await component.instance().deleteFilter(); component.update(); // We are not calling `.setState` directly so we need to re-render @@ -119,14 +133,15 @@ describe('SourceFiltersTable', () => { expect(component).toMatchSnapshot(); }); - it('should add a filter', async () => { + test('should add a filter', async () => { const save = jest.fn(); - const component = shallow( + const component = shallow<SourceFiltersTable>( <SourceFiltersTable - indexPattern={{ + indexPattern={getIndexPatternMock({ save, sourceFilters: [{ value: 'tim*' }], - }} + })} + filterFilter={''} fieldWildcardMatcher={() => {}} /> ); @@ -138,19 +153,20 @@ describe('SourceFiltersTable', () => { expect(component).toMatchSnapshot(); }); - it('should update a filter', async () => { + test('should update a filter', async () => { const save = jest.fn(); - const component = shallow( + const component = shallow<SourceFiltersTable>( <SourceFiltersTable - indexPattern={{ + indexPattern={getIndexPatternMock({ save, sourceFilters: [{ value: 'tim*' }], - }} + })} + filterFilter={''} fieldWildcardMatcher={() => {}} /> ); - await component.instance().saveFilter({ oldFilterValue: 'tim*', newFilterValue: 'ti*' }); + await component.instance().saveFilter({ clientId: 'tim*', value: 'ti*' }); component.update(); // We are not calling `.setState` directly so we need to re-render expect(save).toBeCalled(); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.tsx similarity index 56% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.tsx index 3b485573f3821..dcf8ae9e1323f 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/source_filters_table.tsx @@ -18,33 +18,40 @@ */ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import { createSelector } from 'reselect'; -import { EuiSpacer, EuiOverlayMask, EuiConfirmModal, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui'; +import { EuiSpacer } from '@elastic/eui'; +import { AddFilter, Table, Header, DeleteFilterConfirmationModal } from './components'; +import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; +import { SourceFiltersTableFilter } from './types'; -import { Table } from './components/table'; -import { Header } from './components/header'; -import { AddFilter } from './components/add_filter'; -import { FormattedMessage } from '@kbn/i18n/react'; +export interface SourceFiltersTableProps { + indexPattern: IIndexPattern; + filterFilter: string; + fieldWildcardMatcher: Function; + onAddOrRemoveFilter?: Function; +} -export class SourceFiltersTable extends Component { - static propTypes = { - indexPattern: PropTypes.object.isRequired, - filterFilter: PropTypes.string, - fieldWildcardMatcher: PropTypes.func.isRequired, - onAddOrRemoveFilter: PropTypes.func, - }; +export interface SourceFiltersTableState { + filterToDelete: any; + isDeleteConfirmationModalVisible: boolean; + isSaving: boolean; + filters: SourceFiltersTableFilter[]; +} - constructor(props) { +export class SourceFiltersTable extends Component< + SourceFiltersTableProps, + SourceFiltersTableState +> { + // Source filters do not have any unique ids, only the value is stored. + // To ensure we can create a consistent and expected UX when managing + // source filters, we are assigning a unique id to each filter on the + // client side only + private clientSideId: number = 0; + + constructor(props: SourceFiltersTableProps) { super(props); - // Source filters do not have any unique ids, only the value is stored. - // To ensure we can create a consistent and expected UX when managing - // source filters, we are assigning a unique id to each filter on the - // client side only - this.clientSideId = 0; - this.state = { filterToDelete: undefined, isDeleteConfirmationModalVisible: false, @@ -58,9 +65,9 @@ export class SourceFiltersTable extends Component { } updateFilters = () => { - const sourceFilters = this.props.indexPattern.sourceFilters || []; - const filters = sourceFilters.map(filter => ({ - ...filter, + const sourceFilters = this.props.indexPattern.sourceFilters; + const filters = (sourceFilters || []).map((sourceFilter: any) => ({ + ...sourceFilter, clientId: ++this.clientSideId, })); @@ -68,8 +75,8 @@ export class SourceFiltersTable extends Component { }; getFilteredFilters = createSelector( - state => state.filters, - (state, props) => props.filterFilter, + (state: SourceFiltersTableState) => state.filters, + (state: SourceFiltersTableState, props: SourceFiltersTableProps) => props.filterFilter, (filters, filterFilter) => { if (filterFilter) { const filterFilterToLowercase = filterFilter.toLowerCase(); @@ -82,7 +89,7 @@ export class SourceFiltersTable extends Component { } ); - startDeleteFilter = filter => { + startDeleteFilter = (filter: SourceFiltersTableFilter) => { this.setState({ filterToDelete: filter, isDeleteConfirmationModalVisible: true, @@ -106,35 +113,44 @@ export class SourceFiltersTable extends Component { this.setState({ isSaving: true }); await indexPattern.save(); - onAddOrRemoveFilter && onAddOrRemoveFilter(); + + if (onAddOrRemoveFilter) { + onAddOrRemoveFilter(); + } + this.updateFilters(); this.setState({ isSaving: false }); this.hideDeleteConfirmationModal(); }; - onAddFilter = async value => { + onAddFilter = async (value: string) => { const { indexPattern, onAddOrRemoveFilter } = this.props; indexPattern.sourceFilters = [...(indexPattern.sourceFilters || []), { value }]; this.setState({ isSaving: true }); await indexPattern.save(); - onAddOrRemoveFilter && onAddOrRemoveFilter(); + + if (onAddOrRemoveFilter) { + onAddOrRemoveFilter(); + } + this.updateFilters(); this.setState({ isSaving: false }); }; - saveFilter = async ({ filterId, newFilterValue }) => { + saveFilter = async ({ clientId, value }: SourceFiltersTableFilter) => { const { indexPattern } = this.props; const { filters } = this.state; indexPattern.sourceFilters = filters.map(filter => { - if (filter.clientId === filterId) { + if (filter.clientId === clientId) { return { - value: newFilterValue, - clientId: filter.clientId, + value, + clientId, }; } + return filter; }); @@ -144,55 +160,13 @@ export class SourceFiltersTable extends Component { this.setState({ isSaving: false }); }; - renderDeleteConfirmationModal() { - const { filterToDelete } = this.state; - - if (!filterToDelete) { - return null; - } - - return ( - <EuiOverlayMask> - <EuiConfirmModal - title={ - <FormattedMessage - id="kbn.management.editIndexPattern.source.deleteSourceFilterLabel" - defaultMessage="Delete source filter '{value}'?" - values={{ - value: filterToDelete.value, - }} - /> - } - onCancel={this.hideDeleteConfirmationModal} - onConfirm={this.deleteFilter} - cancelButtonText={ - <FormattedMessage - id="kbn.management.editIndexPattern.source.deleteFilter.cancelButtonLabel" - defaultMessage="Cancel" - /> - } - buttonColor="danger" - confirmButtonText={ - <FormattedMessage - id="kbn.management.editIndexPattern.source.deleteFilter.deleteButtonLabel" - defaultMessage="Delete" - /> - } - defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON} - /> - </EuiOverlayMask> - ); - } - render() { const { indexPattern, fieldWildcardMatcher } = this.props; - - const { isSaving } = this.state; - + const { isSaving, filterToDelete } = this.state; const filteredFilters = this.getFilteredFilters(this.state, this.props); return ( - <div> + <> <Header /> <AddFilter onAddFilter={this.onAddFilter} /> <EuiSpacer size="l" /> @@ -205,8 +179,14 @@ export class SourceFiltersTable extends Component { saveFilter={this.saveFilter} /> - {this.renderDeleteConfirmationModal()} - </div> + {filterToDelete && ( + <DeleteFilterConfirmationModal + filterToDeleteValue={filterToDelete.value} + onCancelConfirmationModal={this.hideDeleteConfirmationModal} + onDeleteFilter={this.deleteFilter} + /> + )} + </> ); } } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/types.ts b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/types.ts new file mode 100644 index 0000000000000..ee3689f017471 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/types.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** @internal **/ +export interface SourceFiltersTableFilter { + value: string; + clientId: string | number; +} From 7ea3f12e31f198d6e79907f26518bbab612266b9 Mon Sep 17 00:00:00 2001 From: Alexey Antonov <alexwizp@gmail.com> Date: Mon, 13 Apr 2020 19:02:22 +0300 Subject: [PATCH 065/121] Index pattern management UI -> TypeScript (scripted_fields_table) (#63247) * Index pattern management UI -> TypeScript (scripted_fields_table) --- .../scripted_field_table.test.tsx.snap} | 40 +++--- .../call_outs.test.tsx.snap} | 4 +- .../call_outs.test.js => call_outs.test.tsx} | 4 +- .../call_outs/{call_outs.js => call_outs.tsx} | 12 +- .../call_outs/{index.js => index.ts} | 0 .../confirmation_modal.test.tsx.snap | 14 ++ .../confirmation_modal.test.tsx | 37 ++++++ .../confirmation_modal/confirmation_modal.tsx | 63 +++++++++ .../components/confirmation_modal/index.ts | 20 +++ .../header.test.tsx.snap} | 0 .../header.test.js => header.test.tsx} | 4 +- .../header/{header.js => header.tsx} | 12 +- .../components/header/{index.js => index.ts} | 0 .../components/{index.js => index.ts} | 1 + .../table.test.tsx.snap} | 7 +- .../components/table/{index.js => index.ts} | 0 .../table.test.js => table.test.tsx} | 49 +++---- .../components/table/{table.js => table.tsx} | 35 +++-- .../{index.js => index.ts} | 0 ....test.js => scripted_field_table.test.tsx} | 67 ++++++---- ...lds_table.js => scripted_fields_table.tsx} | 122 ++++++++---------- .../scripted_fields_table/types.ts | 25 ++++ .../{index.js => index.ts} | 12 +- 23 files changed, 346 insertions(+), 182 deletions(-) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/{__jest__/__snapshots__/scripted_field_table.test.js.snap => __snapshots__/scripted_field_table.test.tsx.snap} (89%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/{__jest__/__snapshots__/call_outs.test.js.snap => __snapshots__/call_outs.test.tsx.snap} (98%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/{__jest__/call_outs.test.js => call_outs.test.tsx} (92%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/{call_outs.js => call_outs.tsx} (94%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/{index.js => index.ts} (100%) create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/index.ts rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/{__jest__/__snapshots__/header.test.js.snap => __snapshots__/header.test.tsx.snap} (100%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/{__jest__/header.test.js => header.test.tsx} (92%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/{header.js => header.tsx} (92%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/{index.js => index.ts} (100%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/{index.js => index.ts} (92%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/{__jest__/__snapshots__/table.test.js.snap => __snapshots__/table.test.tsx.snap} (93%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/{index.js => index.ts} (100%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/{__jest__/table.test.js => table.test.tsx} (71%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/{table.js => table.tsx} (84%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/{index.js => index.ts} (100%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/{__jest__/scripted_field_table.test.js => scripted_field_table.test.tsx} (75%) rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/{scripted_fields_table.js => scripted_fields_table.tsx} (60%) create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/types.ts rename src/legacy/ui/public/scripting_languages/{index.js => index.ts} (83%) diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__jest__/__snapshots__/scripted_field_table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap similarity index 89% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__jest__/__snapshots__/scripted_field_table.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap index a53f4d7f609cb..569b75c848c52 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__jest__/__snapshots__/scripted_field_table.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__snapshots__/scripted_field_table.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ScriptedFieldsTable should filter based on the lang filter 1`] = ` -<div> +<Fragment> <header addScriptedFieldUrl="#" /> @@ -39,11 +39,11 @@ exports[`ScriptedFieldsTable should filter based on the lang filter 1`] = ` ] } /> -</div> +</Fragment> `; exports[`ScriptedFieldsTable should filter based on the query bar 1`] = ` -<div> +<Fragment> <header addScriptedFieldUrl="#" /> @@ -72,11 +72,11 @@ exports[`ScriptedFieldsTable should filter based on the query bar 1`] = ` ] } /> -</div> +</Fragment> `; exports[`ScriptedFieldsTable should hide the table if there are no scripted fields 1`] = ` -<div> +<Fragment> <header addScriptedFieldUrl="#" /> @@ -97,11 +97,11 @@ exports[`ScriptedFieldsTable should hide the table if there are no scripted fiel } items={Array []} /> -</div> +</Fragment> `; exports[`ScriptedFieldsTable should render normally 1`] = ` -<div> +<Fragment> <header addScriptedFieldUrl="#" /> @@ -135,11 +135,11 @@ exports[`ScriptedFieldsTable should render normally 1`] = ` ] } /> -</div> +</Fragment> `; exports[`ScriptedFieldsTable should show a delete modal 1`] = ` -<div> +<Fragment> <header addScriptedFieldUrl="#" /> @@ -173,14 +173,16 @@ exports[`ScriptedFieldsTable should show a delete modal 1`] = ` ] } /> - <eui-overlay-mask> - <eui-confirm-modal - cancelButtonText="Cancel" - confirmButtonText="Delete" - onCancel={[Function]} - onConfirm={[Function]} - title="Delete scripted field 'ScriptedField'?" - /> - </eui-overlay-mask> -</div> + <DeleteScritpedFieldConfirmationModal + deleteField={[Function]} + field={ + Object { + "lang": "", + "name": "ScriptedField", + "script": "", + } + } + hideDeleteConfirmationModal={[Function]} + /> +</Fragment> `; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__jest__/__snapshots__/call_outs.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__snapshots__/call_outs.test.tsx.snap similarity index 98% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__jest__/__snapshots__/call_outs.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__snapshots__/call_outs.test.tsx.snap index e6f0d6cd819e3..4dfda1b9339b1 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__jest__/__snapshots__/call_outs.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__snapshots__/call_outs.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`CallOuts should render normally 1`] = ` -<div> +<Fragment> <EuiCallOut color="danger" iconType="cross" @@ -37,7 +37,7 @@ exports[`CallOuts should render normally 1`] = ` <EuiSpacer size="m" /> -</div> +</Fragment> `; exports[`CallOuts should render without any call outs 1`] = `""`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__jest__/call_outs.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.test.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__jest__/call_outs.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.test.tsx index 12e0ee8839967..407928931191d 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/__jest__/call_outs.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.test.tsx @@ -23,7 +23,7 @@ import { shallow } from 'enzyme'; import { CallOuts } from '../call_outs'; describe('CallOuts', () => { - it('should render normally', async () => { + test('should render normally', () => { const component = shallow( <CallOuts deprecatedLangsInUse={['php']} @@ -34,7 +34,7 @@ describe('CallOuts', () => { expect(component).toMatchSnapshot(); }); - it('should render without any call outs', async () => { + test('should render without any call outs', () => { const component = shallow( <CallOuts deprecatedLangsInUse={[]} painlessDocLink="http://www.elastic.co/painlessDocs" /> ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx similarity index 94% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx index 0c321c8ba8b01..8e38b569a32fa 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/call_outs.tsx @@ -20,16 +20,20 @@ import React from 'react'; import { EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; - import { FormattedMessage } from '@kbn/i18n/react'; -export const CallOuts = ({ deprecatedLangsInUse, painlessDocLink }) => { +interface CallOutsProps { + deprecatedLangsInUse: string[]; + painlessDocLink: string; +} + +export const CallOuts = ({ deprecatedLangsInUse, painlessDocLink }: CallOutsProps) => { if (!deprecatedLangsInUse.length) { return null; } return ( - <div> + <> <EuiCallOut title={ <FormattedMessage @@ -60,6 +64,6 @@ export const CallOuts = ({ deprecatedLangsInUse, painlessDocLink }) => { </p> </EuiCallOut> <EuiSpacer size="m" /> - </div> + </> ); }; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/call_outs/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap new file mode 100644 index 0000000000000..2b320782cb163 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/__snapshots__/confirmation_modal.test.tsx.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DeleteScritpedFieldConfirmationModal should render normally 1`] = ` +<EuiOverlayMask> + <EuiConfirmModal + cancelButtonText="Cancel" + confirmButtonText="Delete" + defaultFocusedButton="confirm" + onCancel={[Function]} + onConfirm={[Function]} + title="Delete scripted field ''?" + /> +</EuiOverlayMask> +`; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx new file mode 100644 index 0000000000000..f3594e7507a6a --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.test.tsx @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { DeleteScritpedFieldConfirmationModal } from './confirmation_modal'; + +describe('DeleteScritpedFieldConfirmationModal', () => { + test('should render normally', () => { + const component = shallow( + <DeleteScritpedFieldConfirmationModal + field={{ name: '', script: '', lang: '' }} + deleteField={() => {}} + hideDeleteConfirmationModal={() => {}} + /> + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx new file mode 100644 index 0000000000000..1e82174f863b0 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/confirmation_modal.tsx @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EUI_MODAL_CONFIRM_BUTTON, EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; + +import { ScriptedFieldItem } from '../../types'; + +interface DeleteScritpedFieldConfirmationModalProps { + field: ScriptedFieldItem; + hideDeleteConfirmationModal: ( + event?: React.KeyboardEvent<HTMLDivElement> | React.MouseEvent<HTMLButtonElement> + ) => void; + deleteField: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void; +} + +export const DeleteScritpedFieldConfirmationModal = ({ + field, + hideDeleteConfirmationModal, + deleteField, +}: DeleteScritpedFieldConfirmationModalProps) => { + const title = i18n.translate('kbn.management.editIndexPattern.scripted.deleteFieldLabel', { + defaultMessage: "Delete scripted field '{fieldName}'?", + values: { fieldName: field.name }, + }); + const cancelButtonText = i18n.translate( + 'kbn.management.editIndexPattern.scripted.deleteField.cancelButton', + { defaultMessage: 'Cancel' } + ); + const confirmButtonText = i18n.translate( + 'kbn.management.editIndexPattern.scripted.deleteField.deleteButton', + { defaultMessage: 'Delete' } + ); + + return ( + <EuiOverlayMask> + <EuiConfirmModal + title={title} + onCancel={hideDeleteConfirmationModal} + onConfirm={deleteField} + cancelButtonText={cancelButtonText} + confirmButtonText={confirmButtonText} + defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON} + /> + </EuiOverlayMask> + ); +}; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/index.ts b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/index.ts new file mode 100644 index 0000000000000..b87b572333e6f --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/confirmation_modal/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 { DeleteScritpedFieldConfirmationModal } from './confirmation_modal'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/__snapshots__/header.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/__snapshots__/header.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__snapshots__/header.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/header.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/header.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx index 3e377ccfbdd41..19479de8f2aa4 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/__jest__/header.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.test.tsx @@ -20,10 +20,10 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { Header } from '../header'; +import { Header } from './header'; describe('Header', () => { - it('should render normally', async () => { + test('should render normally', () => { const component = shallow(<Header addScriptedFieldUrl="" />); expect(component).toMatchSnapshot(); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.tsx similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.tsx index 97c235d82f870..b8f832dad72af 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/header.tsx @@ -18,13 +18,15 @@ */ import React from 'react'; -import PropTypes from 'prop-types'; - import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -export const Header = ({ addScriptedFieldUrl }) => ( +interface HeaderProps { + addScriptedFieldUrl: string; +} + +export const Header = ({ addScriptedFieldUrl }: HeaderProps) => ( <EuiFlexGroup alignItems="center"> <EuiFlexItem> <EuiTitle size="s"> @@ -56,7 +58,3 @@ export const Header = ({ addScriptedFieldUrl }) => ( </EuiFlexItem> </EuiFlexGroup> ); - -Header.propTypes = { - addScriptedFieldUrl: PropTypes.string.isRequired, -}; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/header/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.ts index 5c0bb41eab765..7d74776fb2bca 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/index.ts @@ -20,3 +20,4 @@ export { Table } from './table'; export { Header } from './header'; export { CallOuts } from './call_outs'; +export { DeleteScritpedFieldConfirmationModal } from './confirmation_modal'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/__snapshots__/table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__snapshots__/table.test.tsx.snap similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/__snapshots__/table.test.js.snap rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__snapshots__/table.test.tsx.snap index 2da4d84463b29..8439887dd468a 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/__snapshots__/table.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__snapshots__/table.test.tsx.snap @@ -41,6 +41,7 @@ exports[`Table should render normally 1`] = ` "icon": "pencil", "name": "Edit", "onClick": [Function], + "type": "icon", }, Object { "color": "danger", @@ -48,6 +49,7 @@ exports[`Table should render normally 1`] = ` "icon": "trash", "name": "Delete", "onClick": [Function], + "type": "icon", }, ], "name": "", @@ -58,8 +60,9 @@ exports[`Table should render normally 1`] = ` items={ Array [ Object { - "id": 1, - "name": "Elastic", + "lang": "Elastic", + "name": "1", + "script": "", }, ] } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx similarity index 71% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/table.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx index 4545bfa8f64db..13b3875f58687 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/table.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.test.tsx @@ -19,45 +19,50 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; import { Table } from '../table'; +import { ScriptedFieldItem } from '../../types'; +import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; -const indexPattern = { - fieldFormatMap: { - Elastic: { - type: { - title: 'string', - }, - }, - }, -}; +const getIndexPatternMock = (mockedFields: any = {}) => ({ ...mockedFields } as IIndexPattern); -const items = [{ id: 1, name: 'Elastic' }]; +const items: ScriptedFieldItem[] = [{ name: '1', lang: 'Elastic', script: '' }]; describe('Table', () => { - it('should render normally', async () => { - const component = shallowWithI18nProvider( + let indexPattern: IIndexPattern; + + beforeEach(() => { + indexPattern = getIndexPatternMock({ + fieldFormatMap: { + Elastic: { + type: { + title: 'string', + }, + }, + }, + }); + }); + + test('should render normally', () => { + const component = shallow<Table>( <Table indexPattern={indexPattern} items={items} editField={() => {}} deleteField={() => {}} - onChange={() => {}} /> ); expect(component).toMatchSnapshot(); }); - it('should render the format', async () => { - const component = shallowWithI18nProvider( + test('should render the format', () => { + const component = shallow( <Table indexPattern={indexPattern} items={items} editField={() => {}} deleteField={() => {}} - onChange={() => {}} /> ); @@ -65,16 +70,15 @@ describe('Table', () => { expect(formatTableCell).toMatchSnapshot(); }); - it('should allow edits', () => { + test('should allow edits', () => { const editField = jest.fn(); - const component = shallowWithI18nProvider( + const component = shallow( <Table indexPattern={indexPattern} items={items} editField={editField} deleteField={() => {}} - onChange={() => {}} /> ); @@ -83,16 +87,15 @@ describe('Table', () => { expect(editField).toBeCalled(); }); - it('should allow deletes', () => { + test('should allow deletes', () => { const deleteField = jest.fn(); - const component = shallowWithI18nProvider( + const component = shallow( <Table indexPattern={indexPattern} items={items} editField={() => {}} deleteField={deleteField} - onChange={() => {}} /> ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.tsx similarity index 84% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.tsx index 5e05dd95827c7..14aed11b32203 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/table.tsx @@ -18,27 +18,24 @@ */ import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; - -import { EuiInMemoryTable } from '@elastic/eui'; - +import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; +import { EuiInMemoryTable, EuiBasicTableColumn } from '@elastic/eui'; -export class Table extends PureComponent { - static propTypes = { - indexPattern: PropTypes.object.isRequired, - items: PropTypes.array.isRequired, - editField: PropTypes.func.isRequired, - deleteField: PropTypes.func.isRequired, - }; +import { ScriptedFieldItem } from '../../types'; +import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public'; - renderFormatCell = value => { - const { indexPattern } = this.props; +interface TableProps { + indexPattern: IIndexPattern; + items: ScriptedFieldItem[]; + editField: (field: ScriptedFieldItem) => void; + deleteField: (field: ScriptedFieldItem) => void; +} - const title = - indexPattern.fieldFormatMap[value] && indexPattern.fieldFormatMap[value].type - ? indexPattern.fieldFormatMap[value].type.title - : ''; +export class Table extends PureComponent<TableProps> { + renderFormatCell = (value: string) => { + const { indexPattern } = this.props; + const title = get(indexPattern, ['fieldFormatMap', value, 'type', 'title'], ''); return <span>{title}</span>; }; @@ -46,7 +43,7 @@ export class Table extends PureComponent { render() { const { items, editField, deleteField } = this.props; - const columns = [ + const columns: Array<EuiBasicTableColumn<ScriptedFieldItem>> = [ { field: 'displayName', name: i18n.translate('kbn.management.editIndexPattern.scripted.table.nameHeader', { @@ -101,6 +98,7 @@ export class Table extends PureComponent { name: '', actions: [ { + type: 'icon', name: i18n.translate('kbn.management.editIndexPattern.scripted.table.editHeader', { defaultMessage: 'Edit', }), @@ -112,6 +110,7 @@ export class Table extends PureComponent { onClick: editField, }, { + type: 'icon', name: i18n.translate('kbn.management.editIndexPattern.scripted.table.deleteHeader', { defaultMessage: 'Delete', }), diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/index.ts diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__jest__/scripted_field_table.test.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx similarity index 75% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__jest__/scripted_field_table.test.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx index 5be963ad94b7d..914d80f9f61d7 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/__jest__/scripted_field_table.test.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_field_table.test.tsx @@ -18,9 +18,10 @@ */ import React from 'react'; -import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers'; +import { shallow } from 'enzyme'; import { ScriptedFieldsTable } from '../scripted_fields_table'; +import { IIndexPattern } from '../../../../../../../../../plugins/data/common/index_patterns'; jest.mock('@elastic/eui', () => ({ EuiTitle: 'eui-title', @@ -36,18 +37,20 @@ jest.mock('@elastic/eui', () => ({ default: () => {}, }, })); -jest.mock('../components/header', () => ({ Header: 'header' })); -jest.mock('../components/call_outs', () => ({ CallOuts: 'call-outs' })); -jest.mock('../components/table', () => ({ +jest.mock('./components/header', () => ({ Header: 'header' })); +jest.mock('./components/call_outs', () => ({ CallOuts: 'call-outs' })); +jest.mock('./components/table', () => ({ // Note: this seems to fix React complaining about non lowercase attributes Table: () => { return 'table'; }, })); + jest.mock('ui/scripting_languages', () => ({ getSupportedScriptingLanguages: () => ['painless'], getDeprecatedScriptingLanguages: () => [], })); + jest.mock('ui/documentation_links', () => ({ documentationLinks: { scriptedFields: { @@ -61,16 +64,22 @@ const helpers = { getRouteHref: () => '#', }; -const indexPattern = { - getScriptedFields: () => [ - { name: 'ScriptedField', lang: 'painless', script: 'x++' }, - { name: 'JustATest', lang: 'painless', script: 'z++' }, - ], -}; +const getIndexPatternMock = (mockedFields: any = {}) => ({ ...mockedFields } as IIndexPattern); describe('ScriptedFieldsTable', () => { - it('should render normally', async () => { - const component = shallowWithI18nProvider( + let indexPattern: IIndexPattern; + + beforeEach(() => { + indexPattern = getIndexPatternMock({ + getScriptedFields: () => [ + { name: 'ScriptedField', lang: 'painless', script: 'x++' }, + { name: 'JustATest', lang: 'painless', script: 'z++' }, + ], + }); + }); + + test('should render normally', async () => { + const component = shallow<ScriptedFieldsTable>( <ScriptedFieldsTable indexPattern={indexPattern} helpers={helpers} /> ); @@ -82,8 +91,8 @@ describe('ScriptedFieldsTable', () => { expect(component).toMatchSnapshot(); }); - it('should filter based on the query bar', async () => { - const component = shallowWithI18nProvider( + test('should filter based on the query bar', async () => { + const component = shallow( <ScriptedFieldsTable indexPattern={indexPattern} helpers={helpers} /> ); @@ -98,16 +107,16 @@ describe('ScriptedFieldsTable', () => { expect(component).toMatchSnapshot(); }); - it('should filter based on the lang filter', async () => { - const component = shallowWithI18nProvider( + test('should filter based on the lang filter', async () => { + const component = shallow<ScriptedFieldsTable>( <ScriptedFieldsTable - indexPattern={{ + indexPattern={getIndexPatternMock({ getScriptedFields: () => [ { name: 'ScriptedField', lang: 'painless', script: 'x++' }, { name: 'JustATest', lang: 'painless', script: 'z++' }, { name: 'Bad', lang: 'somethingElse', script: 'z++' }, ], - }} + })} helpers={helpers} /> ); @@ -123,12 +132,12 @@ describe('ScriptedFieldsTable', () => { expect(component).toMatchSnapshot(); }); - it('should hide the table if there are no scripted fields', async () => { - const component = shallowWithI18nProvider( + test('should hide the table if there are no scripted fields', async () => { + const component = shallow( <ScriptedFieldsTable - indexPattern={{ + indexPattern={getIndexPatternMock({ getScriptedFields: () => [], - }} + })} helpers={helpers} /> ); @@ -141,22 +150,22 @@ describe('ScriptedFieldsTable', () => { expect(component).toMatchSnapshot(); }); - it('should show a delete modal', async () => { - const component = shallowWithI18nProvider( + test('should show a delete modal', async () => { + const component = shallow<ScriptedFieldsTable>( <ScriptedFieldsTable indexPattern={indexPattern} helpers={helpers} /> ); await component.update(); // Fire `componentWillMount()` - component.instance().startDeleteField({ name: 'ScriptedField' }); + component.instance().startDeleteField({ name: 'ScriptedField', lang: '', script: '' }); await component.update(); // Ensure the modal is visible expect(component).toMatchSnapshot(); }); - it('should delete a field', async () => { + test('should delete a field', async () => { const removeScriptedField = jest.fn(); - const component = shallowWithI18nProvider( + const component = shallow<ScriptedFieldsTable>( <ScriptedFieldsTable indexPattern={{ ...indexPattern, @@ -167,10 +176,12 @@ describe('ScriptedFieldsTable', () => { ); await component.update(); // Fire `componentWillMount()` - component.instance().startDeleteField({ name: 'ScriptedField' }); + component.instance().startDeleteField({ name: 'ScriptedField', lang: '', script: '' }); + await component.update(); await component.instance().deleteField(); await component.update(); + expect(removeScriptedField).toBeCalled(); }); }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx similarity index 60% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx index 69343a5175a25..ba044296a693a 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx @@ -18,31 +18,42 @@ */ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import { getSupportedScriptingLanguages, getDeprecatedScriptingLanguages, } from 'ui/scripting_languages'; import { documentationLinks } from 'ui/documentation_links'; -import { EuiSpacer, EuiOverlayMask, EuiConfirmModal, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { Table, Header, CallOuts } from './components'; - -export class ScriptedFieldsTable extends Component { - static propTypes = { - indexPattern: PropTypes.object.isRequired, - fieldFilter: PropTypes.string, - scriptedFieldLanguageFilter: PropTypes.string, - helpers: PropTypes.shape({ - redirectToRoute: PropTypes.func.isRequired, - getRouteHref: PropTypes.func.isRequired, - }), - onRemoveField: PropTypes.func, +import { EuiSpacer } from '@elastic/eui'; + +import { Table, Header, CallOuts, DeleteScritpedFieldConfirmationModal } from './components'; +import { ScriptedFieldItem } from './types'; + +import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; + +interface ScriptedFieldsTableProps { + indexPattern: IIndexPattern; + fieldFilter?: string; + scriptedFieldLanguageFilter?: string; + helpers: { + redirectToRoute: Function; + getRouteHref: Function; }; + onRemoveField?: () => void; +} - constructor(props) { +interface ScriptedFieldsTableState { + deprecatedLangsInUse: string[]; + fieldToDelete: ScriptedFieldItem | undefined; + isDeleteConfirmationModalVisible: boolean; + fields: ScriptedFieldItem[]; +} + +export class ScriptedFieldsTable extends Component< + ScriptedFieldsTableProps, + ScriptedFieldsTableState +> { + constructor(props: ScriptedFieldsTableProps) { super(props); this.state = { @@ -64,7 +75,8 @@ export class ScriptedFieldsTable extends Component { const deprecatedLangs = getDeprecatedScriptingLanguages(); const supportedLangs = getSupportedScriptingLanguages(); - for (const { lang } of fields) { + for (const field of fields) { + const lang: string = field.lang; if (deprecatedLangs.includes(lang) || !supportedLangs.includes(lang)) { deprecatedLangsInUse.push(lang); } @@ -91,7 +103,8 @@ export class ScriptedFieldsTable extends Component { let filteredFields = languageFilteredFields; if (fieldFilter) { - const normalizedFieldFilter = this.props.fieldFilter.toLowerCase(); + const normalizedFieldFilter = fieldFilter.toLowerCase(); + filteredFields = languageFilteredFields.filter(field => field.name.toLowerCase().includes(normalizedFieldFilter) ); @@ -100,18 +113,7 @@ export class ScriptedFieldsTable extends Component { return filteredFields; }; - renderCallOuts() { - const { deprecatedLangsInUse } = this.state; - - return ( - <CallOuts - deprecatedLangsInUse={deprecatedLangsInUse} - painlessDocLink={documentationLinks.scriptedFields.painless} - /> - ); - } - - startDeleteField = field => { + startDeleteField = (field: ScriptedFieldItem) => { this.setState({ fieldToDelete: field, isDeleteConfirmationModalVisible: true }); }; @@ -124,55 +126,29 @@ export class ScriptedFieldsTable extends Component { const { fieldToDelete } = this.state; indexPattern.removeScriptedField(fieldToDelete); - onRemoveField && onRemoveField(); - this.fetchFields(); - this.hideDeleteConfirmationModal(); - }; - renderDeleteConfirmationModal() { - const { fieldToDelete } = this.state; - - if (!fieldToDelete) { - return null; + if (onRemoveField) { + onRemoveField(); } - const title = i18n.translate('kbn.management.editIndexPattern.scripted.deleteFieldLabel', { - defaultMessage: "Delete scripted field '{fieldName}'?", - values: { fieldName: fieldToDelete.name }, - }); - const cancelButtonText = i18n.translate( - 'kbn.management.editIndexPattern.scripted.deleteField.cancelButton', - { defaultMessage: 'Cancel' } - ); - const confirmButtonText = i18n.translate( - 'kbn.management.editIndexPattern.scripted.deleteField.deleteButton', - { defaultMessage: 'Delete' } - ); - - return ( - <EuiOverlayMask> - <EuiConfirmModal - title={title} - onCancel={this.hideDeleteConfirmationModal} - onConfirm={this.deleteField} - cancelButtonText={cancelButtonText} - confirmButtonText={confirmButtonText} - defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON} - /> - </EuiOverlayMask> - ); - } + this.fetchFields(); + this.hideDeleteConfirmationModal(); + }; render() { const { helpers, indexPattern } = this.props; + const { fieldToDelete, deprecatedLangsInUse } = this.state; const items = this.getFilteredItems(); return ( - <div> + <> <Header addScriptedFieldUrl={helpers.getRouteHref(indexPattern, 'addField')} /> - {this.renderCallOuts()} + <CallOuts + deprecatedLangsInUse={deprecatedLangsInUse} + painlessDocLink={documentationLinks.scriptedFields.painless} + /> <EuiSpacer size="l" /> @@ -183,8 +159,14 @@ export class ScriptedFieldsTable extends Component { deleteField={this.startDeleteField} /> - {this.renderDeleteConfirmationModal()} - </div> + {fieldToDelete && ( + <DeleteScritpedFieldConfirmationModal + deleteField={this.deleteField} + field={fieldToDelete} + hideDeleteConfirmationModal={this.hideDeleteConfirmationModal} + /> + )} + </> ); } } diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/types.ts b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/types.ts new file mode 100644 index 0000000000000..c1227393c561f --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/types.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/** @internal **/ +export interface ScriptedFieldItem { + name: string; + lang: string; + script: string; +} diff --git a/src/legacy/ui/public/scripting_languages/index.js b/src/legacy/ui/public/scripting_languages/index.ts similarity index 83% rename from src/legacy/ui/public/scripting_languages/index.js rename to src/legacy/ui/public/scripting_languages/index.ts index 2f43a44d66068..283a3273a2a5d 100644 --- a/src/legacy/ui/public/scripting_languages/index.js +++ b/src/legacy/ui/public/scripting_languages/index.ts @@ -17,23 +17,25 @@ * under the License. */ +import { IHttpService } from 'angular'; +import { i18n } from '@kbn/i18n'; + import chrome from '../chrome'; import { toastNotifications } from '../notify'; -import { i18n } from '@kbn/i18n'; -export function getSupportedScriptingLanguages() { +export function getSupportedScriptingLanguages(): string[] { return ['painless']; } -export function getDeprecatedScriptingLanguages() { +export function getDeprecatedScriptingLanguages(): string[] { return []; } -export function GetEnabledScriptingLanguagesProvider($http) { +export function GetEnabledScriptingLanguagesProvider($http: IHttpService) { return () => { return $http .get(chrome.addBasePath('/api/kibana/scripts/languages')) - .then(res => res.data) + .then((res: any) => res.data) .catch(() => { toastNotifications.addDanger( i18n.translate('common.ui.scriptingLanguages.errorFetchingToastDescription', { From 52747c9c1775c0e961a06ff808f8fac6fb189743 Mon Sep 17 00:00:00 2001 From: Brandon Kobel <brandon.kobel@elastic.co> Date: Mon, 13 Apr 2020 09:02:48 -0700 Subject: [PATCH 066/121] Only fetching TaskManager's available tasks once per call to fillPool (#61991) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../task_manager/server/lib/fill_pool.test.ts | 4 +- .../task_manager/server/lib/fill_pool.ts | 49 +++++++++---------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts b/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts index 3863fdaf9da62..ebb72c3ed36d6 100644 --- a/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts +++ b/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts @@ -10,7 +10,7 @@ import { fillPool } from './fill_pool'; import { TaskPoolRunResult } from '../task_pool'; describe('fillPool', () => { - test('stops filling when there are no more tasks in the store', async () => { + test('stops filling when pool runs all claimed tasks, even if there is more capacity', async () => { const tasks = [ [1, 2, 3], [4, 5], @@ -22,7 +22,7 @@ describe('fillPool', () => { await fillPool(fetchAvailableTasks, converter, run); - expect(_.flattenDeep(run.args)).toEqual([1, 2, 3, 4, 5]); + expect(_.flattenDeep(run.args)).toEqual([1, 2, 3]); }); test('stops filling when the pool has no more capacity', async () => { diff --git a/x-pack/plugins/task_manager/server/lib/fill_pool.ts b/x-pack/plugins/task_manager/server/lib/fill_pool.ts index 60470b22c00a9..9e4894587203d 100644 --- a/x-pack/plugins/task_manager/server/lib/fill_pool.ts +++ b/x-pack/plugins/task_manager/server/lib/fill_pool.ts @@ -5,12 +5,12 @@ */ import { performance } from 'perf_hooks'; -import { after } from 'lodash'; import { TaskPoolRunResult } from '../task_pool'; export enum FillPoolResult { NoTasksClaimed = 'NoTasksClaimed', RanOutOfCapacity = 'RanOutOfCapacity', + PoolFilled = 'PoolFilled', } type BatchRun<T> = (tasks: T[]) => Promise<TaskPoolRunResult>; @@ -35,33 +35,28 @@ export async function fillPool<TRecord, TRunner>( run: BatchRun<TRunner> ): Promise<FillPoolResult> { performance.mark('fillPool.start'); - const markClaimedTasksOnRerunCycle = after(2, () => - performance.mark('fillPool.claimedOnRerunCycle') - ); - while (true) { - const instances = await fetchAvailableTasks(); + const instances = await fetchAvailableTasks(); - if (!instances.length) { - performance.mark('fillPool.bailNoTasks'); - performance.measure( - 'fillPool.activityDurationUntilNoTasks', - 'fillPool.start', - 'fillPool.bailNoTasks' - ); - return FillPoolResult.NoTasksClaimed; - } - markClaimedTasksOnRerunCycle(); - const tasks = instances.map(converter); + if (!instances.length) { + performance.mark('fillPool.bailNoTasks'); + performance.measure( + 'fillPool.activityDurationUntilNoTasks', + 'fillPool.start', + 'fillPool.bailNoTasks' + ); + return FillPoolResult.NoTasksClaimed; + } + const tasks = instances.map(converter); - if ((await run(tasks)) === TaskPoolRunResult.RanOutOfCapacity) { - performance.mark('fillPool.bailExhaustedCapacity'); - performance.measure( - 'fillPool.activityDurationUntilExhaustedCapacity', - 'fillPool.start', - 'fillPool.bailExhaustedCapacity' - ); - return FillPoolResult.RanOutOfCapacity; - } - performance.mark('fillPool.cycle'); + if ((await run(tasks)) === TaskPoolRunResult.RanOutOfCapacity) { + performance.mark('fillPool.bailExhaustedCapacity'); + performance.measure( + 'fillPool.activityDurationUntilExhaustedCapacity', + 'fillPool.start', + 'fillPool.bailExhaustedCapacity' + ); + return FillPoolResult.RanOutOfCapacity; } + performance.mark('fillPool.cycle'); + return FillPoolResult.PoolFilled; } From 0c09a7756fb76f26b3da81b58af00b4555d0a213 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko <jo.naumenko@gmail.com> Date: Mon, 13 Apr 2020 09:47:03 -0700 Subject: [PATCH 067/121] Added connectors loading spinner to show the actions forms only when connectors is loaded (#63211) * Added connectors loading spinner to show the actions forms only when connectors is loaded * Added warning message for actions with removed connectors * Fixed loading connectors spinner --- .../action_connector_form/action_form.tsx | 180 +++++++++++------- 1 file changed, 106 insertions(+), 74 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx index 5890d9fe07f0e..87a8d572fda0f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx @@ -24,6 +24,7 @@ import { EuiToolTip, EuiIconTip, EuiLink, + EuiCallOut, } from '@elastic/eui'; import { HttpSetup, ToastsApi } from 'kibana/public'; import { loadActionTypes, loadAllActions } from '../../lib/action_connector_api'; @@ -85,8 +86,10 @@ export const ActionForm = ({ ); const [isAddActionPanelOpen, setIsAddActionPanelOpen] = useState<boolean>(true); const [connectors, setConnectors] = useState<ActionConnector[]>([]); + const [isLoadingConnectors, setIsLoadingConnectors] = useState<boolean>(false); const [isLoadingActionTypes, setIsLoadingActionTypes] = useState<boolean>(false); const [actionTypesIndex, setActionTypesIndex] = useState<ActionTypeIndex | undefined>(undefined); + const [emptyActionsIds, setEmptyActionsIds] = useState<string[]>([]); // load action types useEffect(() => { @@ -128,6 +131,7 @@ export const ActionForm = ({ async function loadConnectors() { try { + setIsLoadingConnectors(true); const actionsResponse = await loadAllActions({ http }); setConnectors(actionsResponse); } catch (e) { @@ -139,6 +143,8 @@ export const ActionForm = ({ } ), }); + } finally { + setIsLoadingConnectors(false); } } const preconfiguredMessage = i18n.translate( @@ -387,13 +393,25 @@ export const ActionForm = ({ > <EuiEmptyPrompt title={ - <FormattedMessage - id="xpack.triggersActionsUI.sections.alertForm.emptyConnectorsLabel" - defaultMessage="No {actionTypeName} connectors." - values={{ - actionTypeName, - }} - /> + emptyActionsIds.find((emptyId: string) => actionItem.id === emptyId) ? ( + <FormattedMessage + id="xpack.triggersActionsUI.sections.alertForm.emptyConnectorsLabel" + defaultMessage="No {actionTypeName} connectors." + values={{ + actionTypeName, + }} + /> + ) : ( + <EuiCallOut + title={i18n.translate( + 'xpack.triggersActionsUI.sections.alertForm.unableToLoadConnectorTitle', + { + defaultMessage: 'Unable to load connector.', + } + )} + color="warning" + /> + ) } actions={[ <EuiButton @@ -448,6 +466,7 @@ export const ActionForm = ({ params: {}, }); setActionIdByIndex(actions.length.toString(), actions.length - 1); + setEmptyActionsIds([...emptyActionsIds, actions.length.toString()]); } } @@ -492,81 +511,94 @@ export const ActionForm = ({ }); } - return ( - <Fragment> - {actions.map((actionItem: AlertAction, index: number) => { - const actionConnector = connectors.find(field => field.id === actionItem.id); - // connectors doesn't exists - if (!actionConnector) { - return getAddConnectorsForm(actionItem, index); - } + const alertActionsList = actions.map((actionItem: AlertAction, index: number) => { + const actionConnector = connectors.find(field => field.id === actionItem.id); + // connectors doesn't exists + if (!actionConnector) { + return getAddConnectorsForm(actionItem, index); + } + + const actionErrors: { errors: IErrorObject } = actionTypeRegistry + .get(actionItem.actionTypeId) + ?.validateParams(actionItem.params); - const actionErrors: { errors: IErrorObject } = actionTypeRegistry - .get(actionItem.actionTypeId) - ?.validateParams(actionItem.params); + return getActionTypeForm(actionItem, actionConnector, actionErrors, index); + }); - return getActionTypeForm(actionItem, actionConnector, actionErrors, index); - })} - <EuiSpacer size="m" /> - {isAddActionPanelOpen === false ? ( - <EuiButton - iconType="plusInCircle" - data-test-subj="addAlertActionButton" - onClick={() => setIsAddActionPanelOpen(true)} - > + return ( + <Fragment> + {isLoadingConnectors ? ( + <SectionLoading> <FormattedMessage - id="xpack.triggersActionsUI.sections.alertForm.addActionButtonLabel" - defaultMessage="Add action" + id="xpack.triggersActionsUI.sections.alertForm.loadingConnectorsDescription" + defaultMessage="Loading connectors…" /> - </EuiButton> - ) : null} - {isAddActionPanelOpen ? ( + </SectionLoading> + ) : ( <Fragment> - <EuiFlexGroup id="alertActionTypeTitle" justifyContent="spaceBetween"> - <EuiFlexItem grow={false}> - <EuiTitle size="xs"> - <h5> - <FormattedMessage - defaultMessage="Actions: Select an action type" - id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeTitle" - /> - </h5> - </EuiTitle> - </EuiFlexItem> - {hasDisabledByLicenseActionTypes && ( - <EuiFlexItem grow={false}> - <EuiTitle size="xs"> - <h5> - <EuiLink - href={VIEW_LICENSE_OPTIONS_LINK} - target="_blank" - className="actActionForm__getMoreActionsLink" - > + {alertActionsList} + <EuiSpacer size="m" /> + {isAddActionPanelOpen === false ? ( + <EuiButton + iconType="plusInCircle" + data-test-subj="addAlertActionButton" + onClick={() => setIsAddActionPanelOpen(true)} + > + <FormattedMessage + id="xpack.triggersActionsUI.sections.alertForm.addActionButtonLabel" + defaultMessage="Add action" + /> + </EuiButton> + ) : null} + {isAddActionPanelOpen ? ( + <Fragment> + <EuiFlexGroup id="alertActionTypeTitle" justifyContent="spaceBetween"> + <EuiFlexItem grow={false}> + <EuiTitle size="xs"> + <h5> <FormattedMessage - defaultMessage="Get more actions" - id="xpack.triggersActionsUI.sections.actionForm.getMoreActionsTitle" + defaultMessage="Actions: Select an action type" + id="xpack.triggersActionsUI.sections.alertForm.selectAlertActionTypeTitle" /> - </EuiLink> - </h5> - </EuiTitle> - </EuiFlexItem> - )} - </EuiFlexGroup> - <EuiSpacer /> - <EuiFlexGroup gutterSize="s" wrap> - {isLoadingActionTypes ? ( - <SectionLoading> - <FormattedMessage - id="xpack.triggersActionsUI.sections.alertForm.loadingActionTypesDescription" - defaultMessage="Loading action types…" - /> - </SectionLoading> - ) : ( - actionTypeNodes - )} - </EuiFlexGroup> + </h5> + </EuiTitle> + </EuiFlexItem> + {hasDisabledByLicenseActionTypes && ( + <EuiFlexItem grow={false}> + <EuiTitle size="xs"> + <h5> + <EuiLink + href={VIEW_LICENSE_OPTIONS_LINK} + target="_blank" + className="actActionForm__getMoreActionsLink" + > + <FormattedMessage + defaultMessage="Get more actions" + id="xpack.triggersActionsUI.sections.actionForm.getMoreActionsTitle" + /> + </EuiLink> + </h5> + </EuiTitle> + </EuiFlexItem> + )} + </EuiFlexGroup> + <EuiSpacer /> + <EuiFlexGroup gutterSize="s" wrap> + {isLoadingActionTypes ? ( + <SectionLoading> + <FormattedMessage + id="xpack.triggersActionsUI.sections.alertForm.loadingActionTypesDescription" + defaultMessage="Loading action types…" + /> + </SectionLoading> + ) : ( + actionTypeNodes + )} + </EuiFlexGroup> + </Fragment> + ) : null} </Fragment> - ) : null} + )} {actionTypesIndex && activeActionItem ? ( <ConnectorAddModal key={activeActionItem.index} From 69b436e820c7bb1dc5598051bb917c2e314e5fb8 Mon Sep 17 00:00:00 2001 From: Nathan Reese <reese.nathan@gmail.com> Date: Mon, 13 Apr 2020 11:22:11 -0600 Subject: [PATCH 068/121] [Maps] turn on blended layer for geojson upload (#63200) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../client_file_source/geojson_file_source.js | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js b/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js index 1003f8329da22..df11fe9f32770 100644 --- a/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js +++ b/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js @@ -10,11 +10,11 @@ import { ES_GEO_FIELD_TYPE, GEOJSON_FILE, DEFAULT_MAX_RESULT_WINDOW, + SCALING_TYPES, } from '../../../../common/constants'; import { ClientFileCreateSourceEditor } from './create_client_file_source_editor'; import { ESSearchSource } from '../es_search_source'; import uuid from 'uuid/v4'; -import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import { registerSource } from '../source_registry'; @@ -91,23 +91,22 @@ const viewIndexedData = ( importErrorHandler(indexResponses); return; } - const { fields, id } = indexPatternResp; - const geoFieldArr = fields.filter(field => - Object.values(ES_GEO_FIELD_TYPE).includes(field.type) - ); - const geoField = _.get(geoFieldArr, '[0].name'); - const indexPatternId = id; + const { fields, id: indexPatternId } = indexPatternResp; + const geoField = fields.find(field => Object.values(ES_GEO_FIELD_TYPE).includes(field.type)); if (!indexPatternId || !geoField) { addAndViewSource(null); } else { - // Only turn on bounds filter for large doc counts - const filterByMapBounds = indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW; const source = new ESSearchSource( { id: uuid(), indexPatternId, - geoField, - filterByMapBounds, + geoField: geoField.name, + // Only turn on bounds filter for large doc counts + filterByMapBounds: indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW, + scalingType: + geoField.type === ES_GEO_FIELD_TYPE.GEO_POINT + ? SCALING_TYPES.CLUSTERS + : SCALING_TYPES.LIMIT, }, inspectorAdapters ); From 5559b09dccbf682686a48d7bfc3b4123e3aa245c Mon Sep 17 00:00:00 2001 From: Ryland Herrick <ryalnd@gmail.com> Date: Mon, 13 Apr 2020 12:24:09 -0500 Subject: [PATCH 069/121] Consistent terminology around cypress test data (#63279) * Uses "data" or "test data" when referring to the general idea * Uses "archive" when referring to the specific data/implementation * Adds a few grammar/spelling tweaks --- x-pack/legacy/plugins/siem/cypress/README.md | 32 +++++++------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/x-pack/legacy/plugins/siem/cypress/README.md b/x-pack/legacy/plugins/siem/cypress/README.md index a031fea172be5..89bafce9c9dc8 100644 --- a/x-pack/legacy/plugins/siem/cypress/README.md +++ b/x-pack/legacy/plugins/siem/cypress/README.md @@ -129,31 +129,21 @@ yarn cypress:run-as-ci ``` Note that with this type of execution you don't need to have running a kibana and elasticsearch instance. This is because - the command, as it would happen in the CI, will launch the instances. The elasticsearch instance will be fed with the data - placed in: `x-pack/test/siem_cypress/es_archives` + the command, as it would happen in the CI, will launch the instances. The elasticsearch instance will be fed data + found in: `x-pack/test/siem_cypress/es_archives` 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. ### Test data -As said before when running the tests as Jenkins the tests are fed with the data placed in: `x-pack/test/siem_cypress/es_archives`. +As mentioned above, when running the tests as Jenkins the tests are populated with data ("archives") found in: `x-pack/test/siem_cypress/es_archives`. -Currently there are two different ways of feeding data: -1. By default -2. Specifying a specific set of data for a specific test +By default, each test is populated with some base data: an empty kibana index and a set of auditbeat data (the `empty_kibana` and `auditbeat` archives, respectively). This is usually enough to cover most of the scenarios that we are testing. -#### By default +#### Running tests with additional archives -When a execution of the test is going to be done an empty kibana and a set of audibteat data are loaded (empty_kibana and auditbeat). With this data usually is enough to cover most of the scenarios that we are testing. - -#### Running tests with custom data - -Sometimes the default data is not enough and we need a specific set of data in order to being able to test the desired behaviour. - -In that case in the hooks of the test use the function `esArchiverLoad` to load the set of data neeed and `esArchiverUnload` to remove the changes done in the data. - -Example: +When the base data is insufficient, one can specify additional archives. Use `esArchiverLoad` to load the necessary archive, and `esArchiverUnload` to remove the archive from elasticsearch: ```typescript import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; @@ -174,11 +164,11 @@ describe('This are going to be a set of tests', () => { ``` -Note that loading and unloading data takes a signifcant amount of time so try to minimize the use of it when possible. +Note that loading and unloading data take a significant amount of time, so try to minimize their use. -### Current sets of data +### Current archives -The current sets of data can be found in: `x-pack/test/siem_cypress/es_archives` folder. +The current archives can be found in `x-pack/test/siem_cypress/es_archives/`. - auditbeat - Auditbeat data generated in Sep, 2019 with the following hosts present: @@ -197,9 +187,9 @@ The current sets of data can be found in: `x-pack/test/siem_cypress/es_archives` - signals - Set of data with 108 opened signals linked to "Signals test" custom rule. -### How to generate new test data +### How to generate a new archive -We are using es_archiver in order to generate the data that our Cypress tests needs. +We are using es_archiver in order to manage the data that our Cypress tests needs. 1. Setup if possible a clean instance of kibana and elasticsearch (if not, possible please try to clean the data that you are going to generate). 2. With the kibana and elasticsearch instance up and running, create the data that you need for your test. From a58cc5da12a250610aae1cee078124ee350fd29b Mon Sep 17 00:00:00 2001 From: patrykkopycinski <patryk.kopycinski@elastic.co> Date: Mon, 13 Apr 2020 19:40:48 +0200 Subject: [PATCH 070/121] [SIEM] Fix AlertsTable id (#63368) --- .../siem/public/components/alerts_viewer/alerts_table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx index 05d8f97bb8849..dd608babef48f 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/alerts_table.tsx @@ -17,7 +17,7 @@ export interface OwnProps { start: number; } -const ALERTS_TABLE_ID = 'timeline-alerts-table'; +const ALERTS_TABLE_ID = 'alerts-table'; const defaultAlertsFilters: Filter[] = [ { meta: { From 1084b1c7b9ec09c98baa74ad56db3f5d2a394826 Mon Sep 17 00:00:00 2001 From: Maggie Ghamry <46542915+maggieghamry@users.noreply.github.com> Date: Mon, 13 Apr 2020 13:41:12 -0400 Subject: [PATCH 071/121] Update to pagination for workpad and templates (#62050) Added logic to hide pagination if no Canvas workpads exists, and disable the previous/next arrows if there is only one page, for both workapds and templates --- .../components/workpad_loader/workpad_loader.js | 16 +++++++++++----- .../workpad_templates/workpad_templates.js | 12 +++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.js b/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.js index 9b30b3e1ec7ca..30d4ded8571c5 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.js +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.js @@ -266,11 +266,17 @@ export class WorkpadLoader extends React.PureComponent { data-test-subj="canvasWorkpadLoaderTable" /> <EuiSpacer /> - <EuiFlexGroup gutterSize="none" justifyContent="flexEnd"> - <EuiFlexItem grow={false}> - <EuiPagination activePage={pageNumber} onPageClick={setPage} pageCount={totalPages} /> - </EuiFlexItem> - </EuiFlexGroup> + {rows.length > 0 && ( + <EuiFlexGroup gutterSize="none" justifyContent="flexEnd"> + <EuiFlexItem grow={false}> + <EuiPagination + activePage={pageNumber} + onPageClick={setPage} + pageCount={totalPages} + /> + </EuiFlexItem> + </EuiFlexGroup> + )} </WorkpadDropzone> </Fragment> ); diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_templates/workpad_templates.js b/x-pack/legacy/plugins/canvas/public/components/workpad_templates/workpad_templates.js index c80db544bf370..a9a157f5675f8 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_templates/workpad_templates.js +++ b/x-pack/legacy/plugins/canvas/public/components/workpad_templates/workpad_templates.js @@ -113,11 +113,13 @@ export class WorkpadTemplates extends React.PureComponent { className="canvasWorkpad__dropzoneTable canvasWorkpad__dropzoneTable--tags" /> <EuiSpacer /> - <EuiFlexGroup gutterSize="none" justifyContent="flexEnd"> - <EuiFlexItem grow={false}> - <EuiPagination activePage={pageNumber} onPageClick={setPage} pageCount={totalPages} /> - </EuiFlexItem> - </EuiFlexGroup> + {rows.length > 0 && ( + <EuiFlexGroup gutterSize="none" justifyContent="flexEnd"> + <EuiFlexItem grow={false}> + <EuiPagination activePage={pageNumber} onPageClick={setPage} pageCount={totalPages} /> + </EuiFlexItem> + </EuiFlexGroup> + )} </Fragment> ); }; From 19fcc6111a1ce526c0c4157de6de36b40f4d634d Mon Sep 17 00:00:00 2001 From: Corey Robertson <corey.robertson@elastic.co> Date: Mon, 13 Apr 2020 14:21:02 -0400 Subject: [PATCH 072/121] Use MapInput type from Maps plugin (#61539) --- .../functions/common/saved_map.ts | 29 +++---------------- .../input_type_to_expression/map.test.ts | 10 +++---- .../input_type_to_expression/map.ts | 4 +-- 3 files changed, 11 insertions(+), 32 deletions(-) diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts index 4b045b0c5edcf..cba19ce7da80f 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts @@ -5,8 +5,6 @@ */ import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; -import { TimeRange, Filter as DataFilter } from 'src/plugins/data/public'; -import { EmbeddableInput } from 'src/plugins/embeddable/public'; import { getQueryFilters } from '../../../public/lib/build_embeddable_filters'; import { Filter, MapCenter, TimeRange as TimeRangeArg } from '../../../types'; import { @@ -15,6 +13,7 @@ import { EmbeddableExpression, } from '../../expression_types'; import { getFunctionHelp } from '../../../i18n'; +import { MapEmbeddableInput } from '../../../../../plugins/maps/public'; interface Arguments { id: string; @@ -24,32 +23,12 @@ interface Arguments { timerange: TimeRangeArg | null; } -// Map embeddable is missing proper typings, so type is just to document what we -// are expecting to pass to the embeddable -export type SavedMapInput = EmbeddableInput & { - id: string; - isLayerTOCOpen: boolean; - timeRange?: TimeRange; - refreshConfig: { - isPaused: boolean; - interval: number; - }; - hideFilterActions: true; - filters: DataFilter[]; - mapCenter?: { - lat: number; - lon: number; - zoom: number; - }; - hiddenLayers?: string[]; -}; - const defaultTimeRange = { from: 'now-15m', to: 'now', }; -type Output = EmbeddableExpression<SavedMapInput>; +type Output = EmbeddableExpression<MapEmbeddableInput>; export function savedMap(): ExpressionFunctionDefinition< 'savedMap', @@ -108,8 +87,8 @@ export function savedMap(): ExpressionFunctionDefinition< filters: getQueryFilters(filters), timeRange: args.timerange || defaultTimeRange, refreshConfig: { - isPaused: false, - interval: 0, + pause: false, + value: 0, }, mapCenter: center, diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts index 4c294fb37c2db..f9ff94ee7d8f1 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts @@ -5,7 +5,7 @@ */ import { toExpression } from './map'; -import { SavedMapInput } from '../../../functions/common/saved_map'; +import { MapEmbeddableInput } from '../../../../../maps/public'; import { fromExpression, Ast } from '@kbn/interpreter/common'; const baseSavedMapInput = { @@ -13,15 +13,15 @@ const baseSavedMapInput = { filters: [], isLayerTOCOpen: false, refreshConfig: { - isPaused: true, - interval: 0, + pause: true, + value: 0, }, hideFilterActions: true as true, }; describe('toExpression', () => { it('converts to a savedMap expression', () => { - const input: SavedMapInput = { + const input: MapEmbeddableInput = { ...baseSavedMapInput, }; @@ -39,7 +39,7 @@ describe('toExpression', () => { }); it('includes optional input values', () => { - const input: SavedMapInput = { + const input: MapEmbeddableInput = { ...baseSavedMapInput, mapCenter: { lat: 1, diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts index e3f9eca61ae28..e0cb71c17774c 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SavedMapInput } from '../../../functions/common/saved_map'; +import { MapEmbeddableInput } from '../../../../../maps/public'; -export function toExpression(input: SavedMapInput): string { +export function toExpression(input: MapEmbeddableInput): string { const expressionParts = [] as string[]; expressionParts.push('savedMap'); From e27526fd92eaa0094b70ddb2119a326543475c2c Mon Sep 17 00:00:00 2001 From: Corey Robertson <corey.robertson@elastic.co> Date: Mon, 13 Apr 2020 15:29:24 -0400 Subject: [PATCH 073/121] Move away from npStart for embeddables in canvas (#62680) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../canvas/canvas_plugin_src/plugin.ts | 28 +++- .../renderers/embeddable/embeddable.tsx | 143 +++++++++--------- .../canvas_plugin_src/renderers/index.js | 5 +- .../components/embeddable_flyout/flyout.tsx | 7 +- .../components/embeddable_flyout/index.tsx | 1 + x-pack/legacy/plugins/canvas/public/legacy.ts | 2 + .../legacy/plugins/canvas/public/plugin.tsx | 18 ++- 7 files changed, 114 insertions(+), 90 deletions(-) diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/plugin.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/plugin.ts index 7cd1efe9e27c8..a654c6b28b350 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/plugin.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/plugin.ts @@ -6,11 +6,14 @@ import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { CanvasSetup } from '../public'; +import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public'; +import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; +import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public'; import { functions } from './functions/browser'; import { typeFunctions } from './expression_types'; // @ts-ignore: untyped local -import { renderFunctions } from './renderers'; +import { renderFunctions, renderFunctionFactories } from './renderers'; import { elementSpecs } from './elements'; // @ts-ignore Untyped Local @@ -30,13 +33,26 @@ interface SetupDeps { canvas: CanvasSetup; } +export interface StartDeps { + embeddable: EmbeddableStart; + uiActions: UiActionsStart; + inspector: InspectorStart; +} + /** @internal */ -export class CanvasSrcPlugin implements Plugin<{}, {}, SetupDeps, {}> { - public setup(core: CoreSetup, plugins: SetupDeps) { +export class CanvasSrcPlugin implements Plugin<void, void, SetupDeps, StartDeps> { + public setup(core: CoreSetup<StartDeps>, plugins: SetupDeps) { plugins.canvas.addFunctions(functions); plugins.canvas.addTypes(typeFunctions); + plugins.canvas.addRenderers(renderFunctions); + core.getStartServices().then(([coreStart, depsStart]) => { + plugins.canvas.addRenderers( + renderFunctionFactories.map((factory: any) => factory(coreStart, depsStart)) + ); + }); + plugins.canvas.addElements(elementSpecs); plugins.canvas.addDatasourceUIs(datasourceSpecs); plugins.canvas.addModelUIs(modelSpecs); @@ -45,11 +61,7 @@ export class CanvasSrcPlugin implements Plugin<{}, {}, SetupDeps, {}> { plugins.canvas.addTagUIs(tagSpecs); plugins.canvas.addTemplates(templateSpecs); plugins.canvas.addTransformUIs(transformSpecs); - - return {}; } - public start(core: CoreStart, plugins: {}) { - return {}; - } + public start(core: CoreStart, plugins: StartDeps) {} } diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx index 817be6e144fc8..a1096d50c1653 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx @@ -7,7 +7,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { I18nContext } from 'ui/i18n'; -import { npStart } from 'ui/new_platform'; +import { CoreStart } from '../../../../../../../src/core/public'; +import { StartDeps } from '../../plugin'; import { IEmbeddable, EmbeddableFactory, @@ -28,86 +29,88 @@ const embeddablesRegistry: { [key: string]: IEmbeddable; } = {}; -const renderEmbeddable = (embeddableObject: IEmbeddable, domNode: HTMLElement) => { - return ( - <div - className={CANVAS_EMBEDDABLE_CLASSNAME} - style={{ width: domNode.offsetWidth, height: domNode.offsetHeight, cursor: 'auto' }} - > - <I18nContext> - <EmbeddablePanel - embeddable={embeddableObject} - getActions={npStart.plugins.uiActions.getTriggerCompatibleActions} - getEmbeddableFactory={npStart.plugins.embeddable.getEmbeddableFactory} - getAllEmbeddableFactories={npStart.plugins.embeddable.getEmbeddableFactories} - notifications={npStart.core.notifications} - overlays={npStart.core.overlays} - inspector={npStart.plugins.inspector} - SavedObjectFinder={getSavedObjectFinder( - npStart.core.savedObjects, - npStart.core.uiSettings - )} - /> - </I18nContext> - </div> - ); +const renderEmbeddableFactory = (core: CoreStart, plugins: StartDeps) => { + return (embeddableObject: IEmbeddable, domNode: HTMLElement) => { + return ( + <div + className={CANVAS_EMBEDDABLE_CLASSNAME} + style={{ width: domNode.offsetWidth, height: domNode.offsetHeight, cursor: 'auto' }} + > + <I18nContext> + <EmbeddablePanel + embeddable={embeddableObject} + getActions={plugins.uiActions.getTriggerCompatibleActions} + getEmbeddableFactory={plugins.embeddable.getEmbeddableFactory} + getAllEmbeddableFactories={plugins.embeddable.getEmbeddableFactories} + notifications={core.notifications} + overlays={core.overlays} + inspector={plugins.inspector} + SavedObjectFinder={getSavedObjectFinder(core.savedObjects, core.uiSettings)} + /> + </I18nContext> + </div> + ); + }; }; -const embeddable = () => ({ - name: 'embeddable', - displayName: strings.getDisplayName(), - help: strings.getHelpDescription(), - reuseDomNode: true, - render: async ( - domNode: HTMLElement, - { input, embeddableType }: EmbeddableExpression<EmbeddableInput>, - handlers: RendererHandlers - ) => { - const uniqueId = handlers.getElementId(); - - if (!embeddablesRegistry[uniqueId]) { - const factory = Array.from(npStart.plugins.embeddable.getEmbeddableFactories()).find( - embeddableFactory => embeddableFactory.type === embeddableType - ) as EmbeddableFactory<EmbeddableInput>; - - if (!factory) { - handlers.done(); - throw new EmbeddableFactoryNotFoundError(embeddableType); - } - - const embeddableObject = await factory.createFromSavedObject(input.id, input); +export const embeddableRendererFactory = (core: CoreStart, plugins: StartDeps) => { + const renderEmbeddable = renderEmbeddableFactory(core, plugins); + return () => ({ + name: 'embeddable', + displayName: strings.getDisplayName(), + help: strings.getHelpDescription(), + reuseDomNode: true, + render: async ( + domNode: HTMLElement, + { input, embeddableType }: EmbeddableExpression<EmbeddableInput>, + handlers: RendererHandlers + ) => { + const uniqueId = handlers.getElementId(); + + if (!embeddablesRegistry[uniqueId]) { + const factory = Array.from(plugins.embeddable.getEmbeddableFactories()).find( + embeddableFactory => embeddableFactory.type === embeddableType + ) as EmbeddableFactory<EmbeddableInput>; + + if (!factory) { + handlers.done(); + throw new EmbeddableFactoryNotFoundError(embeddableType); + } - embeddablesRegistry[uniqueId] = embeddableObject; - ReactDOM.unmountComponentAtNode(domNode); + const embeddableObject = await factory.createFromSavedObject(input.id, input); - const subscription = embeddableObject.getInput$().subscribe(function(updatedInput) { - const updatedExpression = embeddableInputToExpression(updatedInput, embeddableType); + embeddablesRegistry[uniqueId] = embeddableObject; + ReactDOM.unmountComponentAtNode(domNode); - if (updatedExpression) { - handlers.onEmbeddableInputChange(updatedExpression); - } - }); + const subscription = embeddableObject.getInput$().subscribe(function(updatedInput) { + const updatedExpression = embeddableInputToExpression(updatedInput, embeddableType); - ReactDOM.render(renderEmbeddable(embeddableObject, domNode), domNode, () => handlers.done()); + if (updatedExpression) { + handlers.onEmbeddableInputChange(updatedExpression); + } + }); - handlers.onResize(() => { ReactDOM.render(renderEmbeddable(embeddableObject, domNode), domNode, () => handlers.done() ); - }); - handlers.onDestroy(() => { - subscription.unsubscribe(); - handlers.onEmbeddableDestroyed(); + handlers.onResize(() => { + ReactDOM.render(renderEmbeddable(embeddableObject, domNode), domNode, () => + handlers.done() + ); + }); - delete embeddablesRegistry[uniqueId]; + handlers.onDestroy(() => { + subscription.unsubscribe(); + handlers.onEmbeddableDestroyed(); - return ReactDOM.unmountComponentAtNode(domNode); - }); - } else { - embeddablesRegistry[uniqueId].updateInput(input); - } - }, -}); + delete embeddablesRegistry[uniqueId]; -export { embeddable }; + return ReactDOM.unmountComponentAtNode(domNode); + }); + } else { + embeddablesRegistry[uniqueId].updateInput(input); + } + }, + }); +}; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/index.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/index.js index 48364be06e539..84f92f5149893 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/index.js +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/index.js @@ -7,7 +7,7 @@ import { advancedFilter } from './advanced_filter'; import { debug } from './debug'; import { dropdownFilter } from './dropdown_filter'; -import { embeddable } from './embeddable/embeddable'; +import { embeddableRendererFactory } from './embeddable/embeddable'; import { error } from './error'; import { image } from './image'; import { markdown } from './markdown'; @@ -26,7 +26,6 @@ export const renderFunctions = [ advancedFilter, debug, dropdownFilter, - embeddable, error, image, markdown, @@ -41,3 +40,5 @@ export const renderFunctions = [ text, timeFilter, ]; + +export const renderFunctionFactories = [embeddableRendererFactory]; diff --git a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/flyout.tsx b/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/flyout.tsx index 08cd3084c35cf..4916a27fcbe60 100644 --- a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/flyout.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/flyout.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; -import { npStart } from 'ui/new_platform'; import { EuiFlyout, EuiFlyoutHeader, EuiFlyoutBody, EuiTitle } from '@elastic/eui'; import { SavedObjectFinderUi, @@ -13,6 +12,7 @@ import { } from '../../../../../../../src/plugins/saved_objects/public/'; import { ComponentStrings } from '../../../i18n'; import { CoreStart } from '../../../../../../../src/core/public'; +import { CanvasStartDeps } from '../../plugin'; const { AddEmbeddableFlyout: strings } = ComponentStrings; @@ -22,11 +22,12 @@ export interface Props { availableEmbeddables: string[]; savedObjects: CoreStart['savedObjects']; uiSettings: CoreStart['uiSettings']; + getEmbeddableFactories: CanvasStartDeps['embeddable']['getEmbeddableFactories']; } export class AddEmbeddableFlyout extends React.Component<Props> { onAddPanel = (id: string, savedObjectType: string, name: string) => { - const embeddableFactories = npStart.plugins.embeddable.getEmbeddableFactories(); + const embeddableFactories = this.props.getEmbeddableFactories(); // Find the embeddable type from the saved object type const found = Array.from(embeddableFactories).find(embeddableFactory => { @@ -42,7 +43,7 @@ export class AddEmbeddableFlyout extends React.Component<Props> { }; render() { - const embeddableFactories = npStart.plugins.embeddable.getEmbeddableFactories(); + const embeddableFactories = this.props.getEmbeddableFactories(); const availableSavedObjects = Array.from(embeddableFactories) .filter(factory => { diff --git a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx b/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx index a86784d374f49..c13cbfd042237 100644 --- a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx @@ -105,6 +105,7 @@ export class EmbeddableFlyoutPortal extends React.Component<Props & WithKibanaPr availableEmbeddables={Object.keys(allowedEmbeddables)} savedObjects={this.props.kibana.services.savedObjects} uiSettings={this.props.kibana.services.uiSettings} + getEmbeddableFactories={this.props.kibana.services.embeddable.getEmbeddableFactories} />, this.el ); diff --git a/x-pack/legacy/plugins/canvas/public/legacy.ts b/x-pack/legacy/plugins/canvas/public/legacy.ts index a6caa1985325e..4af7c9b2bd057 100644 --- a/x-pack/legacy/plugins/canvas/public/legacy.ts +++ b/x-pack/legacy/plugins/canvas/public/legacy.ts @@ -26,7 +26,9 @@ const shimSetupPlugins: CanvasSetupDeps = { }; const shimStartPlugins: CanvasStartDeps = { ...npStart.plugins, + embeddable: npStart.plugins.embeddable, expressions: npStart.plugins.expressions, + inspector: npStart.plugins.inspector, uiActions: npStart.plugins.uiActions, __LEGACY: { // ToDo: Copy directly into canvas diff --git a/x-pack/legacy/plugins/canvas/public/plugin.tsx b/x-pack/legacy/plugins/canvas/public/plugin.tsx index d9e5e6b4b084b..3ea3ce625ca71 100644 --- a/x-pack/legacy/plugins/canvas/public/plugin.tsx +++ b/x-pack/legacy/plugins/canvas/public/plugin.tsx @@ -11,6 +11,8 @@ import { initLoadingIndicator } from './lib/loading_indicator'; import { featureCatalogueEntry } from './feature_catalogue_entry'; import { ExpressionsSetup, ExpressionsStart } from '../../../../../src/plugins/expressions/public'; import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; +import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public'; +import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public'; // @ts-ignore untyped local import { argTypeSpecs } from './expression_types/arg_types'; import { transitions } from './transitions'; @@ -31,7 +33,9 @@ export interface CanvasSetupDeps { } export interface CanvasStartDeps { + embeddable: EmbeddableStart; expressions: ExpressionsStart; + inspector: InspectorStart; uiActions: UiActionsStart; __LEGACY: { absoluteToParsedUrl: (url: string, basePath: string) => any; @@ -48,14 +52,19 @@ export interface CanvasStartDeps { // These interfaces are empty for now but will be populate as we need to export // things for other plugins to use at startup or runtime export type CanvasSetup = CanvasApi; -export interface CanvasStart {} // eslint-disable-line @typescript-eslint/no-empty-interface +export type CanvasStart = void; /** @internal */ export class CanvasPlugin implements Plugin<CanvasSetup, CanvasStart, CanvasSetupDeps, CanvasStartDeps> { + // TODO: Do we want to completely move canvas_plugin_src into it's own plugin? + private srcPlugin = new CanvasSrcPlugin(); + public setup(core: CoreSetup<CanvasStartDeps>, plugins: CanvasSetupDeps) { const { api: canvasApi, registries } = getPluginApi(plugins.expressions); + this.srcPlugin.setup(core, { canvas: canvasApi }); + core.application.register({ id: 'canvas', title: 'Canvas App', @@ -84,10 +93,6 @@ export class CanvasPlugin canvasApi.addElements(legacyRegistries.elements.getOriginalFns()); canvasApi.addTypes(legacyRegistries.types.getOriginalFns()); - // TODO: Do we want to completely move canvas_plugin_src into it's own plugin? - const srcPlugin = new CanvasSrcPlugin(); - srcPlugin.setup(core, { canvas: canvasApi }); - // Register core canvas stuff canvasApi.addFunctions(initFunctions({ typesRegistry: plugins.expressions.__LEGACY.types })); canvasApi.addArgumentUIs(argTypeSpecs); @@ -99,8 +104,7 @@ export class CanvasPlugin } public start(core: CoreStart, plugins: CanvasStartDeps) { + this.srcPlugin.start(core, plugins); initLoadingIndicator(core.http.addLoadingCountSource); - - return {}; } } From 301b795db6b988adb5875ef4a9d96fdb20c66ed5 Mon Sep 17 00:00:00 2001 From: Nathan Reese <reese.nathan@gmail.com> Date: Mon, 13 Apr 2020 13:30:18 -0600 Subject: [PATCH 074/121] [Maps] update geospatial filters to use geo_shape query for geo_point fields (#62966) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../map/mb/draw_control/draw_control.js | 19 ++-- .../maps/public/elasticsearch_geo_utils.js | 99 ++++++------------- 2 files changed, 34 insertions(+), 84 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js index df2988d399c5b..cc0e665525036 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js @@ -12,7 +12,6 @@ import DrawRectangle from 'mapbox-gl-draw-rectangle-mode'; import { DrawCircle } from './draw_circle'; import { createDistanceFilterWithMeta, - createSpatialFilterWithBoundingBox, createSpatialFilterWithGeometry, getBoundingBoxGeometry, roundCoordinates, @@ -84,23 +83,17 @@ export class DrawControl extends React.Component { roundCoordinates(geometry.coordinates); try { - const options = { + const filter = createSpatialFilterWithGeometry({ + geometry: + this.props.drawState.drawType === DRAW_TYPE.BOUNDS + ? getBoundingBoxGeometry(geometry) + : geometry, indexPatternId: this.props.drawState.indexPatternId, geoFieldName: this.props.drawState.geoFieldName, geoFieldType: this.props.drawState.geoFieldType, geometryLabel: this.props.drawState.geometryLabel, relation: this.props.drawState.relation, - }; - const filter = - this.props.drawState.drawType === DRAW_TYPE.BOUNDS - ? createSpatialFilterWithBoundingBox({ - ...options, - geometry: getBoundingBoxGeometry(geometry), - }) - : createSpatialFilterWithGeometry({ - ...options, - geometry, - }); + }); this.props.addFilters([filter]); } catch (error) { // TODO notify user why filter was not created diff --git a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js index 79467e26ec3fa..617cf537fd5c3 100644 --- a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js +++ b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js @@ -231,28 +231,16 @@ function createGeoBoundBoxFilter(geometry, geoFieldName, filterProps = {}) { }; } -function createGeoPolygonFilter(polygonCoordinates, geoFieldName, filterProps = {}) { - return { - geo_polygon: { - ignore_unmapped: true, - [geoFieldName]: { - points: polygonCoordinates[POLYGON_COORDINATES_EXTERIOR_INDEX].map(coordinatePair => { - return { - lon: coordinatePair[LON_INDEX], - lat: coordinatePair[LAT_INDEX], - }; - }), - }, - }, - ...filterProps, - }; -} - export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { ensureGeoField(geoFieldType); const safePolygon = convertMapExtentToPolygon(mapExtent); + // Extent filters are used to dynamically filter data for the current map view port. + // Continue to use geo_bounding_box queries for extent filters + // 1) geo_bounding_box queries are faster than polygon queries + // 2) geo_shape benefits of pre-indexed shapes and + // compatability across multi-indices with geo_point and geo_shape do not apply to this use case. if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { return createGeoBoundBoxFilter(safePolygon, geoFieldName); } @@ -267,15 +255,7 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) { }; } -export function createSpatialFilterWithBoundingBox(options) { - return createGeometryFilterWithMeta({ ...options, isBoundingBox: true }); -} - -export function createSpatialFilterWithGeometry(options) { - return createGeometryFilterWithMeta(options); -} - -function createGeometryFilterWithMeta({ +export function createSpatialFilterWithGeometry({ preIndexedShape, geometry, geometryLabel, @@ -283,16 +263,16 @@ function createGeometryFilterWithMeta({ geoFieldName, geoFieldType, relation = ES_SPATIAL_RELATIONS.INTERSECTS, - isBoundingBox = false, }) { ensureGeoField(geoFieldType); - const relationLabel = - geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT - ? i18n.translate('xpack.maps.es_geo_utils.shapeFilter.geoPointRelationLabel', { - defaultMessage: 'in', - }) - : getEsSpatialRelationLabel(relation); + const isGeoPoint = geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT; + + const relationLabel = isGeoPoint + ? i18n.translate('xpack.maps.es_geo_utils.shapeFilter.geoPointRelationLabel', { + defaultMessage: 'in', + }) + : getEsSpatialRelationLabel(relation); const meta = { type: SPATIAL_FILTER_TYPE, negate: false, @@ -301,47 +281,24 @@ function createGeometryFilterWithMeta({ alias: `${geoFieldName} ${relationLabel} ${geometryLabel}`, }; - if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { - const shapeQuery = { - relation, - }; - - if (preIndexedShape) { - shapeQuery.indexed_shape = preIndexedShape; - } else { - shapeQuery.shape = geometry; - } - - return { - meta, - geo_shape: { - ignore_unmapped: true, - [geoFieldName]: shapeQuery, - }, - }; - } - - // geo_points supports limited geometry types - ensureGeometryType(geometry.type, [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON]); - - if (geometry.type === GEO_JSON_TYPE.MULTI_POLYGON) { - return { - meta, - query: { - bool: { - should: geometry.coordinates.map(polygonCoordinates => { - return createGeoPolygonFilter(polygonCoordinates, geoFieldName); - }), - }, - }, - }; - } + const shapeQuery = { + // geo_shape query with geo_point field only supports intersects relation + relation: isGeoPoint ? ES_SPATIAL_RELATIONS.INTERSECTS : relation, + }; - if (isBoundingBox) { - return createGeoBoundBoxFilter(geometry, geoFieldName, { meta }); + if (preIndexedShape) { + shapeQuery.indexed_shape = preIndexedShape; + } else { + shapeQuery.shape = geometry; } - return createGeoPolygonFilter(geometry.coordinates, geoFieldName, { meta }); + return { + meta, + geo_shape: { + ignore_unmapped: true, + [geoFieldName]: shapeQuery, + }, + }; } export function createDistanceFilterWithMeta({ From a6ecd4c2783c81090072936c142faf6a0dc1bfe0 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck <thomas@elastic.co> Date: Mon, 13 Apr 2020 15:33:43 -0400 Subject: [PATCH 075/121] [Maps] Add SOURCE_TYPES enumeration (#62975) --- .../ems_raster_tile_to_ems_vector_tile.js | 4 ++-- .../migrations/move_apply_global_query.js | 6 +++-- .../maps/common/migrations/references.js | 8 +++++-- .../maps/common/migrations/references.test.js | 14 +++++------ .../maps/common/migrations/scaling_type.ts | 4 ++-- .../migrations/top_hits_time_to_sort.js | 4 ++-- .../server/maps_telemetry/maps_telemetry.ts | 4 ++-- .../components/embeddables/map_config.ts | 5 ++-- x-pack/plugins/maps/common/constants.ts | 23 ++++++++++--------- .../public/layers/blended_vector_layer.ts | 8 +++++-- .../client_file_source/geojson_file_source.js | 6 ++--- .../ems_file_source/ems_file_source.js | 6 ++--- .../sources/ems_tms_source/ems_tms_source.js | 6 ++--- .../es_geo_grid_source/es_geo_grid_source.js | 8 +++---- .../es_geo_grid_source.test.ts | 4 ++-- .../es_pew_pew_source/es_pew_pew_source.js | 6 ++--- .../es_search_source/es_search_source.js | 8 +++---- .../es_search_source/es_search_source.test.ts | 4 ++-- .../kibana_regionmap_source.js | 6 ++--- .../kibana_tilemap_source.js | 6 ++--- .../layers/sources/wms_source/wms_source.js | 6 ++--- .../xyz_tms_source/xyz_tms_source.test.ts | 4 ++-- .../sources/xyz_tms_source/xyz_tms_source.ts | 6 ++--- .../maps/public/layers/tile_layer.test.ts | 4 ++-- 24 files changed, 86 insertions(+), 74 deletions(-) diff --git a/x-pack/legacy/plugins/maps/common/migrations/ems_raster_tile_to_ems_vector_tile.js b/x-pack/legacy/plugins/maps/common/migrations/ems_raster_tile_to_ems_vector_tile.js index 94f4018bbdbb7..091cfd8605cb6 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/ems_raster_tile_to_ems_vector_tile.js +++ b/x-pack/legacy/plugins/maps/common/migrations/ems_raster_tile_to_ems_vector_tile.js @@ -5,11 +5,11 @@ */ import _ from 'lodash'; -import { EMS_TMS, LAYER_TYPE } from '../constants'; +import { SOURCE_TYPES, LAYER_TYPE } from '../constants'; function isEmsTileSource(layerDescriptor) { const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); - return sourceType === EMS_TMS; + return sourceType === SOURCE_TYPES.EMS_TMS; } function isTileLayer(layerDescriptor) { diff --git a/x-pack/legacy/plugins/maps/common/migrations/move_apply_global_query.js b/x-pack/legacy/plugins/maps/common/migrations/move_apply_global_query.js index 490e760d8c003..0d6b0052d2b0d 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/move_apply_global_query.js +++ b/x-pack/legacy/plugins/maps/common/migrations/move_apply_global_query.js @@ -5,11 +5,13 @@ */ import _ from 'lodash'; -import { ES_GEO_GRID, ES_PEW_PEW, ES_SEARCH } from '../constants'; +import { SOURCE_TYPES } from '../constants'; function isEsSource(layerDescriptor) { const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); - return [ES_GEO_GRID, ES_PEW_PEW, ES_SEARCH].includes(sourceType); + return [SOURCE_TYPES.ES_GEO_GRID, SOURCE_TYPES.ES_PEW_PEW, SOURCE_TYPES.ES_SEARCH].includes( + sourceType + ); } // Migration to move applyGlobalQuery from layer to sources. diff --git a/x-pack/legacy/plugins/maps/common/migrations/references.js b/x-pack/legacy/plugins/maps/common/migrations/references.js index a96af700da37c..3980705fd7cfa 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/references.js +++ b/x-pack/legacy/plugins/maps/common/migrations/references.js @@ -7,11 +7,15 @@ // Can not use public Layer classes to extract references since this logic must run in both client and server. import _ from 'lodash'; -import { ES_GEO_GRID, ES_SEARCH, ES_PEW_PEW } from '../constants'; +import { SOURCE_TYPES } from '../constants'; function doesSourceUseIndexPattern(layerDescriptor) { const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); - return sourceType === ES_GEO_GRID || sourceType === ES_SEARCH || sourceType === ES_PEW_PEW; + return ( + sourceType === SOURCE_TYPES.ES_GEO_GRID || + sourceType === SOURCE_TYPES.ES_SEARCH || + sourceType === SOURCE_TYPES.ES_PEW_PEW + ); } export function extractReferences({ attributes, references = [] }) { diff --git a/x-pack/legacy/plugins/maps/common/migrations/references.test.js b/x-pack/legacy/plugins/maps/common/migrations/references.test.js index 40f6fd72a48d7..50a45c81339dc 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/references.test.js +++ b/x-pack/legacy/plugins/maps/common/migrations/references.test.js @@ -5,16 +5,16 @@ */ import { extractReferences, injectReferences } from './references'; -import { ES_GEO_GRID, ES_SEARCH, ES_PEW_PEW } from '../constants'; +import { SOURCE_TYPES } from '../constants'; const layerListJSON = { esSearchSource: { - withIndexPatternId: `[{\"sourceDescriptor\":{\"type\":\"${ES_SEARCH}\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\"}}]`, - withIndexPatternRef: `[{\"sourceDescriptor\":{\"type\":\"${ES_SEARCH}\",\"indexPatternRefName\":\"layer_0_source_index_pattern\"}}]`, + withIndexPatternId: `[{\"sourceDescriptor\":{\"type\":\"${SOURCE_TYPES.ES_SEARCH}\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\"}}]`, + withIndexPatternRef: `[{\"sourceDescriptor\":{\"type\":\"${SOURCE_TYPES.ES_SEARCH}\",\"indexPatternRefName\":\"layer_0_source_index_pattern\"}}]`, }, esGeoGridSource: { - withIndexPatternId: `[{\"sourceDescriptor\":{\"type\":\"${ES_GEO_GRID}\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\"}}]`, - withIndexPatternRef: `[{\"sourceDescriptor\":{\"type\":\"${ES_GEO_GRID}\",\"indexPatternRefName\":\"layer_0_source_index_pattern\"}}]`, + withIndexPatternId: `[{\"sourceDescriptor\":{\"type\":\"${SOURCE_TYPES.ES_GEO_GRID}\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\"}}]`, + withIndexPatternRef: `[{\"sourceDescriptor\":{\"type\":\"${SOURCE_TYPES.ES_GEO_GRID}\",\"indexPatternRefName\":\"layer_0_source_index_pattern\"}}]`, }, join: { withIndexPatternId: @@ -23,8 +23,8 @@ const layerListJSON = { '[{"joins":[{"right":{"indexPatternRefName":"layer_0_join_0_index_pattern"}}]}]', }, pewPewSource: { - withIndexPatternId: `[{\"sourceDescriptor\":{\"type\":\"${ES_PEW_PEW}\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\"}}]`, - withIndexPatternRef: `[{\"sourceDescriptor\":{\"type\":\"${ES_PEW_PEW}\",\"indexPatternRefName\":\"layer_0_source_index_pattern\"}}]`, + withIndexPatternId: `[{\"sourceDescriptor\":{\"type\":\"${SOURCE_TYPES.ES_PEW_PEW}\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\"}}]`, + withIndexPatternRef: `[{\"sourceDescriptor\":{\"type\":\"${SOURCE_TYPES.ES_PEW_PEW}\",\"indexPatternRefName\":\"layer_0_source_index_pattern\"}}]`, }, }; diff --git a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts index 5823ddd6b42e3..551975fbacea5 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts +++ b/x-pack/legacy/plugins/maps/common/migrations/scaling_type.ts @@ -5,13 +5,13 @@ */ import _ from 'lodash'; -import { ES_SEARCH, SCALING_TYPES } from '../constants'; +import { SOURCE_TYPES, SCALING_TYPES } from '../constants'; import { LayerDescriptor, ESSearchSourceDescriptor } from '../descriptor_types'; import { MapSavedObjectAttributes } from '../../../../../plugins/maps/common/map_saved_object_type'; function isEsDocumentSource(layerDescriptor: LayerDescriptor) { const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); - return sourceType === ES_SEARCH; + return sourceType === SOURCE_TYPES.ES_SEARCH; } export function migrateUseTopHitsToScalingType({ diff --git a/x-pack/legacy/plugins/maps/common/migrations/top_hits_time_to_sort.js b/x-pack/legacy/plugins/maps/common/migrations/top_hits_time_to_sort.js index 7392dfa71bf3a..055c867486f6c 100644 --- a/x-pack/legacy/plugins/maps/common/migrations/top_hits_time_to_sort.js +++ b/x-pack/legacy/plugins/maps/common/migrations/top_hits_time_to_sort.js @@ -5,11 +5,11 @@ */ import _ from 'lodash'; -import { ES_SEARCH, SORT_ORDER } from '../constants'; +import { SOURCE_TYPES, SORT_ORDER } from '../constants'; function isEsDocumentSource(layerDescriptor) { const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type'); - return sourceType === ES_SEARCH; + return sourceType === SOURCE_TYPES.ES_SEARCH; } export function topHitsTimeToSort({ attributes }) { diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts index 0300f22eeeb82..27c0211446e85 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_telemetry.ts @@ -12,7 +12,7 @@ import { } from 'src/core/server'; import { IFieldType, IIndexPattern } from 'src/plugins/data/public'; import { - EMS_FILE, + SOURCE_TYPES, ES_GEO_FIELD_TYPE, MAP_SAVED_OBJECT_TYPE, TELEMETRY_TYPE, @@ -100,7 +100,7 @@ export function buildMapsTelemetry({ const emsLayersCount = layerLists.map(lList => _(lList) .countBy((layer: LayerDescriptor) => { - const isEmsFile = _.get(layer, 'sourceDescriptor.type') === EMS_FILE; + const isEmsFile = _.get(layer, 'sourceDescriptor.type') === SOURCE_TYPES.EMS_FILE; return isEmsFile && _.get(layer, 'sourceDescriptor.id'); }) .pick((val, key) => key !== 'false') diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/map_config.ts b/x-pack/legacy/plugins/siem/public/components/embeddables/map_config.ts index e8b267122f86f..8c96e0b75a136 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/map_config.ts +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/map_config.ts @@ -13,6 +13,7 @@ import { LayerMappingDetails, } from './types'; import * as i18n from './translations'; +import { SOURCE_TYPES } from '../../../../../../plugins/maps/common/constants'; const euiVisColorPalette = euiPaletteColorBlind(); // Update field mappings to modify what fields will be returned to map tooltip @@ -101,7 +102,7 @@ export const lmc: LayerMappingCollection = { export const getLayerList = (indexPatternIds: IndexPatternMapping[]) => { return [ { - sourceDescriptor: { type: 'EMS_TMS', isAutoSelect: true }, + sourceDescriptor: { type: SOURCE_TYPES.EMS_TMS, isAutoSelect: true }, id: uuid.v4(), label: null, minZoom: 0, @@ -260,7 +261,7 @@ export const getLineLayer = ( layerDetails: LayerMapping ) => ({ sourceDescriptor: { - type: 'ES_PEW_PEW', + type: SOURCE_TYPES.ES_PEW_PEW, applyGlobalQuery: true, id: uuid.v4(), indexPatternId, diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index f3997f741a1bf..1468bf7fdc1f2 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -56,15 +56,18 @@ export enum SORT_ORDER { DESC = 'desc', } -export const EMS_TMS = 'EMS_TMS'; -export const EMS_FILE = 'EMS_FILE'; -export const ES_GEO_GRID = 'ES_GEO_GRID'; -export const ES_SEARCH = 'ES_SEARCH'; -export const ES_PEW_PEW = 'ES_PEW_PEW'; -export const EMS_XYZ = 'EMS_XYZ'; // identifies a custom TMS source. Name is a little unfortunate. -export const WMS = 'WMS'; -export const KIBANA_TILEMAP = 'KIBANA_TILEMAP'; -export const REGIONMAP_FILE = 'REGIONMAP_FILE'; +export enum SOURCE_TYPES { + EMS_TMS = 'EMS_TMS', + EMS_FILE = 'EMS_FILE', + ES_GEO_GRID = 'ES_GEO_GRID', + ES_SEARCH = 'ES_SEARCH', + ES_PEW_PEW = 'ES_PEW_PEW', + EMS_XYZ = 'EMS_XYZ', // identifies a custom TMS source. Name is a little unfortunate. + WMS = 'WMS', + KIBANA_TILEMAP = 'KIBANA_TILEMAP', + REGIONMAP_FILE = 'REGIONMAP_FILE', + GEOJSON_FILE = 'GEOJSON_FILE', +} export enum FIELD_ORIGIN { SOURCE = 'source', @@ -77,8 +80,6 @@ export const SOURCE_META_ID_ORIGIN = `${SOURCE_DATA_ID_ORIGIN}_${META_ID_ORIGIN_ export const FORMATTERS_ID_ORIGIN_SUFFIX = 'formatters'; export const SOURCE_FORMATTERS_ID_ORIGIN = `${SOURCE_DATA_ID_ORIGIN}_${FORMATTERS_ID_ORIGIN_SUFFIX}`; -export const GEOJSON_FILE = 'GEOJSON_FILE'; - export const MIN_ZOOM = 0; export const MAX_ZOOM = 24; diff --git a/x-pack/plugins/maps/public/layers/blended_vector_layer.ts b/x-pack/plugins/maps/public/layers/blended_vector_layer.ts index 80bf0299380d9..9a9ea2968ceeb 100644 --- a/x-pack/plugins/maps/public/layers/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/layers/blended_vector_layer.ts @@ -11,9 +11,9 @@ import { getDefaultDynamicProperties } from './styles/vector/vector_style_defaul import { IDynamicStyleProperty } from './styles/vector/properties/dynamic_style_property'; import { IStyleProperty } from './styles/vector/properties/style_property'; import { + SOURCE_TYPES, COUNT_PROP_LABEL, COUNT_PROP_NAME, - ES_GEO_GRID, LAYER_TYPE, AGG_TYPE, RENDER_AS, @@ -180,7 +180,11 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { const sourceDataRequest = this.getSourceDataRequest(); if (sourceDataRequest) { const requestMeta = sourceDataRequest.getMeta(); - if (requestMeta && requestMeta.sourceType && requestMeta.sourceType === ES_GEO_GRID) { + if ( + requestMeta && + requestMeta.sourceType && + requestMeta.sourceType === SOURCE_TYPES.ES_GEO_GRID + ) { isClustered = true; } } diff --git a/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js b/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js index df11fe9f32770..137513ad7c612 100644 --- a/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js +++ b/x-pack/plugins/maps/public/layers/sources/client_file_source/geojson_file_source.js @@ -8,7 +8,7 @@ import { AbstractVectorSource } from '../vector_source'; import React from 'react'; import { ES_GEO_FIELD_TYPE, - GEOJSON_FILE, + SOURCE_TYPES, DEFAULT_MAX_RESULT_WINDOW, SCALING_TYPES, } from '../../../../common/constants'; @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { registerSource } from '../source_registry'; export class GeojsonFileSource extends AbstractVectorSource { - static type = GEOJSON_FILE; + static type = SOURCE_TYPES.GEOJSON_FILE; static isIndexingSource = true; @@ -130,7 +130,7 @@ const previewGeojsonFile = (onPreviewSource, inspectorAdapters) => { registerSource({ ConstructorFunction: GeojsonFileSource, - type: GEOJSON_FILE, + type: SOURCE_TYPES.GEOJSON_FILE, }); export const uploadLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js b/x-pack/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js index d3ccc0cb55821..e8af17b911939 100644 --- a/x-pack/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js +++ b/x-pack/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js @@ -7,7 +7,7 @@ import { AbstractVectorSource } from '../vector_source'; import { VECTOR_SHAPE_TYPES } from '../vector_feature_types'; import React from 'react'; -import { EMS_FILE, FIELD_ORIGIN } from '../../../../common/constants'; +import { SOURCE_TYPES, FIELD_ORIGIN } from '../../../../common/constants'; import { getEMSClient } from '../../../meta'; import { EMSFileCreateSourceEditor } from './create_source_editor'; import { i18n } from '@kbn/i18n'; @@ -21,7 +21,7 @@ const sourceTitle = i18n.translate('xpack.maps.source.emsFileTitle', { }); export class EMSFileSource extends AbstractVectorSource { - static type = EMS_FILE; + static type = SOURCE_TYPES.EMS_FILE; static createDescriptor({ id, tooltipProperties = [] }) { return { @@ -159,7 +159,7 @@ export class EMSFileSource extends AbstractVectorSource { registerSource({ ConstructorFunction: EMSFileSource, - type: EMS_FILE, + type: SOURCE_TYPES.EMS_FILE, }); export const emsBoundariesLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js b/x-pack/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js index 1da3680dfdc86..79121c4cdb31f 100644 --- a/x-pack/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js +++ b/x-pack/plugins/maps/public/layers/sources/ems_tms_source/ems_tms_source.js @@ -14,7 +14,7 @@ import { TileServiceSelect } from './tile_service_select'; import { UpdateSourceEditor } from './update_source_editor'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; -import { EMS_TMS } from '../../../../common/constants'; +import { SOURCE_TYPES } from '../../../../common/constants'; import { getInjectedVarFunc, getUiSettings } from '../../../kibana_services'; import { registerSource } from '../source_registry'; @@ -23,7 +23,7 @@ const sourceTitle = i18n.translate('xpack.maps.source.emsTileTitle', { }); export class EMSTMSSource extends AbstractTMSSource { - static type = EMS_TMS; + static type = SOURCE_TYPES.EMS_TMS; static createDescriptor(sourceConfig) { return { @@ -148,7 +148,7 @@ export class EMSTMSSource extends AbstractTMSSource { registerSource({ ConstructorFunction: EMSTMSSource, - type: EMS_TMS, + type: SOURCE_TYPES.EMS_TMS, }); export const emsBaseMapLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 04f944396ab35..b9ef13e520bf8 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -17,8 +17,8 @@ import { COLOR_GRADIENTS } from '../../styles/color_utils'; import { CreateSourceEditor } from './create_source_editor'; import { UpdateSourceEditor } from './update_source_editor'; import { + SOURCE_TYPES, DEFAULT_MAX_BUCKETS_LIMIT, - ES_GEO_GRID, COUNT_PROP_NAME, COLOR_MAP_TYPE, RENDER_AS, @@ -45,7 +45,7 @@ const heatmapTitle = i18n.translate('xpack.maps.source.esGridHeatmapTitle', { }); export class ESGeoGridSource extends AbstractESAggSource { - static type = ES_GEO_GRID; + static type = SOURCE_TYPES.ES_GEO_GRID; static createDescriptor({ indexPatternId, geoField, requestType, resolution }) { return { @@ -311,7 +311,7 @@ export class ESGeoGridSource extends AbstractESAggSource { }, meta: { areResultsTrimmed: false, - sourceType: ES_GEO_GRID, + sourceType: SOURCE_TYPES.ES_GEO_GRID, }, }; } @@ -420,7 +420,7 @@ export class ESGeoGridSource extends AbstractESAggSource { registerSource({ ConstructorFunction: ESGeoGridSource, - type: ES_GEO_GRID, + type: SOURCE_TYPES.ES_GEO_GRID, }); export const clustersLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts index 727435c3cbfef..e35bb998ce7db 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -7,7 +7,7 @@ jest.mock('../../../kibana_services', () => {}); jest.mock('ui/new_platform'); import { ESGeoGridSource } from './es_geo_grid_source'; -import { ES_GEO_GRID, GRID_RESOLUTION, RENDER_AS } from '../../../../common/constants'; +import { GRID_RESOLUTION, RENDER_AS, SOURCE_TYPES } from '../../../../common/constants'; describe('ESGeoGridSource', () => { const geogridSource = new ESGeoGridSource( @@ -17,7 +17,7 @@ describe('ESGeoGridSource', () => { geoField: 'bar', metrics: [], resolution: GRID_RESOLUTION.COARSE, - type: ES_GEO_GRID, + type: SOURCE_TYPES.ES_GEO_GRID, requestType: RENDER_AS.HEATMAP, }, {} diff --git a/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js index ea3a2d2fe634d..57e5afb99404b 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js @@ -16,7 +16,7 @@ import { getDefaultDynamicProperties } from '../../styles/vector/vector_style_de import { i18n } from '@kbn/i18n'; import { FIELD_ORIGIN, - ES_PEW_PEW, + SOURCE_TYPES, COUNT_PROP_NAME, VECTOR_STYLES, } from '../../../../common/constants'; @@ -35,7 +35,7 @@ const sourceTitle = i18n.translate('xpack.maps.source.pewPewTitle', { }); export class ESPewPewSource extends AbstractESAggSource { - static type = ES_PEW_PEW; + static type = SOURCE_TYPES.ES_PEW_PEW; static createDescriptor({ indexPatternId, sourceGeoField, destGeoField }) { return { @@ -232,7 +232,7 @@ export class ESPewPewSource extends AbstractESAggSource { registerSource({ ConstructorFunction: ESPewPewSource, - type: ES_PEW_PEW, + type: SOURCE_TYPES.ES_PEW_PEW, }); export const point2PointLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index ce9932bd15cea..96679f0e85941 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -17,7 +17,7 @@ import { hitsToGeoJson } from '../../../elasticsearch_geo_utils'; import { CreateSourceEditor } from './create_source_editor'; import { UpdateSourceEditor } from './update_source_editor'; import { - ES_SEARCH, + SOURCE_TYPES, ES_GEO_FIELD_TYPE, DEFAULT_MAX_BUCKETS_LIMIT, SORT_ORDER, @@ -69,7 +69,7 @@ function getDocValueAndSourceFields(indexPattern, fieldNames) { } export class ESSearchSource extends AbstractESSource { - static type = ES_SEARCH; + static type = SOURCE_TYPES.ES_SEARCH; constructor(descriptor, inspectorAdapters) { super( @@ -404,7 +404,7 @@ export class ESSearchSource extends AbstractESSource { return { data: featureCollection, - meta: { ...meta, sourceType: ES_SEARCH }, + meta: { ...meta, sourceType: SOURCE_TYPES.ES_SEARCH }, }; } @@ -570,7 +570,7 @@ export class ESSearchSource extends AbstractESSource { registerSource({ ConstructorFunction: ESSearchSource, - type: ES_SEARCH, + type: SOURCE_TYPES.ES_SEARCH, }); export const esDocumentsLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts b/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts index 2197e24aedb59..66cc2ddd85404 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts +++ b/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.test.ts @@ -8,11 +8,11 @@ jest.mock('../../../kibana_services'); import { ESSearchSource } from './es_search_source'; import { VectorLayer } from '../../vector_layer'; -import { ES_SEARCH, SCALING_TYPES } from '../../../../common/constants'; +import { SCALING_TYPES, SOURCE_TYPES } from '../../../../common/constants'; import { ESSearchSourceDescriptor } from '../../../../common/descriptor_types'; const descriptor: ESSearchSourceDescriptor = { - type: ES_SEARCH, + type: SOURCE_TYPES.ES_SEARCH, id: '1234', indexPatternId: 'myIndexPattern', geoField: 'myLocation', diff --git a/x-pack/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js b/x-pack/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js index 7f4bcfa41f7c4..be333f8ee85a4 100644 --- a/x-pack/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js +++ b/x-pack/plugins/maps/public/layers/sources/kibana_regionmap_source/kibana_regionmap_source.js @@ -10,7 +10,7 @@ import { CreateSourceEditor } from './create_source_editor'; import { getKibanaRegionList } from '../../../meta'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; -import { FIELD_ORIGIN, REGIONMAP_FILE } from '../../../../common/constants'; +import { FIELD_ORIGIN, SOURCE_TYPES } from '../../../../common/constants'; import { KibanaRegionField } from '../../fields/kibana_region_field'; import { registerSource } from '../source_registry'; @@ -19,7 +19,7 @@ const sourceTitle = i18n.translate('xpack.maps.source.kbnRegionMapTitle', { }); export class KibanaRegionmapSource extends AbstractVectorSource { - static type = REGIONMAP_FILE; + static type = SOURCE_TYPES.REGIONMAP_FILE; static createDescriptor({ name }) { return { @@ -99,7 +99,7 @@ export class KibanaRegionmapSource extends AbstractVectorSource { registerSource({ ConstructorFunction: KibanaRegionmapSource, - type: REGIONMAP_FILE, + type: SOURCE_TYPES.REGIONMAP_FILE, }); export const kibanaRegionMapLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js b/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js index b21bb6bdbbad4..bbb653eff32e2 100644 --- a/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js +++ b/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_tilemap_source.js @@ -11,7 +11,7 @@ import { getKibanaTileMap } from '../../../meta'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; import _ from 'lodash'; -import { KIBANA_TILEMAP } from '../../../../common/constants'; +import { SOURCE_TYPES } from '../../../../common/constants'; import { registerSource } from '../source_registry'; const sourceTitle = i18n.translate('xpack.maps.source.kbnTMSTitle', { @@ -19,7 +19,7 @@ const sourceTitle = i18n.translate('xpack.maps.source.kbnTMSTitle', { }); export class KibanaTilemapSource extends AbstractTMSSource { - static type = KIBANA_TILEMAP; + static type = SOURCE_TYPES.KIBANA_TILEMAP; static createDescriptor() { return { @@ -86,7 +86,7 @@ export class KibanaTilemapSource extends AbstractTMSSource { registerSource({ ConstructorFunction: KibanaTilemapSource, - type: KIBANA_TILEMAP, + type: SOURCE_TYPES.KIBANA_TILEMAP, }); export const kibanaBasemapLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/wms_source/wms_source.js b/x-pack/plugins/maps/public/layers/sources/wms_source/wms_source.js index 749560a2bb4b1..33f764784124e 100644 --- a/x-pack/plugins/maps/public/layers/sources/wms_source/wms_source.js +++ b/x-pack/plugins/maps/public/layers/sources/wms_source/wms_source.js @@ -12,7 +12,7 @@ import { WMSCreateSourceEditor } from './wms_create_source_editor'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel, getUrlLabel } from '../../../../common/i18n_getters'; import { WmsClient } from './wms_client'; -import { WMS } from '../../../../common/constants'; +import { SOURCE_TYPES } from '../../../../common/constants'; import { registerSource } from '../source_registry'; const sourceTitle = i18n.translate('xpack.maps.source.wmsTitle', { @@ -20,7 +20,7 @@ const sourceTitle = i18n.translate('xpack.maps.source.wmsTitle', { }); export class WMSSource extends AbstractTMSSource { - static type = WMS; + static type = SOURCE_TYPES.WMS; static createDescriptor({ serviceUrl, layers, styles, attributionText, attributionUrl }) { return { @@ -92,7 +92,7 @@ export class WMSSource extends AbstractTMSSource { registerSource({ ConstructorFunction: WMSSource, - type: WMS, + type: SOURCE_TYPES.WMS, }); export const wmsLayerWizardConfig = { diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.test.ts b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.test.ts index 8a5cfb01e5821..4031a18bff7cb 100644 --- a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.test.ts +++ b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.test.ts @@ -7,11 +7,11 @@ import { XYZTMSSource } from './xyz_tms_source'; import { ILayer } from '../../layer'; import { TileLayer } from '../../tile_layer'; -import { EMS_XYZ } from '../../../../common/constants'; +import { SOURCE_TYPES } from '../../../../common/constants'; import { XYZTMSSourceDescriptor } from '../../../../common/descriptor_types'; const descriptor: XYZTMSSourceDescriptor = { - type: EMS_XYZ, + type: SOURCE_TYPES.EMS_XYZ, urlTemplate: 'https://example.com/{x}/{y}/{z}.png', id: 'foobar', }; diff --git a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts index dd96c31573316..8b64480f92961 100644 --- a/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts +++ b/x-pack/plugins/maps/public/layers/sources/xyz_tms_source/xyz_tms_source.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { TileLayer } from '../../tile_layer'; import { getDataSourceLabel, getUrlLabel } from '../../../../common/i18n_getters'; -import { EMS_XYZ } from '../../../../common/constants'; +import { SOURCE_TYPES } from '../../../../common/constants'; import { registerSource } from '../source_registry'; import { AbstractTMSSource } from '../tms_source'; import { LayerDescriptor, XYZTMSSourceDescriptor } from '../../../../common/descriptor_types'; @@ -19,7 +19,7 @@ export const sourceTitle = i18n.translate('xpack.maps.source.ems_xyzTitle', { }); export class XYZTMSSource extends AbstractTMSSource { - static type = EMS_XYZ; + static type = SOURCE_TYPES.EMS_XYZ; readonly _descriptor: XYZTMSSourceDescriptor; @@ -83,5 +83,5 @@ export class XYZTMSSource extends AbstractTMSSource { registerSource({ ConstructorFunction: XYZTMSSource, - type: EMS_XYZ, + type: SOURCE_TYPES.EMS_XYZ, }); diff --git a/x-pack/plugins/maps/public/layers/tile_layer.test.ts b/x-pack/plugins/maps/public/layers/tile_layer.test.ts index 43465eac7f3ce..f8c2fd9db60fa 100644 --- a/x-pack/plugins/maps/public/layers/tile_layer.test.ts +++ b/x-pack/plugins/maps/public/layers/tile_layer.test.ts @@ -5,13 +5,13 @@ */ import { TileLayer } from './tile_layer'; -import { EMS_XYZ } from '../../common/constants'; +import { SOURCE_TYPES } from '../../common/constants'; import { XYZTMSSourceDescriptor } from '../../common/descriptor_types'; import { ITMSSource, AbstractTMSSource } from './sources/tms_source'; import { ILayer } from './layer'; const sourceDescriptor: XYZTMSSourceDescriptor = { - type: EMS_XYZ, + type: SOURCE_TYPES.EMS_XYZ, urlTemplate: 'https://example.com/{x}/{y}/{z}.png', id: 'foobar', }; From 9b25fe1ebdf03df51cde86a7f8c1dbf789e97877 Mon Sep 17 00:00:00 2001 From: Melori Arellano <melori@elastic.co> Date: Mon, 13 Apr 2020 13:57:50 -0600 Subject: [PATCH 076/121] [DOCS] Add ILM tutorial (#59502) * Add tutorial for ILM with filebeat * Change screenshots and add additional steps * Update screenshots, add numbered steps, and other minor edits * Incorporate feedback: update links, formatting, and minor edits * Move tip inline with list * Apply suggestions from code review Co-Authored-By: James Rodewig <james.rodewig@elastic.co> * Move TIP inline . . . again * Put TIP inline Co-authored-by: James Rodewig <james.rodewig@elastic.co> --- docs/images/tutorial-ilm-custom-policy.png | Bin 0 -> 482469 bytes .../tutorial-ilm-delete-phase-creation.png | Bin 0 -> 71022 bytes docs/images/tutorial-ilm-delete-rollover.png | Bin 0 -> 123735 bytes .../tutorial-ilm-hotphaserollover-default.png | Bin 0 -> 252951 bytes ...ilm-modify-default-warm-phase-rollover.png | Bin 0 -> 455134 bytes .../example-index-lifecycle-policy.asciidoc | 186 ++++++++++++++++-- 6 files changed, 171 insertions(+), 15 deletions(-) create mode 100644 docs/images/tutorial-ilm-custom-policy.png create mode 100644 docs/images/tutorial-ilm-delete-phase-creation.png create mode 100644 docs/images/tutorial-ilm-delete-rollover.png create mode 100644 docs/images/tutorial-ilm-hotphaserollover-default.png create mode 100644 docs/images/tutorial-ilm-modify-default-warm-phase-rollover.png diff --git a/docs/images/tutorial-ilm-custom-policy.png b/docs/images/tutorial-ilm-custom-policy.png new file mode 100644 index 0000000000000000000000000000000000000000..03b67829f605ca339df644110f9cf57838c58fb7 GIT binary patch literal 482469 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 t@YYzZ@L<f9YI%`0Gsp&&~jx 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/ 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%0Ajk^cTBDf5MIV^*xGnX-IyK;!to& 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%0A-u)(+JN=&jSQVuGgHz2})5-77DS$to$x%-)x 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%0AtjdC=Yawo!&?AoSq<_WoT!*B){*CHr#gKBZB) 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�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%0DH-hF}t}(70MP^-9;d zVj8`AQF6vtdOs*}0tyjN|M;T%11qBpH8Wz}W{MjI^~HAJI5oLe!zJVhzDVt(GG9*^ zezf%dA{7mzn_^qnu!^zrO+d9RcuH}Z2yQ(#zGN?U0s&|~Z|}jGPoqCSUs^VEC<m^m zk|sT{;*<@>k&_2L#H?3!^nWxzNv<@G^9b`F2)s2teo4?_RLf#0EUzB4n=-Q`INA^0 z8zK3-z%EkDg;&|PMzK_3T}?rh2;cw82s{nkjyT&epIo{1K0d~ha*HEG82+l4>83k9 z`6p=4;qMd7G<Iw9Amy*uYNK$g-u+vr+Q2&K2JsDxdWw*$Cqd9Mb2u2nW96AimiFTS z*&Y?qKS%;>l<E?vT&rldP%hn**O;Q19l!U@6E0`zE=a791P#bG2UawlXR~l{CO<WB zbl{NeBalP@{ZC0ZMJI%?+#f)fz$-N|o@6aifycK0u4OI8=66IFCwq@cxw?Rv=d;yZ zI@PJa;JnAClL;X+Q1`DXJNhb`g1Q-7U#5t&rpw;DhHh`k9EPlnS>j?nE3NhozA#fn zn9KK7E!Y!uo3x0FrSetz`E0WLqfshpWD|&6%6H3s4sXe@&7JqhlmW8>p?}w6Djie5 zStOT%*R>@>-%5(uR6#d>w_vW*FDadBdjI3(%RaM_vDaTvcK}gQuZj6h`a#3S&%0iI zEVZ2uYTa9cHno^+LSA;(YT*gfe@^bK^KD04y_rZaH!7A+gW#B1)cJOfte(T;Z&0(| z7}Rq+OmpXYKr@|7G3UQFmh%hE#vNRC$}M?oJazl;#h=YKZ~%8T{7?SkRWmU)E142V zVSoX|ocI{;Kd>0`_xp9oRa3{ulB^lO`899XU1^R05TK4XzSPQf*lUyV*Ojoj2+RP0 zHUDM_**k9yXj_XfC*cC=Jt_N-2v0tlxAW{5;k>?w-sO4nC#B7jODdn2uHtDfIi9Zc zH;KXbTjDuVmM7=4Pc1SAy>FfmdF=a!3j$O&t)sqh0DMW<y=aB6Cp3!=uvhSO?E6sR zoR-2qxP=cRd%p9}5g!i81wD^!9Bh-gIA&|p(5$82-h3d;4Qj@$XBks`^G+S}uaNvm zq*g@?doCS}SBg#RdxpE{o+^pc?G^}KM)c9AHWm3LIfBOf?AL2oeLhZiZ1h;{D8|-S z*h*E7Jf(`Hy{__Tnpaz{f4+I!my%cJ2HgyBK6^{s(5{|VyRx!@`ra?lM$KMbyur-f zs7TYX6qmu)S84{fe^0UKV>2#(l+CzEX={My<iBn#>CTgubJVo46H*6HhA|1{*Y973 zo(6pBxI6)FZdc5dSSaFS_nSHvU~Y4JnX;kn`n_LGxE4?|4~&h}o3VJbzFzj2CuoIi zGuz8!UlOu6-@T)+sgUI&e><Se$DDKk`6<-I7cMg<)`e%i-?IjVmNcPJh5;O7XX+%R zuFH%{{rh@RUw=0jLH%$<__Pr898z7^VNTHI8B+|LZfIJS`9%~WJ+LZN7nHB8H>VO! z&9ymlk<@ozDN;3wLcn<`*(s>-RB(7XCZz~SOJLxdkI!*zRn#6`wmr#ld<+dtkjxMd zsQYo<^8APZeY){vVqg1CU`K^y_UEnTqRHH5A;v_FtY>|{k5LaXv*0k>#<1xlw|3jN zm?i13hE1vaidviMGU&Zs(p3p~IsXdaU2gwe{6W2r{sQtlHr1Jlb25j2{$5K%`-c`Q z-$Y9y@3V%*+d;UbuGR`0Od{3^+Etoe7V(~#YWnxt6p<<%b^5YXXYypT_US=r^X`Ri zhFGY)2ED)7Xxrl&AHRYy=KC<m3fl%>iwxs&)~UWfT-S8v<0Z5@zc1)8_Wdi6{`@kU z+%O&{*Q8n{tMAmP_O)>zQog!14eDAmKOMjgsda70l~4~Q#1AHJ|8ObzHMt#m?Ic_$ zKc8m=nVp0<Pohhh<>N;j@zvFMfg=@2EjLR5+I4!(-?b`w7>$>~UXzYi4j;llQ>WV+ zgN#&5PM@yf;n$?5+k<BIj20%w!Ag8+ofu-qg)VC>?$d3=dj(8R+MaV=Tu=4!VKD`H zhkY4F?s?E#UeG=7WMuADZ9M3<C);K74v%Fa)-KB;fVj8`*pz<G2RL4B@#2X2s!84e zDt~wvMT)_e7?;I@=CT%*MD_9g{({tYeHS<(dST`ifJR(+qdH$}p_H4Bs=?#hMctA| z%4f=BSDVyDw2qBi$L>`hNi?Q;5S&wPy4-h?h>=M^!-Q><^PPCxf33nCakjVKy)wA! z4}Qh6)HXLLx*g@ySacXQAbZb*7dyU}g+#1hZMpLio?lM}T}<Iwch}Zm7EFGb+ll~- z5?l<|BXhGzQ2l!A^<Y&W%AP7Wi%AZz6DAk0#haNwcA6Icu%B=T@?dX$mDWt%dB3q7 z&L9NaLN-dKTImZ9%*S*{jM3@qjyc|VnpN&WcES1jJ^JvfRzS8ua@+1Zm2jm~3d1;? zcTt~oO#YEjvDjvJR+`EQ#MXA-OC*8s!rd{W5`qVYBxq_4-Tw%f{`n!}3U8Q0llmYn zO#NA9<6WZYTD5M{vBZ%ql);|e^~+E{_PNb(pBw%44xaa<Hwxa*eQM(xj20gbV{$&p zM;rwVqG7RS4~WY620p+4o4wZT0D6|cm{8WM|An-Ez;ZOeEVL4*&6*<e`4Mxe(4H4m zcI+E{^v8*eHEa+YCQtb|Z#e6so=Ib`0XQunle7l^>}|tmx2~7O+pErOj;ni)U~Rw2 zTJ1x-E)MOOuhT+?^~oG^?B$Ax#?A){y`6?)aITAX`h|%ho(wmm%8csPeRf93<ho5M zU4W7D5KDm*lt;{+7LrS~_x=$kV5d`xxt2IEMw6fJE?0aH2A5(#_vqWw$3`av>G<Ac z=WUzrL<p1BW%Y%y!#BUj`3`Nr>vzXR?Rxpqi_!w`eE7B+0$V_geOm0d^|D^4%k{34 z=*&RgxMO8MPi$L{@*7`~YQw79n0`yjA>p&=o8AG}TCm@w5#mGGwaiXGXbZet3o=UP zutmE;$Ul<z{;L+aRH3LF!etKF+`?cCe<8!{C(k6g#BBYGkuUiW($L?T)&xfc<S>8a zMx*Zw{$p!mZ|4P|fmJ!nbs;y6V5IE=)Z;brZq9FIHuZcrls9^S_Y`i+Ol|=krrQiv zV%=Z)&G$LHM#t7iP7AJ%epYdJL;ri+izw2yJ2pH`FsiqAv@|xEP*O&ST-G(x$Y$eL zn}vM^b0B}6G7A)A+`KH0Vz=VrMx%5986r7@n}EDxmW3n78Kc1zkf|##N>5+nYv!6G zv-?@(6A6ZbzCKyojO=DiGLk<G*W33?vdlXLR7`yfOQbDnJm&Z6i)Crp;X5we+u~@p zR0FS2XNT;A--jqs=1mPa=o=!CMvvL(4`XOj3+N803I_^eqxuGbjGzMyK!};}FZXEa zuD<d1sVm_o;|`w~oT@g(13gj~P9b9hmDFhNA);V|zuNtU1|ggTX|i{$*1x#T9J2)c z9B<+I|2SL?9-R@t7l!S6GDjQ17ow~7JaMLxz5}kv0}ntX>=<-_sX)4E!)Mv7fsPCo zD*gJc&n=S0f_X!Z>@O_bJzCIJh;9D(`{%1|zc~N9qVA_W@I&Oeogc7TCf_P|MmrII zI(l+>+AaSoF%y8-RUUjzu-YDie&Swt<jjg>kAKp76D5xFr<K9gmfeT0X3)My2-Uc6 zj_#zu#%)wEwR7MPn8H7t2boU@`#RIwUjIu^Zci@CpX;E9{UAudVX5<o4_+^yg>D4G zMO3J@aT_*@shjY*uxy@q*zc%2Q!QRPnEzb?lW|Yn`Zf(?$0vKMBmL*Q)2Gq-OoQ7H z?~s2C)-Id@ZO;Qd^g<FHPpcTU;c}L?)uE}|>tOvIOt9Y=y}sxDl~*L%k=l~xXKVKi zly-S#<sk%(Xv0v?9P3F4^@U6?>~DH_zz1o`$mDAMyZM?TwxPdcK~;g8n^swm$QGi3 zq#tn?Tc(YPQm}*CqP~CK_t({Y0<`~;;YKJ_&lM}U@RSH8!>Otzi%lJ+-=Z<d3DO~; zxPGr*aV;m^KT3C1BM^<+jo3JtTQ&vV7*zD<r0sF?dxjcsz_f<&q9jUta}~r(R`ujN zvFAy#FcII4Entvu87nmI^N)qUdQ}Os<RWVSDG1_)L<`}-LIP8I2&wKQMAP<Hs7R#7 z=WvL+s0(jvu#msg(!j1QsqQ-?lv0NHy}z@FbMZ#X6O%NY9=a7)iDJGcGV8h<9ghd< zGd!6waR<capZ>e}Ysy1_k5=z^-e5SZBq~5HDy{osX`z5eqGB4hGic|u%F1VC88AOI zC4ykMs6UXYOAAELzbrJsbbQp#U71g-ftL5Wo_ZIw-=GDPOD>?(^Phcod4loOQAHPS z=-9NDYf%`?zshwN?7Uj@3_W8Lck=xqgp7l1S3iZn4qEAJRw!Uzh-!e!y<NZjkjmb{ zzO4P7$7v)aVmfa8{@mBox69n{9gAj6Ml~AVB$<8%zBI8?<hyVl4KuA_8l6t$55?7v z#=i~Cp86-*L+!(8iBYSV|BmV<`;Cct1+f$#wT(u?N-`PRCsKzxR$0FA4S9E15AEtX z6foRvcV=J2xiFQLdV_bUM1zDpPf~LdDhf0a+Exywq4%#sI_x1S{7mFuD@&!QZOw^0 zq~0k9m96@FC{4O3{{UM{LTY|x05GL%xU*P{Cc`B<<X(eMhJM(`3<b=W2NLU~7H{jR zTqn4g5%Z)`ZnJ7kRR7;BfPQXl${C9d$x+3<B$%5g`Q1czNO(PwS*|~*v{voz43GBp zUjh-o>pIrLT+Z&cjv<gj3Ogh8bwThm=T2;q;6Nfw6mHhtFK8@^5x|*n<>zoQ(7GbS z8ie?VHHNZY9=nS>ZT1%v>AkB1t`9D}uvK7SS}B#MYY23kXVkUrF&gb+4nBYzoTsL- z!j9A1+rU=nm@%vXUYg<slIfac4=L6hDkri_p0o`1oXMTnwuBheQCh$0WK&smjLs=I z-Tv+QI=D>3FL$NLZU_PJ=n(tVEY<vU>UEFl1$U00V)@j5=P#=;hn)pMvF`RS;rv}d zZAEpaTo?bj;Q7S}?sj9+HS3dE<iceMErm<n8j{P;ZldJI*evf7$J1h9^^cb;aBBps z!rI8(_a(bF!plvOL5ONTIVy|1h~)?N2qxrpbBb>l>Xo_z`Ig5y=3QWm7&w#ILO=~( zWX91@J0l@itwAjt`PcfLOn_T;CF8+GTK=hTQ?DjhKg?G5-8ikW@bGbi^<>J&iR(>V z-Pjn%yG&YUpxCh87psXmiUtK65GAB;C?bpu20Q)Fp=10=#v*Ux?UB^)gKL^gnduy3 zQvxChYYFvamDSoZdAk-;<peQ(W_d(>hJ*{>x2gO5E(N)jj?+c@%%^uXBRKPq+Daho z+zFD~T3f%~*b3V#<--C~#TGiff3v$BMoT&PtVnb(x0kAGQY^u@;NRcdkBS9w7~gw~ zkn;uB92muFE_gvSNj_-aSmC<;ZU))48<&$Qq|hDX*0UBrWCo?umX3E(bYD^+W|f&q zpElP6Kawacjm})|DU&$8$=`oM@uF|l^tt|xC8-1cu+$2kt!^p4jNC1~oP6>x-Y$j# zNM*xQ<2u6oV_eMc&i&fD&h=t7ZPpHir}NDN5A4s~RN#lWjDsrOQkZ=tAL;5|M1W`w zyQ*lAmxU5oAQGjv+LoFhCr52NWBGzgB@Frd;ByU?!1P{RC<65q21>@06Gf$d2dzy5 zF>rJ6r$*4KH^)!o2ZNbTB1Xhd?ynUPk**>CEkDm}$u8@%xOEm-Dsxq7$9@cxWLBAT zQFzs$=u2UXAN}-zu>C0Qdgt==JCu)!93HNn&BBpdOB}G)iP=;>B3DY-H~91U`Pm5~ zKU=78#c}ncDhY4Df&6BkW9=%=mhX`Vc>a&zTXsH<mq;v$dBKacv{PT+PfO=EU!d5l z6Kn8|hJyda*;fX|)wJ6N5(p9k1HpZ8ch}(VuEE`cdjxlPcX!tWcZb0V?hHOSci!*R ztvcWN?)%=lw`%{Gs@c`MyLa#IN7h=8neuFnCf08SKGy=k5C%l`cZF+5saqx#?;9e` zForHmu4A68JPXnCbK3|5ITuz!Uyq?~#`0ObVg!cSws!~ChKc8ez{ZV>AB%kzBt<X@ zcf0TS!uz2UIsqPmevIVZK2DeViphlAbA?eXzEur+;UJTawyweJMApK~2*}r6?b%M3 zCy}jwZe{qcL7Sb#myC(_sma8vRP-G>GQMh&(TEG<uASaS4*|Z7JAw5{g=AkLzi2Rv z{*%G1cUQ}OmBoG{)A|lX5UKm_Ms#nv$z{dO`FjMWBEqi#hB_q<-Lr9MroAne;QbJV z7P-d$C|kSj>)AirVRM+@x6|IJfkr;zy*i?<e&iDPN@PzI9RK1tgZ1NLdP0byx0aqx z-<~u(+G1(ulDH}(I9-rol+>S7z=0ucU38-3JRta|xc<zRSFu0XK38reh=y1J`AWzT zF9;PMr_J@uQiDv;u#SH$rIUo+Zk3tdu${+eAD>ID?Wk0iClJ(8lVWJPB&8*FAJ|7z z(PSuB5g48n2t{3UpTs`KwO(PRZgnMAEJX5qrqEpHtH+8I^6Bw^<nqn^x_|`^kK5Kt zOxHMC2<qQludY;}b_!LkbJg{D9(Nz-Sc1YM#7LG*&di}9Iy1(PWWzg-Q0d9T=pNpm zd~F7G*V83V+e&i{$}Rg`(E+u^Sp-m4gnd;o=dkM<)vUR6s2-kU?7S%B$pnFan_l#M zHF*G0<ijB6*?fI_>kX~-0yqD~Nx9KOg{RTMAHTgKL~Qp8wo#1=R)AX~7-i#S&x~>< zcjVKkz}&SY+Zs0M3byjzbRV<kda&wXuXMU>lE<m#F8&qM&a>8#W5WpdoDV98KB)&$ zCAa>VwK89;wjCN}H^fP+<oS+<EGW&4c5mn&IXPg`d?FsRC$A>Ag<a2aJ+<!Z!a_*x zw9fu?-1wF2KPZCS9RZaT!|=QvpURQHgI50n`ut^%D7SXGtp%O`B2x^G7R)5n;c&on zO9CUVxF@Bn<QD2d6=PS3z1+YA_N_0Mjt`~9<VYq<h|~3phFK$R1+Ef*iXp4m>s}7l zmP;K&di|Ij4n%(EYb(7Wo1#&)MmZBdynbL{eU~~(6*O_XYxnP@`ov-N$<eCbX|&04 z)HONCrmBM*8duv1sPxap40paah`m|&g!G>O$)6lm9}~nc=3`F=FE;AR>;~mFej21O zYwzJm&LXV3TZXIKOKQ<(XvpY|gceoIJ5S#bqU16>p0|(O(Q$09<Qm#2Qjhf&@|~-3 z?Bz%fB>nlGz}_iq{lCVI2|E@W&Hv()QvW5i)oN9vsdvv|PwIC2ac82onto%=cM!$s z*SD@j`<^bfL>D8%zg72geAlIhzzuUCJFmxB@vjJ}$eZ;ddfNoM4L}l;Aug6r7kPzt z`|s7`2DFQOi|DFcNeE+ZdWE>l>FO{^_=x!+xKHBGxcfS4I2IEsl&pu)S?Gu-=;C;= zS{UD&buQ>=-28l@!bd+p2YPDo***FTc^>@yRTflaSMGRO^Ep=$Y>=y6U$j>@RvMB! zgVZMo;B>m-Pz>9F^3sBhwO_2}YI61Xn(FU6Y(NUR?vq48YuM8h{prn8Rq94iF=Qjv zi=>+3JYa*(tWKTltj?@9qg`8ydN`8^C)4bI%@!<7R!-QlR_Ll8V=_lW>(}-+r&)97 z)I|wrQ;2=0ozQx|E@<lW70+*oG5pVeOfnOQzsq>z^6B?Y#lNPMTL+;46T$oT1Vt;h z#^&ZYeLe)L2B40W8KvtvEtC<1pr&?G-zB`8Hq@!)!m{c6C&2b>yG`Y~buBIZcC<{s z7am1)dtf+Y$G6t2zVPCg_{P~<`?wc&+HS}SHc!;-Wg=Pn9!}M~!<4X%JQ*3jO1?|S z5y!Q|zbt}`7KDQRt|MpiN2k4^zHKkw_0aGj(AYm9;Qn|B|3VZV6s2qV@UIpKU|}0+ zFs$4C5yZXXm~dg&-*=g!xcvw}erEB13kpDiAl#U0ABH1v3<vQyuDt?HZ(09q*cu3P zobMOhUbTh~cmD~8?ZbiQ2s@>jpV^rNeW2qHGRHT?ynE3(28FUeFgivI1peh~C~&`v zI5G(!9^W<muu&`_7vCuHgW}aD;+X4SPrEB4RpJS@fff2#d|s{N?BV<OtNBg__~%_t zwQ0R~;osl%PhxjaQqZS&N7>Yv7heA~u7Cc|@UKO3t#0dDUH^|chrdyhg*N^R@#i;; zZwe_z*J1zssJ}N2eJ}xkO?~Zr=fvON^v{h`eSlSX!)uf_L$~#hXYk**a;`20U2ul| z8W7%pCgcBo7c-du+MWWeWU52{e<xED07Lc07gKlb_~id{9F9FCQ|DqO!{6V&?}1S- zAo9QQ5Mcf8GrK9ZmpK9PxO-ABJHGhF#oFgLYVoiTd)&Hn@XtupzgdG_v<Pz;h`GF@ zyX7iZ+XY$h-SI+E@e7VD|3qW^`~U7PNzV(L-!!;`*K7QGi)yN&yQJL;WrO|NQH?IC z4#skqi3K&y65cI%gLt{w24APa(r?kz!osmb3zK%Gi_CUO1sy82LA=~(gOP@fnHre3 zE#76jst^E9Z%zzGf99~&5^}ND{S=nQUeRFc3Y?of{`)okx5~-fu!Hd59|nt3$P8uJ z^%@#obnlK|AwoTb8?VYKEH+h`pTLCHrSHY=Na?j&xS!U9UiqIO-OmtahnGCjaYl!> z=SS3lPH(!1F9}>TENv{_XFtvjU-!F%Ucvqw7+4Gj_Ju@@QG-&~Om-|xin<u^FP2|h z4lIa+J?Ui7$L6W{|9<`c(`b~i-*sJMeKRehWVccix;~iWWw&%Ry_b8uJw+Z*=V*F@ zm`Qzhg=sEoLGv$?&&Eum*QY!dIqhkwEl#@uN^uzm%oA1+K#^mt>~_mi0R_Gsp=S`N z=-C&+oR{?}7f4o(jbcAwWWL_%AB>{ESw{rltMOnZlUSS+rhgJ(yq1NPQT2>`udx6N zwg|%o{=6E>`~dvemyHDYezY5<a%w%+jK)HOJ)YIhybAf_yg5Eh98AdPrfsmJtXo1~ z{H>++vP>?!O<Ercw^j8O7p5&~D(%xI29(!Dz?zMzAE!ua+`{>)E0!kY=DgF6HD2l< z9#^V3fgnCUJn*f4D?q#rPEwWAwM=v-#ki7^jiDogU_{Kapq|#x^U+x`^3>%KuxhY? z+x{d(ejlz#UcM}$r_=TLzgYhN$G291cBi8KMn-p_6lgw|d7#Wd{5>|>3xJ4pn+40T zG3e5Dztwkqa|}XdNW%^k6yP0&jj6!qu>I29VxU_h%hP%}lDK~UX@#WJhEtzZlkvWq zLNCduWKSWP5FhdDa4O%;Z_UWQgo!y;er|&<x?okeE`DcyrsU?<PM|&^(U$at#+pl} zGp1H=qwPl(yO_f8FsJ&foE8`UF3tY&uHLn_V7=CY-H_e>jBSWZhDUV_q^)R_h8S+Q zEtW!9e{@9V%<%vD;OYV*_*fwbx4R_<-{5lw+L^709&0d&fDHuVD9e5Z5y*Z{=SmKU z>`xaJ1=zQ_o)YLZS^9~kd95_n)i}-W)s%PeyPVCjKs8MStNr{3qcU^VE}D-Cxs>?a z&ydoa69UZT(}UK$-GZU&jYFB*A_yZ`_WM=(e`Tk7bA8*Ja%GbhazDcq<fbTES!plU zIH@ku@OZnN;_<pz;yV!5x*w^~XE-@8bm^y0)rxxe@)^SLsl8_Mxd&0or)hZ$cYVjN zbyBT0W%vk{`-;gp6@7kyW2Q{7&!)$<TkfFvgzXS3TThv*+dPq5qFwLPPwe6gUhg#8 zJ!;JL0i8`X$sbRZItNcND|!<o+#$Cq<#u&?%|<Ed=@6xHSm8XlSpmYX4J@hYHt-kh z)-h$8z#kcQ;H$iY^QMYCw=;%Gr_dZA>(99*PQ6oYo@6%Fai`urPl>vsvy>=3LtUqH zOvix&n2)`Cb!)e+uF6{q(Hg6@?Lc}xby{uwfc4BHN*kS$I(_d%kf62_Qm*Q8QDQSz zCBv*%8G@)+lk$o>n9FB{p_Mv&s@rCCs>8}i>vXwZk^A&R|H_DHtmDx_6?KD6Dn8X^ z)zlp$;~E*OE<$A*N8Q6$-@s+-`yf_Xp&DH}M#4``38#qV;qED}^=E`>!BwY7;NJIU zd)R-!`~S_}pkVn9Y1Ydh2JO!SeBu4VjNN9T<~kCa`6MzX&@CYujFnoDi$EyfBM&kJ zc-<bDGybwh2Vfgy%cbKQ_+PEn_&$D&b-C5LHU|bbST6zfyl)Dj{v!;BSuA9|ZnwM# zTD6-9D)NGT3nj-i=K<N{ZHGM03NAKJ>IVV`BJtIA1iqhN<@-N5mBfs)u7+b`a<E-a zR)f8%*;UdiSDJ$T@6uoKc-_w|%_Im&usiQA(~W-bhmWg+&eps|Fm_i;lzW*U5;iyM zWGA@7Meg6}*ILVaJS=JUq%|IkQ%mj8t30oS{P_yW<l3bm*d1j8-9WiSflz)hpDiN| z;?Vm|q=@veMRucAtId;83!LH51}(fF2cjLI^%MdFkNZmI%bncK1^jBH*`mph4qaD% zi}e=Ot%f$s1+hb)<$KkW4RI9k1$x4wH1uY^#(*A)eewSC_}&=VCO;ryC8kjekmnuG zP5632<fuw-@2|vVd$$!ksf`z+YM>P|9`Nm!)B=(QHanarKEzKDc#AofX&jLHg+9Zg zPsD?nkQEgSjK$K&y>El}P>zF}wxUt+7g?ST6R83PGj%oSC?eN-)OCA(tLYJDu^m3H zh}ka{T%Y1CAQOh+1+s|p1v}`mYaQyUHDTkbhwxt|cRz5izAgow4}pRMLM=Xg@P`aq z8QmYn)!2i&YIINiKm}c!-TFeT6-zA)*N^F3qQx5Wz3Cgo7<i=&FZZ=ez^lZd#;}z( zWnb;?GU6&?5Z$WZ^wd<HcCWRWItKp@oTe*U1d+G1QOjds|K{!4c#pvA>C^cEUwAJv zF+HkHvsKpAvqITmX>WUgQ1{oCSRbs)B`m*(v6C9dr6i>~u&`z6<zYBi_L|VD+sl{O zqB0CHP@{hYTuLL`dqrG@peyFG+@Wa|sH)pf%#!2Va=b-qR5B#dM<vV(v;~kJpS<2! zFV5u{c^u*Aiv%}`Z+5Tpam;}T8vG`|E0KSl>Gt2gcDx;`N_6h)NTk?YPsR@Llx+@B zX&k-{dz&k2k~p8|)S|lUV`uA7?tSuBTKeVaKaIp+wUWOo5X%=uDh>u(q_m};ObpWt z`eb-+de0p73;dN`OJrN;ARhM7ZFBwGy#Hs}DMQzHcu$!<7w{r#wkC&viEI+@jlJrL z<(vYmPB?nxT0@A+7wkWjYgQvdbAo@#0bv<71tD5Qlr?<#gvum!)i=u&2&JE~*se77 zZgC_Q;<8`khs(OywM&s@hsM-XeZc1(8hZ2Rv)2$Sn*|eEteGJW$0d1eWI=&s%h)qC zEsh}cI8QvzI$bngsPcyxZK<GkSf&d~IzS3fW<(W*hg3HRi#})?q}!5bJiouyB&v&H zfVhRUe0^!f5Zkk|--tCiti#+K6lzxl(}`m(Q_hSTkl_NFwKkwoE)2nR7OHFT$}IhY zFl*S2<bt*{c7XqLvmx#2LQSD*x)l9QWP%zk|3bwIj`>&yhR$#q`aOHehOjFk6nJu| zr!DBYgA_~fyK~>bN8srtw|JgNS9ExRm284NZa!n27PVX+8JhudH1QQmRu5Amd%}#V zH8u>~WH&n+W6p6veSFG0|Nd>ZMVYJ~C`N=vo8@;=In}JGN#-lfElZ4AR#SBShfFb? z{H7_f84g!W5Egm4RZXnUy~qbWEj(ks+YnqMR3!QFxl`c&=Xv>tpl#AmOW7GLOb!&? zCVMtn`T99j@~Y*_sSsn@tsG`m@&s&i2ZTy9+`SRyH4!H5o?POBm9reNwwOLdqm_xy zO$Yy1tGjYdtl)cm_aMyO_af~@C_Rj=n2#Q_XUx!oBIn@v<Y2_LwBVOD9bJt>PVbv- z%*_b@XW^uzksc~t_9ij&L+v?cTeQ-Hcn0sDox=3q2M*m{tG9e1J~IV%Lc%8xyZGU~ zGm(5E*xIk!4Q1p{+0a^NS8uAzMwZXt2V9HLlD?ZkK%}?^ilbR^s?jeVFPak&X8O-L zWjLKEIG@;^823lP0SX}N=>g~@!XjQIk(bqtinrs#yYQctVY<hi!8{h(`WwEClg=7l zoeL>9LrD*@FOjuX1@QhnbgCU_fuV1TU==$Xk#NV~j@RETHQ08r*t|~*xXUf&556k2 zb=o!XsdJ=C3*oMoY{x>lcGx-`1wC;n;<6{frFI(gb?L+ehkP3diK#Wb-vU+ue#>P< zm}NC|7B%3-FJO{r6hyHAMIOdg*)BFOVcF56h5CVSbdod!D<5x7PA>VyIF_TcaF3K_ zvqN}emnAOdoI!NX7efj1TAJjq5O(VbmqVN6kZ)L6YNX!YG%p<P`0#zfB#q)No>?b& ziJEHLXAlk2`c$D2^7WO)rF0fQZ5Yl__aX__U{>w&$4M~tdccm(Lq>-sotKaRHhv%9 zG^_ScJ);B?{=Fn{Z`u=5N3$g#?Un3wr(MRyxoNfu+ZVssH;6I+{rWX2C%j>J%2(kl z<Y0-=RKc*J)N07P!KQGPbSoRZSA5p3@KmqJIe8inF}dmTsi>Y-l;72|dwujX89Zv? zVMHf^`S<I4cJ#L=?WaXq+6E<5MzGI$Dxzi~nVh0spr5a|j7KFmU@_rKCW4Ilm;tnc zJT`u9XxF<(nGJ=k&}u3<%-`Wcd1-+r&|)3p<Z~kkUpVbYerI^fDrp!*Nzd-#fSHes z23S1qtj7UxC7P*?$8{G+>BM0On{V*KmCTf0KSFC=e9rJl8;(cQy~3i$tQO|0u{^Xc zm`n)=SbXF#DwqqoY{#!=|B(<HZ$aWM8Z{T%Q$zaJ%$}vBqD-XTk%~MfX&ie}h^gZ# zDj<LP=Kv7?V7gL(b#_HctK0*?lxSRw;IC0JJdjkm5=oUg%GCLWbW42*5AG5f2}-4? z#%JQDeL7rj#cvBqp&{qi>T$so?!2WpZ2brwpjnSgX~?1DEDR<dVtDE7{-5ny46%lS zo~!{J))J;=vnG!9P&F|Q-#z}Fa0H9-v>Olb&)SyTk?=8rVqy+@nCbDJ7zS7>OzK9P z^dIX2?LdPLlElPQtY~4`T9<xzDOv09sDjUUG{cqRIiD=V_-SF4$r8On(^zc2Ywri# z;h4G(39D2#XM-0U`Z@wf<w_c>ceE|%%P3e^ic-DstmOq>eaP2iUCwH!V|%z|#YBcf zLZf<$#&ypN8}!LVa@+;)VC_~4aB>$nSs!Rd4!K>iw`PeM`u#0z#aq4*FR|b~*X!iS zmrI#c=(f;eJB%&<KnGl9TrH#fB!8kY>J$+;%7wFW-)i7W&XXL1vBd_nqoO)QeqYm( z<}Me;ShwElkoR!j{MgY=kE)FU+FZEeBOAk{EHA}*$JYmM{B)#$rx3v0oRt|6&)Y}F zN&Ak^EivCPc+XW8yH+vfN#X3?nn5AzW1lm~MNA`Ii%d*6wG%nN*k0J|3kp$MT)3aM zuH&*ajRZ9C-4CJA_jk(wiH`Wz?Sd}cQ5(XY0TRMRtlb<MX6UiOsIL_hNf)@iac_A( zw(T2z^-#>(z*<|O67J_g*0dko+2yM-n>2VjymG}^;*u8Q2V`wT2Qhg+^%i>Q?v;{u zR855R)pXHFp(Pczm$O)iGp?t$V_E@C@t?ZIwcI30>Sl~h7a#b_GKG~e?nZCQubOc- zr+W8`^F?(kJf2j*qCmMa6#XV^6Bq?wbC~6OaQy4rC#U1#iy`z}#S9OW<s{7@rvA6n z0U4}MHZxeJ6ykp_H&5+QH-bYU(%;@m{rBrn2}TL}W1yc)yi`emrl#W10@mi5wySI7 zq9^Unb9Zg6z&q)bGZSUgt+CSOF;M}=_u;2IeF~9%s%|`-cFPf%bQ)o&`C6R%jbf8o z0)1?a$DJ>IL5{0qXIf9=1YGCbO8>qAz@XnHqH$Bg36J>s-cpWXRWmCCKZHiu2BlYZ z!`8A)XPF(ktDrVm5(Ps9U&?+@Y2LRZMbwCPwgv>e+kUWN`iu{7Tb%2(NxC?=T$Odm z7306PJfOx5vRn#^3-fmam&VjGumcO<SUs+?DfS=szHcov4GSq?Gr)iD^5|L$X%@O0 zK~Px^5tdT*(y2qVYg7oJq3f58!An@SC>njr)3cK*p#VU^@Jyn7{TOk#&R?_7T0G`> zDAiIJ7TYbj0P{YS#wBn#LY|Dg4U@vJU7h?A&C!Cm79+{vs$V(r-kV3GOzcLrt2c(; zSH5f?)7`lxIgV(M30Eq3kazVuQWG@)1lcggIT{KG$h)9b%Mh+K_s36mnTxR>*&Uh! zzLqvqxT}x_HKk5d;&SP`!{z0tdD<WIc3#{DZ<Sh7bgiV&ZIz;vy(vr7OgXn9_80se z5|UStB}hk$R#$2PnUIo~?xAyt0yxOGGdnN%kcT74iT<?Gq21iQ4f!J{>YGVsH1N<q zke!i0J!$yPz;F9)0XbC|SFT7yGs-KhB>sc-$c$b`-4{L`IF6p02uprPI|p(xcuxs- z;T{7sa`Ek?X<0N<qI#l7Q;HXFUk8&fYjgukJzGd0qOS+<VE;7MvpO~gJe0`-4$|-< ze~fshG@0^c>Bj|+!h<EWI=01!5-{%MckAomJuH=2UmX3g1HvG=KUGeF(hc;&9qas# z;+h#V6w|5|iW2n8loEd`_V;1rZ;h<nU>;np7>vnoU<=k`_{C8@^F)eA`3C-M+9-+~ zYwbh4RU{$+M-g6DFhB@cJg33EdF*C+cExiUZ(RUjM^)V$n4g@V=mF4asvSc3R-tV7 zdqj_4z!QJD|1P)N(eJKEkae={mGixMf4;aJLY0>d9Phi+!Sr~pKMp_=q~s}+vjUE? zG|u0h*e-qdZ&z9zQm@vw;0~n$Qf6=`qJf60tInUXCQjn@G!?jSMrDL&LHj1lWtlD3 ztMD%N7#4jJ*0vzRG&yo%*nhjuodHuZOWFP}6qJ5^;<n`NESIYQ?)?)0rEL=vU@D{a z>in9GiNs)iex;~*n+s%MW=q;N@}lSL2r(ICaXZ0IVfQRsYH;1d?R8u-OU9e*v3})_ zjmrc#*|mE7$ql~f#?FdAgd<bpC)GTo>06xa{uNR`!5>@Xqc<rI8eNvE=-g__LVK_H z@7;p-@;n~EP04`6VJwwKYv6302NZkf{3c%_%cxJt8*;`51fU!jSV2AKEnMnh1T!C8 z6Z0_YqEbVQ*#RklTghFqgvbvo-^WAhAF03JK1v~Ez1gu{gTdVO*%)>4dtt=g5V_#o z4u<jd4uNFBnDZZnO01}hYO!5#y4>Q5_RFH6F>c0pjjr1cSgkBLS$cLZV0%{PTV>CI zY~(S4><{K!AGRw?eg**e-21E~#`4V?i7Ub2jX4i&Boq{JG0Pl}iY4oJG9&qVBD8j^ z4dPMW5$_A@6^M<+_;eH>r#R<yr^K;CVinwu4sSLo`37teotkWKyf9dg6JR<c?j*rW z(NP?^;`|eQ7A+UL7<lLbh+B!n3(e2>qZ4hJ_u?vN>|`&~wU)SigQ|*$;rilcTe(zv z9YD-9?-2!0`E(Z4So9t_BFqThS2?m5r|Nny6P{8{&Fj-O%v{!udEm%0aC7@a=fJtp zAbSo!=CVfmv8r?_ydvt<@z|l7Ju6&+=bqgA5t~ORb1<xtug1v&4t59kX|!+++PVE4 zW3>Gi;^G^H9uz8yFTs89(pzo$Xv;Dz#uV{z7x-`|U%H69TD$lpP~_O0OG}@955+BG zh#8M&kw)FsO}v#cZ|6_Sxi%<!{4DwnKFEIPEm56`yel@ZzIMo>vv?N3e8S&c(NFX+ zwhZ$?lwn??HJz!oo~hB@57Cl@6W0wZkFX$e?)8{<n)rCn5Pb^cxjuQAYz$o(HarJc zvor!&$!20-S_8Pl6VFX0e8|?0xEnKy#u~UYvOYyI0DFcR%9y*g$2Gx1*&#z^^#iEL zAAh}Of_{hipE#)P=UAC`tF6v6!E7NQzNU7f!1cGwckRp0DY9MBT{w1&Wh_k^*)5bL zB_@qBtwz3%Z$#~)W1O6AmU4^s3!ww2Cd5YvxsdxR_ZtSi00^gshQRKh=*7s^{sbSN zDF59cy<0*!Xn%>&c0S)iRy6tD(aQbW5u3v0@VWCPlZ(>AIX=ko)p2YE=W(exh1E5! zc6^S`Cqi#5lM9uJ|CN2+cOPYEXD3D3bA>4?HuvR^(Sgq#QJt<xY4^kOvBVRb%c9lH zIuUf81Sy_vfZsPyhDip0Yn-msZpR|_y8{Tm+?n`X^e0OeJ2i>?$M@&hgZ|e+iKk<I z(}qHgZ6cOj@u46Df+dgFBNO>a<0OBOEhy8tN22swA0M<uB5{gc%k%}jOg>k%X@tIc z7gdZV8Bxtc$#^e}8KI-(&@U41RlbI_w6vTibTsA6xn*kH#vP7B$}6_?lJety&dOAX z;_BMk3|SVJ0zl$Ukk+cfs9J{9XS}IlJxjkePbcY8k8zsMu^v<^Ox#9Bq!MU3#)Pwq zCdJvmz6oC^)Tk$_a}0<^w#_dzFnW`f^^G?nVX9F>)f(*Haqt>&N#0ZxKnOn%Y?dOP zcpxJo)hd4QFEsOZ+&fp5@AjJXYhaSktmDmb9(2);X5Fz}3VUwcLUvZ|x(#3aEWlLS zOeo*frGNYeu|6q<#K6}SfE>^r*2jKWUuV3l^C=lIpYe2>lHn%DRnYNQ>g+eaP9@4o zwbJv7iZb?_8`(!SBNbOy6v0<(U{a_giCMLYX7WZG<>6MRbSKhtT#yiEC3Ui0Af{Gl zr<~sT8`0%{(n9f;*b&Q+775_l^tPX8*Y%--Vkn%581qa4py}jmmfbVq0sqWaFLQ&g zETEgGn-FtUJ$!<yy8+3jDe24aWuJzK+xIf%yGtcZALI9GI(?WF6p-Q_brmdGgbp>e zOS$j}i>a(OfdG|IE$SL8lPg`DyzPW&X_Y2T88+?N=OLQXq{dQxUB$N>&cI3c(O&}x z2`3&?Gfvd+<w>_(spkx{es{h{!#s*cxEUjBKH;`Y<wl%^OZBb|xM4+&SuI&q4a82~ zHz`FZ@$>#_(-7v~p~BO>CNafx@QQCVv*+onYocGvPBJ+av^w)JLqRAr4`bSta378% zB`)ybpGx@iC<IIPj!B46SPhL=c9E&F4kB!_|H^+@9Gd|8M2rzsA7@7JIkHwgKzlyV zYu2p*k@7!mJzPX~*7X$89uqVI^sqjSVUL|@e`8RU{+{nth@7=#KA7vlzLJKL65gop z`|$HbNxH+e2^VbYk18f#aGlu+Un@~#2j2$Y<fFiXzQOTQlb$|qwOHg^0`RPS|Hs_n z_AK}IvxnPNO+v$G&*o~gYm@!?DQ-KVvwU}f%JOZ?l8wAPk&dSa?}L?QAxfXC#)=Ig zX7xVp*&_L5c{^8w)HUCh$wqy!C((pQ=U}Pb!Tw{MyP=!GnU6c)nGeIUfI%nNFWD`* z`Q#%9rQz;rO2={Q=rZdWzv1(tuRJmqeP4+(_Erxv)32p1s3PqnEm%N^A)k098<OH7 z|DPYUF*>&vhx3Oq)kr=Lpx%<IGDDU>5C9-DH_%#x2l{@WKMufh+FB}TQ;_?E_j)Ga z-6txeO16h1WK@UXcq`kw4BO~%Py4B)qCzAkM6u~?F>q~*VbJ|6Z3$J>(+}XCEO)j! zz$k^?wFr^4uzh2$gyJWwiTb9DnHj}ppRQ7XNAd7d+A+d6SXdt}Fqx)kiWOh&7NXTl zULo*o$xMtkidrHPJ4#7HG|&!RQ3#LG&gM)3BTX)yj)oDFMZEFC3qv1Ya2&~cb&X~; z!Sv!5D1wLk0-+r364@&jNzD=VzYzQM?GMSIcT{IJ${}7Uv~XCBctGID-MsfS3|W&3 zlXPAa^O$vCuiR*W7Mr2rTcv4LC8ZoA8-dSOJed6np?8u35ZjH|;Oed{%Z^*_E%eNY z-qKJ<dInWgk=Vt!^k^Bx`$Fl#<z{zxA2uuaGO>&T(w>)_9Xe<UIgB_R3KAd?R$97p zs>}>o^#%KRMpCIrO~oK^9GDOq8>8M&;e9@q5@=Zl3-Beej?XF;HtSztb@>pJ>6^!} z6vt%Tl2pZPpi*S%j*{fC7}(SEH6c-hq`Ly|es^B0(HXUCRU-;!^JTHA9!5E%0hfL& zjpU+Yn?Irn(w6U;p|%Mm3QP-Y22#!Y52<~?C<2n#+MOm^h=Z;};y$6G#VX5*WkQO6 z9uvpx&u-wFKcAscVNP3q-B1z5McU=DBF{Zc3m($LPv7r<evOfGmg^+3;$tR#_ZaR* zR-7XuCivb|-dcC|5P^#B!}Uw#A=pUug^29vn9k;}&=tL2?KlGD#G?UGe^TY5O--HA z1nEZ9EeipQ&gKs>5Xivr1vwpX5&rMq-?w*uI<VHnP*SHXC!;tSFE6~I&kLe~f2WZB z>$ctHi^}Ws@RB1rbT=>C@s$=woLIbm9<e8=%XeM*#ICsVmCAeL+1?!dI8wjsyCgbi zusH!5mw7BF*JvWYQlOTkd&ipEXxJq0o|R<-m10e&%)cGg6fiXFOl?^?ceUT2RuV9L zet3K&qw?lqoe4^(Wa>U)ZLm%}D8K)CY3tqPVPnKc1P*J;s&+aOkVk1e43A&9NUT1+ z8-dI>5yn?vqKxO~`kaD5{2eRyma9$ronR_AX8GyqC=v#;`nRmhMfieA*@W%(W%cQa zaun4}D^;4DO#jmb{`O8m81|Owa&T_WP4<A!mqs&RNy@PXH@&N38CwtXr7<Jhqi4E~ z^Kj!g-Fyi-X(a61r`qxy9H!3uP{jA<hJAM0jZAm<91_OiTH6dmUX!&DfkB<^1SDS> zG3q=f@R6%!&(0DxLp67a-AYy1SC<dzoclyOHv_Xx(HMjlPEM)!>0LqhIyI)41HODK z*N0g@Kg#wa#{zQEt?6;_Id{W`Bsx;0R8VE02Y){c3rm#yC+FT{SzLJJ{bd@jHM_ey znLcr|#vi3gz`nYmPu|y6xajD{A1tiJ=x7+&jAj}lsz5L-8q|so`62H3MI8~KGQ!)T z`Z~p<vR{^}3XJAs`fg}smHByb!ka17!2C=&3W*G}t6uRhxBlI)C<gwICiDhPIwF&S zCbz2;cWy`g+paVWr4(_y&Sy)-qYC|KmABzVNEg=$?cPkr{pl0fOX4054{nlgwulme zGudKnfb|fq0*OA3*1)J1`HNHRBUP;3Kb_LYEJD@j;m*4TMu|Vwk4GF}S%CE4w|`43 z;7LXOD*K+U&?Kk@1N?Tuy8KY4+FaLl_R_-7!JRHSSdI&Ec9?KQiyNV}wl3ayr@Z-{ zQqdoDvs}V}PfywtGzhoN2GGU~5tbE?knjJQ(0&^9j`zWKFIgk6wZh^e%bK6tKHh~f zy!c=Z<)F1s8rg~wD55<z4;*7%k5hXi1{cHp1^7QKMGB~;xIWS0;{u+>cVE5mKUnX? zhezS<HzDJmOPMp7(lm@@!w0&kD!;xwPj|F#`+}CS1Y^!66SoevHU=9`KN2pBb^<2T zICS|%u+#h|h)A=PcQ#gAuVU&w*<j!PoMI`@54b-2a)M?(s$FYLp;4*B(3AuW2*J*K zd43>eV3-e4w>3Pgg%4qnoF%YwzA00e=qO0fuB)q?s<&`=S9Z4V$MIr!)u{eWbiqnU zer3JZ#=+a*5RHWn)Q@K<-_MrSD&EQinl$4$e)Sg<7dLvkLo^;82{w!`;(m^pouaKZ zGKy*{w5f60rnE$;kBdXE6_OtESo)TfmKNsc`#4m@u!gp6Tc8S9D9(=TpMbJ-y-#As z)zSnX4ovz6282b&qH&xweuB@N2vPXDzif)^?Cl}V8rOz%h{r4@c|ndsudg|a<aIR+ zEyf?aI+Pq@oF-D)BsocW)}1kQ8iZGx>|$f57b*%XP4G&dRaO=n4rgmg`BppvK7RO+ zU{OfCTvUu-Eq)BL5CxUnfU5THry~7SixkAa+g7ZQO-}IaN1#QklcorGGcH(Eb4`i` zf7~i<Q%&Nh`)=O5zT9|R<I|7y3F}kJe!fjI;{iFOb1)w?;$6ru8;->gCvRm|r{HIq zx`>{dnkpqLU&`g)nL;ypG=PGii+}iV%QGC|G(1yysaMG|>8NFy;%U(Cdb$Nrw1cuk z`L`eB-Wn~cYr($C^LXs9L3Xq&f|5>GTjOhkA3~pVwHADb<IINEn#TFJk6;AEY_$Zu zZ<#Y(2-cma`TxUeBKeL1RjQ|XGvlbZ7pU{$EeFS?q=$4@1WO~=*l5*b^yMCSr%qL( z^Oq$8J!bI-V%}dDS=)@3c#a0&ZW?rxqoAy<lJOhfxtCl+0r-267pt-Zh3NYm@q~Z} zR-$hm%NpCWFaW{>y*X%AF;I#olWX!!(xK!-C4f|Q(w?v%S^mf7=D5gyx$jUiPDCF) zNtPRXsiTzpNNH}L7w1e}qbiHpNpe__&+f`&R}}5gWwmQ)r7>B$3$^_xuS#i<O1}`V z-{@3p{>B!~&{!^G@n-!pe4((awuPNyBsC3ihUd6Jbv#Wsn(>VD0~t;Fd~T)_Ull~| zj{LB>(BrQ483MwKmcPPg=uK-}T5Pim-fUyB!2hqfI-lbjM{<gi^_iRhne$Bw20d)1 z&xNI{UoiJIH<!eoQBwE1l8XRjcvbB#ua6ajY~0rsC}8zs{=ruyLJCNYXzTMvpwD|e zM>W1rG$!EM8Y`e8!7>%hc<t>{g~(+_%XwW$IL{CYR=FiT_XWk5kNX&^X7xyVd@Y!C z{}z_x!d&-O&Htxh{CaW_hmUrb$NqGS&3AN}aWD9<AgdDp=gM~>lC{Qwn*#B`KQDg6 zA>n9m3y_jlQRcFa!D5fHAs;_W<!r~TL#mf0&CLHJ+oDXF1Kv?b|LA$#bSh;N{~h1H z4UVnYKfI--1$<g6+=r#9?^>ujQ4N<wfA>HFGqnbJB3wGwNMi+eJ$3;UOB@e|i?jQi zF$PkfJg@e)3zH28WM91vtHLvHO*Q)^iTy+B#m6o$>8iKDkk_}KD_jffZ*>|cem#Oa zqXdCNO1goNqWaZSzVpBkXSEO83a88N1C`C|5$X0F>+zMh@Vhx%>B$CuaPDi5s3#lo z;MNUJHd#(Aime%0rr&|s8DQI<vdXLGZlQ05;c7cD{C89NC1n-AL{SC)l(x(CNup4! zfKyNf`>rNmQB^4wOEeoqi|r3+@=E<*wv8seO5PmAg)_14#;GnFTlm4m#jX6gU3vX- z`EW}dz&6RRYHNLy#){q4Z8n;;-MXJOh`mkuMR(%C3r<nMm6|ajMjd3}oVe(B6d-xT zV*PY?ad#!)-+M`cd_2!{zw;S~``lE|zxT$H!61a-F|zBB*PxyF5xjkOEZ`0*pDnau zT77J87r$mV+=GO)LiP@t$FFkJAJ3j2^HYS}!-gFIuM}Uua&GUX`)gK5YVNeQT#nFP zq$1=owrx?Kl$Yq%S4^xGK6n55aWz?v87kf4<S7ku_1lh|_BfCAA9il-nKf{%PdeCW zXM_L1y~K}y)H(=NAn1UszxUWX9F*7g6;xyAuw7JA)EAJJu?dF06nss6&%ogg(#ef} z>_`zgJz$)wE>3!y7gD!e7O8x7$3q(6P3fIQX~iIhB7dNCd@-5Dtd8@BpPB1fkkH0G zRRn=&6(E0!qXFVc{_m$5G%v?pi$D+$OJYKTHgPm>rfF0g!dEut*_o{7dz@6zgMlel zLi#&%&M`lG&AUvj1`t?3NucvM=)ywW@>0fli$(Tn2HRu5e-%-?u-(&#Vr}}<5`9mI zIui0Iv#F9$K@mAm4?(F(`hr^{@k&&a-Q@9dqTp`NLg}dcrJ7bjsj%Dq_0c+_ui}wa z$KyeVt$;Ta*~w$sd0xXz2CKp((1t%r&d0nza@8s8Hc9i7Oxf_=Fk`7BqC=DBB6x_7 z89sJdVMmFJj*1|;USs)tn0*?eC|FIi_fer2^iV+^4ZKK701h-bPZCA>0vD!Q4_w%3 z$evXs%)@$qjj7k2Du=%dFD@`eflvUMeY4bR8axh>d~SEeJYQ&Qyw)V-(pj*vBltzb zU!O|d1Zf{EX$*YL?U$kp_KaFKujMd^WRe#GJKZKezIUGVkzTB>qm6*(a1giVDCz0Z zP$S3stUBW&5X9l^mm`DHX=xa_vdqQIZmuS8l22-rOmdK(uV23xy^pCchwZd(ZDBcX zEgBI>OlfRfJ<*8_M~JbQ(XLpga7N-dubli6ZvLG**`iA4fv?@&#zi_@q7hO1z&f|d zL_dAGkiCb=Zb9%E#pSo{e>mTv2=7SzHAx>Jr*<8eV}=a`k7Z#O=VY&a7}2lA>wL{% z7;Z3ssg)gIeGJicN1w6KRd$=Sm_$fZgbuW1ol&#pH)IR?=)QVyA(wesS$afFz<~cd zua?D|(Ef2dGlls=x8r;j|7*3Jfg4$$Y^2akoUU>IB}L0_6W{so$Nbp1487`=q)L^G z!{Y4ijaRRc9jf9c@v{k$KCz%MP!i_dsXW)vK%QkZx7aC48_VH5$e@?d|3QfT62oCC zw^mBt+Nh_YTDP9y;okg-dx>B#S{Xab0a{%Jg^CqO@Y|?%tCssC(+e2Wwi0u$ufJKu z_R3?aWN+m$8XB1<3SdP49a%I00|<$8yn%+R7CX#}5wW|!E&)%lR+e53d^BuXqB5mN z%}w1Bln!^dI*Sm?DCoUaWZDqPh)E6Nd?^UaySnWsh5=6F&vz%Y(SL|5){F4-RreVO z1T{%GJD~M(hAn<9PNZ!@xpa-1rSG%ZCS6Ww<bUQxP@U!Eys6M>{V-ds$VrT{<_F$* zp*5<`BfyXEc<nmhdX2cFYVyqUxGF_Q75{C{wj9@g#e5WoKi#Sy24J>ZZ<xO6AVlMf z>K?1@^cXD#7|r*laJeV3RSp<!6&6#}fvSI-L<>dUBV%pC0Tf~8El-F;OUy|vDL*7L z>4&^0_L=jrw+1oJlEHd`J6T#DtT8J~SJvM&jN6jAB}izsn+H~aIq!YUJYMgsghI#Z zSLamQwJgOl77u@196@yrlF#kT>Bn^&1||ptrKII!_FXxuuvqj)1KxeWWnEkaRp0Hg z3}Cb_!_2+Rvy_K>y4ihCq|@ANS^@t`klvoA=QUU$$4fnw-m3NH`b+*lE9=q;nw;1Q zXX@_5waC~sHr4$T`#)V#sXt;sB?}&&AoD`_z`GV4M19PV$n>VPWOc$UJg&JvUm`v> zg6j9^6Oyl(FG5JyxjIyABW5KG{79P|HmoA(Xt8Fn%^xo?90=3O#7}aWW;H6d<`eXI zC1{>Sy(<D{m!a{NT}XJjfrUk?7eqNfv|V2S<mO71%Hg5)``d%5Qv_Antm8zZqJ^IV z*r^r>i$)d^HGFFV$JE5+tyUX$BVxKAv&c#Wvjtb8<F<9WxY^>i;G`AgHCJGwN1Izc z2d(0C-&Js&Z<BkHm!FRNR!&J+wPJMrpw#+Ni8L}v(}7oa2ZJ&w?N7`X#BfTZ2)VB< zUbIA;p;eOMd$kDANP)n03I2HzPz#zZV4bNwN^z-5bCFA9S8Ofywp@cNmIldpQUwli zKSE9e@%^1?fPHt{R6ZJ21{Na(r%dfwM{E6cSAxre>5}kd0y1-a-l$)c-EtF>Sw`8m zsPZs`1eT-qj(OEJ`MOc~_62}pk1nb-NVkN)<ezmmuj5tF@aEK91S943?PTqZz6W62 ze4+v39PWcs(ni>($SQG{;W-AbUE!#)HWMfZ%abuQCYH0f?3geyW1g~=T;Jd#UREH8 zQZ1RB7DoR}vdgCa!9C49v0f|LXWK4cS|qrjI;x?5>iQvMW1}H@Jw^O~hQ}nMg^_Fd z5<Z>%^4!wjp#=1o+))XVA}R{p8~U98mMkLkovieQbEq+C)IDfVs{Zj{(5@Rmd=uA& zdN|5_n>Nlz`_j5!4cXdO6zn~1UJuAv)wfKa{wxx#9(K2ndwn*G8yy~;Fzvt}4b1}4 z<NI*t8ot74aXY}zrN_9>II3*;CjaEbEd`Ev;(|Nb@R)>N-)(Jg1Bh_x`bEz}LNYX} zKIw)nYR_GrQ4#z95L)-+<8?obdh1Phv11awHOe%w6+S7{Z`gMnSro5uL`S5@IAD&b zx~JexPS6n4q<Jw(v-Nquc93XLz`qsw^%+FA)kv|ZKbKKnDgKzrVH4%S-6qqg>J$=X z7dji1^+VIZi-<VN6B~8SpDRsPs`@(O_U_9V-`#O11hKr6vJbTEy0MvRk=1u=m)^In zAj@Ol7tX{Ve5l&ZVN=YB2{t{&!i$sX7g{!4;gr7HnN?)gekWw;cY#~gb*WNXWP=%| z3vL0~8qd0^6?`oV2vl`oPqV*YbM3MDFyMOwXW+jrKaBV}I4ZLcJb2OQfjCoe^|*D# z<n(CQ4CG*VYt~NJ-`>pD4cYKUetiP@*SNdKF8=r$*{QglquU<5e2ypWi;`H#NsamX zbfM@jlTxpE{^zZ`iR5P%op4ZoU7ZTxm7ff@i2ez3L3OcbGifyRM|J0ZSX9T0GKoQ- zWOKET?dz!r6k#19%h-x=%I6Z7;d}S!>)*eqDD>OILi~Sg0SvS_WpAfiWP?-=7;K&n z$WTQ($*sN)%pvSj>?+{YY0t){PQ&MKc)fRs^h0r9b1k<mqmyXAU8ZEVxwUm38yowT z#GvbRGp}hRtI)K#P8&<TUOpJ%sVI_I*=N-ooc@(Zw+ZJ$F*>WWw%D3@!0(c=NIo-Q zQt%#uOV1td(#@7-*TCaKeP@3+)ww-s?}y>PWq1FT?4|nj-DIXQ7>WDg<}eCX@I}Ur ze%JV6jOQ|rZzhC$^}0E{#H?pWI|KtTVsMePnfY*i7F0;L@TDF>lu{urs=OM<>;uBt z*M}Lty=^9Ds}X|hqiJdWhifkT)HSmXsN^cyG^2pFn@r-?DMU!}szqy?W1xL?#;p9j z<%HD+#HlS3c$2)iMHs;>K6-dY!eRa{Oqs@AvTKk!&yzDy%IC65JGG9@5?PR#OC5(i zC%j=Zb8h^W?9~&db{fF#`o-}2Y)RcX<$Vf^6?aXD0H#)*F=5xe8(t6!(I3_jZU*^u zL6C>`B_`)+I}`Z$9gAP1j3uLiyY)E~eMM603N+5kP*T;=5XdbdJz0@f6(?!HCH?&U zV5R->v&p$V#IZVED&r>p@iqbHQkPr~<TaMUgGx5Z^PF=#e{i+OM{GP?$8j)QUVgFq ziI~{J&CFNO9!RN>#o&{^?O^Oto5#!-gtO#{MZ5le4o8!Q?_pIsP?UB;W&2Bm&H5Q@ zFt4U_A>L0|>&}ysp_1H!Tlt%&PekN=1o5UIgM7V;6@wp;;)+2t(Pa@OkgPgzwH4gh zdPma!sW~g*8(pwzj&@16TgY7zx=4kD8{UYk)Hkvp&YJ5T^`A_z><7P@zoh7>_)naD zrP}di7&PDf+|nk=@AqoOvM|0Hrn)?QHt`wvvfUMlyDRRS*-|_6Wv?p^&UUoGCaERh z*t@xaNyEBYL)7Du{C+$DE_e33bwpMjK$;;x1`ix?=?qG*XT|o-(hb4q6We|uwVUcZ zg|yGPgZ6p;9jNyPkw6|+!%<mFE#$bm{p0J)q{+Zr1t|~uGyij=>yxFoG&IA;^-JzU z_T%s=@SNm_-dBQag<A?=t(-62FgGgz`&+s1!CVvy_=0NuYXRG5LK}hc57&|}6AT__ zsl`*3x|+`ZQ#5bI(5|2b*Q;<T`Y9+4yHAR!ua@0&2wtBjg;=&K*v2U%);qm(U5_<d zPDX6TCGz^wn{1#l6ZEfTgmqk|+l872*ousYTC|&$bH`ILzl*(=J6~VA!|%vG`2&=r zi?r+aNuV7?&~%yA3h>BWs__#DLJ@kaD0K5~xk(-}cjKD3?#;nq&>_`@Om3^=eZhzk zRh;buTUt8og{<H1#^F{#M^T_QY2bT)GOM_yaG_A(Y?;0;!M`&!0F?f0Ts)mX>PtyQ zmFjG0sKH(*&i}@Wc4#9gR}>zPG;BF1FE20PK2yno=SYB$lT(9J^B#YC`k;B^b45U% zPL~Vd<rzHaxMJsjzG%R{qi$<UFu}j=Gh2lep+Lxvz@XD7TT)R;sVM$MzfbV?T2&E9 znj1KL?5yH&5jCqPGNk`Kph`f_U`>@Y`Ld_-`PjVr<t=<VvlegBm1EV#(KDob?dO?* zm(l2+EkN&Cb-|{_D&MfXYiM$Eu-VvQPK_FWe5|$xO|@8_ZC}^feJhkIyNB4mvtRER zG~V4ld@cxCbr$nkAadxuB5HFvH5L;ZVI(1!vUR|;OiUmZDIT1vHIY=+%#L5RTVeLP z#@}lzDM8rX1!5tgU@9sYS;i+>U&@Zsn&z9LEr&7>WrpoE7fbt_tnoHu$7(x>h3rEi z-3a{j-JuCPruCeN3_3#+&1mlGS@HiJF#50G8Q<RF5r;dgyj6izX`f?M^Nv&afLcPK zC2iSIC<@Ik(L3<_DGH7CmI4N|{pJy<2t?yJp6A9(R0rLp>=VCzaeCx)|IOOLwx_xc zt>~~k-E>JYaX)wH%xt!-cb_j<V>v8ylDMXnwX>+opL|=;>XE_Y`bXM4c;e;RTU_fB zu}immIzm?e1S|Z)vcHT2=W1AUK;Zg%NfyefIRboyqF!;NWvv((<LDwvO#4ST>W(Yk z@VV{bqB849L^AgVXGB2J90*9~y^q9xRw61^k4@R~>0iYHu5n?X)4$vw-Av)!9Q__B znhpAxAV}LUP?w!r9@L<MJ^4Tr=Vm^U6|5*o94!DuFT;4l!R)kBLQol7ZRbS`l{pRh zvBkO_xEDE1EE1?~Hq+&oaFuMR*w?TW9w^=t%2fpmm7uM-?g1#e#9L7Cmf@y_-fbO+ zvYjtsZ}-D_eoxK6?G{}n^yf2!-y3FAA`>ax?eWUSiDrijy&$KuNXNOl%`GYEn`5A+ z7qKcm2N*?H4Yypxi-k1x;uND(@TbVP!B<BT{j~9SM?Jec?(Q3%c5{{$Ck&2nNXgDw zXOc*(^ekLd?|9Dx>{v?E)Bx8rbdT*|Cu!g@i7np_uf;ifd9hWLFGouX8AhT~R!bVh zdPFbjN9wCE8crAzwSRa`>Bh*d8$D^n<*9od$5q#|B$=?r54AjeO61XHaoBaUT<LGO zQKB}mU)cM!)#aY_<st}{9WW_9Kp3Msf29uzn9KCEe+j{`I}L8Q6Fp*Qm-B6#<Hn{2 zmXhl0jzl-o!1q0DivaHB3_IY&ch#wvRDY`6SFEai8yu_>c^%+LNz?q<9#lkHwDh~3 z4gaLv?ayW%r9*^mxLN-rv%e^5)`JJGh8^wobz^w}?C8R2Uu!i(|KaEN=UbZT<otO7 zmhq;MH7GZ~eg4ClE=4SnOnU?PuJ`q#|3JvGW)Y{X*18}4X}|V0ZA$6L3?waibvkZU zTVaYS5yd~KSE58tO^s0ef#6HkJY8MU+}tPUIVMc?48J{|%XKEw-{gmTj5cI7;H%?q z-Jj_WU2s$ou*1kfa+844vVeQv;iBpu6v^2%4k#(HG#M#yAoqzUQ<&avTGd1R-H40N zHS(B_AX8VDfuesTARz!zQ&UT6y2)gu72*1J(yy**VBaTnRH}95+X+78p7X1BJ?5m> z>6mMXt>-|c<yXFlUQkw!wdXus&wt+rIkOl!TDcw5uIINaBP?)xvzK#fT_@?hxlKpE zig>tQXyfj4efVzm#oxc@M<8;)?l@Nc^yvV8)nFsYAQAwjIDowSKVJ1AJLDuT?z0yb zkjqMy8{00{{Pqx0LFFusdw=rT_*hLYi&xc_w|$Iz{%sUxBTuI9Edtp~?bYnlgg!4> zy$RP&Y7OMQkZx`+=}=PR)2TdY9@(F>LF1&}M3RWt{nYNA)N+;=NI}6mG9seM7}+T+ zy6lLylft;*6z6KwV&GBHYFgp?WO{8(yOYOmwMBU#hAMZL&|BEll<k7xCUy~rkZF!q zZbsf)m(u}ldMdJRV5W<Fw9SGEg_jY(iM*6h=G1TD%zX5~OUF4r{X5bqySNl}D-WB+ z_RAx2&;M%gJENjnmPQd#5kv$eNE9R~NpcP%NwR_>89|aTfTSS}h)7N<NREO8Ns@*z zB#B4TkkbHzq#+F>ISdSMd+&G7JqJABz3<0c>%H|pf4DZYdv|wLSL*7j>W_-yZ6hBn zTDAP@j!DT4)`+gqiL~CrD+48m9i2KV`srNDB;02xC=U&dY8Q@AkLE~cimXl`BpZxq zi4YI(W3Lq6Bo6!HJnThL#(A#}{u^ESWoj$1+_-qY|MI39yrrBkO34Jr3wWWJ%2B-c zg58(f-+r;0Qd*lXN4)tqk!Jc@cGC66M8&&QTXW9-FAra6UyhZ<+1apRoePT#giY($ zo;!|3gt9O`YUyk_@x7V|(qWT&$||BVRt74g<9u{Q%&-b&(f3Wdbv0scr=8ZZLV71I z%fw)om3ze6)R&9V%j)B!i1Q~tGn%2Ij1D>dyyZMfsgm><KM4~l26T(g?8CfD8jbC8 z<5v0Aa+l}US|K#bVf`XJmvhqwkZ+nEo%i>mkjU2)1xjx)S~RBJ!B1`XSpQV@E-jAR z#4G8U+WJ*~C6MBWHz6ydFyfK$yw9cGhLJ?bc-Ny&`8K8dm(n9riV%w1+YGzm{g?*j zbdj`hA#Q`+Ao{g#1e?VRmf{e*A6PnGrRUie++~m@u>iJpSe&EEai+y)Joc-(wyXDp z0TH17Ouu6>ZD6j6hfajMFb#H?RXq`?9M7WpnOt<XVAP6^RB@%|Q=UDkL+$P({?4{! zx4{k47zR78QHQ(og_mQj%qO}p*rX@2uYchBVzzPTO&~!SY=elk$|00&_ReIEPvWSk z&f-VMlBluRnDAk{h8TtyJtWqKi`vR0sMs4UneDXb4y3F>sM1_nPdRsQ|LS96ip<`% zNuoMmU)o}c@~n`AUFO@G?pLGiqhIoIw}M$F4yIsgZ-pU(7qb;IRGZt6y~la8fi$3n zCK+zZTLas6UN>3B_}PVt9m2k*&TcI2_ly~82Tg1Bw2j~H>C18x6QR_d86Li14la<_ z+K{7|P`UCt^H6<=N#{$5#Wj}9;UV<fO1WXW%KEq1N18;n1XjByQ~g?L{!hMYT>FS- zyeGgIlWkH>I8ztHP}-OtHB4&NJsmi2fTChOX21AgNi<apl*Wjth-%gwb^m$;&Mnt5 z1EKk`?PG*syK4KAnFad!t0dPZ8J|Nn^@sJ2sTQ5Ph1Pb7x!e}$6N(9?oC=r{F1Io* zKnR|?eL?`C>Rn9_3q(@R<m)3|eX5};FTQqbAgk|=z_l%r_?fMpHkzBsJMEy7_Ve*p zAGJ^bdwOV|b{sU)oZHDZ<VkyC5Qdt?p5XMZ$hci2Cy&{fEZ53%0lalCWmkK{Zq!}+ zjIm@VNT_2vP&FyZ-U$!MO#>p>hq~-0hCEM--tW!oXfl{!Dj#EC+|G;@ahxz)$&38j zAUlyYtrFY!v?oc?!~T-{+GQRJX~_6n)fdG5y0@o;g)4M{gn4PpNsfB2y?2oyORKrq zupIk=moEg|$;4M^c3kpw*-gxK35Hr_=^v95adCBRaAxfkPO%!)ZEj-*iM4uDLubA` zrC>Bc-b;nnPwdrhuOp!1uD_XWFUt~^TdPxHl=TzDErKqW=PU%LzZBuEoslAAbi1Eh z$UXRGqWg0gG;HS1m3)wZ)7J}8xlEYd$J(xP_WEk^y`mlHvacXqb6d_+ecM1O<<#yP zZ(ktBo@VTXm7?K_2EAkw%y<Vc`$7E@r=cAeaa@mC67+K8^ejI|#fV^3Y8IcC_{syD zp3XMF4@_nY66h~6l^qP)(~IYwN<rBo-J{1;yY>&n*~d6H7>nixO2>pX)ie~1e26cP zR_fbxHw2ol`&OhCAu{g+>D1GgbaK_nqwh~`?2OL+*!MdDg{2G2A2FnQQyp$ETSx(J z-9m@sDW1)gUpNMtoz#h5t##RyFd92`MPfHL#vEG%G#dzooLRF+4Jg(N-c<|Mth^^% z>TBRxhs@vb+1!<%blM5LRHRlGV(;rcWx0Qtd^<th@$%;|HAS)Vt|R`2{5l^y`h)K6 z=SCtc_Ag^rtFJ)QoP;hOmkB37G-$X)9p&ndUXq4980|BNkC0GyzpQ9cM+ok8$9z3% z<BGszSCP8<IBZODE;8MF#4N>a!fdXmqqpm-06RMoc-o6(no*FdMv_?Z?)BGbPsOKf z^5i@3vlfKuCqe{+S)`=Y>k#VT_3#YK@lH3T>TKB1uCDIf&^c-T*$8HH-S7<>A$wVB zV<+ekX<PhUZk9?N#|Lf$hxT0g_naG@E@;YI3%&#<UVCb-9ZIx&-O%;Ss5nKREiohS z1x_F7XGHC4oJEjk^s1vZO+YZMm~P)dy$*Y?80eaWwYbvVE_t*XEO1I$C*ESdiQQ_g z;ZT=Pi%tYJn_R=y-)QO>z0nID<P~J7ns#Mtpq14hdG^7B@s8;CxuNRJ(p9d{yB}S! zBGum~n3o0=Bh8~c9;|}VljlTD{cg(~`>@0n^(uL&;6cO0RAXeUz3&vfoXCiAI{a~u zrS8Qtf7~18H<=JGa;skBsPm6B6&3H4NlfZ$n?wedhcg#@(0?DqJwoN}YF2&c(VjR` zm%2mZ=1wj#Nt)q@ic0|7QPl1CfM>s1bL8;6gZpgAXR}b{ZyC?!RDbm5o~BQW!Z9dt zay-c4a=|}z1CAU;M`w=qo}82H;)hn_TRipvVzhJ%w>mK}mI~WjMy~5u^fQ$5JmucV zrMcocI>x7lIbLUO)FQs+(eFM5_<pZsmr#WgvExyW>SGLg38V*ODJ)ABJ3%$V1f*)e zRkvusvKiasX9m;!J%)SKY5Sh&MwBZmXn52UIwEP`i24W>J{z{OM?@BxQdx98=<Su^ z$#Kz+4e(}t*33jZ7y5Gbi@74R$+49VXzr298&FN?GY{PR=SBjY49{4K2i}4iOQVI# ztilRQ?{YIehHb&^yk1lcqV5Xi-Cl=%loT)s`d<7^oD+V#<wPWu3#b#Z;`Nz0*S4%2 zbHFvguX;G3?X+_^a8K~eNi(0E95UVY{<|EVOR29<j!=#JgXy^E#j*$U7UOsyp7*M? zvVZ5wS5c5=Ta~N^59moltY3(Qrna-?^gBcAh$M8YGeOlcUVc!B@KA*c_vGX3Iv0?l zgx4SuI3-@edM?<Lv{+Av&(#FW@3?M{iZTtUD`%AAz(j&HpCOT*_EjD(S4l|ZA3V#y zOuAtF2&8(?KWdDv38}UA!VOb5ZP|#K@B~jq$HqRd+n?0g|Irftqv`yf=jTeh(Q}3_ zA~!IyNe9DvrgPha!QR!&2D;%z-5ai1uQ?zlLnCHSXw<0qVqG|H-`{yX?_o<$7F}3E z**7NOWk2~;lzli!#BQ_$f~*@;3o09UKH4Y4WV7aYIPRCB8S!Z$f<{Bj=v#3?*wmdi zO;@J@?H3=OmOX!miYv;3CqR<w(z$pFlS8B|Hiu-kLpO)KY;A2lP(^zDhehBYzqOEh z-LZTQr7lqvuU;1&O{#NbS8u(Ydu97g!`Air%cos7Z<{VFX6*7Dj3vb!2UIt7?@~UD z^6DICFLnoqshLJ%i@&FB$FMqh2DIMlJ`YAlG$Lz8DK1S)(?R?-KWH238F|S7cREJm zZ!l(Omgr7qeM}fzQVIPqJsBcek>+{3M3}as%O-$>spkIXZt~b1)OhPXPdg#yLY`Qz zTJF`^XPl-JydowRLc5+36?7B~mhE}pt6b?v`ewFo%`%d8<Z)yYY|v&g7Z9<{$9gfU zK6qhSJFt0p$#>^@wu!rd;D9=zAjL=3W-VdLtN`aeUxP~3SO&GPN^)6qE*vCm?!6&{ zZ-<!&hxo3O#pe7xFdEcGYzxhqcx;#N-H4XqnVsu_?0IMeMe}uiRP>=&N|kLUjCV~X zB35gax%F~Qku_^h?fTy69gl%|tIYPiuesYT^P1?^F>15f*wNJ-cb<>W)BGBaMfbDT z!osOA+7e)mUH$&7uvfE|^eq=rsvg-af*d=G*Kbe9x=IU8d!`U(PktN0OqJ6aut9}j z-`&3netfq08vi_-ueTKb4rgX#bE{j0_ga6M-RdG;$@O?RqP556?OKkiphm%EIIa66 z#4|m8N{|d<N-WAkiAuv5gk>D!AU2G1)oxE-hBAQR?i)6gO#aD1RL|^i4r_N@BDDE4 zHQrsLc-=}RfLW@2t2+@#8zNLUEPg!rh5a_UBwOnkShDls!+O%9j{$EvcP1)Bm9rq; z{B~Y%$+Ro&O{!uvFFaQB8zrIC1Hb*^z+9PAd+1VZEK(72wQcg#iyw9o^Q|g^8eCt> z%ZEQnp|YPW!M26=yBu>BV+Bo2mH4}~1ErIA856?3nzn|a(%M-v^063oM}%87`iR>| zx`G5h;Ji8maMPr4n<Bw%5nXN8X4oAC1){kLC=b^Tkx+Ipa0f(K^CC#`H=eNo`3+pw z6^dH{eUJ8YE8jEtJnA)kJIKwAw>8aV-u`~9E^!%t>#BfWZ+w*EDBGh>Q}7ezlmYR3 z@>k+ms`AJe9%HZ3_7U*3QfPNAlBw9<2*ukVs?@?c+L+&~o|wITnmdjL2#OmH@Aw>z zQ~!pjVGu-dw~o#=T!-J*Cx`l2*JmzELfNODSDH=R>*{u1y!znKVK}e<+-1tgcRU}r z+kH_`a=2MDL|MtUCYfK?n%tv5O^L>4fE%#2MpA2euUg`UU8bJvKGj~jowIvc0~!$) z09~Aa)|*meP8xc5mK+6fY#ifHqQz=P5*j9jII(dLd3KD7tUf{$+ZrncSo@pb@7FLB z%;g%?wg&>hbVeq4RaxmFy;K~HPwSR!Y(6u^6xyiPlUQ0kp9$mQrN(NV6G6?Jt)Wb3 zi$qPSF|zfo#9J~cFWYTr(Rq`%CLhAS)mC!xdu<yoA@rn~(IQglr^D`_<Qb;$;t~>U z2p%0D?zX4s4_>=Y<-fK=_bT(yeoYj5W8sOe5w}Un=vP@W@?r0kyW=~HD9^?c_;7K& zr_B5_@!xRTjn%dTTJ=xV9x)H(M6TWiO}HwAUt-ycP$6DCxOP6cINV{RfDHTCquN3( z-#T}zAL?lWnNPl2^sc!kZx4j#0;1unPa3>meku$O(nD0g6qGq}rk`d!roDKDo)y}Z zN+aSL;;BS#I0CXS7^UI+OLpl$GEFrJ@!kCRW!rPI_~u5gWv4yf*108FAymTaUMIK| z#bRIjjrQtVC5VHYTS4B>GQpnmWNDp|<hG@0GsrZGtZCVBYICJSPoSClMtGQqu30vd z@S`=#{x`JFx?|=sdkI3wC^fiYXtjdu9lS4mn52>iZTMF9=7e7shBRCwTeTgzKN5)& zEBk1h9%X@SAUo<Y)9k}Ov03bUG{Z%ezV@5KR^D)|jiMZLB?}E@Gp7Y8D<3F=oMNAR z)gqU&sGzuNXHF9uF(ErdPeXs5wf&PTm<(RSQ-D?m4q~z%fM;z@UR6JFk1s_*&()7O z-)S9)rUkhky-;@++%#b-vR)m7uF<1+GNZn2eD8z5V+CU;8jC&aLbSIBjcGrBe(7Fx z5H8jxb9s7hWasTNEk@)9`K&5H9$gVKdS6+D^2@~!vb087;Xf*(bcI*PZ`apwm}=D} zP9!svyBF%^j_eL>uNpt;h?!(*_OZWb?1C=H%myuaJTedwWHMc_mj&sVL#B4S1%>)Z z^-Z=)DY>~IM22laNzpdfNUSN5dDlAFTgKJiW=V2;TZzAx;X#?m8p0VX`9Svr70@wR zJ-G%F2(I*;_qj~T74&VgaTlXcop5!KpMzjR<09qY(#LN+X3%e<^o<{qO?B60tp<^U zAH9oUM^%%GWXHt~f@^OGTATO2{-B~7LB%H;m1_cqc$@4&pS$=@^5118nrqi;J)kyv z#Y^s`3L<#nHxA{Y?s~$#C&Y-H9G9cKmN9Kg|B^_Xmu{%F_ZD5{Wd2i;tRi@CT+h>< zNT*h>ic(DRdReeU)q-I~h%!o(VPiwt;#&H(fKUpK8|OkM1iG>LLS@DxgY{dx$v}Ni z$v9qp&Sy0eUTbE-D_NP|*w)2QbldK0W3~jm=!vSBA9l87y~YY=0_q~^se#0Nb$I%z zwMpzx3ZGi0`DeDk<-Zn7#ZdFwr6nbKX;TwZ@sj&LVl`-OV-`~oxfKfH;pw?eeS<8l zq&>3bv7Rw6-Io;+@uHJ;Ngv4#JNVJn7u%fApHANyqxHloCdm4w**<PlMI$N;MgzQ_ z8k9PJvX>7Jawyihmw;oOT>dTnac)CpeSS~p_*2&DBt>=TeZc#>umCvauK=;63Q9_b zuILHMmLQU^!+OTRkw%c&(wFZ*qz9#{n(EDqVtY<!H_oh1ugUTpJ;mGEbNR*(AGQQG z+%2GKAu`zx9Boiot*M9dEw1O=q{R&jBvp`1z02Z*CzUWE;)_tl76|CxT0hw(G4u<% zm5Wai!!IXrKv|b4tPNI|EI4j(S7^CLGSRsb7P_5A+g!oqNYx+}ZX?-iRLI;(hO6$# zv#glH%;hc6s>XdvF0I8tBPt*a!6ozSh*5}Pm$Xd!!kWbBrq1_h=K)`yxuEu$yPu6O zdGZd0$0Wat>MxFlIri-N%q!hT!&b*!AjNJ*!N>15r_qM~3DC@xA+AW@?O@P^quFHb z^}|?wUVoP7m-8u4#5@nx#rDvZ-UmW(pNc-__vjYe`yCkAm#r&epcknZ!-fkAK{Yo< zV9T{XA|AJ|an*F>p*=a!$~CLf47n>#uaD{IHli7-MmBeRYz(1(JgfD-(~v}@8i;|X z#QY{&txYzqA-g>2aMK}r^c0V<{s8i!C&hs~PdBKZaGPH7Bf+qpY}dD^t|_sSkX$AB zK8`YJ-M%3h8NUFKOGhJH?9+@!``&jwda~9pQpfO#QSi78spymxo_5^(^hRPWse|hc zhvtQZ4hFZX^@%H};6q8eKU}crli=}ktD9`X41RTUygKkG&#t&48n=y4)l2WWUatQ} z{A07LB+NQX)ddlhTLzffd6*9d9IUJgt)d|Hmn4{C`E)%KPmN}s$F!IMpp?(o7%geT zlISP~Vb;TU959CukB0|33dF4E6_=2WOpKoMOja7lZ8&n~>39o^R1&e39w6QD*@!n# zz5Fs2PYQ?m7v5?dxawJFY<}9kC9B#?j6Q_Y-mV=X<?t3$+@`4g<d<)gq{J>F8u`kL zd@?6QdsBO_JoJ)+9~V5CO9dm_?vu*i;q`3Ru<_IiP(DxyR7raD=sjD-vG&G~3bLu% zz2*fy<f{YXmFBp7Jxn7GZIY<0W#oc(t6mt9rF|Gx9KVo@rni0Z2)ovy7;J$C)7`b* zyk06ORs_U>&j4WqEhM72t1a*b8u0M}U;An-QM9f)<(+4(!sFLGS3HwL&-x--*?(*q zX#3t&!*)1Wu)pU!4yYs2w0BNNNMW)XoDi}NlDq7v=nWA#tj+|sx?hViZr_qO<)RVO zMXc}E1xk_(yTAvR)lj<WfiUB}nz-`fq@tQ0Y1zFR*z~&;7(&dbeWC$2oq6a2Z_ISg zDVj)jTkX$t2kYLiOz|nQi^=z<SzRi&SY=%Aml}05W^||w=oCLnv4>A|emb6_*Uc2U z4|C96EzQ9>7C2~=^uV!+(kU{ucd`!F#pyq%?A5nC+lN@Vx%_ZILO`AdPd-1ANO|dJ zda^FFJt>`b3*80dF*$vv*QBK=hYWU|i)P1wl_9w!b>(mw;w;|U>lQLJTxqTX8X<gG zhfh00hCMx1lR?&PhT1^j2%GL0HM{!57pmkkCq89s>bLK`FbLYnHb3NdRG-MSAhu<l zjaE|1$aH*kiGxz>sbL7Vc!GLG>c`O3OL&%|ynqP~Nj!Gb#QTws&RecD#~k(K@Ya!h z7X0y7vPa*eXN@htgz)c%_pwpMoBH0E#yW9B9gu;Mn8tu9%TG4QhI%r;!l$M96z$RX zm8`tEjqYCJtKY7>ELohQTbN0gAaszXIJLi)SQ(w-(mP(gS`6EO`^mfzoAQ|BNs#gs zXl8w0?}bd1wrjXt4>dm^?@ki#cvDsdTtITO_F|G0#9PzevG;IA>V7LW%FAw|6m&jG zv28Bj+Jp)&1G~n@JPO9}Qe(u3uTdjuw-$NjOQz39+*M6Xa~ru)y|RLwi5xZcH#NKN zKv5b?6r$T2o17e8rPS!3JumXK-ubcvZVI?J>TT3k-8+<dTe_w1iO2PK{FnFl8c#w? z8WU}rb9<7+hp%X-lTxya=R5q6C}G#Q3fjFw4VPcxM@ZJB_qSJ?6jam?YD$vm8F`W@ zH6A2&ms2{_?}%)#3{%{jtuz?jS0fAlRQatb_8Y~<21h!JZrw%Oft|ACeWPsSDG>p> zF`=w?qaNnw=5PD%Fa#<Fs)R(hF|hEe*$)#nHXc;b$k^w-$#M+$`*ygBL5*9dDbz@T zZ|B>R@7i6W3e)=}vW)(LuA*?-VAC7&ns9dO(m8#m2IM&aw+$oTM3*injqcZi516DR zI(~b3opzJfAE7<(wwh;(OK6C~b(5w|Yqjmqq|x>sJd7x0EBw9~{Y_HV6{JzmWN?tc zx-m$yf_lE=vb!@#X3=#@@^UcxpXcO5Mn;aWb`Jr`&-9{Yl@!B!FDae!g42T;>zFJQ zu9ZLEz;~(2`0_N$3Kp<&)nzpGgrhl7^ow)bBNx9<9#;mUbE>9&siUQLS*iGvEQ;-3 zyy$+|#_8#KAoitdsG>qop1CF_sCq=mdzzf!ff(Nn)q35hy3gg!ZF4|6@GdZB<ormH zap=8(;JFkRcr!6vI^Y2^$$qOcmm3Ilfoa$EPueLcNNAA=B7s1Q2v3x-k;gaTvC>My zxrW1LpOqKQZ=M}4&1v=J>u_j6z1+s*%BPL=Mtk8d<^B|1dKZL%xF(Ly&aR&x@8khY z{hnsMf!!0njyItc{kd9>F^)jF745-VOiBZ~^4v;`j2Vb~)D+Axl+{lWEo-&Xh&wD; zT*9qP7x0;Q;2w~LTu^a2q!*$fgWnp{c^FDM?PoYf?X{2aN){~wqSxxF<Bh!%zX2}p z>JnL`Tl_}$)@1og4<|uayg`X%rpHEGhsM)NzmruaXD#`FVcv=n<4X6K!uwF$E=1S+ zdS0I1mfciOt7G-Az$IB_&Tz{%Mo%c)vdjB~F>*gFLYhTvz_TvAj=}J*_3jlded%u| zjUyh#w7@ol?CWhkkRv+jLynP~+vEC8uS_^5t_PWT^xF7>0EsoI!oiV@X3A$!xEht# zsDikV6M>5hx+*?Q_^MZI&h<!N>g4GD{tK_U$kFcp<Ka)<Op~4{rc84d7;YUa#c?)5 z{v{#39)1SJB}wbE+4=v7?CRh+xAS?h*x2y0iz}CV_%%*(@%*%0E5U+^NMX=K_V?t= z6s_1Uy4l+tS2s2;w{JzqJ>-`!XjQPEu25(O)xT<P#=jM$qGA(TYzzy#l;AQyt+Xwk z5Az`XERg12VWQ$h7(~Jlv6~2r?1=s0#GxBIJ$Rj*JVLOS-XBOO3svE0dSee>7n^>n ztNU(Jf(%iGk#lves1H=P#pERWhR@ED8##SHpb_vOY;I|On_e{-BKA5UptVI!!q){Y ztTdTT`Isi_#Fcktc(JP#GZ(<m^Z-%A$$OjMC@FL_Wo%3=g4XR^Ef}-7thH+La-4G` zt(@+{g}@L>|Mu_fT=-!?-5x9kD+$zI4sHvl&dkof{&;ve<a)oxbKUE`K%L|5RYZr- zDwW?p_R??keDcW^y7tIYomL6WF<!3i4aQ(JA2;_<NUhiIn*R+!tBk^mZo;>^Ym_|4 ziXE-rYmr74Bb~ds9g974t%HMeEH=x`_yv`mcX)${I$|{v?lKCva`uWrs^2^(72+<6 zzXjR@q!5s>GHKr2lHYNY@_K#~yNnDYsq7k|>5(PqIe+(;<D;aRl`ds-B#ySw7}h%% z+R^(UP*Jo~!j6fj)%%^-kCz+}2Zy>1_BFB%tul|Sfo#TCu8hl@QYUl$!Tnj@;6nZK zi620r4lb8yh3f8wh(WE6jC;8rQaH{k%~Xkyjy%K{kYVwSau}a<bZBThPu0;^kKa@u zX!19U87g7x4;GUb#3RX~Wr!_71z%j0(>Nv#e0*FcA$!J4Lp2mRTFF5JWdgC+<3H+W zmopX_aC`?cV#poUdAj%M3``MBr}tifu<H=@SK8cMsU%(5PrIgkwv5X^>&-YFk>yc+ z5A(YJ&|m5PgPy0s<orI!<Ddy?U0)zO+&$DfZfPkmpp|9aYrWy|<a@sFrMmRl%^Y;R zJ;u|cH82v>J<<=kZs3rFT={l7u8-uDBm1f(JN?=XB_j4Fp&==%3Ix~L@DsE*RG!Cx z4cF~<?8^oDNIQk^2&l^I3{yLei)?#xQrruV({YpsVrNpzMD3e;8czZUyK_R9xCkBV z56FAPz2Cq>P)3pIGW2ww>r5-H((ZdTUKcvyaO#JeB(vrgkw4b7(PQ4SR@^J~cR25= zq}^BkVu`3wrc9-zq)OcBa{`Ifbbz)zev$05L8y)AI$LzxTH*BZ;Xn0-?Co<}zvWGs z6n0RVrheX+lNIrduiOJQK#N$Ij;pbyp3piFd=X)X!9tC_k$TBqaJ`1bn$^`xupiV| zdZJ;<O{g)`tKo2HQ#r|}62k?D+I85LkP34cwnK#Gs1!9UHZEGmq=xTJq9KS}u<7*N zBu7MY2sq8LA@S9T)b4elIzgZiS=6U4D;l!5>FG?LTW<}Gnnrh!h#CdsI7nL~mUSYl z(xIS14X``6*Y~M(hTz*va}BWKxQ(>vB1|eqniSChlg0oQX%J~VNR`EPo+o9XF`3FJ zsAWtIvdL?IWpHHf7eV)}EKS$UI7YmjMNVnX|N8Ss48<4uH!aIcSOUUz>>YcjDzr=$ zq^1iYwYPy?$G*^6#deNLF~n#zbdGs@RX|{?HYWFXXgk4Go?<8{1GrHHt_P9SG~K(( z0f$1Wk8P9JWk?^xI}PO90^WuB0YTJvrrqTGYjik_u*r1&QZiSgWsY7~B=CKQUbNVp zcVv4r0s;#6?Od6Pg2#N9cp2UD0WB`AYs@pB&ler2f@r9kepZFDU7n#p1TExPIB{UG zUhu`5u8m)uBet^3k;-xG9y+`K8diW;oQ%ls%2SiosHclCoWFGSu7%@=*w;MCqDd}| zue8^S?ueqaWRJO(B5Sqfi`p3VT;|Qr=98<;*idBPE!j|5djIV>a`?)DO^ZF^Pph4n z7rPUKdkmqOwK=q@5*5n8fpTAt1}$(QaL6mXldJ)1I_5LF>8Af&BHjhLj;)oKYkxb2 z6F#{%pPb0hFzy)p(8MIF-g{3~MWhLdWV&|`C}O-NC^(9};^~GjLy$s#+Wq>riHr<@ zA;hWl?wMDAMEo_u6=$?(87c0lUo;PtmmN(QBmG5V`fvhHJP9hjK#Q}1GJh0^{BiAz zIaBhz{%E$Zw|>!w7y-R(P4>NCGw(kU(7}0*$TzA#@cWmuKFFvW_>s|x@0@P_Ew274 zCV%z6vid9hj9W_WME~30I;~v;P&lSf9QEeRKJw2+_<r>ql>jWSazq5>Sz!LnFEeAz za_9O=%c<zko;dxna)0wc&wq~SRTRw)uD_H4{hP*rY134CA3&3ZHIEqi89V<h_5Sr2 zF>`!hWut(<1=aTh0TlINwh4DWtp-u9R4Kk|z*oPuRyke1FzK1(7&Be9H;LNCy<?<X zfx|$1l_f5SC^Ryv-vkyty|a@Bs{?hVqKZpU>jF?9&(Lzpa?*3%9mHVxq-z{20*4f# z)+Kh+M#>j<CKnN9N!Bs2lpdEVyREv_2|Mp0=XI!kI<!F=DEoq47qOSzZ7A7<@?f$` z+$$nLU9h_P-D2yl=<Tt-r+)TWl3_3k(csoSy|u%eyEo;z?m6Lu$%^ZjO17u-0>MFz z&=l;1-VKZts7uedXLNolEyl1h3f6#~j2q5cgdql`OfC9-G@uMXPHH(Y-*tC;+1<Pa zp>aEJSLanf7-qSK9qgwWwFME|0~v#11_)U3UM0E%mewOXkOh{U9-T;&)PjRHg)f;} zg2WBsaiz-1CCZ2fFa!98_j<A8>aujvYD2E)I@YV`+f*<QM&@TZ8!*FQNHibV6N3oW zL5`H7mnzc`L)vt~I_=Q!4v58?=-|OPp20qk3Tcc0)YSCAzywidxjn%S_B7q|Q>h6$ zECVg~PsK9?EFx;XiocnxK8z_sL0s2Irog7FHAN+;>0{e8c0`V}Xd;PE4PuMe9087= zngUY8rbq1%X|Q5gN*XK%>^;4=RtYmkq)XR!RU=%|5dtD`Mqwnxp=&&AdT@Rn`OVft z0}a8r*O!pyrhrcjax>j&Uua!wbVQz0cyozGO6c09Y=0$pc_{gR8A`z#8U5!T1REz^ z_=S}I2iy5p5<t<M?Y?Aq!Vc;MM<u(=Gp&DVJHttymp>l;TgXkaa~B>0mnYSf-6p^3 zZ_07b3-8daSkn4zp`U+95!n#Ax%No1VQ!kp<PgFoEOejob1;+6o;LchcF$#Zq2MHF zGis#zYE^0r&uE`VG%NCF_QWlaS{IXJZ8?)5>ehFciY^@e9F7@s^j1PPC~`M<Io@|Y z%5_@VU^;O@3k%_ndSLBSJtv`CbAL+m(dUV{oEFc;D62-zk`ClvzqykbnqD)ph1mvC zs%+|Z)eUZpvx#@9f>gjs!G%!dEgr{J2FH&3JzLs)lUq`g&g&AgyGNXR`ua80fo-t1 zRrvQK)Sks9_~B2%=QR6MrL~$`^uGPIEQ`8xj`Bo^jQJYHY4Lq@4gd2&rZo`s90g=g z5U6B4!><?;>J9?`8$tFbu^1)be||;dw`vQ?PLgu*p8{r|^5=Z?>h@D4PLKB&xpY=` zHEn1Cl4{P6MEv~!rlj&W{V5)O+rr`br#)n6hxzL-^d~=cAa3-n;2#?AKYaKfK>v!# zU##x`lPh|HfMq>?5G8=uG%Q%Ys;chJ_O-BPTj`pGiM;ct*Cr}*?`+mtsbyZ1&JgE$ zhP)zVnFSHP{z#)M!hDa6rClMQ>=|5Ka2M%<o0^zToEjW2FP}n~2D;S3R!UYrm-P0y z<CYUQ77ZoN;S&&EyD9ey@9!U)wlA>aY50*A{dbLi|K6+}pZt|o-9en@f6)3a<lJSs zLF9d||9%4h>^q_K6+y-g$A(W7|3PbYQ#t&;?Y%yte+S&pzOA@#p0jCBc3l3qr~q0I zQoqF$I+m`$|M!T)^S?o?f|vAv0h;}Xx8uz&oCPnsw#m8Xm>%I(e>=Hn@u6w)4%uns zUc9V=N88Gl@cRP)v8*%N`0thmg*3o0QrRO%eeNXZjoG#`gCf>*3@<1qgHN?jc=M_R zFS%7Dk@Ym8naSY4+b=gMLA*&<)UR~Jc^>Z|V@rI|ftx+l4SKk3RAa1VGU0VJ(diFg zH9e8Tf7?iKW+D9h2^BWsfx~4+bzfGdaa#!Faf8n)f-hdnh<kxr_QXxR_N9f8i!j;g zFPokc_*@u!>fS7MhHM0>L*~;Lob{)VJ7l}OF~<c)F!!RmqX4EjJ|A47$Ofu<xJGxP zFe8ymU*_~gXEe__;?)i+keq(;s_Fi<5Q2<dM15yL39e8I+g1|m=yQx+Sk9Hv_uc6l z?JR?EY2O}Iv$eQ>daii>2!Ji8*1w0H!t_nK8D=5{FF2j!QR(sV6YQ3+C+>hRKD}Wx zYje@i&#t7TLiQ{!<xHFOUhOCvon<bm>;5^%UL_u1;o*F~xpmtE;I4(PcvyNB(lhsH z2Q3TSTAdEz+;Y}AJ;SCkV1kj5;O^+tGrUXTuYzY#GP+QMYS4YsWyn|Du)Fw@%js*C zU(Y<IN#OEdC6fPlK&AvGFW>uv_I`i(@#;cUlvb@IH&r-!=)F(&B}_j+BwD|}{avah zWCN1pfkX0xGr%!|{6Pa+;u<*5iqRKtr}@JlOIf|cyMSeQ;CC9f(-8f0sH?m;&n?Z& zJE)wV!D*)YNnSHY1gv<e>7U-6p|#WV_(?YOMu0&3`fcj%uSfoCA58}U(@Myy-8#d~ ze{J{AzQn2l^aRAfn9q>sFUIoUqIiqv>KmuT@;i2a1>5iNJ2?RY{t^fH{(po&6bFF5 zBko9r-#`Cjh#z<tk}iosGfxr5IeZ-|KpHPh34%`#(8NuUwAq>~t0%KHl&d<Zaz3do z&hWJCxvOF(%xQ4<EZqL*iBnSO<4I*b%CX`S5)wbArlL+G<E}3N+Z^(iAnPB~{I7>@ zgPBCQ36Cu98`nZ}VEDqyaIPe=BYx6O`kS`XBq;4~H5g}-s&;z*z-VB?qvI*RDmM+! zm2VxL&M&JS<4k!R8%O&$LQC*r7GT|faY;g4(@wNQEO0Ngspn>=#X@KY--rFik%kSh zfwv8mfG|R>iSAW<C6m?tGpOyO2zisf<25zRJJEW}@nrd2&1rb7_yF~|>xYkbhIr<v zfNvL^#n&GsF`PysAcQ7yxcOi)vMTn|2>RE=|3o}yKgsaBmDev{o}M;MB+$6uJ}~s( zv=(A|CxeGa{OW<iJ>7pUAPvByHr0uYzhbg8ohjV{8VeadWBHF-2Lali)*<K8X;hq^ z{7;|(9R)P*d6Gc*AGQ8l3HS@tnh62oQmLGhUH(@CpC0c22-^P#)qf)FKUU%YXH=Wf z;%lgvV}&CRlGy%4f^+0HM_J}Zbmk%igi_@A1<K}>RKHO3O&5}OZv%M{ojcJ{s^vE6 zV^yfXm@pSFSDeI#9HrAKua=Ej;ghWJ{=;5%2N-e!{W0#e=$6aiaB?o=UERs?`H{Yw z%ZDccaYnYco%ad+b4x6NgRgIf^mxTd+oda-6Mm+xjr{*G!>auN$-n1lbH?%nln$?~ zZ@#x&<1*ubvOr(0w-b}&g%!qeZwJ}%#`EF-lB{=CW=2pKYqQfmR^jHQOTOkQYVpvM zu8FQ!7xRe#dD+B(-;=`w9{T(XI{KnKGrylrpKkA`Il-E--|DazlJDJp9fKd%p>d#@ z;j<k(%D+@xn+JC;!I6zdFGnLAqh$2sAzL({hqDr@t(Jz3#l&LAm5z0_T5ons_J%DX z(hftzTcNAI`KTnwYC^5_s$j8fm4pb!aPQl0Ue}hCl@YY9R90!EjbF9V(WHZ4bxIaR zzcb#zmE+L0yQULO=BB^d;AzaX3iVnuw%D-%x3!MBO%{9aV9L1~iV<!mqdS-zpoi`~ zB@SI%5+WTv78S#&m-PknPhY})eWs`&<@Lpl2v0u-H+yN56y^L5c!Pdb<XC&FXD=9e zP>ee+{pe^+jdIJ!knM<Dr63DTTNS=lOF7s%mPFS=ER+qWM0?AJARl=VKpEJ0$V#p8 z#tk5O$!&^n#eJs;JA@t=jTX0xia9RR8X9%m@tmrP>N>1bW-OP9+M|`VnDrfRT&F-E z*F3kc7-pOMSj<=u1>cf@GTwrh`}q~xWA;ks1apv8ei#U(%nyp<U&VIVz#qX2)<>hi zt$JzdQ(H{grPNB#mSgl+1Vu0uqdQU`Wz^btJ0f@2^wRg{Rud$OW#9=oe)GdmQK8Tj zy&>gsa6M=W*UMj4yq=8ek7K_P-%+P*g7O#_#SXu8Qy<xzv#6^rl7T~OwWb?o79nN4 zCD`MY!$TR*h62Beoelu}T?E(|CGC9G4QU@<>+3zz_R`b{(kO+bK-za8*>OUal}7He zUBjDJ<l5W1Kb7|kj-c+`67FdGj7IKO%J3f4I(i|S1hZ$F0Cx<|r+Wl8{#k+eL-02~ zm;&{)PHdADsYf7hZ?5dQJ^F{OZB6y#Vuqm3<$sa)?^<bTzy}~vpH(fXFPQg!np=L^ z=MLzYe}8*ZE`us$K8^Ql?lEP)OpiIR%ljs`k@>o~XniK-Cnw6py%NQPaEqj#u{^e} zhXijW?~*~VnNz!Vjm;V2(!GN%pZ{bZie<^g;|;Y>s~^5Qa#0e0254}x7{F){<iC8@ zbXD=+&v0PHJs&qgeYo`}@kFrB+gE>#T4y%+*|S*&@V&oT^PfifFZP7uGfrUD&hTo) z{S1hH`Jb`)=f3|6RFm$7C&}peN-a0sqQ)O8<G*<@8^NE(6Iw-AdHlk5JZ-P|=l}FX z99~V5{regGA^VyNfsI>_7nUdOkDvbj!E6PvHgXyQ7SC+E&Y<Jk&AWDh<Sd`|4d?h5 z4g4*L3AF&a^D!9*r)}ob!2JZN+W^=f6;>f<&o0hi@%$5#oS!z}ilhzhS3R9J0?U7H zG5!b5|6HbS1GCC;dn*#NjsFC71ns<iLOs*BaZIjPkwJ?INjN;<-vdQWg<^TL*Z&Ke CFT!;I literal 0 HcmV?d00001 diff --git a/docs/images/tutorial-ilm-delete-phase-creation.png b/docs/images/tutorial-ilm-delete-phase-creation.png new file mode 100644 index 0000000000000000000000000000000000000000..91a55733c284e9782c21b802b96da6adf696682b GIT binary patch literal 71022 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%0D%&VtwN{!(}%v>Y78`( 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%0A%ddlZuGX_hJd~KH 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 literal 0 HcmV?d00001 diff --git a/docs/images/tutorial-ilm-delete-rollover.png b/docs/images/tutorial-ilm-delete-rollover.png new file mode 100644 index 0000000000000000000000000000000000000000..ba021ecc2ac5c5cb302fbecafbbb9abc49fecd3c GIT binary patch literal 123735 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 literal 0 HcmV?d00001 diff --git a/docs/images/tutorial-ilm-hotphaserollover-default.png b/docs/images/tutorial-ilm-hotphaserollover-default.png new file mode 100644 index 0000000000000000000000000000000000000000..a9088c63d885ddf96e9928c4d4b60bd721be9825 GIT binary patch literal 252951 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 literal 0 HcmV?d00001 diff --git a/docs/images/tutorial-ilm-modify-default-warm-phase-rollover.png b/docs/images/tutorial-ilm-modify-default-warm-phase-rollover.png new file mode 100644 index 0000000000000000000000000000000000000000..c6f1e9b40e9777450420d36d1dbe5122466ea36f GIT binary patch literal 455134 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≤HxUyZFe%r=|9)j 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 literal 0 HcmV?d00001 diff --git a/docs/management/index-lifecycle-policies/example-index-lifecycle-policy.asciidoc b/docs/management/index-lifecycle-policies/example-index-lifecycle-policy.asciidoc index f68708f1b6394..e6d94e9ca61a3 100644 --- a/docs/management/index-lifecycle-policies/example-index-lifecycle-policy.asciidoc +++ b/docs/management/index-lifecycle-policies/example-index-lifecycle-policy.asciidoc @@ -1,23 +1,179 @@ [role="xpack"] + [[example-using-index-lifecycle-policy]] -=== Example of using an index lifecycle policy +=== Tutorial: Use {ilm-init} to manage {filebeat} time-based indices + +With {ilm} ({ilm-init}), you can create policies that perform actions automatically +on indices as they age and grow. {ilm-init} policies help you to manage +performance, resilience, and retention of your data during its lifecycle. This tutorial shows +you how to use {kib}’s *Index Lifecycle Policies* to modify and create {ilm-init} +policies. You can learn more about all of the actions, benefits, and lifecycle +phases in the {ref}/overview-index-lifecycle-management.html[{ilm-init} overview]. + + +[discrete] +[[example-using-index-lifecycle-policy-scenario]] +==== Scenario + +You’re tasked with sending syslog files to an {es} cluster. This +log data has the following data retention guidelines: + +* Keep logs on hot data nodes for 30 days +* Roll over to a new index if the size reaches 50GB +* After 30 days: +** Move the logs to warm data nodes +** Set {ref}/glossary.html#glossary-replica-shard[replica shards] to 1 +** {ref}/indices-forcemerge.html[Force merge] multiple index segments to free up the space used by deleted documents +* Delete logs after 90 days + + +[discrete] +[[example-using-index-lifecycle-policy-prerequisites]] +==== Prerequisites + +To complete this tutorial, you'll need: + +* An {es} cluster with hot and warm nodes configured for shard allocation +awareness. If you’re using {cloud}/ec-getting-started-templates-hot-warm.html[{ess}], +choose the hot-warm architecture deployment template. + ++ +For a self-managed cluster, add node attributes as described for {ref}/shard-allocation-filtering.html[shard allocation filtering] +to label data nodes as hot or warm. This step is required to migrate shards between +nodes configured with specific hardware for the hot or warm phases. ++ +For example, you can set this in your `elasticsearch.yml` for each data node: ++ +[source,yaml] +-------------------------------------------------------------------------------- +node.attr.data: "warm" +-------------------------------------------------------------------------------- + +* A server with {filebeat} installed and configured to send logs to the `elasticsearch` +output as described in {filebeat-ref}/filebeat-getting-started.html[Getting Started with {filebeat}]. + +[discrete] +[[example-using-index-lifecycle-policy-view-fb-ilm-policy]] +==== View the {filebeat} {ilm-init} policy + +{filebeat} includes a default {ilm-init} policy that enables rollover. {ilm-init} +is enabled automatically if you’re using the default `filebeat.yml` and index template. + +To view the default policy in {kib}, go to *Management > Index Lifecycle Policies*, +search for _filebeat_, and choose the _filebeat-version_ policy. + +This policy initiates the rollover action when the index size reaches 50GB or +becomes 30 days old. + +[role="screenshot"] +image::images/tutorial-ilm-hotphaserollover-default.png["Default policy"] + + +[float] +==== Modify the policy + +The default policy is enough to prevent the creation of many tiny daily indices. +You can modify the policy to meet more complex requirements. + +. Activate the warm phase. + ++ +. Set either of the following options to control when the index moves to the warm phase: + +** Provide a value for *Timing for warm phase*. Setting this to *15* keeps the +indices on hot nodes for a range of 15-45 days, depending on when the initial +rollover occurred. + +** Enable *Move to warm phase on rollover*. The index might move to the warm phase +more quickly than intended if it reaches the *Maximum index size* before the +the *Maximum age*. + +. In the *Select a node attribute to control shard allocation* dropdown, select +*data:warm(2)* to migrate shards to warm data nodes. + +. Change *Number of replicas* to *1*. + +. Enable *Force merge data* and set *Number of segments* to *1*. ++ +NOTE: When rollover is enabled in the hot phase, action timing in the other phases +is based on the rollover date. + ++ +[role="screenshot"] +image::images/tutorial-ilm-modify-default-warm-phase-rollover.png["Modify to add warm phase"] + +. Activate the delete phase and set *Timing for delete phase* to *90* days. ++ +[role="screenshot"] +image::images/tutorial-ilm-delete-rollover.png["Add a delete phase"] + +[float] +==== Create a custom policy + +If meeting a specific retention time period is most important, you can create a +custom policy. For this option, you will use {filebeat} daily indices without +rollover. + +. Create a custom policy in {kib}, go to *Management > Index Lifecycle Policies > +Create Policy*. + +. Activate the warm phase and configure it as follows: ++ +|=== +|*Setting* |*Value* + +|Timing for warm phase +|30 days from index creation + +|Node attribute +|`data:warm` + +|Number of replicas +|1 + +|Force merge data +|enable + +|Number of segments +|1 +|=== + ++ +[role="screenshot"] +image::images/tutorial-ilm-custom-policy.png["Modify the custom policy to add a warm phase"] + -A common use case for managing index lifecycle policies is when you’re using -{beats-ref}/beats-reference.html[Beats] to continually send time-series data, -such as metrics and log data, to {es}. When you create the Beats packages, an -index template is installed. The template includes a default policy to apply -when new indices are created. ++ +. Activate the delete phase and set the timing. ++ +|=== +|*Setting* |*Value* +|Timing for delete phase +|90 +|=== -You can edit the policy in {kib}'s *Index Lifecycle Policies*. For example, you might: ++ +[role="screenshot"] +image::images/tutorial-ilm-delete-phase-creation.png["Delete phase"] -* Rollover the index when it reaches 50 GB in size or is 30 days old. These -settings are the default for the Beats lifecycle policy. This avoids -having 1000s of tiny indices. When a rollover occurs, a new “hot” index is -created and added to the index alias. +. Configure the index to use the new policy in *{kib} > Management > Index Lifecycle +Policies* -* Move the index into the warm phase, shrink the index down to a single shard, -and force merge to a single segment. +.. Find your {ilm-init} policy. +.. Click the *Actions* link next to your policy name. +.. Choose *Add policy to index template*. +.. Select your {filebeat} index template name from the *Index template* list. For example, `filebeat-7.5.x`. +.. Click *Add Policy* to save the changes. -* After 60 days, move the index into the cold phase and onto less expensive hardware. ++ +NOTE: If you initially used the default {filebeat} {ilm-init} policy, you will +see a notice that the template already has a policy associated with it. Confirm +that you want to overwrite that configuration. -* Delete the index after 90 days. ++ ++ +TIP: When you change the policy associated with the index template, the active +index will continue to use the policy it was associated with at index creation +unless you manually update it. The next new index will use the updated policy. +For more reasons that your {ilm-init} policy changes might be delayed, see +{ref}/update-lifecycle-policy.html#update-lifecycle-policy[Update Lifecycle Policy]. From 25cedbe60c89173900be726a550c2c20c22577ca Mon Sep 17 00:00:00 2001 From: Corey Robertson <corey.robertson@elastic.co> Date: Mon, 13 Apr 2020 16:26:00 -0400 Subject: [PATCH 077/121] [Canvas] Migrate saved object mappings and migrations to Kibana Platform (#58891) * Move saved object mappings and migratins to kibana platform * Remove ts-ignore Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- x-pack/legacy/plugins/canvas/index.js | 4 -- .../legacy/plugins/canvas/migrations.test.js | 37 ------------------ x-pack/plugins/canvas/server/plugin.ts | 4 ++ .../server/saved_objects/custom_element.ts} | 27 ++++--------- .../canvas/server/saved_objects/index.ts} | 14 ++----- .../migrations/remove_attributes_id.test.ts | 39 +++++++++++++++++++ .../migrations/remove_attributes_id.ts | 14 +++++++ .../canvas/server/saved_objects/workpad.ts | 33 ++++++++++++++++ 8 files changed, 101 insertions(+), 71 deletions(-) delete mode 100644 x-pack/legacy/plugins/canvas/migrations.test.js rename x-pack/{legacy/plugins/canvas/server/mappings.ts => plugins/canvas/server/saved_objects/custom_element.ts} (56%) rename x-pack/{legacy/plugins/canvas/migrations.js => plugins/canvas/server/saved_objects/index.ts} (53%) create mode 100644 x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.test.ts create mode 100644 x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.ts create mode 100644 x-pack/plugins/canvas/server/saved_objects/workpad.ts diff --git a/x-pack/legacy/plugins/canvas/index.js b/x-pack/legacy/plugins/canvas/index.js index 489b9600f200e..a1d4b35826b00 100644 --- a/x-pack/legacy/plugins/canvas/index.js +++ b/x-pack/legacy/plugins/canvas/index.js @@ -7,9 +7,7 @@ import { resolve } from 'path'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; import { init } from './init'; -import { mappings } from './server/mappings'; import { CANVAS_APP, CANVAS_TYPE, CUSTOM_ELEMENT_TYPE } from './common/lib'; -import { migrations } from './migrations'; export function canvas(kibana) { return new kibana.Plugin({ @@ -33,8 +31,6 @@ export function canvas(kibana) { 'plugins/canvas/lib/window_error_handler.js', ], home: ['plugins/canvas/legacy_register_feature'], - mappings, - migrations, savedObjectsManagement: { [CANVAS_TYPE]: { icon: 'canvasApp', diff --git a/x-pack/legacy/plugins/canvas/migrations.test.js b/x-pack/legacy/plugins/canvas/migrations.test.js deleted file mode 100644 index 182ef3b18cce7..0000000000000 --- a/x-pack/legacy/plugins/canvas/migrations.test.js +++ /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 { migrations } from './migrations'; -import { CANVAS_TYPE } from './common/lib'; - -describe(`${CANVAS_TYPE}`, () => { - describe('7.0.0', () => { - const migrate = doc => migrations[CANVAS_TYPE]['7.0.0'](doc); - - it('does not throw error on empty object', () => { - const migratedDoc = migrate({}); - expect(migratedDoc).toMatchInlineSnapshot(`Object {}`); - }); - - it('removes id from "attributes"', () => { - const migratedDoc = migrate({ - foo: true, - attributes: { - id: '123', - bar: true, - }, - }); - expect(migratedDoc).toMatchInlineSnapshot(` -Object { - "attributes": Object { - "bar": true, - }, - "foo": true, -} -`); - }); - }); -}); diff --git a/x-pack/plugins/canvas/server/plugin.ts b/x-pack/plugins/canvas/server/plugin.ts index 0325de9cf29e2..91a5634734559 100644 --- a/x-pack/plugins/canvas/server/plugin.ts +++ b/x-pack/plugins/canvas/server/plugin.ts @@ -14,6 +14,7 @@ import { initRoutes } from './routes'; import { registerCanvasUsageCollector } from './collectors'; import { loadSampleData } from './sample_data'; import { setupInterpreter } from './setup_interpreter'; +import { customElementType, workpadType } from './saved_objects'; interface PluginsSetup { expressions: ExpressionsServerSetup; @@ -29,6 +30,9 @@ export class CanvasPlugin implements Plugin { } public async setup(coreSetup: CoreSetup, plugins: PluginsSetup) { + coreSetup.savedObjects.registerType(customElementType); + coreSetup.savedObjects.registerType(workpadType); + plugins.features.registerFeature({ id: 'canvas', name: 'Canvas', diff --git a/x-pack/legacy/plugins/canvas/server/mappings.ts b/x-pack/plugins/canvas/server/saved_objects/custom_element.ts similarity index 56% rename from x-pack/legacy/plugins/canvas/server/mappings.ts rename to x-pack/plugins/canvas/server/saved_objects/custom_element.ts index bf2be51882b1a..dadead0263be1 100644 --- a/x-pack/legacy/plugins/canvas/server/mappings.ts +++ b/x-pack/plugins/canvas/server/saved_objects/custom_element.ts @@ -4,26 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -// @ts-ignore converting /libs/constants to TS breaks CI -import { CANVAS_TYPE, CUSTOM_ELEMENT_TYPE } from '../common/lib/constants'; +import { SavedObjectsType } from 'src/core/server'; +import { CUSTOM_ELEMENT_TYPE } from '../../../../legacy/plugins/canvas/common/lib/constants'; -export const mappings = { - [CANVAS_TYPE]: { - dynamic: false, - properties: { - name: { - type: 'text', - fields: { - keyword: { - type: 'keyword', - }, - }, - }, - '@timestamp': { type: 'date' }, - '@created': { type: 'date' }, - }, - }, - [CUSTOM_ELEMENT_TYPE]: { +export const customElementType: SavedObjectsType = { + name: CUSTOM_ELEMENT_TYPE, + hidden: false, + namespaceAgnostic: false, + mappings: { dynamic: false, properties: { name: { @@ -41,4 +29,5 @@ export const mappings = { '@created': { type: 'date' }, }, }, + migrations: {}, }; diff --git a/x-pack/legacy/plugins/canvas/migrations.js b/x-pack/plugins/canvas/server/saved_objects/index.ts similarity index 53% rename from x-pack/legacy/plugins/canvas/migrations.js rename to x-pack/plugins/canvas/server/saved_objects/index.ts index d5b3d3fb1ce2a..dd7e74b87e2f4 100644 --- a/x-pack/legacy/plugins/canvas/migrations.js +++ b/x-pack/plugins/canvas/server/saved_objects/index.ts @@ -4,15 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CANVAS_TYPE } from './common/lib'; +import { workpadType } from './workpad'; +import { customElementType } from './custom_element'; -export const migrations = { - [CANVAS_TYPE]: { - '7.0.0': doc => { - if (doc.attributes) { - delete doc.attributes.id; - } - return doc; - }, - }, -}; +export { customElementType, workpadType }; diff --git a/x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.test.ts b/x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.test.ts new file mode 100644 index 0000000000000..a7112504e9980 --- /dev/null +++ b/x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.test.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 { removeAttributesId } from './remove_attributes_id'; + +const context: any = { + log: jest.fn(), +}; + +describe(`removeAttributesId`, () => { + it('does not throw error on empty object', () => { + const migratedDoc = removeAttributesId({} as any, context); + expect(migratedDoc).toMatchInlineSnapshot(`Object {}`); + }); + + it('removes id from "attributes"', () => { + const migratedDoc = removeAttributesId( + { + foo: true, + attributes: { + id: '123', + bar: true, + }, + } as any, + context + ); + expect(migratedDoc).toMatchInlineSnapshot(` +Object { + "attributes": Object { + "bar": true, + }, + "foo": true, +} +`); + }); +}); diff --git a/x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.ts b/x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.ts new file mode 100644 index 0000000000000..893a73d7b5913 --- /dev/null +++ b/x-pack/plugins/canvas/server/saved_objects/migrations/remove_attributes_id.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SavedObjectMigrationFn } from 'src/core/server'; + +export const removeAttributesId: SavedObjectMigrationFn = doc => { + if (typeof doc.attributes === 'object' && doc.attributes !== null) { + delete (doc.attributes as any).id; + } + return doc; +}; diff --git a/x-pack/plugins/canvas/server/saved_objects/workpad.ts b/x-pack/plugins/canvas/server/saved_objects/workpad.ts new file mode 100644 index 0000000000000..e83ba9720b43a --- /dev/null +++ b/x-pack/plugins/canvas/server/saved_objects/workpad.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 { SavedObjectsType } from 'src/core/server'; +import { CANVAS_TYPE } from '../../../../legacy/plugins/canvas/common/lib/constants'; +import { removeAttributesId } from './migrations/remove_attributes_id'; + +export const workpadType: SavedObjectsType = { + name: CANVAS_TYPE, + hidden: false, + namespaceAgnostic: false, + mappings: { + dynamic: false, + properties: { + name: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + }, + }, + }, + '@timestamp': { type: 'date' }, + '@created': { type: 'date' }, + }, + }, + migrations: { + '7.0.0': removeAttributesId, + }, +}; From 48fd5c025526e3aa6736ca1db2a1f757c90ea508 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Mon, 13 Apr 2020 16:26:45 -0400 Subject: [PATCH 078/121] [Endpoint] Policy list support for URL pagination state (#63291) * store changes to support pagination via url * Fix storing location when pagination happens * Initial set of tests * Redux spy middleware and async utility * Add better types to `waitForAction` * Add more docs * fix urlSearchParams selector to account for array of values * full set of tests for policy list store concerns * More efficient redux spy middleware (no more sleep()) * Set spy middleware `dispatch` to a `jest.fn` and expose `mock` info. * Fix url param selector to return first param value when it is defined multiple times * Removed PageId and associated hook * clean up TODO items * Fixes post-merge frm `master` * Address code review comments --- .../endpoint/store/policy_list/action.ts | 13 +- .../endpoint/store/policy_list/index.test.ts | 168 +++++++++++++++--- .../endpoint/store/policy_list/middleware.ts | 19 +- .../endpoint/store/policy_list/reducer.ts | 29 +-- .../endpoint/store/policy_list/selectors.ts | 50 +++++- .../store/policy_list/services/ingest.ts | 2 +- .../store/policy_list/test_mock_utils.ts | 151 ++++++++++++++++ .../endpoint/store/routing/action.ts | 14 +- .../public/applications/endpoint/types.ts | 10 ++ .../endpoint/view/policy/policy_list.tsx | 17 +- .../applications/endpoint/view/use_page_id.ts | 28 --- 11 files changed, 384 insertions(+), 117 deletions(-) create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts delete mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts index 3f4f3f39e9be0..3db224f049c05 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/action.ts @@ -21,15 +21,4 @@ interface ServerFailedToReturnPolicyListData { payload: ServerApiError; } -interface UserPaginatedPolicyListTable { - type: 'userPaginatedPolicyListTable'; - payload: { - pageSize: number; - pageIndex: number; - }; -} - -export type PolicyListAction = - | ServerReturnedPolicyListData - | UserPaginatedPolicyListTable - | ServerFailedToReturnPolicyListData; +export type PolicyListAction = ServerReturnedPolicyListData | ServerFailedToReturnPolicyListData; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts index 0cf0eb8bfa3cd..4d153b5e03cd2 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/index.test.ts @@ -4,71 +4,106 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PolicyListState } from '../../types'; +import { EndpointAppLocation, PolicyListState } from '../../types'; import { applyMiddleware, createStore, Dispatch, Store } from 'redux'; import { AppAction } from '../action'; import { policyListReducer } from './reducer'; import { policyListMiddlewareFactory } from './middleware'; import { coreMock } from '../../../../../../../../src/core/public/mocks'; -import { CoreStart } from 'kibana/public'; -import { selectIsLoading } from './selectors'; +import { isOnPolicyListPage, selectIsLoading, urlSearchParams } from './selectors'; import { DepsStartMock, depsStartMock } from '../../mocks'; +import { + createSpyMiddleware, + MiddlewareActionSpyHelper, + setPolicyListApiMockImplementation, +} from './test_mock_utils'; +import { INGEST_API_DATASOURCES } from './services/ingest'; describe('policy list store concerns', () => { - const sleep = () => new Promise(resolve => setTimeout(resolve, 1000)); - let fakeCoreStart: jest.Mocked<CoreStart>; + let fakeCoreStart: ReturnType<typeof coreMock.createStart>; let depsStart: DepsStartMock; let store: Store<PolicyListState>; let getState: typeof store['getState']; let dispatch: Dispatch<AppAction>; + let waitForAction: MiddlewareActionSpyHelper['waitForAction']; beforeEach(() => { fakeCoreStart = coreMock.createStart({ basePath: '/mock' }); depsStart = depsStartMock(); + setPolicyListApiMockImplementation(fakeCoreStart.http); + let actionSpyMiddleware; + ({ actionSpyMiddleware, waitForAction } = createSpyMiddleware<PolicyListState>()); + store = createStore( policyListReducer, - applyMiddleware(policyListMiddlewareFactory(fakeCoreStart, depsStart)) + applyMiddleware(policyListMiddlewareFactory(fakeCoreStart, depsStart), actionSpyMiddleware) ); getState = store.getState; dispatch = store.dispatch; }); - // https://github.com/elastic/kibana/issues/58972 - test.skip('it sets `isLoading` when `userNavigatedToPage`', async () => { - expect(selectIsLoading(getState())).toBe(false); - dispatch({ type: 'userNavigatedToPage', payload: 'policyListPage' }); - expect(selectIsLoading(getState())).toBe(true); - await sleep(); - expect(selectIsLoading(getState())).toBe(false); + it('it does nothing on `userChangedUrl` if pathname is NOT `/policy`', async () => { + const state = getState(); + expect(isOnPolicyListPage(state)).toBe(false); + dispatch({ + type: 'userChangedUrl', + payload: { + pathname: '/foo', + search: '', + hash: '', + } as EndpointAppLocation, + }); + expect(getState()).toEqual(state); }); - // https://github.com/elastic/kibana/issues/58896 - test.skip('it sets `isLoading` when `userPaginatedPolicyListTable`', async () => { + it('it reports `isOnPolicyListPage` correctly when router pathname is `/policy`', async () => { + dispatch({ + type: 'userChangedUrl', + payload: { + pathname: '/policy', + search: '', + hash: '', + }, + }); + expect(isOnPolicyListPage(getState())).toBe(true); + }); + + it('it sets `isLoading` when `userChangedUrl`', async () => { expect(selectIsLoading(getState())).toBe(false); dispatch({ - type: 'userPaginatedPolicyListTable', + type: 'userChangedUrl', payload: { - pageSize: 10, - pageIndex: 1, + pathname: '/policy', + search: '', + hash: '', }, }); expect(selectIsLoading(getState())).toBe(true); - await sleep(); + await waitForAction('serverReturnedPolicyListData'); expect(selectIsLoading(getState())).toBe(false); }); - test('it resets state on `userNavigatedFromPage` action', async () => { + it('it resets state on `userChangedUrl` and pathname is NOT `/policy`', async () => { + dispatch({ + type: 'userChangedUrl', + payload: { + pathname: '/policy', + search: '', + hash: '', + }, + }); + await waitForAction('serverReturnedPolicyListData'); dispatch({ - type: 'serverReturnedPolicyListData', + type: 'userChangedUrl', payload: { - policyItems: [], - pageIndex: 20, - pageSize: 50, - total: 200, + pathname: '/foo', + search: '', + hash: '', }, }); - dispatch({ type: 'userNavigatedFromPage', payload: 'policyListPage' }); expect(getState()).toEqual({ + apiError: undefined, + location: undefined, policyItems: [], isLoading: false, pageIndex: 0, @@ -76,4 +111,85 @@ describe('policy list store concerns', () => { total: 0, }); }); + it('uses default pagination params when not included in url', async () => { + dispatch({ + type: 'userChangedUrl', + payload: { + pathname: '/policy', + search: '', + hash: '', + }, + }); + await waitForAction('serverReturnedPolicyListData'); + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 10 }, + }); + }); + + describe('when url contains search params', () => { + const dispatchUserChangedUrl = (searchParams: string = '') => + dispatch({ + type: 'userChangedUrl', + payload: { + pathname: '/policy', + search: searchParams, + hash: '', + }, + }); + + it('uses pagination params from url', async () => { + dispatchUserChangedUrl('?page_size=50&page_index=0'); + await waitForAction('serverReturnedPolicyListData'); + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 50 }, + }); + }); + it('uses defaults for params not in url', async () => { + dispatchUserChangedUrl('?page_index=99'); + expect(urlSearchParams(getState())).toEqual({ + page_index: 99, + page_size: 10, + }); + dispatchUserChangedUrl('?page_size=50'); + expect(urlSearchParams(getState())).toEqual({ + page_index: 0, + page_size: 50, + }); + }); + it('accepts only positive numbers for page_index and page_size', async () => { + dispatchUserChangedUrl('?page_size=-50&page_index=-99'); + await waitForAction('serverReturnedPolicyListData'); + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 10 }, + }); + }); + it('it ignores non-numeric values for page_index and page_size', async () => { + dispatchUserChangedUrl('?page_size=fifty&page_index=ten'); + await waitForAction('serverReturnedPolicyListData'); + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { + query: { kuery: 'datasources.package.name: endpoint', page: 1, perPage: 10 }, + }); + }); + it('accepts only known values for `page_size`', async () => { + dispatchUserChangedUrl('?page_size=300&page_index=10'); + await waitForAction('serverReturnedPolicyListData'); + expect(fakeCoreStart.http.get).toHaveBeenCalledWith(INGEST_API_DATASOURCES, { + query: { kuery: 'datasources.package.name: endpoint', page: 11, perPage: 10 }, + }); + }); + it(`ignores unknown url search params`, async () => { + dispatchUserChangedUrl('?page_size=20&page_index=10&foo=bar'); + expect(urlSearchParams(getState())).toEqual({ + page_index: 10, + page_size: 20, + }); + }); + it(`uses last param value if param is defined multiple times`, async () => { + dispatchUserChangedUrl('?page_size=20&page_size=50&page_index=20&page_index=40'); + expect(urlSearchParams(getState())).toEqual({ + page_index: 20, + page_size: 20, + }); + }); + }); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts index adc176740fb4b..c073d26a676f0 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts @@ -6,6 +6,7 @@ import { MiddlewareFactory, PolicyListState, GetDatasourcesResponse } from '../../types'; import { sendGetEndpointSpecificDatasources } from './services/ingest'; +import { isOnPolicyListPage, urlSearchParams } from './selectors'; export const policyListMiddlewareFactory: MiddlewareFactory<PolicyListState> = coreStart => { const http = coreStart.http; @@ -13,22 +14,10 @@ export const policyListMiddlewareFactory: MiddlewareFactory<PolicyListState> = c return ({ getState, dispatch }) => next => async action => { next(action); - if ( - (action.type === 'userNavigatedToPage' && action.payload === 'policyListPage') || - action.type === 'userPaginatedPolicyListTable' - ) { - const state = getState(); - let pageSize: number; - let pageIndex: number; - - if (action.type === 'userPaginatedPolicyListTable') { - pageSize = action.payload.pageSize; - pageIndex = action.payload.pageIndex; - } else { - pageSize = state.pageSize; - pageIndex = state.pageIndex; - } + const state = getState(); + if (action.type === 'userChangedUrl' && isOnPolicyListPage(state)) { + const { page_index: pageIndex, page_size: pageSize } = urlSearchParams(state); let response: GetDatasourcesResponse; try { diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts index b964f4f023866..30c1deac7f5e1 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/reducer.ts @@ -7,6 +7,7 @@ import { Reducer } from 'redux'; import { PolicyListState } from '../../types'; import { AppAction } from '../action'; +import { isOnPolicyListPage } from './selectors'; const initialPolicyListState = (): PolicyListState => { return { @@ -16,6 +17,7 @@ const initialPolicyListState = (): PolicyListState => { pageIndex: 0, pageSize: 10, total: 0, + location: undefined, }; }; @@ -39,19 +41,26 @@ export const policyListReducer: Reducer<PolicyListState, AppAction> = ( }; } - if ( - action.type === 'userPaginatedPolicyListTable' || - (action.type === 'userNavigatedToPage' && action.payload === 'policyListPage') - ) { - return { + if (action.type === 'userChangedUrl') { + const newState = { ...state, - apiError: undefined, - isLoading: true, + location: action.payload, }; - } + const isCurrentlyOnListPage = isOnPolicyListPage(newState); + const wasPreviouslyOnListPage = isOnPolicyListPage(state); - if (action.type === 'userNavigatedFromPage' && action.payload === 'policyListPage') { - return initialPolicyListState(); + // If on the current page, then return new state with location information + // Also adjust some state if user is just entering the policy list view + if (isCurrentlyOnListPage) { + if (!wasPreviouslyOnListPage) { + newState.apiError = undefined; + newState.isLoading = true; + } + return newState; + } + return { + ...initialPolicyListState(), + }; } return state; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts index 7ca25e81ce75a..ce13d89b2b8c2 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/selectors.ts @@ -4,7 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PolicyListState } from '../../types'; +import { createSelector } from 'reselect'; +import { parse } from 'query-string'; +import { PolicyListState, PolicyListUrlSearchParams } from '../../types'; + +const PAGE_SIZES = Object.freeze([10, 20, 50]); export const selectPolicyItems = (state: PolicyListState) => state.policyItems; @@ -17,3 +21,47 @@ export const selectTotal = (state: PolicyListState) => state.total; export const selectIsLoading = (state: PolicyListState) => state.isLoading; export const selectApiError = (state: PolicyListState) => state.apiError; + +export const isOnPolicyListPage = (state: PolicyListState) => { + return state.location?.pathname === '/policy'; +}; + +const routeLocation = (state: PolicyListState) => state.location; + +/** + * Returns the supported URL search params, populated with defaults if none where present in the URL + */ +export const urlSearchParams: ( + state: PolicyListState +) => PolicyListUrlSearchParams = createSelector(routeLocation, location => { + const searchParams = { + page_index: 0, + page_size: 10, + }; + if (!location) { + return searchParams; + } + + const query = parse(location.search); + + // Search params can appear multiple times in the URL, in which case the value for them, + // once parsed, would be an array. In these case, we take the first value defined + searchParams.page_index = Number( + (Array.isArray(query.page_index) ? query.page_index[0] : query.page_index) ?? 0 + ); + searchParams.page_size = Number( + (Array.isArray(query.page_size) ? query.page_size[0] : query.page_size) ?? 10 + ); + + // If pageIndex is not a valid positive integer, set it to 0 + if (!Number.isFinite(searchParams.page_index) || searchParams.page_index < 0) { + searchParams.page_index = 0; + } + + // if pageSize is not one of the expected page sizes, reset it to 10 + if (!PAGE_SIZES.includes(searchParams.page_size)) { + searchParams.page_size = 10; + } + + return searchParams; +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts index 16c885f26f0a4..bfbb5f94e8950 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts @@ -17,7 +17,7 @@ import { } from '../../../types'; const INGEST_API_ROOT = `/api/ingest_manager`; -const INGEST_API_DATASOURCES = `${INGEST_API_ROOT}/datasources`; +export const INGEST_API_DATASOURCES = `${INGEST_API_ROOT}/datasources`; const INGEST_API_FLEET = `${INGEST_API_ROOT}/fleet`; const INGEST_API_FLEET_AGENT_STATUS = `${INGEST_API_FLEET}/agent-status`; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts new file mode 100644 index 0000000000000..0d41ae0d76da4 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts @@ -0,0 +1,151 @@ +/* + * 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 { HttpStart } from 'kibana/public'; +import { Dispatch } from 'redux'; +import { INGEST_API_DATASOURCES } from './services/ingest'; +import { EndpointDocGenerator } from '../../../../../common/generate_data'; +import { AppAction, GetDatasourcesResponse, GlobalState, MiddlewareFactory } from '../../types'; + +const generator = new EndpointDocGenerator('policy-list'); + +/** + * It sets the mock implementation on the necessary http methods to support the policy list view + * @param mockedHttpService + * @param responseItems + */ +export const setPolicyListApiMockImplementation = ( + mockedHttpService: jest.Mocked<HttpStart>, + responseItems: GetDatasourcesResponse['items'] = [generator.generatePolicyDatasource()] +): void => { + mockedHttpService.get.mockImplementation((...args) => { + const [path] = args; + if (typeof path === 'string') { + if (path === INGEST_API_DATASOURCES) { + return Promise.resolve<GetDatasourcesResponse>({ + items: responseItems, + total: 10, + page: 1, + perPage: 10, + success: true, + }); + } + } + return Promise.reject(new Error(`MOCK: unknown policy list api: ${path}`)); + }); +}; + +/** + * Utilities for testing Redux middleware + */ +export interface MiddlewareActionSpyHelper<S = GlobalState> { + /** + * Returns a promise that is fulfilled when the given action is dispatched or a timeout occurs. + * The use of this method instead of a `sleep()` type of delay should avoid test case instability + * especially when run in a CI environment. + * + * @param actionType + */ + waitForAction: (actionType: AppAction['type']) => Promise<void>; + /** + * A property holding the information around the calls that were processed by the internal + * `actionSpyMiddlware`. This property holds the information typically found in Jets's mocked + * function `mock` property - [see here for more information](https://jestjs.io/docs/en/mock-functions#mock-property) + * + * **Note**: this property will only be set **after* the `actionSpyMiddlware` has been + * initialized (ex. via `createStore()`. Attempting to reference this property before that time + * will throw an error. + * Also - do not hold on to references to this property value if `jest.clearAllMocks()` or + * `jest.resetAllMocks()` is called between usages of the value. + */ + dispatchSpy: jest.Mock<Dispatch<AppAction>>['mock']; + /** + * Redux middleware that enables spying on the action that are dispatched through the store + */ + actionSpyMiddleware: ReturnType<MiddlewareFactory<S>>; +} + +/** + * Creates a new instance of middleware action helpers + * Note: in most cases (testing concern specific middleware) this function should be given + * the state type definition, else, the global state will be used. + * + * @example + * // Use in Policy List middleware testing + * const middlewareSpyUtils = createSpyMiddleware<PolicyListState>(); + * store = createStore( + * policyListReducer, + * applyMiddleware( + * policyListMiddlewareFactory(fakeCoreStart, depsStart), + * middlewareSpyUtils.actionSpyMiddleware + * ) + * ); + * // Reference `dispatchSpy` ONLY after creating the store that includes `actionSpyMiddleware` + * const { waitForAction, dispatchSpy } = middlewareSpyUtils; + * // + * // later in test + * // + * it('...', async () => { + * //... + * await waitForAction('serverReturnedPolicyListData'); + * // do assertions + * // or check how action was called + * expect(dispatchSpy.calls.length).toBe(2) + * }); + */ +export const createSpyMiddleware = <S = GlobalState>(): MiddlewareActionSpyHelper<S> => { + type ActionWatcher = (action: AppAction) => void; + + const watchers = new Set<ActionWatcher>(); + let spyDispatch: jest.Mock<Dispatch<AppAction>>; + + return { + waitForAction: async (actionType: string) => { + // Error is defined here so that we get a better stack trace that points to the test from where it was used + const err = new Error(`action '${actionType}' was not dispatched within the allocated time`); + + await new Promise((resolve, reject) => { + const watch: ActionWatcher = action => { + if (action.type === actionType) { + watchers.delete(watch); + clearTimeout(timeout); + resolve(); + } + }; + + // We timeout before jest's default 5s, so that a better error stack is returned + const timeout = setTimeout(() => { + watchers.delete(watch); + reject(err); + }, 4500); + watchers.add(watch); + }); + }, + + get dispatchSpy() { + if (!spyDispatch) { + throw new Error( + 'Spy Middleware has not been initialized. Access this property only after using `actionSpyMiddleware` in a redux store' + ); + } + return spyDispatch.mock; + }, + + actionSpyMiddleware: api => { + return next => { + spyDispatch = jest.fn(action => { + next(action); + // loop through the list of watcher (if any) and call them with this action + for (const watch of watchers) { + watch(action); + } + return action; + }); + return spyDispatch; + }; + }, + }; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts index f22272bc68233..fd72a02b33588 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/routing/action.ts @@ -5,21 +5,11 @@ */ import { Immutable } from '../../../../../common/types'; -import { EndpointAppLocation, PageId } from '../../types'; - -interface UserNavigatedToPage { - readonly type: 'userNavigatedToPage'; - readonly payload: PageId; -} - -interface UserNavigatedFromPage { - readonly type: 'userNavigatedFromPage'; - readonly payload: PageId; -} +import { EndpointAppLocation } from '../../types'; interface UserChangedUrl { readonly type: 'userChangedUrl'; readonly payload: Immutable<EndpointAppLocation>; } -export type RoutingAction = UserNavigatedToPage | UserNavigatedFromPage | UserChangedUrl; +export type RoutingAction = UserChangedUrl; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index f9ad8f6708f6b..a625c49bf7d5a 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -95,6 +95,8 @@ export interface PolicyListState { pageIndex: number; /** data is being retrieved from server */ isLoading: boolean; + /** current location information */ + location?: Immutable<EndpointAppLocation>; } /** @@ -117,6 +119,14 @@ export interface PolicyDetailsState { }; } +/** + * The URL search params that are supported by the Policy List page view + */ +export interface PolicyListUrlSearchParams { + page_index: number; + page_size: number; +} + /** * Endpoint Policy configuration */ diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx index 06ba74aa46732..295312fff01dd 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx @@ -9,8 +9,7 @@ import { EuiBasicTable, EuiText, EuiTableFieldDataColumnType, EuiLink } from '@e import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { useDispatch } from 'react-redux'; -import { useHistory } from 'react-router-dom'; -import { usePageId } from '../use_page_id'; +import { useHistory, useLocation } from 'react-router-dom'; import { selectApiError, selectIsLoading, @@ -50,9 +49,9 @@ const renderPolicyNameLink = (value: string, _item: PolicyData) => { }; export const PolicyList = React.memo(() => { - usePageId('policyListPage'); - const { services, notifications } = useKibana(); + const history = useHistory(); + const location = useLocation(); const dispatch = useDispatch<(action: PolicyListAction) => void>(); const policyItems = usePolicyListSelector(selectPolicyItems); @@ -84,15 +83,9 @@ export const PolicyList = React.memo(() => { const handleTableChange = useCallback( ({ page: { index, size } }: TableChangeCallbackArguments) => { - dispatch({ - type: 'userPaginatedPolicyListTable', - payload: { - pageIndex: index, - pageSize: size, - }, - }); + history.push(`${location.pathname}?page_index=${index}&page_size=${size}`); }, - [dispatch] + [history, location.pathname] ); const columns: Array<EuiTableFieldDataColumnType<PolicyData>> = useMemo( diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts b/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts deleted file mode 100644 index 85ed8a39fb386..0000000000000 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/use_page_id.ts +++ /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 { useEffect } from 'react'; -import { useDispatch } from 'react-redux'; -import { RoutingAction } from '../store/routing'; -import { PageId } from '../types'; - -/** - * Dispatches a 'userNavigatedToPage' action with the given 'pageId' as the action payload. - * When the component is un-mounted, a `userNavigatedFromPage` action will be dispatched - * with the given `pageId`. - * - * @param pageId A page id - */ -export function usePageId(pageId: PageId) { - const dispatch: (action: RoutingAction) => unknown = useDispatch(); - useEffect(() => { - dispatch({ type: 'userNavigatedToPage', payload: pageId }); - - return () => { - dispatch({ type: 'userNavigatedFromPage', payload: pageId }); - }; - }, [dispatch, pageId]); -} From 0666dbd35fe3ad8e8cd8824c23ed66c7465c8a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= <mikecote@users.noreply.github.com> Date: Mon, 13 Apr 2020 16:29:48 -0400 Subject: [PATCH 079/121] Fix task manager query to return tasks to retry (#63360) * Fix task manager query to also return tasks to retry * Fix failing jest tests --- .../server/queries/mark_available_tasks_as_claimed.ts | 7 ++++--- x-pack/plugins/task_manager/server/task_store.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts index b0d9dc61c9667..8f7cc47f936b2 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts @@ -11,7 +11,7 @@ import { RangeFilter, mustBeAllOf, MustCondition, - MustNotCondition, + BoolClauseWithAnyCondition, } from './query_clauses'; export const TaskWithSchedule: ExistsFilter = { @@ -54,15 +54,16 @@ export const IdleTaskWithExpiredRunAt: MustCondition<TermFilter | RangeFilter> = }, }; -export const InactiveTasks: MustNotCondition<TermFilter | RangeFilter> = { +// TODO: Fix query clauses to support this +export const InactiveTasks: BoolClauseWithAnyCondition<any> = { bool: { must_not: [ { bool: { should: [{ term: { 'task.status': 'running' } }, { term: { 'task.status': 'claiming' } }], + must: { range: { 'task.retryAt': { gt: 'now' } } }, }, }, - { range: { 'task.retryAt': { gt: 'now' } } }, ], }, }; diff --git a/x-pack/plugins/task_manager/server/task_store.test.ts b/x-pack/plugins/task_manager/server/task_store.test.ts index 97794311fb3d2..4ecefcb7984eb 100644 --- a/x-pack/plugins/task_manager/server/task_store.test.ts +++ b/x-pack/plugins/task_manager/server/task_store.test.ts @@ -407,9 +407,9 @@ describe('TaskStore', () => { { term: { 'task.status': 'running' } }, { term: { 'task.status': 'claiming' } }, ], + must: { range: { 'task.retryAt': { gt: 'now' } } }, }, }, - { range: { 'task.retryAt': { gt: 'now' } } }, ], }, }, @@ -553,9 +553,9 @@ describe('TaskStore', () => { { term: { 'task.status': 'running' } }, { term: { 'task.status': 'claiming' } }, ], + must: { range: { 'task.retryAt': { gt: 'now' } } }, }, }, - { range: { 'task.retryAt': { gt: 'now' } } }, ], }, }, From 6f46e6b827ce5c35e7195bb32bf0bc6361686189 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell <aaron.caldwell@elastic.co> Date: Mon, 13 Apr 2020 14:32:32 -0600 Subject: [PATCH 080/121] Migrate legacy maps service to NP & update refs (#60942) * Get legacy maps into basic NP plugin form. Swap out legacy services for NP * Pull service settings from injected vars. Return new instance of service settings from setup * Use NP service settings in vega maps. Clean up legacy shim * Use NP maps service in region maps. Clean up shim. Add exports to NP service * Pull zoom precision out to separate module since it's dependent on config * Update paths to point to NP resources * More path updates, clean up, use IServiceSettings * Remove dependency on legacy service settings. Add tile_map dependency ng-sanitize * More path cleanup. Use zoomPrecision provided through plugin inteface * Move getPrecision into contract-provided function since it depends on config * Move tests to new service location, remove vis dir * Update test paths. Move origin const declaration into public * Clean up, fixes * Fix type errors. General cleaning * Inject toast service into map when needed * Fix typo in regionmap config * i18n fixes * Update jest test path * Fix karma tests * i18n fixes * Type updates. Add mapsLegacy to np karma mock * Remove html sanitizer * Fix vega test that depends on serviceSettings * Revise xpack license handling to use NP serviceSettings. Remove angular bindings Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .i18nrc.json | 1 + .../core_plugins/kibana/public/index.scss | 2 +- .../__tests__/region_map_visualization.js | 48 +++- .../region_map/public/choropleth_layer.js | 4 +- .../public/components/region_map_options.tsx | 9 +- .../core_plugins/region_map/public/legacy.ts | 9 +- .../core_plugins/region_map/public/plugin.ts | 10 +- .../public/region_map_visualization.js | 12 +- .../public/shim/legacy_dependencies_plugin.ts | 11 - .../core_plugins/region_map/public/types.ts | 2 +- .../core_plugins/region_map/public/util.ts | 2 +- .../coordinate_maps_visualization.js | 55 +++- .../public/__tests__/geohash_layer.js | 2 +- .../public/base_maps_visualization.js | 12 +- .../public/components/wms_options.tsx | 3 +- .../tile_map/public/geohash_layer.js | 3 +- .../core_plugins/tile_map/public/legacy.ts | 1 + .../tile_map/public/markers/scaled_circles.js | 3 +- .../core_plugins/tile_map/public/plugin.ts | 13 +- .../public/shim/legacy_dependencies_plugin.ts | 9 +- .../tile_map/public/tile_map_fn.js | 2 +- .../tile_map/public/tile_map_type.js | 4 +- .../tile_map/public/tile_map_visualization.js | 21 +- .../tile_map/public/tilemap_fn.test.js | 4 +- .../core_plugins/tile_map/public/types.ts | 2 +- .../public/shim/timelion_legacy_module.ts | 1 - .../public/__tests__/vega_visualization.js | 33 ++- .../vis_type_vega/public/legacy.ts | 6 +- .../vis_type_vega/public/plugin.ts | 11 +- .../public/shim/legacy_dependencies_plugin.ts | 49 ---- .../public/vega_view/vega_map_layer.js | 2 +- .../public/vega_view/vega_map_view.js | 27 +- .../public/vega_visualization.js | 3 +- .../new_platform/new_platform.karma_mock.js | 6 + .../ui/public/new_platform/new_platform.ts | 2 + .../ui/public/vis/map/service_settings.js | 256 ------------------ src/plugins/maps_legacy/kibana.json | 6 + .../__tests__/map/ems_mocks/sample_files.json | 0 .../map/ems_mocks/sample_manifest.json | 0 .../map/ems_mocks/sample_style_bright.json | 0 .../ems_mocks/sample_style_bright_vector.json | 0 .../sample_style_bright_vector_source.json | 0 .../map/ems_mocks/sample_style_dark.json | 0 .../ems_mocks/sample_style_desaturated.json | 0 .../__tests__/map/ems_mocks/sample_tiles.json | 0 .../public}/__tests__/map/kibana_map.js | 0 .../public}/__tests__/map/service_settings.js | 2 +- .../maps_legacy/public}/_index.scss | 0 .../maps_legacy/public/common/origin.ts} | 5 +- src/plugins/maps_legacy/public/index.ts | 61 +++++ .../maps_legacy/public/kibana_services.js} | 15 +- .../maps_legacy/public}/map/_index.scss | 0 .../public}/map/_leaflet_overrides.scss | 0 .../maps_legacy/public}/map/_legend.scss | 0 .../maps_legacy/public}/map/color_util.js | 0 .../public}/map/convert_to_geojson.js | 0 .../public}/map/decode_geo_hash.test.ts | 0 .../public}/map/decode_geo_hash.ts | 52 +--- .../public}/map/grid_dimensions.js | 0 .../maps_legacy/public}/map/kibana_map.js | 27 +- .../public}/map/kibana_map_layer.js | 0 .../maps_legacy/public}/map/map_messages.js | 9 +- .../maps_legacy/public/map/precision.ts | 74 +++++ .../public}/map/service_settings.d.ts | 2 +- .../public/map/service_settings.js | 254 +++++++++++++++++ .../public}/map/zoom_to_precision.ts | 0 src/plugins/maps_legacy/public/plugin.ts | 57 ++++ .../update_tilemap_settings.js | 17 +- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 70 files changed, 733 insertions(+), 492 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts delete mode 100644 src/legacy/ui/public/vis/map/service_settings.js create mode 100644 src/plugins/maps_legacy/kibana.json rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_files.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_manifest.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_bright.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_bright_vector.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_bright_vector_source.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_dark.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_desaturated.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_tiles.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/kibana_map.js (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/service_settings.js (99%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/_index.scss (100%) rename src/{legacy/core_plugins/vis_type_vega/public/shim/index.ts => plugins/maps_legacy/public/common/origin.ts} (90%) create mode 100644 src/plugins/maps_legacy/public/index.ts rename src/{legacy/core_plugins/vis_type_vega/public/legacy_imports.ts => plugins/maps_legacy/public/kibana_services.js} (64%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/_index.scss (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/_leaflet_overrides.scss (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/_legend.scss (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/color_util.js (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/convert_to_geojson.js (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/decode_geo_hash.test.ts (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/decode_geo_hash.ts (79%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/grid_dimensions.js (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/kibana_map.js (96%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/kibana_map_layer.js (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/map_messages.js (93%) create mode 100644 src/plugins/maps_legacy/public/map/precision.ts rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/service_settings.d.ts (97%) create mode 100644 src/plugins/maps_legacy/public/map/service_settings.js rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/map/zoom_to_precision.ts (100%) create mode 100644 src/plugins/maps_legacy/public/plugin.ts diff --git a/.i18nrc.json b/.i18nrc.json index 19d361aed9344..e18f529b92ac3 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -24,6 +24,7 @@ "src/legacy/core_plugins/management", "src/plugins/management" ], + "maps_legacy": "src/plugins/maps_legacy", "indexPatternManagement": "src/plugins/index_pattern_management", "advancedSettings": "src/plugins/advanced_settings", "kibana_legacy": "src/plugins/kibana_legacy", diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss index 9b7d0afcd7e39..fbfb0a06fabcf 100644 --- a/src/legacy/core_plugins/kibana/public/index.scss +++ b/src/legacy/core_plugins/kibana/public/index.scss @@ -17,7 +17,7 @@ @import './visualize/index'; // Has to come after visualize because of some // bad cascading in the Editor layout -@import 'src/legacy/ui/public/vis/index'; +@import '../../../../plugins/maps_legacy/public/index'; // Home styles @import '../../../../plugins/home/public/application/index'; diff --git a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js index 3880f42d52561..6e1b0b7160941 100644 --- a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js @@ -23,12 +23,18 @@ import _ from 'lodash'; import ChoroplethLayer from '../choropleth_layer'; import { ImageComparator } from 'test_utils/image_comparator'; import worldJson from './world.json'; -import EMS_CATALOGUE from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json'; -import EMS_FILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_files.json'; -import EMS_TILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json'; -import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_bright'; -import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated'; -import EMS_STYLE_DARK_MAP from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_dark'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_CATALOGUE from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_FILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_TILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_DARK_MAP from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark'; import initialPng from './initial.png'; import toiso3Png from './toiso3.png'; @@ -44,6 +50,10 @@ import { createRegionMapTypeDefinition } from '../region_map_type'; import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setInjectedVarFunc } from '../../../../../plugins/maps_legacy/public/kibana_services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ServiceSettings } from '../../../../../plugins/maps_legacy/public/map/service_settings'; const THRESHOLD = 0.45; const PIXEL_DIFF = 96; @@ -92,7 +102,31 @@ describe('RegionMapsVisualizationTests', function() { let getManifestStub; beforeEach( ngMock.inject((Private, $injector) => { - const serviceSettings = $injector.get('serviceSettings'); + setInjectedVarFunc(injectedVar => { + switch (injectedVar) { + case 'mapConfig': + return { + emsFileApiUrl: '', + emsTileApiUrl: '', + emsLandingPageUrl: '', + }; + case 'tilemapsConfig': + return { + deprecated: { + config: { + options: { + attribution: '123', + }, + }, + }, + }; + case 'version': + return '123'; + default: + return 'not found'; + } + }); + const serviceSettings = new ServiceSettings(); const uiSettings = $injector.get('config'); const regionmapsConfig = { includeElasticMapsService: true, diff --git a/src/legacy/core_plugins/region_map/public/choropleth_layer.js b/src/legacy/core_plugins/region_map/public/choropleth_layer.js index e637a217bfbc3..4ea9cc1f7bfbf 100644 --- a/src/legacy/core_plugins/region_map/public/choropleth_layer.js +++ b/src/legacy/core_plugins/region_map/public/choropleth_layer.js @@ -22,11 +22,9 @@ import L from 'leaflet'; import _ from 'lodash'; import d3 from 'd3'; import { i18n } from '@kbn/i18n'; -import { KibanaMapLayer } from 'ui/vis/map/kibana_map_layer'; import * as topojson from 'topojson-client'; import { toastNotifications } from 'ui/notify'; -import * as colorUtil from 'ui/vis/map/color_util'; - +import { colorUtil, KibanaMapLayer } from '../../../../plugins/maps_legacy/public'; import { truncatedColorMaps } from '../../../../plugins/charts/public'; const EMPTY_STYLE = { diff --git a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx index 187b27953830d..31a27c4da7fcf 100644 --- a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx +++ b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx @@ -21,9 +21,12 @@ import React, { useCallback, useMemo } from 'react'; import { EuiIcon, EuiLink, EuiPanel, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - -import { FileLayerField, VectorLayer, ServiceSettings } from 'ui/vis/map/service_settings'; import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { + FileLayerField, + VectorLayer, + IServiceSettings, +} from '../../../../../plugins/maps_legacy/public'; import { NumberInputOption, SelectOption, @@ -43,7 +46,7 @@ const mapFieldForOption = ({ description, name }: FileLayerField) => ({ }); export type RegionMapOptionsProps = { - serviceSettings: ServiceSettings; + serviceSettings: IServiceSettings; } & VisOptionsProps<RegionMapVisParams>; function RegionMapOptions(props: RegionMapOptionsProps) { diff --git a/src/legacy/core_plugins/region_map/public/legacy.ts b/src/legacy/core_plugins/region_map/public/legacy.ts index 08615946affa2..b0cc767a044e8 100644 --- a/src/legacy/core_plugins/region_map/public/legacy.ts +++ b/src/legacy/core_plugins/region_map/public/legacy.ts @@ -20,21 +20,18 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { RegionMapPluginSetupDependencies, RegionMapsConfig } from './plugin'; +import { RegionMapPluginSetupDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; -const regionmapsConfig = npSetup.core.injectedMetadata.getInjectedVar( - 'regionmap' -) as RegionMapsConfig; - const plugins: Readonly<RegionMapPluginSetupDependencies> = { expressions: npSetup.plugins.expressions, visualizations: npSetup.plugins.visualizations, + mapsLegacy: npSetup.plugins.mapsLegacy, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. - __LEGACY: new LegacyDependenciesPlugin(regionmapsConfig), + __LEGACY: new LegacyDependenciesPlugin(), }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index cae569f8fd26d..1453c2155e2d6 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -32,10 +32,14 @@ import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim' import { createRegionMapFn } from './region_map_fn'; // @ts-ignore import { createRegionMapTypeDefinition } from './region_map_type'; +import { IServiceSettings, MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public'; /** @private */ interface RegionMapVisualizationDependencies extends LegacyDependenciesPluginSetup { uiSettings: IUiSettingsClient; + regionmapsConfig: RegionMapsConfig; + serviceSettings: IServiceSettings; + notificationService: any; } /** @internal */ @@ -43,6 +47,7 @@ export interface RegionMapPluginSetupDependencies { expressions: ReturnType<ExpressionsPublicPlugin['setup']>; visualizations: VisualizationsSetup; __LEGACY: LegacyDependenciesPlugin; + mapsLegacy: MapsLegacyPluginSetup; } /** @internal */ @@ -61,10 +66,13 @@ export class RegionMapPlugin implements Plugin<Promise<void>, void> { public async setup( core: CoreSetup, - { expressions, visualizations, __LEGACY }: RegionMapPluginSetupDependencies + { expressions, visualizations, mapsLegacy, __LEGACY }: RegionMapPluginSetupDependencies ) { const visualizationDependencies: Readonly<RegionMapVisualizationDependencies> = { uiSettings: core.uiSettings, + regionmapsConfig: core.injectedMetadata.getInjectedVar('regionmap') as RegionMapsConfig, + serviceSettings: mapsLegacy.serviceSettings, + notificationService: core.notifications.toasts, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/region_map/public/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/region_map_visualization.js index 72f9d66e7d2bf..f08d53ee35c8d 100644 --- a/src/legacy/core_plugins/region_map/public/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/region_map_visualization.js @@ -28,8 +28,16 @@ import { truncatedColorMaps } from '../../../../plugins/charts/public'; // TODO: reference to TILE_MAP plugin should be removed import { BaseMapsVisualizationProvider } from '../../tile_map/public/base_maps_visualization'; -export function createRegionMapVisualization({ serviceSettings, $injector, uiSettings }) { - const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings); +export function createRegionMapVisualization({ + serviceSettings, + $injector, + uiSettings, + notificationService, +}) { + const BaseMapsVisualization = new BaseMapsVisualizationProvider( + serviceSettings, + notificationService + ); const tooltipFormatter = new TileMapTooltipFormatter($injector); return class RegionMapsVisualization extends BaseMapsVisualization { diff --git a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts index c47fc40fbacd7..3a7615e83f281 100644 --- a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts @@ -19,31 +19,20 @@ import chrome from 'ui/chrome'; import { CoreStart, Plugin } from 'kibana/public'; -import 'ui/vis/map/service_settings'; -import { RegionMapsConfig } from '../plugin'; /** @internal */ export interface LegacyDependenciesPluginSetup { $injector: any; serviceSettings: any; - regionmapsConfig: RegionMapsConfig; } export class LegacyDependenciesPlugin implements Plugin<Promise<LegacyDependenciesPluginSetup>, void> { - constructor(private readonly regionmapsConfig: RegionMapsConfig) {} - public async setup() { const $injector = await chrome.dangerouslyGetActiveInjector(); return { $injector, - regionmapsConfig: this.regionmapsConfig, - // Settings for EMSClient. - // EMSClient, which currently lives in the tile_map vis, - // will probably end up being exposed from the future vis_type_maps plugin, - // which would register both the tile_map and the region_map vis plugins. - serviceSettings: $injector.get('serviceSettings'), } as LegacyDependenciesPluginSetup; } diff --git a/src/legacy/core_plugins/region_map/public/types.ts b/src/legacy/core_plugins/region_map/public/types.ts index 2097aebd27ce0..8585bf720e0cf 100644 --- a/src/legacy/core_plugins/region_map/public/types.ts +++ b/src/legacy/core_plugins/region_map/public/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { VectorLayer, FileLayerField } from 'ui/vis/map/service_settings'; +import { VectorLayer, FileLayerField } from '../../../../plugins/maps_legacy/public'; import { WMSOptions } from '../../tile_map/public/types'; export interface RegionMapVisParams { diff --git a/src/legacy/core_plugins/region_map/public/util.ts b/src/legacy/core_plugins/region_map/public/util.ts index 69a7a1815bc8e..24c721da1f31a 100644 --- a/src/legacy/core_plugins/region_map/public/util.ts +++ b/src/legacy/core_plugins/region_map/public/util.ts @@ -17,7 +17,7 @@ * under the License. */ -import { FileLayer, VectorLayer } from 'ui/vis/map/service_settings'; +import { FileLayer, VectorLayer } from '../../../../plugins/maps_legacy/public'; // TODO: reference to TILE_MAP plugin should be removed import { ORIGIN } from '../../../../legacy/core_plugins/tile_map/common/origin'; diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js index 2c142b19d9096..3904c43707906 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js @@ -25,12 +25,18 @@ import initial from './initial.png'; import blues from './blues.png'; import shadedGeohashGrid from './shadedGeohashGrid.png'; import heatmapRaw from './heatmap_raw.png'; -import EMS_CATALOGUE from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json'; -import EMS_FILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_files.json'; -import EMS_TILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json'; -import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_bright'; -import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated'; -import EMS_STYLE_DARK_MAP from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_dark'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_CATALOGUE from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_FILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_TILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_DARK_MAP from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark'; import { createTileMapVisualization } from '../tile_map_visualization'; import { createTileMapTypeDefinition } from '../tile_map_type'; @@ -38,6 +44,15 @@ import { createTileMapTypeDefinition } from '../tile_map_type'; import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type'; +import { + getPrecision, + getZoomPrecision, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../plugins/maps_legacy/public/map/precision'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ServiceSettings } from '../../../../../plugins/maps_legacy/public/map/service_settings'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setInjectedVarFunc } from '../../../../../plugins/maps_legacy/public/kibana_services'; function mockRawData() { const stack = [dummyESResponse]; @@ -75,13 +90,39 @@ describe('CoordinateMapsVisualizationTest', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject((Private, $injector) => { - const serviceSettings = $injector.get('serviceSettings'); + setInjectedVarFunc(injectedVar => { + switch (injectedVar) { + case 'mapConfig': + return { + emsFileApiUrl: '', + emsTileApiUrl: '', + emsLandingPageUrl: '', + }; + case 'tilemapsConfig': + return { + deprecated: { + config: { + options: { + attribution: '123', + }, + }, + }, + }; + case 'version': + return '123'; + default: + return 'not found'; + } + }); + const serviceSettings = new ServiceSettings(); const uiSettings = $injector.get('config'); dependencies = { serviceSettings, uiSettings, $injector, + getPrecision, + getZoomPrecision, }; visType = new BaseVisType(createTileMapTypeDefinition(dependencies)); diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js b/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js index 857432079e376..fc029d6bccb6e 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js @@ -18,13 +18,13 @@ */ import expect from '@kbn/expect'; -import { KibanaMap } from 'ui/vis/map/kibana_map'; import { GeohashLayer } from '../geohash_layer'; // import heatmapPng from './heatmap.png'; import scaledCircleMarkersPng from './scaledCircleMarkers.png'; // import shadedCircleMarkersPng from './shadedCircleMarkers.png'; import { ImageComparator } from 'test_utils/image_comparator'; import GeoHashSampleData from './dummy_es_response.json'; +import { KibanaMap } from '../../../../../plugins/maps_legacy/public'; describe('geohash_layer', function() { let domNode; diff --git a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js index d38159c91ef9f..1dac4607280cc 100644 --- a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js @@ -19,22 +19,25 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { KibanaMap } from 'ui/vis/map/kibana_map'; +import { KibanaMap } from '../../../../plugins/maps_legacy/public'; import * as Rx from 'rxjs'; import { filter, first } from 'rxjs/operators'; -import 'ui/vis/map/service_settings'; import { toastNotifications } from 'ui/notify'; import chrome from 'ui/chrome'; const WMS_MINZOOM = 0; const WMS_MAXZOOM = 22; //increase this to 22. Better for WMS -export function BaseMapsVisualizationProvider(serviceSettings) { +export function BaseMapsVisualizationProvider(mapServiceSettings, notificationService) { /** * Abstract base class for a visualization consisting of a map with a single baselayer. * @class BaseMapsVisualization * @constructor */ + + const serviceSettings = mapServiceSettings; + const toastService = notificationService; + return class BaseMapsVisualization { constructor(element, vis) { this.vis = vis; @@ -94,8 +97,9 @@ export function BaseMapsVisualizationProvider(serviceSettings) { const centerFromUIState = uiState.get('mapCenter'); options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : this.vis.params.mapZoom; options.center = centerFromUIState ? centerFromUIState : this.vis.params.mapCenter; + const services = { toastService }; - this._kibanaMap = new KibanaMap(this._container, options); + this._kibanaMap = new KibanaMap(this._container, options, services); this._kibanaMap.setMinZoom(WMS_MINZOOM); //use a default this._kibanaMap.setMaxZoom(WMS_MAXZOOM); //use a default diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx index b8535e72e8818..e74c260d3b8e5 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx @@ -21,8 +21,7 @@ import React, { useMemo } from 'react'; import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - -import { TmsLayer } from 'ui/vis/map/service_settings'; +import { TmsLayer } from '../../../../../plugins/maps_legacy/public'; import { Vis } from '../../../../../plugins/visualizations/public'; import { RegionMapVisParams } from '../../../region_map/public/types'; import { SelectOption, SwitchOption } from '../../../../../plugins/charts/public'; diff --git a/src/legacy/core_plugins/tile_map/public/geohash_layer.js b/src/legacy/core_plugins/tile_map/public/geohash_layer.js index a604e02be7c8c..b9acf1a15208f 100644 --- a/src/legacy/core_plugins/tile_map/public/geohash_layer.js +++ b/src/legacy/core_plugins/tile_map/public/geohash_layer.js @@ -20,8 +20,7 @@ import L from 'leaflet'; import { min, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; - -import { KibanaMapLayer } from 'ui/vis/map/kibana_map_layer'; +import { KibanaMapLayer } from '../../../../plugins/maps_legacy/public'; import { HeatmapMarkers } from './markers/heatmap'; import { ScaledCirclesMarkers } from './markers/scaled_circles'; import { ShadedCirclesMarkers } from './markers/shaded_circles'; diff --git a/src/legacy/core_plugins/tile_map/public/legacy.ts b/src/legacy/core_plugins/tile_map/public/legacy.ts index 7b1f916076f61..741e118750f32 100644 --- a/src/legacy/core_plugins/tile_map/public/legacy.ts +++ b/src/legacy/core_plugins/tile_map/public/legacy.ts @@ -27,6 +27,7 @@ import { plugin } from '.'; const plugins: Readonly<TileMapPluginSetupDependencies> = { expressions: npSetup.plugins.expressions, visualizations: npSetup.plugins.visualizations, + mapsLegacy: npSetup.plugins.mapsLegacy, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js b/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js index 88d6db82946c7..f39de6ca7d179 100644 --- a/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js +++ b/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js @@ -22,8 +22,7 @@ import _ from 'lodash'; import d3 from 'd3'; import $ from 'jquery'; import { EventEmitter } from 'events'; -import * as colorUtil from 'ui/vis/map/color_util'; - +import { colorUtil } from '../../../../../plugins/maps_legacy/public'; import { truncatedColorMaps } from '../../../../../plugins/charts/public'; export class ScaledCirclesMarkers extends EventEmitter { diff --git a/src/legacy/core_plugins/tile_map/public/plugin.ts b/src/legacy/core_plugins/tile_map/public/plugin.ts index f2addbe3ab872..2b97407b17b38 100644 --- a/src/legacy/core_plugins/tile_map/public/plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/plugin.ts @@ -32,16 +32,22 @@ import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim' import { createTileMapFn } from './tile_map_fn'; // @ts-ignore import { createTileMapTypeDefinition } from './tile_map_type'; +import { IServiceSettings, MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public'; /** @private */ interface TileMapVisualizationDependencies extends LegacyDependenciesPluginSetup { + serviceSettings: IServiceSettings; uiSettings: IUiSettingsClient; + getZoomPrecision: any; + getPrecision: any; + notificationService: any; } /** @internal */ export interface TileMapPluginSetupDependencies { expressions: ReturnType<ExpressionsPublicPlugin['setup']>; visualizations: VisualizationsSetup; + mapsLegacy: MapsLegacyPluginSetup; __LEGACY: LegacyDependenciesPlugin; } @@ -55,9 +61,14 @@ export class TileMapPlugin implements Plugin<Promise<void>, void> { public async setup( core: CoreSetup, - { expressions, visualizations, __LEGACY }: TileMapPluginSetupDependencies + { expressions, visualizations, mapsLegacy, __LEGACY }: TileMapPluginSetupDependencies ) { + const { getZoomPrecision, getPrecision, serviceSettings } = mapsLegacy; const visualizationDependencies: Readonly<TileMapVisualizationDependencies> = { + serviceSettings, + getZoomPrecision, + getPrecision, + notificationService: core.notifications.toasts, uiSettings: core.uiSettings, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts index 063b12bf0a2db..5296e98b09efe 100644 --- a/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts @@ -18,12 +18,12 @@ */ import chrome from 'ui/chrome'; -import 'ui/vis/map/service_settings'; import { CoreStart, Plugin } from 'kibana/public'; +// TODO: Determine why visualizations don't populate without this +import 'angular-sanitize'; /** @internal */ export interface LegacyDependenciesPluginSetup { - serviceSettings: any; $injector: any; } @@ -34,11 +34,6 @@ export class LegacyDependenciesPlugin return { $injector, - // Settings for EMSClient. - // EMSClient, which currently lives in the tile_map vis, - // will probably end up being exposed from the future vis_type_maps plugin, - // which would register both the tile_map and the region_map vis plugins. - serviceSettings: $injector.get('serviceSettings'), } as LegacyDependenciesPluginSetup; } diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_fn.js b/src/legacy/core_plugins/tile_map/public/tile_map_fn.js index 2f54d23590c33..5ad4a2c33db25 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_fn.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_fn.js @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { convertToGeoJson } from 'ui/vis/map/convert_to_geojson'; +import { convertToGeoJson } from '../../../../plugins/maps_legacy/public'; import { i18n } from '@kbn/i18n'; export const createTileMapFn = () => ({ diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_type.js b/src/legacy/core_plugins/tile_map/public/tile_map_type.js index fe82ad5c7352b..ae3a839b600e9 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_type.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_type.js @@ -19,9 +19,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; - -import { convertToGeoJson } from 'ui/vis/map/convert_to_geojson'; - +import { convertToGeoJson } from '../../../../plugins/maps_legacy/public'; import { Schemas } from '../../../../plugins/vis_default_editor/public'; import { createTileMapVisualization } from './tile_map_visualization'; import { TileMapOptions } from './components/tile_map_options'; diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js index 910def8a0c78e..fdce8bc51fe86 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js @@ -23,15 +23,19 @@ import { BaseMapsVisualizationProvider } from './base_maps_visualization'; import { TileMapTooltipFormatterProvider } from './editors/_tooltip_formatter'; import { npStart } from 'ui/new_platform'; import { getFormat } from '../../../ui/public/visualize/loader/pipeline_helpers/utilities'; -import { - scaleBounds, - zoomPrecision, - getPrecision, - geoContains, -} from '../../../ui/public/vis/map/decode_geo_hash'; +import { scaleBounds, geoContains } from '../../../../plugins/maps_legacy/public'; -export const createTileMapVisualization = ({ serviceSettings, $injector }) => { - const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings); +export const createTileMapVisualization = ({ + serviceSettings, + $injector, + getZoomPrecision, + getPrecision, + notificationService, +}) => { + const BaseMapsVisualization = new BaseMapsVisualizationProvider( + serviceSettings, + notificationService + ); const tooltipFormatter = new TileMapTooltipFormatterProvider($injector); return class CoordinateMapsVisualization extends BaseMapsVisualization { @@ -59,6 +63,7 @@ export const createTileMapVisualization = ({ serviceSettings, $injector }) => { updateVarsObject.data.boundingBox = geohashAgg.aggConfigParams.boundingBox; } // todo: autoPrecision should be vis parameter, not aggConfig one + const zoomPrecision = getZoomPrecision(); updateVarsObject.data.precision = geohashAgg.aggConfigParams.autoPrecision ? zoomPrecision[this.vis.getUiState().get('mapZoom')] : getPrecision(geohashAgg.aggConfigParams.precision); diff --git a/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js b/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js index 0913d6fc92e8a..6da37f4c5ef86 100644 --- a/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js +++ b/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js @@ -22,7 +22,7 @@ import { functionWrapper } from '../../../../plugins/expressions/common/expressi import { createTileMapFn } from './tile_map_fn'; jest.mock('ui/new_platform'); -jest.mock('ui/vis/map/convert_to_geojson', () => ({ +jest.mock('../../../../plugins/maps_legacy/public', () => ({ convertToGeoJson: jest.fn().mockReturnValue({ featureCollection: { type: 'FeatureCollection', @@ -37,7 +37,7 @@ jest.mock('ui/vis/map/convert_to_geojson', () => ({ }), })); -import { convertToGeoJson } from 'ui/vis/map/convert_to_geojson'; +import { convertToGeoJson } from '../../../../plugins/maps_legacy/public'; describe('interpreter/functions#tilemap', () => { const fn = functionWrapper(createTileMapFn()); diff --git a/src/legacy/core_plugins/tile_map/public/types.ts b/src/legacy/core_plugins/tile_map/public/types.ts index 5f1c3f9b03c9e..e1b4c27319123 100644 --- a/src/legacy/core_plugins/tile_map/public/types.ts +++ b/src/legacy/core_plugins/tile_map/public/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { TmsLayer } from 'ui/vis/map/service_settings'; +import { TmsLayer } from '../../../../plugins/maps_legacy/public'; import { MapTypes } from './map_types'; export interface WMSOptions { diff --git a/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts b/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts index 9de8477e3978c..8fadf223e1807 100644 --- a/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts +++ b/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts @@ -21,7 +21,6 @@ import 'ngreact'; import 'brace/mode/hjson'; import 'brace/ext/searchbox'; import 'ui/accessibility/kbn_ui_ace_keyboard_mode'; -import 'ui/vis/map/service_settings'; import { once } from 'lodash'; // @ts-ignore diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js index c7fbc0815b07c..6412d8a569b2a 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js @@ -49,6 +49,10 @@ import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_ty // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; import { setInjectedVars } from '../services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setInjectedVarFunc } from '../../../../../plugins/maps_legacy/public/kibana_services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ServiceSettings } from '../../../../../plugins/maps_legacy/public/map/service_settings'; const THRESHOLD = 0.1; const PIXEL_DIFF = 30; @@ -69,9 +73,34 @@ describe('VegaVisualizations', () => { beforeEach(ngMock.module('kibana')); beforeEach( - ngMock.inject($injector => { + ngMock.inject(() => { + setInjectedVarFunc(injectedVar => { + switch (injectedVar) { + case 'mapConfig': + return { + emsFileApiUrl: '', + emsTileApiUrl: '', + emsLandingPageUrl: '', + }; + case 'tilemapsConfig': + return { + deprecated: { + config: { + options: { + attribution: '123', + }, + }, + }, + }; + case 'version': + return '123'; + default: + return 'not found'; + } + }); + const serviceSettings = new ServiceSettings(); vegaVisualizationDependencies = { - serviceSettings: $injector.get('serviceSettings'), + serviceSettings, core: { uiSettings: npStart.core.uiSettings, }, diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts index b2c73894d978d..450af4a6f253e 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts @@ -20,16 +20,12 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; import { VegaPluginSetupDependencies, VegaPluginStartDependencies } from './plugin'; -import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; const setupPlugins: Readonly<VegaPluginSetupDependencies> = { ...npSetup.plugins, visualizations: npSetup.plugins.visualizations, - - // Temporary solution - // It will be removed when all dependent services are migrated to the new platform. - __LEGACY: new LegacyDependenciesPlugin(), + mapsLegacy: npSetup.plugins.mapsLegacy, }; const startPlugins: Readonly<VegaPluginStartDependencies> = { diff --git a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts index 38b92a40cd99a..9fa77d28fbbfa 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts @@ -17,7 +17,6 @@ * under the License. */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; -import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public'; import { VisualizationsSetup } from '../../../../plugins/visualizations/public'; @@ -32,13 +31,15 @@ import { import { createVegaFn } from './vega_fn'; import { createVegaTypeDefinition } from './vega_type'; import { VisTypeVegaSetup } from '../../../../plugins/vis_type_vega/public'; +import { IServiceSettings } from '../../../../plugins/maps_legacy/public'; /** @internal */ -export interface VegaVisualizationDependencies extends LegacyDependenciesPluginSetup { +export interface VegaVisualizationDependencies { core: CoreSetup; plugins: { data: ReturnType<DataPublicPlugin['setup']>; }; + serviceSettings: IServiceSettings; } /** @internal */ @@ -47,7 +48,7 @@ export interface VegaPluginSetupDependencies { visualizations: VisualizationsSetup; data: ReturnType<DataPublicPlugin['setup']>; visTypeVega: VisTypeVegaSetup; - __LEGACY: LegacyDependenciesPlugin; + mapsLegacy: any; } /** @internal */ @@ -65,7 +66,7 @@ export class VegaPlugin implements Plugin<Promise<void>, void> { public async setup( core: CoreSetup, - { data, expressions, visualizations, visTypeVega, __LEGACY }: VegaPluginSetupDependencies + { data, expressions, visualizations, visTypeVega, mapsLegacy }: VegaPluginSetupDependencies ) { setInjectedVars({ enableExternalUrls: visTypeVega.config.enableExternalUrls, @@ -79,7 +80,7 @@ export class VegaPlugin implements Plugin<Promise<void>, void> { plugins: { data, }, - ...(await __LEGACY.setup()), + serviceSettings: mapsLegacy.serviceSettings, }; expressions.registerFunction(() => createVegaFn(visualizationDependencies)); diff --git a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts deleted file mode 100644 index 8925f76cffa43..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts +++ /dev/null @@ -1,49 +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. - */ - -// TODO remove this file as soon as serviceSettings is exposed in the new platform -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import chrome from 'ui/chrome'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import 'ui/vis/map/service_settings'; -import { CoreStart, Plugin } from 'kibana/public'; - -/** @internal */ -export interface LegacyDependenciesPluginSetup { - serviceSettings: any; -} - -export class LegacyDependenciesPlugin - implements Plugin<Promise<LegacyDependenciesPluginSetup>, void> { - public async setup() { - const $injector = await chrome.dangerouslyGetActiveInjector(); - - return { - // Settings for EMSClient. - // EMSClient, which currently lives in the tile_map vis, - // will probably end up being exposed from the future vis_type_maps plugin, - // which would register both the tile_map and the region_map vis plugins. - serviceSettings: $injector.get('serviceSettings'), - } as LegacyDependenciesPluginSetup; - } - - public start(core: CoreStart) { - // nothing to do here yet - } -} diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js index 38540e9f218fb..d43eb9c3351ea 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js @@ -19,7 +19,7 @@ import L from 'leaflet'; import 'leaflet-vega'; -import { KibanaMapLayer } from '../legacy_imports'; +import { KibanaMapLayer } from '../../../../../plugins/maps_legacy/public'; export class VegaMapLayer extends KibanaMapLayer { constructor(spec, options) { diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js index 487c90d01ada3..03aef29dc5739 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js @@ -21,10 +21,15 @@ import * as vega from 'vega-lib'; import { i18n } from '@kbn/i18n'; import { VegaBaseView } from './vega_base_view'; import { VegaMapLayer } from './vega_map_layer'; -import { KibanaMap } from '../legacy_imports'; +import { KibanaMap } from '../../../../../plugins/maps_legacy/public'; import { getEmsTileLayerId, getUISettings } from '../services'; export class VegaMapView extends VegaBaseView { + constructor(opts, services) { + super(opts); + this.services = services; + } + async _initViewCustomizations() { const mapConfig = this._parser.mapConfig; let baseMapOpts; @@ -102,14 +107,18 @@ export class VegaMapView extends VegaBaseView { // maxBounds = L.latLngBounds(L.latLng(b[1], b[0]), L.latLng(b[3], b[2])); // } - this._kibanaMap = new KibanaMap(this._$container.get(0), { - zoom, - minZoom, - maxZoom, - center: [mapConfig.latitude, mapConfig.longitude], - zoomControl: mapConfig.zoomControl, - scrollWheelZoom: mapConfig.scrollWheelZoom, - }); + this._kibanaMap = new KibanaMap( + this._$container.get(0), + { + zoom, + minZoom, + maxZoom, + center: [mapConfig.latitude, mapConfig.longitude], + zoomControl: mapConfig.zoomControl, + scrollWheelZoom: mapConfig.scrollWheelZoom, + }, + this.services + ); if (baseMapOpts) { this._kibanaMap.setBaseLayer({ diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js index 96835ef3b10bc..a6e911de7f0cb 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js @@ -116,7 +116,8 @@ export const createVegaVisualization = ({ serviceSettings }) => }; if (vegaParser.useMap) { - this._vegaView = new VegaMapView(vegaViewParams); + const services = { toastService: getNotifications().toasts }; + this._vegaView = new VegaMapView(vegaViewParams, services); } else { this._vegaView = new VegaView(vegaViewParams); } diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 0779d6472671c..33a7fdad065b4 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -309,6 +309,12 @@ export const npSetup = { registerAlias: sinon.fake(), hideTypes: sinon.fake(), }, + + mapsLegacy: { + serviceSettings: sinon.fake(), + getPrecision: sinon.fake(), + getZoomPrecision: sinon.fake(), + }, }, }; diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index cdd7e1a994912..21b80e827e4c2 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -68,6 +68,7 @@ import { VisualizationsSetup, VisualizationsStart, } from '../../../../plugins/visualizations/public'; +import { MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public'; export interface PluginsSetup { bfetch: BfetchPublicSetup; @@ -90,6 +91,7 @@ export interface PluginsSetup { visualizations: VisualizationsSetup; telemetry?: TelemetryPluginSetup; savedObjectsManagement: SavedObjectsManagementPluginSetup; + mapsLegacy: MapsLegacyPluginSetup; indexPatternManagement: IndexPatternManagementSetup; } diff --git a/src/legacy/ui/public/vis/map/service_settings.js b/src/legacy/ui/public/vis/map/service_settings.js deleted file mode 100644 index a014aeb182c67..0000000000000 --- a/src/legacy/ui/public/vis/map/service_settings.js +++ /dev/null @@ -1,256 +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 { uiModules } from '../../modules'; -import _ from 'lodash'; -import MarkdownIt from 'markdown-it'; -import { ORIGIN } from '../../../../core_plugins/tile_map/common/origin'; -import { EMSClient } from '@elastic/ems-client'; -import { i18n } from '@kbn/i18n'; -import 'angular-sanitize'; - -const markdownIt = new MarkdownIt({ - html: false, - linkify: true, -}); - -const TMS_IN_YML_ID = 'TMS in config/kibana.yml'; - -uiModules - .get('kibana', ['ngSanitize']) - .service('serviceSettings', function($sanitize, mapConfig, tilemapsConfig, kbnVersion) { - const attributionFromConfig = $sanitize( - markdownIt.render(tilemapsConfig.deprecated.config.options.attribution || '') - ); - const tmsOptionsFromConfig = _.assign({}, tilemapsConfig.deprecated.config.options, { - attribution: attributionFromConfig, - }); - - class ServiceSettings { - constructor() { - this._showZoomMessage = true; - this._emsClient = new EMSClient({ - language: i18n.getLocale(), - appVersion: kbnVersion, - appName: 'kibana', - fileApiUrl: mapConfig.emsFileApiUrl, - tileApiUrl: mapConfig.emsTileApiUrl, - htmlSanitizer: $sanitize, - landingPageUrl: mapConfig.emsLandingPageUrl, - // Wrap to avoid errors passing window fetch - fetchFunction: function(...args) { - return fetch(...args); - }, - }); - } - - shouldShowZoomMessage({ origin }) { - return origin === ORIGIN.EMS && this._showZoomMessage; - } - - disableZoomMessage() { - this._showZoomMessage = false; - } - - __debugStubManifestCalls(manifestRetrieval) { - const oldGetManifest = this._emsClient.getManifest; - this._emsClient.getManifest = manifestRetrieval; - return { - removeStub: () => { - delete this._emsClient.getManifest; - //not strictly necessary since this is prototype method - if (this._emsClient.getManifest !== oldGetManifest) { - this._emsClient.getManifest = oldGetManifest; - } - }, - }; - } - - async getFileLayers() { - if (!mapConfig.includeElasticMapsService) { - return []; - } - - const fileLayers = await this._emsClient.getFileLayers(); - return fileLayers.map(fileLayer => { - //backfill to older settings - const format = fileLayer.getDefaultFormatType(); - const meta = fileLayer.getDefaultFormatMeta(); - - return { - name: fileLayer.getDisplayName(), - origin: fileLayer.getOrigin(), - id: fileLayer.getId(), - created_at: fileLayer.getCreatedAt(), - attribution: fileLayer.getHTMLAttribution(), - fields: fileLayer.getFieldsInLanguage(), - format: format, //legacy: format and meta are split up - meta: meta, //legacy, format and meta are split up - }; - }); - } - - /** - * Returns all the services published by EMS (if configures) - * It also includes the service configured in tilemap (override) - */ - async getTMSServices() { - let allServices = []; - if (tilemapsConfig.deprecated.isOverridden) { - //use tilemap.* settings from yml - const tmsService = _.cloneDeep(tmsOptionsFromConfig); - tmsService.id = TMS_IN_YML_ID; - tmsService.origin = ORIGIN.KIBANA_YML; - allServices.push(tmsService); - } - - if (mapConfig.includeElasticMapsService) { - const servicesFromManifest = await this._emsClient.getTMSServices(); - const strippedServiceFromManifest = await Promise.all( - servicesFromManifest - .filter(tmsService => tmsService.getId() === mapConfig.emsTileLayerId.bright) - .map(async tmsService => { - //shim for compatibility - const shim = { - origin: tmsService.getOrigin(), - id: tmsService.getId(), - minZoom: await tmsService.getMinZoom(), - maxZoom: await tmsService.getMaxZoom(), - attribution: tmsService.getHTMLAttribution(), - }; - return shim; - }) - ); - allServices = allServices.concat(strippedServiceFromManifest); - } - - return allServices; - } - - /** - * Add optional query-parameters to all requests - * - * @param additionalQueryParams - */ - addQueryParams(additionalQueryParams) { - this._emsClient.addQueryParams(additionalQueryParams); - } - - async getEMSHotLink(fileLayerConfig) { - const fileLayers = await this._emsClient.getFileLayers(); - const layer = fileLayers.find(fileLayer => { - const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy - const hasIdById = fileLayer.hasId(fileLayerConfig.id); - return hasIdByName || hasIdById; - }); - return layer ? layer.getEMSHotLink() : null; - } - - async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) { - const tmsServices = await this._emsClient.getTMSServices(); - const emsTileLayerId = mapConfig.emsTileLayerId; - let serviceId; - if (isDarkMode) { - serviceId = emsTileLayerId.dark; - } else { - if (isDesaturated) { - serviceId = emsTileLayerId.desaturated; - } else { - serviceId = emsTileLayerId.bright; - } - } - const tmsService = tmsServices.find(service => { - return service.getId() === serviceId; - }); - return { - url: await tmsService.getUrlTemplate(), - minZoom: await tmsService.getMinZoom(), - maxZoom: await tmsService.getMaxZoom(), - attribution: await tmsService.getHTMLAttribution(), - origin: ORIGIN.EMS, - }; - } - - async getAttributesForTMSLayer(tmsServiceConfig, isDesaturated, isDarkMode) { - if (tmsServiceConfig.origin === ORIGIN.EMS) { - return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); - } else if (tmsServiceConfig.origin === ORIGIN.KIBANA_YML) { - const config = tilemapsConfig.deprecated.config; - const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); - return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; - } else { - //this is an older config. need to resolve this dynamically. - if (tmsServiceConfig.id === TMS_IN_YML_ID) { - const config = tilemapsConfig.deprecated.config; - const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); - return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; - } else { - //assume ems - return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); - } - } - } - - async _getFileUrlFromEMS(fileLayerConfig) { - const fileLayers = await this._emsClient.getFileLayers(); - const layer = fileLayers.find(fileLayer => { - const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy - const hasIdById = fileLayer.hasId(fileLayerConfig.id); - return hasIdByName || hasIdById; - }); - - if (layer) { - return layer.getDefaultFormatUrl(); - } else { - throw new Error(`File ${fileLayerConfig.name} not recognized`); - } - } - - async getUrlForRegionLayer(fileLayerConfig) { - let url; - if (fileLayerConfig.origin === ORIGIN.EMS) { - url = this._getFileUrlFromEMS(fileLayerConfig); - } else if ( - fileLayerConfig.layerId && - fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`) - ) { - //fallback for older saved objects - url = this._getFileUrlFromEMS(fileLayerConfig); - } else if ( - fileLayerConfig.layerId && - fileLayerConfig.layerId.startsWith(`${ORIGIN.KIBANA_YML}.`) - ) { - //fallback for older saved objects - url = fileLayerConfig.url; - } else { - //generic fallback - url = fileLayerConfig.url; - } - return url; - } - - async getJsonForRegionLayer(fileLayerConfig) { - const url = await this.getUrlForRegionLayer(fileLayerConfig); - const response = await fetch(url); - return await response.json(); - } - } - - return new ServiceSettings(); - }); diff --git a/src/plugins/maps_legacy/kibana.json b/src/plugins/maps_legacy/kibana.json new file mode 100644 index 0000000000000..d66be2b156bb9 --- /dev/null +++ b/src/plugins/maps_legacy/kibana.json @@ -0,0 +1,6 @@ +{ + "id": "mapsLegacy", + "version": "8.0.0", + "kibanaVersion": "kibana", + "ui": true +} diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_files.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_files.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector_source.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector_source.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector_source.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector_source.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_dark.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_dark.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json diff --git a/src/legacy/ui/public/vis/__tests__/map/kibana_map.js b/src/plugins/maps_legacy/public/__tests__/map/kibana_map.js similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/kibana_map.js rename to src/plugins/maps_legacy/public/__tests__/map/kibana_map.js diff --git a/src/legacy/ui/public/vis/__tests__/map/service_settings.js b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js similarity index 99% rename from src/legacy/ui/public/vis/__tests__/map/service_settings.js rename to src/plugins/maps_legacy/public/__tests__/map/service_settings.js index 61925760457c6..a9272ea396639 100644 --- a/src/legacy/ui/public/vis/__tests__/map/service_settings.js +++ b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js @@ -26,7 +26,7 @@ import EMS_TILES from './ems_mocks/sample_tiles.json'; import EMS_STYLE_ROAD_MAP_BRIGHT from './ems_mocks/sample_style_bright'; import EMS_STYLE_ROAD_MAP_DESATURATED from './ems_mocks/sample_style_desaturated'; import EMS_STYLE_DARK_MAP from './ems_mocks/sample_style_dark'; -import { ORIGIN } from '../../../../../core_plugins/tile_map/common/origin'; +import { ORIGIN } from '../../common/origin'; describe('service_settings (FKA tilemaptest)', function() { let serviceSettings; diff --git a/src/legacy/ui/public/vis/_index.scss b/src/plugins/maps_legacy/public/_index.scss similarity index 100% rename from src/legacy/ui/public/vis/_index.scss rename to src/plugins/maps_legacy/public/_index.scss diff --git a/src/legacy/core_plugins/vis_type_vega/public/shim/index.ts b/src/plugins/maps_legacy/public/common/origin.ts similarity index 90% rename from src/legacy/core_plugins/vis_type_vega/public/shim/index.ts rename to src/plugins/maps_legacy/public/common/origin.ts index cfc7b62ff4f86..fdf74cae4ba68 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/shim/index.ts +++ b/src/plugins/maps_legacy/public/common/origin.ts @@ -17,4 +17,7 @@ * under the License. */ -export * from './legacy_dependencies_plugin'; +export const ORIGIN = { + EMS: 'elastic_maps_service', + KIBANA_YML: 'self_hosted', +}; diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts new file mode 100644 index 0000000000000..861f67006ad83 --- /dev/null +++ b/src/plugins/maps_legacy/public/index.ts @@ -0,0 +1,61 @@ +/* + * 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 { MapsLegacyPlugin } from './plugin'; +// @ts-ignore +import * as colorUtil from './map/color_util'; +// @ts-ignore +import { KibanaMap } from './map/kibana_map'; +// @ts-ignore +import { KibanaMapLayer } from './map/kibana_map_layer'; +// @ts-ignore +import { convertToGeoJson } from './map/convert_to_geojson'; +// @ts-ignore +import { scaleBounds, getPrecision, geoContains } from './map/decode_geo_hash'; +// @ts-ignore +import { + VectorLayer, + FileLayerField, + FileLayer, + TmsLayer, + IServiceSettings, +} from './map/service_settings'; + +export function plugin() { + return new MapsLegacyPlugin(); +} + +/** @public */ +export { + scaleBounds, + getPrecision, + geoContains, + colorUtil, + convertToGeoJson, + IServiceSettings, + KibanaMap, + KibanaMapLayer, + VectorLayer, + FileLayerField, + FileLayer, + TmsLayer, +}; + +export type MapsLegacyPluginSetup = ReturnType<MapsLegacyPlugin['setup']>; +export type MapsLegacyPluginStart = ReturnType<MapsLegacyPlugin['start']>; diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy_imports.ts b/src/plugins/maps_legacy/public/kibana_services.js similarity index 64% rename from src/legacy/core_plugins/vis_type_vega/public/legacy_imports.ts rename to src/plugins/maps_legacy/public/kibana_services.js index b868321d6310f..815c6f9e5651f 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy_imports.ts +++ b/src/plugins/maps_legacy/public/kibana_services.js @@ -17,7 +17,14 @@ * under the License. */ -// @ts-ignore -export { KibanaMapLayer } from 'ui/vis/map/kibana_map_layer'; -// @ts-ignore -export { KibanaMap } from 'ui/vis/map/kibana_map'; +let toast; +export const setToasts = notificationToast => (toast = notificationToast); +export const getToasts = () => toast; + +let uiSettings; +export const setUiSettings = coreUiSettings => (uiSettings = coreUiSettings); +export const getUiSettings = () => uiSettings; + +let getInjectedVar; +export const setInjectedVarFunc = getInjectedVarFunc => (getInjectedVar = getInjectedVarFunc); +export const getInjectedVarFunc = () => getInjectedVar; diff --git a/src/legacy/ui/public/vis/map/_index.scss b/src/plugins/maps_legacy/public/map/_index.scss similarity index 100% rename from src/legacy/ui/public/vis/map/_index.scss rename to src/plugins/maps_legacy/public/map/_index.scss diff --git a/src/legacy/ui/public/vis/map/_leaflet_overrides.scss b/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss similarity index 100% rename from src/legacy/ui/public/vis/map/_leaflet_overrides.scss rename to src/plugins/maps_legacy/public/map/_leaflet_overrides.scss diff --git a/src/legacy/ui/public/vis/map/_legend.scss b/src/plugins/maps_legacy/public/map/_legend.scss similarity index 100% rename from src/legacy/ui/public/vis/map/_legend.scss rename to src/plugins/maps_legacy/public/map/_legend.scss diff --git a/src/legacy/ui/public/vis/map/color_util.js b/src/plugins/maps_legacy/public/map/color_util.js similarity index 100% rename from src/legacy/ui/public/vis/map/color_util.js rename to src/plugins/maps_legacy/public/map/color_util.js diff --git a/src/legacy/ui/public/vis/map/convert_to_geojson.js b/src/plugins/maps_legacy/public/map/convert_to_geojson.js similarity index 100% rename from src/legacy/ui/public/vis/map/convert_to_geojson.js rename to src/plugins/maps_legacy/public/map/convert_to_geojson.js diff --git a/src/legacy/ui/public/vis/map/decode_geo_hash.test.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts similarity index 100% rename from src/legacy/ui/public/vis/map/decode_geo_hash.test.ts rename to src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts diff --git a/src/legacy/ui/public/vis/map/decode_geo_hash.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts similarity index 79% rename from src/legacy/ui/public/vis/map/decode_geo_hash.ts rename to src/plugins/maps_legacy/public/map/decode_geo_hash.ts index 3f8430b8628d7..8c39ada03a46b 100644 --- a/src/legacy/ui/public/vis/map/decode_geo_hash.ts +++ b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts @@ -17,11 +17,8 @@ * under the License. */ -import chrome from 'ui/chrome'; import _ from 'lodash'; -const config = chrome.getUiSettingsClient(); - interface DecodedGeoHash { latitude: number[]; longitude: number[]; @@ -74,6 +71,10 @@ function refineInterval(interval: number[], cd: number, mask: number) { } } +export function geohashColumns(precision: number): number { + return geohashCells(precision, 0); +} + /** * Get the number of geohash cells for a given precision * @@ -90,51 +91,6 @@ function geohashCells(precision: number, axis: number) { return cells; } -/** - * Get the number of geohash columns (world-wide) for a given precision - * @param precision the geohash precision - * @returns {number} the number of columns - */ -export function geohashColumns(precision: number): number { - return geohashCells(precision, 0); -} - -const defaultPrecision = 2; -const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; -/** - * Map Leaflet zoom levels to geohash precision levels. - * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide. - */ -export const zoomPrecision: any = {}; -const minGeohashPixels = 16; - -for (let zoom = 0; zoom <= 21; zoom += 1) { - const worldPixels = 256 * Math.pow(2, zoom); - zoomPrecision[zoom] = 1; - for (let precision = 2; precision <= maxPrecision; precision += 1) { - const columns = geohashColumns(precision); - if (worldPixels / columns >= minGeohashPixels) { - zoomPrecision[zoom] = precision; - } else { - break; - } - } -} - -export function getPrecision(val: string) { - let precision = parseInt(val, 10); - - if (Number.isNaN(precision)) { - precision = defaultPrecision; - } - - if (precision > maxPrecision) { - return maxPrecision; - } - - return precision; -} - interface GeoBoundingBoxCoordinate { lat: number; lon: number; diff --git a/src/legacy/ui/public/vis/map/grid_dimensions.js b/src/plugins/maps_legacy/public/map/grid_dimensions.js similarity index 100% rename from src/legacy/ui/public/vis/map/grid_dimensions.js rename to src/plugins/maps_legacy/public/map/grid_dimensions.js diff --git a/src/legacy/ui/public/vis/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js similarity index 96% rename from src/legacy/ui/public/vis/map/kibana_map.js rename to src/plugins/maps_legacy/public/map/kibana_map.js index bc581b1a8fbaf..1c4d0882cb7da 100644 --- a/src/legacy/ui/public/vis/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -24,7 +24,7 @@ import $ from 'jquery'; import _ from 'lodash'; import { zoomToPrecision } from './zoom_to_precision'; import { i18n } from '@kbn/i18n'; -import { ORIGIN } from '../../../../core_plugins/tile_map/common/origin'; +import { ORIGIN } from '../common/origin'; function makeFitControl(fitContainer, kibanaMap) { const FitControl = L.Control.extend({ @@ -39,7 +39,7 @@ function makeFitControl(fitContainer, kibanaMap) { onAdd: function(leafletMap) { this._leafletMap = leafletMap; const fitDatBoundsLabel = i18n.translate( - 'common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel', + 'maps_legacy.kibanaMap.leaflet.fitDataBoundsAriaLabel', { defaultMessage: 'Fit Data Bounds' } ); $(this._fitContainer) @@ -101,7 +101,7 @@ function makeLegendControl(container, kibanaMap, position) { * Serves as simple abstraction for leaflet as well. */ export class KibanaMap extends EventEmitter { - constructor(containerNode, options) { + constructor(containerNode, options, services) { super(); this._containerNode = containerNode; this._leafletBaseLayer = null; @@ -116,6 +116,7 @@ export class KibanaMap extends EventEmitter { this._layers = []; this._listeners = []; this._showTooltip = false; + this.toastService = services ? services.toastService : null; const leafletOptions = { minZoom: options.minZoom, @@ -482,15 +483,21 @@ export class KibanaMap extends EventEmitter { } _addMaxZoomMessage = layer => { - const zoomWarningMsg = createZoomWarningMsg(this.getZoomLevel, this.getMaxZoomLevel); + if (this.toastService) { + const zoomWarningMsg = createZoomWarningMsg( + this.toastService, + this.getZoomLevel, + this.getMaxZoomLevel + ); - this._leafletMap.on('zoomend', zoomWarningMsg); - this._containerNode.setAttribute('data-test-subj', 'zoomWarningEnabled'); + this._leafletMap.on('zoomend', zoomWarningMsg); + this._containerNode.setAttribute('data-test-subj', 'zoomWarningEnabled'); - layer.on('remove', () => { - this._leafletMap.off('zoomend', zoomWarningMsg); - this._containerNode.removeAttribute('data-test-subj'); - }); + layer.on('remove', () => { + this._leafletMap.off('zoomend', zoomWarningMsg); + this._containerNode.removeAttribute('data-test-subj'); + }); + } }; setLegendPosition(position) { diff --git a/src/legacy/ui/public/vis/map/kibana_map_layer.js b/src/plugins/maps_legacy/public/map/kibana_map_layer.js similarity index 100% rename from src/legacy/ui/public/vis/map/kibana_map_layer.js rename to src/plugins/maps_legacy/public/map/kibana_map_layer.js diff --git a/src/legacy/ui/public/vis/map/map_messages.js b/src/plugins/maps_legacy/public/map/map_messages.js similarity index 93% rename from src/legacy/ui/public/vis/map/map_messages.js rename to src/plugins/maps_legacy/public/map/map_messages.js index 211796d734958..7422fa71280fb 100644 --- a/src/legacy/ui/public/vis/map/map_messages.js +++ b/src/plugins/maps_legacy/public/map/map_messages.js @@ -17,11 +17,10 @@ * under the License. */ -import { toastNotifications } from 'ui/notify'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; -import { toMountPoint } from '../../../../../plugins/kibana_react/public'; +import { toMountPoint } from '../../../kibana_react/public'; export const createZoomWarningMsg = (function() { let disableZoomMsg = false; @@ -40,7 +39,7 @@ export const createZoomWarningMsg = (function() { <div> <p> <FormattedMessage - id="common.ui.vis.kibanaMap.zoomWarning" + id="maps_legacy.kibanaMap.zoomWarning" defaultMessage="You've reached the maximum number of zoom levels. To zoom all the way in, upgrade to the {defaultDistribution} of Elasticsearch and Kibana. You'll get @@ -105,12 +104,12 @@ export const createZoomWarningMsg = (function() { 'data-test-subj': 'maxZoomWarning', }; - return (getZoomLevel, getMaxZoomLevel) => { + return (toastService, getZoomLevel, getMaxZoomLevel) => { return () => { const zoomLevel = getZoomLevel(); const maxMapZoom = getMaxZoomLevel(); if (!disableZoomMsg && zoomLevel === maxMapZoom) { - toastNotifications.addDanger(zoomToast); + toastService.addDanger(zoomToast); } }; }; diff --git a/src/plugins/maps_legacy/public/map/precision.ts b/src/plugins/maps_legacy/public/map/precision.ts new file mode 100644 index 0000000000000..a1b3b72f201a4 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/precision.ts @@ -0,0 +1,74 @@ +/* + * 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. + */ + +// @ts-ignore +import { getUiSettings } from '../kibana_services'; +import { geohashColumns } from './decode_geo_hash'; + +/** + * Get the number of geohash columns (world-wide) for a given precision + * @param precision the geohash precision + * @returns {number} the number of columns + */ + +const DEFAULT_PRECISION = 2; + +function getMaxPrecision() { + const config = getUiSettings(); + return parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; +} + +export function getZoomPrecision() { + /** + * Map Leaflet zoom levels to geohash precision levels. + * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide. + */ + const zoomPrecision: any = {}; + const minGeohashPixels = 16; + const maxPrecision = getMaxPrecision(); + + for (let zoom = 0; zoom <= 21; zoom += 1) { + const worldPixels = 256 * Math.pow(2, zoom); + zoomPrecision[zoom] = 1; + for (let precision = 2; precision <= maxPrecision; precision += 1) { + const columns = geohashColumns(precision); + if (worldPixels / columns >= minGeohashPixels) { + zoomPrecision[zoom] = precision; + } else { + break; + } + } + } + return zoomPrecision; +} + +export function getPrecision(val: string) { + let precision = parseInt(val, 10); + const maxPrecision = getMaxPrecision(); + + if (Number.isNaN(precision)) { + precision = DEFAULT_PRECISION; + } + + if (precision > maxPrecision) { + return maxPrecision; + } + + return precision; +} diff --git a/src/legacy/ui/public/vis/map/service_settings.d.ts b/src/plugins/maps_legacy/public/map/service_settings.d.ts similarity index 97% rename from src/legacy/ui/public/vis/map/service_settings.d.ts rename to src/plugins/maps_legacy/public/map/service_settings.d.ts index 6766000861e47..e265accaeb8fd 100644 --- a/src/legacy/ui/public/vis/map/service_settings.d.ts +++ b/src/plugins/maps_legacy/public/map/service_settings.d.ts @@ -44,7 +44,7 @@ export interface VectorLayer extends FileLayer { isEMS: boolean; } -export interface ServiceSettings { +export interface IServiceSettings { getEMSHotLink(layer: FileLayer): Promise<string>; getTMSServices(): Promise<TmsLayer[]>; getFileLayers(): Promise<FileLayer[]>; diff --git a/src/plugins/maps_legacy/public/map/service_settings.js b/src/plugins/maps_legacy/public/map/service_settings.js new file mode 100644 index 0000000000000..11c853d39e107 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/service_settings.js @@ -0,0 +1,254 @@ +/* + * 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 _ from 'lodash'; +import MarkdownIt from 'markdown-it'; +import { EMSClient } from '@elastic/ems-client'; +import { i18n } from '@kbn/i18n'; +import { getInjectedVarFunc } from '../kibana_services'; +import { ORIGIN } from '../common/origin'; + +const TMS_IN_YML_ID = 'TMS in config/kibana.yml'; + +export class ServiceSettings { + constructor() { + const getInjectedVar = getInjectedVarFunc(); + this.mapConfig = getInjectedVar('mapConfig'); + this.tilemapsConfig = getInjectedVar('tilemapsConfig'); + const kbnVersion = getInjectedVar('version'); + + this._showZoomMessage = true; + this._emsClient = new EMSClient({ + language: i18n.getLocale(), + appVersion: kbnVersion, + appName: 'kibana', + fileApiUrl: this.mapConfig.emsFileApiUrl, + tileApiUrl: this.mapConfig.emsTileApiUrl, + landingPageUrl: this.mapConfig.emsLandingPageUrl, + // Wrap to avoid errors passing window fetch + fetchFunction: function(...args) { + return fetch(...args); + }, + }); + this.getTMSOptions(); + } + + getTMSOptions() { + const markdownIt = new MarkdownIt({ + html: false, + linkify: true, + }); + + // TMS attribution + const attributionFromConfig = _.escape( + markdownIt.render(this.tilemapsConfig.deprecated.config.options.attribution || '') + ); + // TMS Options + this.tmsOptionsFromConfig = _.assign({}, this.tilemapsConfig.deprecated.config.options, { + attribution: attributionFromConfig, + }); + } + + shouldShowZoomMessage({ origin }) { + return origin === ORIGIN.EMS && this._showZoomMessage; + } + + disableZoomMessage() { + this._showZoomMessage = false; + } + + __debugStubManifestCalls(manifestRetrieval) { + const oldGetManifest = this._emsClient.getManifest; + this._emsClient.getManifest = manifestRetrieval; + return { + removeStub: () => { + delete this._emsClient.getManifest; + //not strictly necessary since this is prototype method + if (this._emsClient.getManifest !== oldGetManifest) { + this._emsClient.getManifest = oldGetManifest; + } + }, + }; + } + + async getFileLayers() { + if (!this.mapConfig.includeElasticMapsService) { + return []; + } + + const fileLayers = await this._emsClient.getFileLayers(); + return fileLayers.map(fileLayer => { + //backfill to older settings + const format = fileLayer.getDefaultFormatType(); + const meta = fileLayer.getDefaultFormatMeta(); + + return { + name: fileLayer.getDisplayName(), + origin: fileLayer.getOrigin(), + id: fileLayer.getId(), + created_at: fileLayer.getCreatedAt(), + attribution: fileLayer.getHTMLAttribution(), + fields: fileLayer.getFieldsInLanguage(), + format: format, //legacy: format and meta are split up + meta: meta, //legacy, format and meta are split up + }; + }); + } + + /** + * Returns all the services published by EMS (if configures) + * It also includes the service configured in tilemap (override) + */ + async getTMSServices() { + let allServices = []; + if (this.tilemapsConfig.deprecated.isOverridden) { + //use tilemap.* settings from yml + const tmsService = _.cloneDeep(this.tmsOptionsFromConfig); + tmsService.id = TMS_IN_YML_ID; + tmsService.origin = ORIGIN.KIBANA_YML; + allServices.push(tmsService); + } + + if (this.mapConfig.includeElasticMapsService) { + const servicesFromManifest = await this._emsClient.getTMSServices(); + const strippedServiceFromManifest = await Promise.all( + servicesFromManifest + .filter(tmsService => tmsService.getId() === this.mapConfig.emsTileLayerId.bright) + .map(async tmsService => { + //shim for compatibility + return { + origin: tmsService.getOrigin(), + id: tmsService.getId(), + minZoom: await tmsService.getMinZoom(), + maxZoom: await tmsService.getMaxZoom(), + attribution: tmsService.getHTMLAttribution(), + }; + }) + ); + allServices = allServices.concat(strippedServiceFromManifest); + } + + return allServices; + } + + /** + * Add optional query-parameters to all requests + * + * @param additionalQueryParams + */ + addQueryParams(additionalQueryParams) { + this._emsClient.addQueryParams(additionalQueryParams); + } + + async getEMSHotLink(fileLayerConfig) { + const fileLayers = await this._emsClient.getFileLayers(); + const layer = fileLayers.find(fileLayer => { + const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy + const hasIdById = fileLayer.hasId(fileLayerConfig.id); + return hasIdByName || hasIdById; + }); + return layer ? layer.getEMSHotLink() : null; + } + + async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) { + const tmsServices = await this._emsClient.getTMSServices(); + const emsTileLayerId = this.mapConfig.emsTileLayerId; + let serviceId; + if (isDarkMode) { + serviceId = emsTileLayerId.dark; + } else { + if (isDesaturated) { + serviceId = emsTileLayerId.desaturated; + } else { + serviceId = emsTileLayerId.bright; + } + } + const tmsService = tmsServices.find(service => { + return service.getId() === serviceId; + }); + return { + url: await tmsService.getUrlTemplate(), + minZoom: await tmsService.getMinZoom(), + maxZoom: await tmsService.getMaxZoom(), + attribution: await tmsService.getHTMLAttribution(), + origin: ORIGIN.EMS, + }; + } + + async getAttributesForTMSLayer(tmsServiceConfig, isDesaturated, isDarkMode) { + if (tmsServiceConfig.origin === ORIGIN.EMS) { + return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); + } else if (tmsServiceConfig.origin === ORIGIN.KIBANA_YML) { + const config = this.tilemapsConfig.deprecated.config; + const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); + return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; + } else { + //this is an older config. need to resolve this dynamically. + if (tmsServiceConfig.id === TMS_IN_YML_ID) { + const config = this.tilemapsConfig.deprecated.config; + const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); + return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; + } else { + //assume ems + return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); + } + } + } + + async _getFileUrlFromEMS(fileLayerConfig) { + const fileLayers = await this._emsClient.getFileLayers(); + const layer = fileLayers.find(fileLayer => { + const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy + const hasIdById = fileLayer.hasId(fileLayerConfig.id); + return hasIdByName || hasIdById; + }); + + if (layer) { + return layer.getDefaultFormatUrl(); + } else { + throw new Error(`File ${fileLayerConfig.name} not recognized`); + } + } + + async getUrlForRegionLayer(fileLayerConfig) { + let url; + if (fileLayerConfig.origin === ORIGIN.EMS) { + url = this._getFileUrlFromEMS(fileLayerConfig); + } else if (fileLayerConfig.layerId && fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`)) { + //fallback for older saved objects + url = this._getFileUrlFromEMS(fileLayerConfig); + } else if ( + fileLayerConfig.layerId && + fileLayerConfig.layerId.startsWith(`${ORIGIN.KIBANA_YML}.`) + ) { + //fallback for older saved objects + url = fileLayerConfig.url; + } else { + //generic fallback + url = fileLayerConfig.url; + } + return url; + } + + async getJsonForRegionLayer(fileLayerConfig) { + const url = await this.getUrlForRegionLayer(fileLayerConfig); + const response = await fetch(url); + return await response.json(); + } +} diff --git a/src/legacy/ui/public/vis/map/zoom_to_precision.ts b/src/plugins/maps_legacy/public/map/zoom_to_precision.ts similarity index 100% rename from src/legacy/ui/public/vis/map/zoom_to_precision.ts rename to src/plugins/maps_legacy/public/map/zoom_to_precision.ts diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts new file mode 100644 index 0000000000000..751be65e1dbf6 --- /dev/null +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -0,0 +1,57 @@ +/* + * 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. + */ + +// @ts-ignore +import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; +// @ts-ignore +import { setToasts, setUiSettings, setInjectedVarFunc } from './kibana_services'; +// @ts-ignore +import { ServiceSettings } from './map/service_settings'; +// @ts-ignore +import { getPrecision, getZoomPrecision } from './map/precision'; +import { MapsLegacyPluginSetup, MapsLegacyPluginStart } from './index'; + +/** + * These are the interfaces with your public contracts. You should export these + * for other plugins to use in _their_ `SetupDeps`/`StartDeps` interfaces. + * @public + */ + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface MapsLegacySetupDependencies {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface MapsLegacyStartDependencies {} + +export class MapsLegacyPlugin implements Plugin<MapsLegacyPluginSetup, MapsLegacyPluginStart> { + constructor() {} + + public setup(core: CoreSetup, plugins: MapsLegacySetupDependencies) { + setToasts(core.notifications.toasts); + setUiSettings(core.uiSettings); + setInjectedVarFunc(core.injectedMetadata.getInjectedVar); + + return { + serviceSettings: new ServiceSettings(), + getZoomPrecision, + getPrecision, + }; + } + + public start(core: CoreStart, plugins: MapsLegacyStartDependencies) {} +} diff --git a/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js b/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js index 45764016f0311..294bc31e3893e 100644 --- a/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js +++ b/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js @@ -4,20 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import uiRoutes from 'ui/routes'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -import 'ui/vis/map/service_settings'; +import { npSetup } from 'ui/new_platform'; -uiRoutes.addSetupWork(function($injector, serviceSettings) { - const tileMapPluginInfo = xpackInfo.get('features.tilemap'); +const tileMapPluginInfo = xpackInfo.get('features.tilemap'); - if (!tileMapPluginInfo) { - return; - } - - if (!tileMapPluginInfo.license.active || !tileMapPluginInfo.license.valid) { - return; - } +if (tileMapPluginInfo && (tileMapPluginInfo.license.active || tileMapPluginInfo.license.valid)) { + const { serviceSettings } = npSetup.plugins.mapsLegacy; serviceSettings.addQueryParams({ license: tileMapPluginInfo.license.uid }); serviceSettings.disableZoomMessage(); -}); +} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 3cebde793a085..a8574971426f5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -319,8 +319,6 @@ "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "セッションがいっぱいで安全に削除できるアイテムが見つからないため、Kibana は履歴アイテムを保存できません。\n\nこれは大抵新規タブに移動することで解決されますが、より大きな問題が原因である可能性もあります。このメッセージが定期的に表示される場合は、{gitHubIssuesUrl} で問題を報告してください。", "common.ui.url.replacementFailedErrorMessage": "置換に失敗、未解決の表現式: {expr}", "common.ui.url.savedObjectIsMissingNotificationMessage": "保存されたオブジェクトがありません", - "common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel": "データバウンドを合わせる", - "common.ui.vis.kibanaMap.zoomWarning": "ズームレベルが最大に達しました。完全にズームインするには、Elasticsearch と Kibana の {defaultDistribution} にアップグレードしてください。{ems} でより多くのズームレベルが利用できます。または、独自のマップサーバーを構成できます。詳細は { wms } または { configSettings} をご覧ください。", "console.autocomplete.addMethodMetaText": "メソド", "console.consoleDisplayName": "コンソール", "console.consoleMenu.copyAsCurlMessage": "リクエストが URL としてコピーされました", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1daf66117e948..df5cccf1a9b97 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -319,8 +319,6 @@ "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "Kibana 无法将历史记录项存储在您的会话中,因为其已满,并且似乎没有任何可安全删除的项。\n\n通常可通过移至新的标签页来解决此问题,但这会导致更大的问题。如果您有规律地看到此消息,请在 {gitHubIssuesUrl} 提交问题。", "common.ui.url.replacementFailedErrorMessage": "替换失败,未解析的表达式:{expr}", "common.ui.url.savedObjectIsMissingNotificationMessage": "已保存对象缺失", - "common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel": "适应数据边界", - "common.ui.vis.kibanaMap.zoomWarning": "已达到缩放级别最大数目。要一直放大,请升级到 Elasticsearch 和 Kibana 的 {defaultDistribution}。您可以通过 {ems} 免费使用其他缩放级别。或者,您可以配置自己的地图服务器。请前往 { wms } 或 { configSettings} 以获取详细信息。", "console.autocomplete.addMethodMetaText": "方法", "console.consoleDisplayName": "控制台", "console.consoleMenu.copyAsCurlMessage": "请求已复制为 cURL", From 5bc233f3c733323834b669cc7ef4be809d12ddc6 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh <ahmadbamieh@gmail.com> Date: Mon, 13 Apr 2020 23:45:13 +0300 Subject: [PATCH 081/121] [Telemetry] force staging urls in tests (#63356) * specify telemetry url configs * opt out by default except where we are testing telemetry --- test/common/config.js | 4 ++++ x-pack/test/api_integration/config.js | 2 ++ x-pack/test/functional/config.js | 1 - x-pack/test/functional/config_security_basic.js | 1 - 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/common/config.js b/test/common/config.js index faf8cef027170..ca80dfb01012f 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -56,6 +56,10 @@ export default function() { `--elasticsearch.password=${kibanaServerTestUser.password}`, `--home.disableWelcomeScreen=true`, '--telemetry.banner=false', + '--telemetry.optIn=false', + // These are *very* important to have them pointing to staging + '--telemetry.url=https://telemetry-staging.elastic.co/xpack/v2/send', + '--telemetry.optInStatusUrl=https://telemetry-staging.elastic.co/opt_in_status/v2/send', `--server.maxPayloadBytes=1679958`, // newsfeed mock service `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'newsfeed')}`, diff --git a/x-pack/test/api_integration/config.js b/x-pack/test/api_integration/config.js index b62368bf2d608..0eac7c58044e6 100644 --- a/x-pack/test/api_integration/config.js +++ b/x-pack/test/api_integration/config.js @@ -27,6 +27,8 @@ export async function getApiIntegrationConfig({ readConfigFile }) { '--xpack.security.session.idleTimeout=3600000', // 1 hour '--optimize.enabled=false', '--xpack.endpoint.enabled=true', + '--telemetry.optIn=true', + '--xpack.endpoint.enabled=true', '--xpack.ingestManager.enabled=true', '--xpack.ingestManager.fleet.enabled=true', '--xpack.endpoint.alertResultListDefaultDateRange.from=2018-01-10T00:00:00.000Z', diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.js index bc9a67da731cc..f26110513a9b3 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.js @@ -85,7 +85,6 @@ export default async function({ readConfigFile }) { '--stats.maximumWaitTimeForAllCollectorsInS=1', '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions '--xpack.encryptedSavedObjects.encryptionKey="DkdXazszSCYexXqz4YktBGHCRkV6hyNK"', - '--telemetry.banner=false', '--timelion.ui.enabled=true', ], }, diff --git a/x-pack/test/functional/config_security_basic.js b/x-pack/test/functional/config_security_basic.js index 12d94e922a97c..2bb59796b5517 100644 --- a/x-pack/test/functional/config_security_basic.js +++ b/x-pack/test/functional/config_security_basic.js @@ -42,7 +42,6 @@ export default async function({ readConfigFile }) { ...kibanaCommonConfig.get('kbnTestServer.serverArgs'), '--server.uuid=5b2de169-2785-441b-ae8c-186a1936b17d', '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', // server restarts should not invalidate active sessions - '--telemetry.banner=false', ], }, uiSettings: { From 500b069efd2e344147169163983c4535b21fed8f Mon Sep 17 00:00:00 2001 From: Patrick Mueller <pmuellr@gmail.com> Date: Mon, 13 Apr 2020 17:41:22 -0400 Subject: [PATCH 082/121] [Alerting] set correct parameter for unauthented email action (#63086) PR https://github.com/elastic/kibana/pull/60839 added support for unauthenticated emails, but didn't actually do enough to make it work. This PR completes that support, and adds some tests. You can do manual testing now with [maildev](http://maildev.github.io/maildev/). --- .../server/builtin_action_types/email.test.ts | 107 ++++++++++- .../server/builtin_action_types/email.ts | 11 +- .../lib/send_email.test.ts | 175 ++++++++++++++++++ .../builtin_action_types/lib/send_email.ts | 22 ++- 4 files changed, 299 insertions(+), 16 deletions(-) create mode 100644 x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts diff --git a/x-pack/plugins/actions/server/builtin_action_types/email.test.ts b/x-pack/plugins/actions/server/builtin_action_types/email.test.ts index 469df4fd86e2c..658f8f3fd8cf9 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/email.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/email.test.ts @@ -255,7 +255,14 @@ describe('execute()', () => { services, }; sendEmailMock.mockReset(); - await actionType.executor(executorOptions); + const result = await actionType.executor(executorOptions); + expect(result).toMatchInlineSnapshot(` + Object { + "actionId": "some-id", + "data": undefined, + "status": "ok", + } + `); expect(sendEmailMock.mock.calls[0][1]).toMatchInlineSnapshot(` Object { "content": Object { @@ -282,4 +289,102 @@ describe('execute()', () => { } `); }); + + test('parameters are as expected with no auth', async () => { + const config: ActionTypeConfigType = { + service: null, + host: 'a host', + port: 42, + secure: true, + from: 'bob@example.com', + }; + const secrets: ActionTypeSecretsType = { + user: null, + password: null, + }; + const params: ActionParamsType = { + to: ['jim@example.com'], + cc: ['james@example.com'], + bcc: ['jimmy@example.com'], + subject: 'the subject', + message: 'a message to you', + }; + + const actionId = 'some-id'; + const executorOptions: ActionTypeExecutorOptions = { + actionId, + config, + params, + secrets, + services, + }; + sendEmailMock.mockReset(); + await actionType.executor(executorOptions); + expect(sendEmailMock.mock.calls[0][1]).toMatchInlineSnapshot(` + Object { + "content": Object { + "message": "a message to you", + "subject": "the subject", + }, + "routing": Object { + "bcc": Array [ + "jimmy@example.com", + ], + "cc": Array [ + "james@example.com", + ], + "from": "bob@example.com", + "to": Array [ + "jim@example.com", + ], + }, + "transport": Object { + "host": "a host", + "port": 42, + "secure": true, + }, + } + `); + }); + + test('returns expected result when an error is thrown', async () => { + const config: ActionTypeConfigType = { + service: null, + host: 'a host', + port: 42, + secure: true, + from: 'bob@example.com', + }; + const secrets: ActionTypeSecretsType = { + user: null, + password: null, + }; + const params: ActionParamsType = { + to: ['jim@example.com'], + cc: ['james@example.com'], + bcc: ['jimmy@example.com'], + subject: 'the subject', + message: 'a message to you', + }; + + const actionId = 'some-id'; + const executorOptions: ActionTypeExecutorOptions = { + actionId, + config, + params, + secrets, + services, + }; + sendEmailMock.mockReset(); + sendEmailMock.mockRejectedValue(new Error('wops')); + const result = await actionType.executor(executorOptions); + expect(result).toMatchInlineSnapshot(` + Object { + "actionId": "some-id", + "message": "error sending email", + "serviceMessage": "wops", + "status": "error", + } + `); + }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/email.ts b/x-pack/plugins/actions/server/builtin_action_types/email.ts index 7992920fdfcb4..ca8d089ad2946 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/email.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/email.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import nodemailerGetService from 'nodemailer/lib/well-known'; -import { sendEmail, JSON_TRANSPORT_SERVICE } from './lib/send_email'; +import { sendEmail, JSON_TRANSPORT_SERVICE, SendEmailOptions, Transport } from './lib/send_email'; import { portSchema } from './lib/schemas'; import { Logger } from '../../../../../src/core/server'; import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types'; @@ -143,7 +143,7 @@ async function executor( const secrets = execOptions.secrets as ActionTypeSecretsType; const params = execOptions.params as ActionParamsType; - const transport: any = {}; + const transport: Transport = {}; if (secrets.user != null) { transport.user = secrets.user; @@ -155,12 +155,13 @@ async function executor( if (config.service !== null) { transport.service = config.service; } else { - transport.host = config.host; - transport.port = config.port; + // already validated service or host/port is not null ... + transport.host = config.host!; + transport.port = config.port!; transport.secure = getSecureValue(config.secure, config.port); } - const sendEmailOptions = { + const sendEmailOptions: SendEmailOptions = { transport, routing: { from: config.from, diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts new file mode 100644 index 0000000000000..42160dc2fc22b --- /dev/null +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts @@ -0,0 +1,175 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('nodemailer', () => ({ + createTransport: jest.fn(), +})); + +import { Logger } from '../../../../../../src/core/server'; +import { sendEmail } from './send_email'; +import { loggingServiceMock } from '../../../../../../src/core/server/mocks'; +import nodemailer from 'nodemailer'; + +const createTransportMock = nodemailer.createTransport as jest.Mock; +const sendMailMockResult = { result: 'does not matter' }; +const sendMailMock = jest.fn(); + +const mockLogger = loggingServiceMock.create().get() as jest.Mocked<Logger>; + +describe('send_email module', () => { + beforeEach(() => { + jest.resetAllMocks(); + createTransportMock.mockReturnValue({ sendMail: sendMailMock }); + sendMailMock.mockResolvedValue(sendMailMockResult); + }); + + test('handles authenticated email using service', async () => { + const sendEmailOptions = getSendEmailOptions(); + const result = await sendEmail(mockLogger, sendEmailOptions); + expect(result).toBe(sendMailMockResult); + expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "auth": Object { + "pass": "changeme", + "user": "elastic", + }, + "service": "whatever", + }, + ] + `); + expect(sendMailMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "bcc": Array [], + "cc": Array [ + "bob@example.com", + "robert@example.com", + ], + "from": "fred@example.com", + "html": "<p>a message</p> + ", + "subject": "a subject", + "text": "a message", + "to": Array [ + "jim@example.com", + ], + }, + ] + `); + }); + + test('handles unauthenticated email using not secure host/port', async () => { + const sendEmailOptions = getSendEmailOptions(); + delete sendEmailOptions.transport.service; + delete sendEmailOptions.transport.user; + delete sendEmailOptions.transport.password; + sendEmailOptions.transport.host = 'example.com'; + sendEmailOptions.transport.port = 1025; + const result = await sendEmail(mockLogger, sendEmailOptions); + expect(result).toBe(sendMailMockResult); + expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "host": "example.com", + "port": 1025, + "secure": false, + "tls": Object { + "rejectUnauthorized": false, + }, + }, + ] + `); + expect(sendMailMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "bcc": Array [], + "cc": Array [ + "bob@example.com", + "robert@example.com", + ], + "from": "fred@example.com", + "html": "<p>a message</p> + ", + "subject": "a subject", + "text": "a message", + "to": Array [ + "jim@example.com", + ], + }, + ] + `); + }); + + test('handles unauthenticated email using secure host/port', async () => { + const sendEmailOptions = getSendEmailOptions(); + delete sendEmailOptions.transport.service; + delete sendEmailOptions.transport.user; + delete sendEmailOptions.transport.password; + sendEmailOptions.transport.host = 'example.com'; + sendEmailOptions.transport.port = 1025; + sendEmailOptions.transport.secure = true; + const result = await sendEmail(mockLogger, sendEmailOptions); + expect(result).toBe(sendMailMockResult); + expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "host": "example.com", + "port": 1025, + "secure": true, + }, + ] + `); + expect(sendMailMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "bcc": Array [], + "cc": Array [ + "bob@example.com", + "robert@example.com", + ], + "from": "fred@example.com", + "html": "<p>a message</p> + ", + "subject": "a subject", + "text": "a message", + "to": Array [ + "jim@example.com", + ], + }, + ] + `); + }); + + test('passes nodemailer exceptions to caller', async () => { + const sendEmailOptions = getSendEmailOptions(); + + sendMailMock.mockReset(); + sendMailMock.mockRejectedValue(new Error('wops')); + + await expect(sendEmail(mockLogger, sendEmailOptions)).rejects.toThrow('wops'); + }); +}); + +function getSendEmailOptions(): any { + return { + content: { + message: 'a message', + subject: 'a subject', + }, + routing: { + from: 'fred@example.com', + to: ['jim@example.com'], + cc: ['bob@example.com', 'robert@example.com'], + bcc: [], + }, + transport: { + service: 'whatever', + user: 'elastic', + password: 'changeme', + }, + }; +} diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts index 47d7aff8022ce..ffbf7485a8b0b 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts @@ -14,30 +14,30 @@ import { Logger } from '../../../../../../src/core/server'; // an email "service" which doesn't actually send, just returns what it would send export const JSON_TRANSPORT_SERVICE = '__json'; -interface SendEmailOptions { +export interface SendEmailOptions { transport: Transport; routing: Routing; content: Content; } // config validation ensures either service is set or host/port are set -interface Transport { - user: string; - password: string; +export interface Transport { + user?: string; + password?: string; service?: string; // see: https://nodemailer.com/smtp/well-known/ host?: string; port?: number; secure?: boolean; // see: https://nodemailer.com/smtp/#tls-options } -interface Routing { +export interface Routing { from: string; to: string[]; cc: string[]; bcc: string[]; } -interface Content { +export interface Content { subject: string; message: string; } @@ -49,12 +49,14 @@ export async function sendEmail(logger: Logger, options: SendEmailOptions): Prom const { from, to, cc, bcc } = routing; const { subject, message } = content; - const transportConfig: Record<string, any> = { - auth: { + const transportConfig: Record<string, any> = {}; + + if (user != null && password != null) { + transportConfig.auth = { user, pass: password, - }, - }; + }; + } if (service === JSON_TRANSPORT_SERVICE) { transportConfig.jsonTransport = true; From 3623875175720d867e1c37bb10e20d4e4aacb1d9 Mon Sep 17 00:00:00 2001 From: Nathan Reese <reese.nathan@gmail.com> Date: Mon, 13 Apr 2020 15:53:07 -0600 Subject: [PATCH 083/121] [Maps] fix bug where toggling Scaling type does not re-fetch data (#63326) * [Maps] fix bug where toggling Scaling type does not re-fetch data * reset to empty array instead of deleting * move setting of layer type to action creator instead of side effect of UPDATE_SOURCE_PROP * review feedback --- .../maps/public/actions/map_actions.js | 38 +++++++++++++++++-- x-pack/plugins/maps/public/reducers/map.js | 13 +------ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/actions/map_actions.js b/x-pack/legacy/plugins/maps/public/actions/map_actions.js index aa55cf0808ef2..7bfbf5761c5b8 100644 --- a/x-pack/legacy/plugins/maps/public/actions/map_actions.js +++ b/x-pack/legacy/plugins/maps/public/actions/map_actions.js @@ -125,9 +125,21 @@ async function syncDataForAllLayers(dispatch, getState, dataFilters) { export function cancelAllInFlightRequests() { return (dispatch, getState) => { getLayerList(getState()).forEach(layer => { - layer.getInFlightRequestTokens().forEach(requestToken => { - dispatch(cancelRequest(requestToken)); - }); + dispatch(clearDataRequests(layer)); + }); + }; +} + +function clearDataRequests(layer) { + return dispatch => { + layer.getInFlightRequestTokens().forEach(requestToken => { + dispatch(cancelRequest(requestToken)); + }); + dispatch({ + type: UPDATE_LAYER_PROP, + id: layer.getId(), + propName: '__dataRequests', + newValue: [], }); }; } @@ -663,13 +675,31 @@ export function updateSourceProp(layerId, propName, value, newLayerType) { layerId, propName, value, - newLayerType, }); + if (newLayerType) { + dispatch(updateLayerType(layerId, newLayerType)); + } await dispatch(clearMissingStyleProperties(layerId)); dispatch(syncDataForLayer(layerId)); }; } +function updateLayerType(layerId, newLayerType) { + return (dispatch, getState) => { + const layer = getLayerById(layerId, getState()); + if (!layer || layer.getType() === newLayerType) { + return; + } + dispatch(clearDataRequests(layer)); + dispatch({ + type: UPDATE_LAYER_PROP, + id: layerId, + propName: 'type', + newValue: newLayerType, + }); + }; +} + export function syncDataForLayer(layerId) { return async (dispatch, getState) => { const targetLayer = getLayerById(layerId, getState()); diff --git a/x-pack/plugins/maps/public/reducers/map.js b/x-pack/plugins/maps/public/reducers/map.js index 1e20df89c8fad..7e07569b44b83 100644 --- a/x-pack/plugins/maps/public/reducers/map.js +++ b/x-pack/plugins/maps/public/reducers/map.js @@ -74,7 +74,7 @@ const updateLayerInList = (state, layerId, attribute, newValue) => { return { ...state, layerList: updatedList }; }; -const updateLayerSourceDescriptorProp = (state, layerId, propName, value, newLayerType) => { +const updateLayerSourceDescriptorProp = (state, layerId, propName, value) => { const { layerList } = state; const layerIdx = getLayerIndex(layerList, layerId); const updatedLayer = { @@ -84,9 +84,6 @@ const updateLayerSourceDescriptorProp = (state, layerId, propName, value, newLay [propName]: value, }, }; - if (newLayerType) { - updatedLayer.type = newLayerType; - } const updatedList = [ ...layerList.slice(0, layerIdx), updatedLayer, @@ -261,13 +258,7 @@ export function map(state = INITIAL_STATE, action) { case UPDATE_LAYER_PROP: return updateLayerInList(state, action.id, action.propName, action.newValue); case UPDATE_SOURCE_PROP: - return updateLayerSourceDescriptorProp( - state, - action.layerId, - action.propName, - action.value, - action.newLayerType - ); + return updateLayerSourceDescriptorProp(state, action.layerId, action.propName, action.value); case SET_JOINS: const layerDescriptor = state.layerList.find( descriptor => descriptor.id === action.layer.getId() From b54388746dedfadd8f5432f9005c063271afc129 Mon Sep 17 00:00:00 2001 From: The SpaceCake Project <randomuserid@users.noreply.github.com> Date: Mon, 13 Apr 2020 18:42:10 -0400 Subject: [PATCH 084/121] investigation notes field (documentation / metadata) (#63386) * notes field added text to the "investigation notes" field in md which the field supports. * Revert "notes field" This reverts commit dae6ffc683150b9c471f3591073427ae62949a6e. * Revert "Revert "notes field"" This reverts commit f9de4bfc920217740fde316d3462cba409afa654. * Update linux_anomalous_network_activity.json * text change change to "Signals from this rule indicate" --- .../prepackaged_rules/linux_anomalous_network_activity.json | 3 ++- .../prepackaged_rules/linux_anomalous_process_all_hosts.json | 3 ++- .../rules/prepackaged_rules/linux_anomalous_user_name.json | 3 ++- .../rules/prepackaged_rules/rare_process_by_host_linux.json | 3 ++- .../rules/prepackaged_rules/rare_process_by_host_windows.json | 3 ++- .../prepackaged_rules/windows_anomalous_network_activity.json | 3 ++- .../prepackaged_rules/windows_anomalous_process_all_hosts.json | 3 ++- .../rules/prepackaged_rules/windows_anomalous_user_name.json | 3 ++- .../windows_rare_user_type10_remote_login.json | 3 ++- 9 files changed, 18 insertions(+), 9 deletions(-) diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json index fe248a6c1e23e..41f38173dba33 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Linux process for which network activity is rare and unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business or maintenance process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json index d15c4fc794378..103171bcdfe50 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for all of the monitored Linux hosts for which Auditbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json index 2f33948b0a93e..6642bb5d73fbd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating an Unusual Linux User ###\nSignals from this rule indicate activity for a Linux user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to troubleshooting or debugging activity by a developer or site reliability engineer?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json index f071677ae8d33..8ae1b84aaf199 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json @@ -20,5 +20,6 @@ "ML" ], "type": "machine_learning", + "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json index 5e0050c6c25ec..879cee388f5dd 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json index ca18fe95b1fc1..1092bcb20bcc3 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Windows process for which network activity is very unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses, protocol and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json index 1229c4a52b97d..f9adfeb830618 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for all of the Windows hosts for which Winlogbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json index 703dc1a1dc633..a0c6ff5c938f1 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a Windows user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to occasional troubleshooting or support activity?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json index 946cdb95b8e70..7318364c3aac2 100644 --- a/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json +++ b/x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json @@ -20,5 +20,6 @@ "Windows" ], "type": "machine_learning", + "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a rare and unusual Windows RDP (remote desktop) user. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is the user part of a group who normally logs into Windows hosts using RDP (remote desktop protocol)? Is this logon activity part of an expected workflow for the user? \n- Consider the source of the login. If the source is remote, could this be related to occasional troubleshooting or support activity by a vendor or an employee working remotely?", "version": 1 -} \ No newline at end of file +} From 5bc539c6db8c1f735876e0f16adb7bbd5d4b41eb Mon Sep 17 00:00:00 2001 From: Gil Raphaelli <gil@elastic.co> Date: Mon, 13 Apr 2020 22:06:09 -0400 Subject: [PATCH 085/121] update in-app links to metricbeat configuration docs (#63295) --- .../flyout/__snapshots__/flyout.test.js.snap | 24 +++++++++---------- .../apm/enable_metricbeat_instructions.js | 6 ++--- .../beats/enable_metricbeat_instructions.js | 2 +- .../kibana/enable_metricbeat_instructions.js | 2 +- .../enable_metricbeat_instructions.js | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap index eb1c65c6a696d..4a7537166bd8a 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/flyout/__snapshots__/flyout.test.js.snap @@ -161,7 +161,7 @@ exports[`Flyout apm part two should show instructions to migrate to metricbeat 1 "children": <EuiText> <p> <ForwardRef - href="https://www.elastic.co/guide/en/apm/metricbeat/current/metricbeat-installation.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-installation.html" target="_blank" > <FormattedMessage @@ -220,7 +220,7 @@ exports[`Flyout apm part two should show instructions to migrate to metricbeat 1 "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/apm/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-configuration.html" target="_blank" > <FormattedMessage @@ -287,7 +287,7 @@ exports[`Flyout apm part two should show instructions to migrate to metricbeat 1 "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/apm/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-configuration.html" target="_blank" > <FormattedMessage @@ -311,7 +311,7 @@ exports[`Flyout apm part two should show instructions to migrate to metricbeat 1 "children": <EuiText> <p> <ForwardRef - href="https://www.elastic.co/guide/en/apm/metricbeat/current/metricbeat-starting.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-starting.html" target="_blank" > <FormattedMessage @@ -601,7 +601,7 @@ exports[`Flyout beats part two should show instructions to migrate to metricbeat "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/beats/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-configuration.html" target="_blank" > <FormattedMessage @@ -668,7 +668,7 @@ exports[`Flyout beats part two should show instructions to migrate to metricbeat "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/beats/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-configuration.html" target="_blank" > <FormattedMessage @@ -1290,7 +1290,7 @@ exports[`Flyout kibana part two should show instructions to migrate to metricbea "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/kibana/reference/current/monitoring-metricbeat.html" + href="https://www.elastic.co/guide/en/kibana/current/monitoring-metricbeat.html" target="_blank" > <FormattedMessage @@ -1357,7 +1357,7 @@ exports[`Flyout kibana part two should show instructions to migrate to metricbea "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/kibana/reference/current/monitoring-metricbeat.html" + href="https://www.elastic.co/guide/en/kibana/current/monitoring-metricbeat.html" target="_blank" > <FormattedMessage @@ -1629,7 +1629,7 @@ exports[`Flyout logstash part two should show instructions to migrate to metricb "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/logstash/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/logstash/current/monitoring-with-metricbeat.html" target="_blank" > <FormattedMessage @@ -1696,7 +1696,7 @@ exports[`Flyout logstash part two should show instructions to migrate to metricb "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/logstash/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/logstash/current/monitoring-with-metricbeat.html" target="_blank" > <FormattedMessage @@ -1943,7 +1943,7 @@ exports[`Flyout should render the beat type for beats for the enabling metricbea "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/beats/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-configuration.html" target="_blank" > <FormattedMessage @@ -2010,7 +2010,7 @@ exports[`Flyout should render the beat type for beats for the enabling metricbea "link": <React.Fragment> <ForwardRef - href="https://www.elastic.co/guide/en/beats/reference/current/configuring-metricbeat.html" + href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-configuration.html" target="_blank" > <FormattedMessage diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/apm/enable_metricbeat_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/apm/enable_metricbeat_instructions.js index 387a8ff0d9359..9fa33802b0202 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/apm/enable_metricbeat_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/apm/enable_metricbeat_instructions.js @@ -13,7 +13,7 @@ import { getMigrationStatusStep, getSecurityStep } from '../common_instructions' export function getApmInstructionsForEnablingMetricbeat(product, _meta, { esMonitoringUrl }) { const securitySetup = getSecurityStep( - `${ELASTIC_WEBSITE_URL}guide/en/apm/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html` + `${ELASTIC_WEBSITE_URL}guide/en/beats/metricbeat/${DOC_LINK_VERSION}/metricbeat-configuration.html` ); const installMetricbeatStep = { @@ -27,7 +27,7 @@ export function getApmInstructionsForEnablingMetricbeat(product, _meta, { esMoni <EuiText> <p> <EuiLink - href={`${ELASTIC_WEBSITE_URL}guide/en/apm/metricbeat/${DOC_LINK_VERSION}/metricbeat-installation.html`} + href={`${ELASTIC_WEBSITE_URL}guide/en/beats/metricbeat/${DOC_LINK_VERSION}/metricbeat-installation.html`} target="_blank" > <FormattedMessage @@ -115,7 +115,7 @@ export function getApmInstructionsForEnablingMetricbeat(product, _meta, { esMoni <EuiText> <p> <EuiLink - href={`${ELASTIC_WEBSITE_URL}guide/en/apm/metricbeat/${DOC_LINK_VERSION}/metricbeat-starting.html`} + href={`${ELASTIC_WEBSITE_URL}guide/en/beats/metricbeat/${DOC_LINK_VERSION}/metricbeat-starting.html`} target="_blank" > <FormattedMessage diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/beats/enable_metricbeat_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/beats/enable_metricbeat_instructions.js index 1848455ac2386..56e7c9b5af064 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/beats/enable_metricbeat_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/beats/enable_metricbeat_instructions.js @@ -15,7 +15,7 @@ import { getMigrationStatusStep, getSecurityStep } from '../common_instructions' export function getBeatsInstructionsForEnablingMetricbeat(product, _meta, { esMonitoringUrl }) { const beatType = product.beatType; const securitySetup = getSecurityStep( - `${ELASTIC_WEBSITE_URL}guide/en/beats/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html` + `${ELASTIC_WEBSITE_URL}guide/en/beats/metricbeat/${DOC_LINK_VERSION}/metricbeat-configuration.html` ); const installMetricbeatStep = { diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js index 23f3eb71bfb41..98c75dbfe4b37 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js @@ -13,7 +13,7 @@ import { getMigrationStatusStep, getSecurityStep } from '../common_instructions' export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, { esMonitoringUrl }) { const securitySetup = getSecurityStep( - `${ELASTIC_WEBSITE_URL}guide/en/kibana/reference/${DOC_LINK_VERSION}/monitoring-metricbeat.html` + `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/monitoring-metricbeat.html` ); const installMetricbeatStep = { diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/logstash/enable_metricbeat_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/logstash/enable_metricbeat_instructions.js index 70ee43d00ab3d..4a36f394e4bd5 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/logstash/enable_metricbeat_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/logstash/enable_metricbeat_instructions.js @@ -13,7 +13,7 @@ import { getMigrationStatusStep, getSecurityStep } from '../common_instructions' export function getLogstashInstructionsForEnablingMetricbeat(product, _meta, { esMonitoringUrl }) { const securitySetup = getSecurityStep( - `${ELASTIC_WEBSITE_URL}guide/en/logstash/reference/${DOC_LINK_VERSION}/configuring-metricbeat.html` + `${ELASTIC_WEBSITE_URL}guide/en/logstash/${DOC_LINK_VERSION}/monitoring-with-metricbeat.html` ); const installMetricbeatStep = { From 5d7c651cd7eab09601e570946158f5083e18b34a Mon Sep 17 00:00:00 2001 From: kqualters-elastic <56408403+kqualters-elastic@users.noreply.github.com> Date: Tue, 14 Apr 2020 02:05:06 -0400 Subject: [PATCH 086/121] [Endpoint] Update cli mapping to match endpoint package (#63372) * Update cli mapping to match endpoint package --- x-pack/plugins/endpoint/scripts/alert_mapping.json | 3 ++- x-pack/plugins/endpoint/scripts/event_mapping.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/endpoint/scripts/alert_mapping.json b/x-pack/plugins/endpoint/scripts/alert_mapping.json index a21e48b4bc95f..2e0041d0af986 100644 --- a/x-pack/plugins/endpoint/scripts/alert_mapping.json +++ b/x-pack/plugins/endpoint/scripts/alert_mapping.json @@ -394,7 +394,8 @@ "type": "nested" }, "file_extension": { - "type": "long" + "ignore_above": 1024, + "type": "keyword" }, "project_file": { "properties": { diff --git a/x-pack/plugins/endpoint/scripts/event_mapping.json b/x-pack/plugins/endpoint/scripts/event_mapping.json index 59d1ed17852b1..f410edc7abe5e 100644 --- a/x-pack/plugins/endpoint/scripts/event_mapping.json +++ b/x-pack/plugins/endpoint/scripts/event_mapping.json @@ -386,7 +386,8 @@ "type": "nested" }, "file_extension": { - "type": "long" + "ignore_above": 1024, + "type": "keyword" }, "project_file": { "properties": { From f4abaabaee04ed78cb38f32defed37ac969834a5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens <jloleysens@gmail.com> Date: Tue, 14 Apr 2020 08:47:23 +0200 Subject: [PATCH 087/121] Escape single quotes surrounded by double quotes (#63229) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../models/sense_editor/__tests__/editor_input1.txt | 6 ++++++ .../sense_editor/__tests__/sense_editor.test.js | 12 ++++++++++++ .../application/models/sense_editor/sense_editor.ts | 5 +++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt b/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt index f9a4bcb85034d..398a0fdeab61f 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/editor_input1.txt @@ -25,3 +25,9 @@ GET index_1/type1/1/_source?_source_include=f DELETE index_2 + +POST /_sql?format=txt +{ + "query": "SELECT prenom FROM claude_index WHERE prenom = 'claude' ", + "fetch_size": 1 +} diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js index 6afc03df13b4c..34b4cad7fbb6b 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js @@ -470,6 +470,18 @@ curl -XGET "http://localhost:9200/_stats?level=shards" curl -XPUT "http://localhost:9200/index_1/type1/1" -H 'Content-Type: application/json' -d' { "f": 1 +}'`.trim() + ); + + multiReqCopyAsCurlTest( + 'with single quotes', + editorInput1, + { start: { lineNumber: 29 }, end: { lineNumber: 33 } }, + ` +curl -XPOST "http://localhost:9200/_sql?format=txt" -H 'Content-Type: application/json' -d' +{ + "query": "SELECT prenom FROM claude_index WHERE prenom = '\\''claude'\\'' ", + "fetch_size": 1 }'`.trim() ); }); diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts index 9bcd3a6872196..d326543bbe00b 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts @@ -484,8 +484,9 @@ export class SenseEditor { if (esData && esData.length) { ret += " -H 'Content-Type: application/json' -d'\n"; const dataAsString = collapseLiteralStrings(esData.join('\n')); - // since Sense doesn't allow single quote json string any single qoute is within a string. - ret += dataAsString.replace(/'/g, '\\"'); + + // We escape single quoted strings that that are wrapped in single quoted strings + ret += dataAsString.replace(/'/g, "'\\''"); if (esData.length > 1) { ret += '\n'; } // end with a new line From f44d951300169f7fefeb621e5642f42131dae9fc Mon Sep 17 00:00:00 2001 From: Mikhail Shustov <restrry@gmail.com> Date: Tue, 14 Apr 2020 09:11:03 +0200 Subject: [PATCH 088/121] document code splitting for client code (#62593) * add lazy loading section for client bundles * add Pierres suggestion --- src/core/MIGRATION.md | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 5d7b467052029..368d1f47e9c3f 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -24,6 +24,7 @@ - [7. Switch to new platform services](#7-switch-to-new-platform-services) - [8. Migrate to the new plugin system](#8-migrate-to-the-new-plugin-system) - [Bonus: Tips for complex migration scenarios](#bonus-tips-for-complex-migration-scenarios) + - [Keep Kibana fast](#keep-kibana-fast) - [Frequently asked questions](#frequently-asked-questions) - [Is migrating a plugin an all-or-nothing thing?](#is-migrating-a-plugin-an-all-or-nothing-thing) - [Do plugins need to be converted to TypeScript?](#do-plugins-need-to-be-converted-to-typescript) @@ -933,6 +934,66 @@ For a few plugins, some of these steps (such as angular removal) could be a mont One convention that is useful for this is creating a dedicated `public/np_ready` directory to house the code that is ready to migrate, and gradually move more and more code into it until the rest of your plugin is essentially empty. At that point, you'll be able to copy your `index.ts`, `plugin.ts`, and the contents of `./np_ready` over into your plugin in the new platform, leaving your legacy shim behind. This carries the added benefit of providing a way for us to introduce helpful tooling in the future, such as [custom eslint rules](https://github.com/elastic/kibana/pull/40537), which could be run against that specific directory to ensure your code is ready to migrate. +## Keep Kibana fast +**tl;dr**: Load as much code lazily as possible. +Everyone loves snappy applications with responsive UI and hates spinners. Users deserve the best user experiences regardless of whether they run Kibana locally or in the cloud, regardless of their hardware & environment. +There are 2 main aspects of the perceived speed of an application: loading time and responsiveness to user actions. +New platform loads and bootstraps **all** the plugins whenever a user lands on any page. It means that adding every new application affects overall **loading performance** in the new platform, as plugin code is loaded **eagerly** to initialize the plugin and provide plugin API to dependent plugins. +However, it's usually not necessary that the whole plugin code should be loaded and initialized at once. The plugin could keep on loading code covering API functionality on Kibana bootstrap but load UI related code lazily on-demand, when an application page or management section is mounted. +Always prefer to require UI root components lazily when possible (such as in mount handlers). Even if their size may seem negligible, they are likely using some heavy-weight libraries that will also be removed from the initial plugin bundle, therefore, reducing its size by a significant amount. + +```typescript +import { Plugin, CoreSetup, AppMountParameters } from 'src/core/public'; +export class MyPlugin implements Plugin<MyPluginSetup> { + setup(core: CoreSetup, plugins: SetupDeps){ + core.application.register({ + id: 'app', + title: 'My app', + async mount(params: AppMountParameters) { + const { mountApp } = await import('./app/mount_app'); + return mountApp(await core.getStartServices(), params); + }, + }); + plugins.management.sections.getSection('another').registerApp({ + id: 'app', + title: 'My app', + order: 1, + async mount(params) { + const { mountManagementSection } = await import('./app/mount_management_section'); + return mountManagementSection(coreSetup, params); + }, + }) + return { + doSomething(){} + } + } +} +``` + +#### How to understand how big the bundle size of my plugin is? +New platform plugins are distributed as a pre-built with `@kbn/optimizer` package artifacts. It allows us to get rid of the shipping of `optimizer` in the distributable version of Kibana. +Every NP plugin artifact contains all plugin dependencies required to run the plugin, except some stateful dependencies shared across plugin bundles via `@kbn/ui-shared-deps`. +It means that NP plugin artifacts tend to have a bigger size than the legacy platform version. +To understand the current size of your plugin artifact, run `@kbn/optimizer` as +```bash +node scripts/build_kibana_platform_plugins.js --dist --no-examples +``` +and check the output in the `target` sub-folder of your plugin folder +```bash +ls -lh plugins/my_plugin/target/public/ +# output +# an async chunk loaded on demand +... 262K 0.plugin.js +# eagerly loaded chunk +... 50K my_plugin.plugin.js +``` +you might see at least one js bundle - `my_plugin.plugin.js`. This is the only artifact loaded by the platform during bootstrap in the browser. The rule of thumb is to keep its size as small as possible. +Other lazily loaded parts of your plugin present in the same folder as separate chunks under `{number}.plugin.js` names. +If you want to investigate what your plugin bundle consists of you need to run `@kbn/optimizer` with `--profile` flag to get generated [webpack stats file](https://webpack.js.org/api/stats/). +Many OSS tools are allowing you to analyze generated stats file +- [an official tool](http://webpack.github.io/analyse/#modules) from webpack authors +- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/) + ## Frequently asked questions ### Is migrating a plugin an all-or-nothing thing? From 1f732ad29ac7f386d9255d016f80c51367abd685 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris <github@gidi.io> Date: Tue, 14 Apr 2020 10:57:46 +0100 Subject: [PATCH 089/121] [Event Log] Adds namespace into save objects (#62974) Adds a namespace attribute to the saved object object within the Event Log so that each Saved Object can have its own. This change also removes the existing kibana.namespace field. As Event Log is not yet in use, this does not include a migration. --- .../plugins/actions/server/lib/action_executor.ts | 9 ++++----- .../task_runner/create_execution_handler.test.ts | 1 - .../task_runner/create_execution_handler.ts | 7 ++++--- .../server/task_runner/task_runner.test.ts | 15 ++++++++------- .../alerting/server/task_runner/task_runner.ts | 5 ++--- x-pack/plugins/event_log/README.md | 1 - x-pack/plugins/event_log/generated/mappings.json | 6 +----- x-pack/plugins/event_log/generated/schemas.ts | 3 +-- x-pack/plugins/event_log/scripts/mappings.js | 12 +++--------- .../server/routes/_mock_handler_arguments.ts | 2 +- .../event_log/public_api_integration.ts | 2 +- 11 files changed, 25 insertions(+), 38 deletions(-) diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index af0353247d99f..ba8bb79170c63 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -75,7 +75,8 @@ export class ActionExecutor { } = this.actionExecutorContext!; const services = getServices(request); - const namespace = spaces && spaces.getSpaceId(request); + const spaceId = spaces && spaces.getSpaceId(request); + const namespace = spaceId && spaceId !== 'default' ? { namespace: spaceId } : {}; // Ensure user can read the action before processing const { @@ -91,9 +92,7 @@ export class ActionExecutor { } = await encryptedSavedObjectsPlugin.getDecryptedAsInternalUser<RawAction>( 'action', actionId, - { - namespace: namespace === 'default' ? undefined : namespace, - } + namespace ); const actionType = actionTypeRegistry.get(actionTypeId); @@ -112,7 +111,7 @@ export class ActionExecutor { const actionLabel = `${actionTypeId}:${actionId}: ${name}`; const event: IEvent = { event: { action: EVENT_LOG_ACTIONS.execute }, - kibana: { namespace, saved_objects: [{ type: 'action', id: actionId }] }, + kibana: { saved_objects: [{ type: 'action', id: actionId, ...namespace }] }, }; eventLogger.startTiming(event); diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts index 8d037a1ecee91..756080baba626 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.test.ts @@ -91,7 +91,6 @@ test('calls actionsPlugin.execute per selected action', async () => { "alerting": Object { "instance_id": "2", }, - "namespace": "default", "saved_objects": Array [ Object { "id": "1", diff --git a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts index de06c8bbb374a..72f9e70905dc2 100644 --- a/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts +++ b/x-pack/plugins/alerting/server/task_runner/create_execution_handler.ts @@ -87,16 +87,17 @@ export function createExecutionHandler({ apiKey, }); + const namespace = spaceId === 'default' ? {} : { namespace: spaceId }; + const event: IEvent = { event: { action: EVENT_LOG_ACTIONS.executeAction }, kibana: { alerting: { instance_id: alertInstanceId, }, - namespace: spaceId, saved_objects: [ - { type: 'alert', id: alertId }, - { type: 'action', id: action.id }, + { type: 'alert', id: alertId, ...namespace }, + { type: 'action', id: action.id, ...namespace }, ], }, }; diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 520f8d5c99b16..4e6d959f0ce60 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -169,10 +169,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -229,10 +229,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -249,10 +249,10 @@ describe('Task Runner', () => { "alerting": Object { "instance_id": "1", }, - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -269,14 +269,15 @@ describe('Task Runner', () => { "alerting": Object { "instance_id": "1", }, - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, Object { "id": "1", + "namespace": undefined, "type": "action", }, ], @@ -344,10 +345,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -364,10 +365,10 @@ describe('Task Runner', () => { "alerting": Object { "instance_id": "2", }, - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], @@ -560,10 +561,10 @@ describe('Task Runner', () => { "action": "execute", }, "kibana": Object { - "namespace": undefined, "saved_objects": Array [ Object { "id": "1", + "namespace": undefined, "type": "alert", }, ], diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index 2ba56396279ea..190cdc184930c 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -173,7 +173,7 @@ export class TaskRunner { const alertLabel = `${this.alertType.id}:${alertId}: '${name}'`; const event: IEvent = { event: { action: EVENT_LOG_ACTIONS.execute }, - kibana: { namespace, saved_objects: [{ type: 'alert', id: alertId }] }, + kibana: { saved_objects: [{ type: 'alert', id: alertId, namespace }] }, }; eventLogger.startTiming(event); @@ -378,11 +378,10 @@ function generateNewAndResolvedInstanceEvents(params: GenerateNewAndResolvedInst action, }, kibana: { - namespace: params.namespace, alerting: { instance_id: id, }, - saved_objects: [{ type: 'alert', id: params.alertId }], + saved_objects: [{ type: 'alert', id: params.alertId, namespace: params.namespace }], }, message, }; diff --git a/x-pack/plugins/event_log/README.md b/x-pack/plugins/event_log/README.md index 027bbc694801f..38364033cb70b 100644 --- a/x-pack/plugins/event_log/README.md +++ b/x-pack/plugins/event_log/README.md @@ -125,7 +125,6 @@ Here's the event written to the event log index: "duration": 1000000 }, "kibana": { - "namespace": "default", "saved_objects": [ { "type": "action", diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index ab1b4096d17f2..9c1dff60f9727 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -72,10 +72,6 @@ "type": "keyword", "ignore_above": 1024 }, - "namespace": { - "type": "keyword", - "ignore_above": 1024 - }, "alerting": { "properties": { "instance_id": { @@ -86,7 +82,7 @@ }, "saved_objects": { "properties": { - "store": { + "namespace": { "type": "keyword", "ignore_above": 1024 }, diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts index b731093b33b06..5e93f320c009f 100644 --- a/x-pack/plugins/event_log/generated/schemas.ts +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -56,7 +56,6 @@ export const EventSchema = schema.maybe( kibana: schema.maybe( schema.object({ server_uuid: ecsString(), - namespace: ecsString(), alerting: schema.maybe( schema.object({ instance_id: ecsString(), @@ -65,7 +64,7 @@ export const EventSchema = schema.maybe( saved_objects: schema.maybe( schema.arrayOf( schema.object({ - store: ecsString(), + namespace: ecsString(), id: ecsString(), type: ecsString(), }) diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index 9e721b06ec335..de3c9d631fbca 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -20,17 +20,12 @@ exports.EcsKibanaExtensionsMappings = { }, }, }, - // relevant kibana space - namespace: { - type: 'keyword', - ignore_above: 1024, - }, // array of saved object references, for "linking" via search saved_objects: { type: 'nested', properties: { - // 'kibana' for typical saved object, 'task_manager' for TM, etc - store: { + // relevant kibana space + namespace: { type: 'keyword', ignore_above: 1024, }, @@ -61,9 +56,8 @@ exports.EcsEventLogProperties = [ 'error.message', 'user.name', 'kibana.server_uuid', - 'kibana.namespace', 'kibana.alerting.instance_id', - 'kibana.saved_objects.store', + 'kibana.saved_objects.namespace', 'kibana.saved_objects.id', 'kibana.saved_objects.name', 'kibana.saved_objects.type', diff --git a/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts index 6640683bf6005..19933649277aa 100644 --- a/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts @@ -50,9 +50,9 @@ export function fakeEvent(overrides = {}) { duration: 1000000, }, kibana: { - namespace: 'default', saved_objects: [ { + namespace: 'default', type: 'action', id: '968f1b82-0414-4a10-becc-56b6473e4a29', }, diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts index c440971225d78..d664357c3ba12 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts @@ -220,9 +220,9 @@ export default function({ getService }: FtrProviderContext) { duration: 1000000, }, kibana: { - namespace: 'default', saved_objects: [ { + namespace: 'default', type: 'event_log_test', id, }, From 637a9e11a2d713b8aa82d134ebf0c3d09abeace7 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko <dzmitry.lemechko@elastic.co> Date: Tue, 14 Apr 2020 14:25:26 +0300 Subject: [PATCH 090/121] Revert FTR: add chromium-based Edge browser support (#61684) (#63448) --- package.json | 5 +- packages/kbn-pm/dist/index.js | 1105 ++++++++++++++--- .../lib/config/schema.ts | 2 +- test/functional/config.edge.js | 34 - test/functional/services/browser.ts | 4 +- .../web_element_wrapper.ts | 9 +- test/functional/services/remote/browsers.ts | 1 - test/functional/services/remote/remote.ts | 17 +- test/functional/services/remote/webdriver.ts | 50 +- x-pack/test/functional/config.edge.js | 21 - yarn.lock | 322 +---- 11 files changed, 1013 insertions(+), 557 deletions(-) delete mode 100644 test/functional/config.edge.js delete mode 100644 x-pack/test/functional/config.edge.js diff --git a/package.json b/package.json index 2bad3116c9ef2..388e46aedf37d 100644 --- a/package.json +++ b/package.json @@ -376,7 +376,7 @@ "@types/recompose": "^0.30.6", "@types/redux-actions": "^2.6.1", "@types/request": "^2.48.2", - "@types/selenium-webdriver": "4.0.9", + "@types/selenium-webdriver": "^4.0.5", "@types/semver": "^5.5.0", "@types/sinon": "^7.0.13", "@types/strip-ansi": "^3.0.0", @@ -462,7 +462,6 @@ "load-grunt-config": "^3.0.1", "mocha": "^7.1.1", "mock-http-server": "1.3.0", - "ms-chromium-edge-driver": "^0.2.0", "multistream": "^2.1.1", "murmurhash3js": "3.0.1", "mutation-observer": "^1.0.3", @@ -481,7 +480,7 @@ "react-textarea-autosize": "^7.1.2", "regenerate": "^1.4.0", "sass-lint": "^1.12.1", - "selenium-webdriver": "^4.0.0-alpha.7", + "selenium-webdriver": "^4.0.0-alpha.5", "simple-git": "1.116.0", "simplebar-react": "^2.1.0", "sinon": "^7.4.2", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 399720f310f67..fa8884e2ece75 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -79185,7 +79185,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(704); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(922); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(927); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -79370,9 +79370,9 @@ const pAll = __webpack_require__(706); const arrify = __webpack_require__(708); const globby = __webpack_require__(709); const isGlob = __webpack_require__(603); -const cpFile = __webpack_require__(907); -const junk = __webpack_require__(919); -const CpyError = __webpack_require__(920); +const cpFile = __webpack_require__(912); +const junk = __webpack_require__(924); +const CpyError = __webpack_require__(925); const defaultOptions = { ignoreJunk: true @@ -79622,8 +79622,8 @@ const fs = __webpack_require__(23); const arrayUnion = __webpack_require__(710); const glob = __webpack_require__(712); const fastGlob = __webpack_require__(717); -const dirGlob = __webpack_require__(900); -const gitignore = __webpack_require__(903); +const dirGlob = __webpack_require__(905); +const gitignore = __webpack_require__(908); const DEFAULT_FILTER = () => false; @@ -81456,11 +81456,11 @@ module.exports.generateTasks = pkg.generateTasks; Object.defineProperty(exports, "__esModule", { value: true }); var optionsManager = __webpack_require__(719); var taskManager = __webpack_require__(720); -var reader_async_1 = __webpack_require__(871); -var reader_stream_1 = __webpack_require__(895); -var reader_sync_1 = __webpack_require__(896); -var arrayUtils = __webpack_require__(898); -var streamUtils = __webpack_require__(899); +var reader_async_1 = __webpack_require__(876); +var reader_stream_1 = __webpack_require__(900); +var reader_sync_1 = __webpack_require__(901); +var arrayUtils = __webpack_require__(903); +var streamUtils = __webpack_require__(904); /** * Synchronous API. */ @@ -82100,9 +82100,9 @@ var extend = __webpack_require__(837); */ var compilers = __webpack_require__(840); -var parsers = __webpack_require__(867); -var cache = __webpack_require__(868); -var utils = __webpack_require__(869); +var parsers = __webpack_require__(872); +var cache = __webpack_require__(873); +var utils = __webpack_require__(874); var MAX_LENGTH = 1024 * 64; /** @@ -100635,9 +100635,9 @@ var toRegex = __webpack_require__(728); */ var compilers = __webpack_require__(857); -var parsers = __webpack_require__(863); -var Extglob = __webpack_require__(866); -var utils = __webpack_require__(865); +var parsers = __webpack_require__(868); +var Extglob = __webpack_require__(871); +var utils = __webpack_require__(870); var MAX_LENGTH = 1024 * 64; /** @@ -101147,7 +101147,7 @@ var parsers = __webpack_require__(861); * Module dependencies */ -var debug = __webpack_require__(800)('expand-brackets'); +var debug = __webpack_require__(863)('expand-brackets'); var extend = __webpack_require__(737); var Snapdragon = __webpack_require__(767); var toRegex = __webpack_require__(728); @@ -101741,12 +101741,839 @@ exports.createRegex = function(pattern, include) { /* 863 */ /***/ (function(module, exports, __webpack_require__) { +/** + * Detect Electron renderer process, which is node, but we should + * treat as a browser. + */ + +if (typeof process !== 'undefined' && process.type === 'renderer') { + module.exports = __webpack_require__(864); +} else { + module.exports = __webpack_require__(867); +} + + +/***/ }), +/* 864 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = __webpack_require__(865); +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); + +/** + * Colors. + */ + +exports.colors = [ + 'lightseagreen', + 'forestgreen', + 'goldenrod', + 'dodgerblue', + 'darkorchid', + 'crimson' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } + + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; + } +}; + + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return; + + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit') + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + +function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Enable namespaces listed in `localStorage.debug` initially. + */ + +exports.enable(load()); + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + return window.localStorage; + } catch (e) {} +} + + +/***/ }), +/* 865 */ +/***/ (function(module, exports, __webpack_require__) { + + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; +exports.coerce = coerce; +exports.disable = disable; +exports.enable = enable; +exports.enabled = enabled; +exports.humanize = __webpack_require__(866); + +/** + * The currently active debug mode names, and names to skip. + */ + +exports.names = []; +exports.skips = []; + +/** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + +exports.formatters = {}; + +/** + * Previous log timestamp. + */ + +var prevTime; + +/** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ + +function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return exports.colors[Math.abs(hash) % exports.colors.length]; +} + +/** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + +function createDebug(namespace) { + + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } + + return debug; +} + +/** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + +function enable(namespaces) { + exports.save(namespaces); + + exports.names = []; + exports.skips = []; + + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (var i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** + * Disable debug output. + * + * @api public + */ + +function disable() { + exports.enable(''); +} + +/** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + +function enabled(name) { + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; +} + +/** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + +function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; +} + + +/***/ }), +/* 866 */ +/***/ (function(module, exports) { + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; + } + if (ms >= h) { + return Math.round(ms / h) + 'h'; + } + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; +} + + +/***/ }), +/* 867 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Module dependencies. + */ + +var tty = __webpack_require__(478); +var util = __webpack_require__(29); + +/** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + +exports = module.exports = __webpack_require__(865); +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); +}).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); + + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); + + obj[prop] = val; + return obj; +}, {}); + +/** + * The file descriptor to write the `debug()` calls to. + * Set the `DEBUG_FD` env variable to override with another value. i.e.: + * + * $ DEBUG_FD=3 node script.js 3>debug.log + */ + +var fd = parseInt(process.env.DEBUG_FD, 10) || 2; + +if (1 !== fd && 2 !== fd) { + util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() +} + +var stream = 1 === fd ? process.stdout : + 2 === fd ? process.stderr : + createWritableStdioStream(fd); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(fd); +} + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +exports.formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n').map(function(str) { + return str.trim() + }).join(' '); +}; + +/** + * Map %o to `util.inspect()`, allowing multiple lines if needed. + */ + +exports.formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + var name = this.namespace; + var useColors = this.useColors; + + if (useColors) { + var c = this.color; + var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + } else { + args[0] = new Date().toUTCString() + + ' ' + name + ' ' + args[0]; + } +} + +/** + * Invokes `util.format()` with the specified arguments and writes to `stream`. + */ + +function log() { + return stream.write(util.format.apply(util, arguments) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + +function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Copied from `node/src/node.js`. + * + * XXX: It's lame that node doesn't expose this API out-of-the-box. It also + * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. + */ + +function createWritableStdioStream (fd) { + var stream; + var tty_wrap = process.binding('tty_wrap'); + + // Note stream._type is used for test-module-load-list.js + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + stream = new tty.WriteStream(fd); + stream._type = 'tty'; + + // Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + case 'FILE': + var fs = __webpack_require__(23); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); + stream._type = 'fs'; + break; + + case 'PIPE': + case 'TCP': + var net = __webpack_require__(805); + stream = new net.Socket({ + fd: fd, + readable: false, + writable: true + }); + + // FIXME Should probably have an option in net.Socket to create a + // stream from an existing fd which is writable only. But for now + // we'll just add this hack and set the `readable` member to false. + // Test: ./node test/fixtures/echo.js < /etc/passwd + stream.readable = false; + stream.read = null; + stream._type = 'pipe'; + + // FIXME Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stream file type!'); + } + + // For supporting legacy API we put the FD here. + stream.fd = fd; + + stream._isStdio = true; + + return stream; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init (debug) { + debug.inspectOpts = {}; + + var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +/** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ + +exports.enable(load()); + + +/***/ }), +/* 868 */ +/***/ (function(module, exports, __webpack_require__) { + "use strict"; var brackets = __webpack_require__(858); -var define = __webpack_require__(864); -var utils = __webpack_require__(865); +var define = __webpack_require__(869); +var utils = __webpack_require__(870); /** * Characters to use in text regex (we want to "not" match @@ -101901,7 +102728,7 @@ module.exports = parsers; /***/ }), -/* 864 */ +/* 869 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101939,7 +102766,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 865 */ +/* 870 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102015,7 +102842,7 @@ utils.createRegex = function(str) { /***/ }), -/* 866 */ +/* 871 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102026,7 +102853,7 @@ utils.createRegex = function(str) { */ var Snapdragon = __webpack_require__(767); -var define = __webpack_require__(864); +var define = __webpack_require__(869); var extend = __webpack_require__(737); /** @@ -102034,7 +102861,7 @@ var extend = __webpack_require__(737); */ var compilers = __webpack_require__(857); -var parsers = __webpack_require__(863); +var parsers = __webpack_require__(868); /** * Customize Snapdragon parser and renderer @@ -102100,7 +102927,7 @@ module.exports = Extglob; /***/ }), -/* 867 */ +/* 872 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102190,14 +103017,14 @@ function textRegex(pattern) { /***/ }), -/* 868 */ +/* 873 */ /***/ (function(module, exports, __webpack_require__) { module.exports = new (__webpack_require__(849))(); /***/ }), -/* 869 */ +/* 874 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102215,7 +103042,7 @@ utils.define = __webpack_require__(836); utils.diff = __webpack_require__(853); utils.extend = __webpack_require__(837); utils.pick = __webpack_require__(854); -utils.typeOf = __webpack_require__(870); +utils.typeOf = __webpack_require__(875); utils.unique = __webpack_require__(740); /** @@ -102513,7 +103340,7 @@ utils.unixify = function(options) { /***/ }), -/* 870 */ +/* 875 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -102648,7 +103475,7 @@ function isBuffer(val) { /***/ }), -/* 871 */ +/* 876 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102667,9 +103494,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(872); -var reader_1 = __webpack_require__(885); -var fs_stream_1 = __webpack_require__(889); +var readdir = __webpack_require__(877); +var reader_1 = __webpack_require__(890); +var fs_stream_1 = __webpack_require__(894); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -102730,15 +103557,15 @@ exports.default = ReaderAsync; /***/ }), -/* 872 */ +/* 877 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(873); -const readdirAsync = __webpack_require__(881); -const readdirStream = __webpack_require__(884); +const readdirSync = __webpack_require__(878); +const readdirAsync = __webpack_require__(886); +const readdirStream = __webpack_require__(889); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -102822,7 +103649,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 873 */ +/* 878 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102830,11 +103657,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(874); +const DirectoryReader = __webpack_require__(879); let syncFacade = { - fs: __webpack_require__(879), - forEach: __webpack_require__(880), + fs: __webpack_require__(884), + forEach: __webpack_require__(885), sync: true }; @@ -102863,7 +103690,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 874 */ +/* 879 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102872,9 +103699,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(27).Readable; const EventEmitter = __webpack_require__(379).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(875); -const stat = __webpack_require__(877); -const call = __webpack_require__(878); +const normalizeOptions = __webpack_require__(880); +const stat = __webpack_require__(882); +const call = __webpack_require__(883); /** * Asynchronously reads the contents of a directory and streams the results @@ -103250,14 +104077,14 @@ module.exports = DirectoryReader; /***/ }), -/* 875 */ +/* 880 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(876); +const globToRegExp = __webpack_require__(881); module.exports = normalizeOptions; @@ -103434,7 +104261,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 876 */ +/* 881 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -103571,13 +104398,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 877 */ +/* 882 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(878); +const call = __webpack_require__(883); module.exports = stat; @@ -103652,7 +104479,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 878 */ +/* 883 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103713,14 +104540,14 @@ function callOnce (fn) { /***/ }), -/* 879 */ +/* 884 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(878); +const call = __webpack_require__(883); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -103784,7 +104611,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 880 */ +/* 885 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103813,7 +104640,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 881 */ +/* 886 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103821,12 +104648,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(882); -const DirectoryReader = __webpack_require__(874); +const maybe = __webpack_require__(887); +const DirectoryReader = __webpack_require__(879); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(883), + forEach: __webpack_require__(888), async: true }; @@ -103868,7 +104695,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 882 */ +/* 887 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103895,7 +104722,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 883 */ +/* 888 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103931,7 +104758,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 884 */ +/* 889 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -103939,11 +104766,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(874); +const DirectoryReader = __webpack_require__(879); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(883), + forEach: __webpack_require__(888), async: true }; @@ -103963,16 +104790,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 885 */ +/* 890 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(886); -var entry_1 = __webpack_require__(888); -var pathUtil = __webpack_require__(887); +var deep_1 = __webpack_require__(891); +var entry_1 = __webpack_require__(893); +var pathUtil = __webpack_require__(892); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -104038,13 +104865,13 @@ exports.default = Reader; /***/ }), -/* 886 */ +/* 891 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(887); +var pathUtils = __webpack_require__(892); var patternUtils = __webpack_require__(721); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { @@ -104128,7 +104955,7 @@ exports.default = DeepFilter; /***/ }), -/* 887 */ +/* 892 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104159,13 +104986,13 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 888 */ +/* 893 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(887); +var pathUtils = __webpack_require__(892); var patternUtils = __webpack_require__(721); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { @@ -104251,7 +105078,7 @@ exports.default = EntryFilter; /***/ }), -/* 889 */ +/* 894 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104271,8 +105098,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var fsStat = __webpack_require__(890); -var fs_1 = __webpack_require__(894); +var fsStat = __webpack_require__(895); +var fs_1 = __webpack_require__(899); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -104322,14 +105149,14 @@ exports.default = FileSystemStream; /***/ }), -/* 890 */ +/* 895 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(891); -const statProvider = __webpack_require__(893); +const optionsManager = __webpack_require__(896); +const statProvider = __webpack_require__(898); /** * Asynchronous API. */ @@ -104360,13 +105187,13 @@ exports.statSync = statSync; /***/ }), -/* 891 */ +/* 896 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(892); +const fsAdapter = __webpack_require__(897); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -104379,7 +105206,7 @@ exports.prepare = prepare; /***/ }), -/* 892 */ +/* 897 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104402,7 +105229,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 893 */ +/* 898 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104454,7 +105281,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 894 */ +/* 899 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104485,7 +105312,7 @@ exports.default = FileSystem; /***/ }), -/* 895 */ +/* 900 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104505,9 +105332,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var readdir = __webpack_require__(872); -var reader_1 = __webpack_require__(885); -var fs_stream_1 = __webpack_require__(889); +var readdir = __webpack_require__(877); +var reader_1 = __webpack_require__(890); +var fs_stream_1 = __webpack_require__(894); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -104575,7 +105402,7 @@ exports.default = ReaderStream; /***/ }), -/* 896 */ +/* 901 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104594,9 +105421,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(872); -var reader_1 = __webpack_require__(885); -var fs_sync_1 = __webpack_require__(897); +var readdir = __webpack_require__(877); +var reader_1 = __webpack_require__(890); +var fs_sync_1 = __webpack_require__(902); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -104656,7 +105483,7 @@ exports.default = ReaderSync; /***/ }), -/* 897 */ +/* 902 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104675,8 +105502,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(890); -var fs_1 = __webpack_require__(894); +var fsStat = __webpack_require__(895); +var fs_1 = __webpack_require__(899); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -104722,7 +105549,7 @@ exports.default = FileSystemSync; /***/ }), -/* 898 */ +/* 903 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104738,7 +105565,7 @@ exports.flatten = flatten; /***/ }), -/* 899 */ +/* 904 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104759,13 +105586,13 @@ exports.merge = merge; /***/ }), -/* 900 */ +/* 905 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(901); +const pathType = __webpack_require__(906); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -104831,13 +105658,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 901 */ +/* 906 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(902); +const pify = __webpack_require__(907); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -104880,7 +105707,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 902 */ +/* 907 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104971,7 +105798,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 903 */ +/* 908 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104979,9 +105806,9 @@ module.exports = (obj, opts) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const fastGlob = __webpack_require__(717); -const gitIgnore = __webpack_require__(904); -const pify = __webpack_require__(905); -const slash = __webpack_require__(906); +const gitIgnore = __webpack_require__(909); +const pify = __webpack_require__(910); +const slash = __webpack_require__(911); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -105079,7 +105906,7 @@ module.exports.sync = options => { /***/ }), -/* 904 */ +/* 909 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -105548,7 +106375,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 905 */ +/* 910 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105623,7 +106450,7 @@ module.exports = (input, options) => { /***/ }), -/* 906 */ +/* 911 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105641,17 +106468,17 @@ module.exports = input => { /***/ }), -/* 907 */ +/* 912 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const pEvent = __webpack_require__(908); -const CpFileError = __webpack_require__(911); -const fs = __webpack_require__(915); -const ProgressEmitter = __webpack_require__(918); +const pEvent = __webpack_require__(913); +const CpFileError = __webpack_require__(916); +const fs = __webpack_require__(920); +const ProgressEmitter = __webpack_require__(923); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -105765,12 +106592,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 908 */ +/* 913 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(909); +const pTimeout = __webpack_require__(914); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -106061,12 +106888,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 909 */ +/* 914 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(910); +const pFinally = __webpack_require__(915); class TimeoutError extends Error { constructor(message) { @@ -106112,7 +106939,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 910 */ +/* 915 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106134,12 +106961,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 911 */ +/* 916 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(912); +const NestedError = __webpack_require__(917); class CpFileError extends NestedError { constructor(message, nested) { @@ -106153,10 +106980,10 @@ module.exports = CpFileError; /***/ }), -/* 912 */ +/* 917 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(913); +var inherits = __webpack_require__(918); var NestedError = function (message, nested) { this.nested = nested; @@ -106207,7 +107034,7 @@ module.exports = NestedError; /***/ }), -/* 913 */ +/* 918 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -106215,12 +107042,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(914); + module.exports = __webpack_require__(919); } /***/ }), -/* 914 */ +/* 919 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -106249,16 +107076,16 @@ if (typeof Object.create === 'function') { /***/ }), -/* 915 */ +/* 920 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const fs = __webpack_require__(22); -const makeDir = __webpack_require__(916); -const pEvent = __webpack_require__(908); -const CpFileError = __webpack_require__(911); +const makeDir = __webpack_require__(921); +const pEvent = __webpack_require__(913); +const CpFileError = __webpack_require__(916); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -106355,7 +107182,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 916 */ +/* 921 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106363,7 +107190,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const {promisify} = __webpack_require__(29); -const semver = __webpack_require__(917); +const semver = __webpack_require__(922); const defaults = { mode: 0o777 & (~process.umask()), @@ -106512,7 +107339,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 917 */ +/* 922 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -108114,7 +108941,7 @@ function coerce (version, options) { /***/ }), -/* 918 */ +/* 923 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108155,7 +108982,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 919 */ +/* 924 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108201,12 +109028,12 @@ exports.default = module.exports; /***/ }), -/* 920 */ +/* 925 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(921); +const NestedError = __webpack_require__(926); class CpyError extends NestedError { constructor(message, nested) { @@ -108220,7 +109047,7 @@ module.exports = CpyError; /***/ }), -/* 921 */ +/* 926 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -108276,7 +109103,7 @@ module.exports = NestedError; /***/ }), -/* 922 */ +/* 927 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index f4b91d154cbb8..66f17ab579ec3 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -136,7 +136,7 @@ export const schema = Joi.object() browser: Joi.object() .keys({ type: Joi.string() - .valid('chrome', 'firefox', 'ie', 'msedge') + .valid('chrome', 'firefox', 'ie') .default('chrome'), logPollingMs: Joi.number().default(100), diff --git a/test/functional/config.edge.js b/test/functional/config.edge.js deleted file mode 100644 index ed68b41e8c89a..0000000000000 --- a/test/functional/config.edge.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export default async function({ readConfigFile }) { - const defaultConfig = await readConfigFile(require.resolve('./config')); - - return { - ...defaultConfig.getAll(), - - browser: { - type: 'msedge', - }, - - junit: { - reportName: 'MS Chromium Edge UI Functional Tests', - }, - }; -} diff --git a/test/functional/services/browser.ts b/test/functional/services/browser.ts index 13d2365c07191..5017947e95d03 100644 --- a/test/functional/services/browser.ts +++ b/test/functional/services/browser.ts @@ -47,9 +47,7 @@ export async function BrowserProvider({ getService }: FtrProviderContext) { */ public readonly browserType: string = browserType; - public readonly isChromium: boolean = [Browsers.Chrome, Browsers.ChromiumEdge].includes( - browserType - ); + public readonly isChrome: boolean = browserType === Browsers.Chrome; public readonly isFirefox: boolean = browserType === Browsers.Firefox; diff --git a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts index 8b57ecd3c8235..157918df874c8 100644 --- a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts +++ b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts @@ -55,7 +55,6 @@ export class WebElementWrapper { private driver: WebDriver = this.webDriver.driver; private Keys = Key; public isW3CEnabled: boolean = (this.webDriver.driver as any).executor_.w3c === true; - public isChromium: boolean = [Browsers.Chrome, Browsers.ChromiumEdge].includes(this.browserType); public static create( webElement: WebElement | WebElementWrapper, @@ -64,7 +63,7 @@ export class WebElementWrapper { timeout: number, fixedHeaderHeight: number, logger: ToolingLog, - browserType: Browsers + browserType: string ): WebElementWrapper { if (webElement instanceof WebElementWrapper) { return webElement; @@ -88,7 +87,7 @@ export class WebElementWrapper { private timeout: number, private fixedHeaderHeight: number, private logger: ToolingLog, - private browserType: Browsers + private browserType: string ) {} private async _findWithCustomTimeout( @@ -244,7 +243,7 @@ export class WebElementWrapper { return this.clearValueWithKeyboard(); } await this.retryCall(async function clearValue(wrapper) { - if (wrapper.isChromium || options.withJS) { + if (wrapper.browserType === Browsers.Chrome || options.withJS) { // https://bugs.chromium.org/p/chromedriver/issues/detail?id=2702 await wrapper.driver.executeScript(`arguments[0].value=''`, wrapper._webElement); } else { @@ -276,7 +275,7 @@ export class WebElementWrapper { await delay(100); } } else { - if (this.isChromium) { + if (this.browserType === Browsers.Chrome) { // https://bugs.chromium.org/p/chromedriver/issues/detail?id=30 await this.retryCall(async function clearValueWithKeyboard(wrapper) { await wrapper.driver.executeScript(`arguments[0].select();`, wrapper._webElement); diff --git a/test/functional/services/remote/browsers.ts b/test/functional/services/remote/browsers.ts index aa6e364d0a09d..46d81f1737a55 100644 --- a/test/functional/services/remote/browsers.ts +++ b/test/functional/services/remote/browsers.ts @@ -21,5 +21,4 @@ export enum Browsers { Chrome = 'chrome', Firefox = 'firefox', InternetExplorer = 'ie', - ChromiumEdge = 'msedge', } diff --git a/test/functional/services/remote/remote.ts b/test/functional/services/remote/remote.ts index b0724488cb5db..e571a1a7e5551 100644 --- a/test/functional/services/remote/remote.ts +++ b/test/functional/services/remote/remote.ts @@ -64,23 +64,18 @@ export async function RemoteProvider({ getService }: FtrProviderContext) { lifecycle, config.get('browser.logPollingMs') ); - const isW3CEnabled = (driver as any).executor_.w3c; const caps = await driver.getCapabilities(); - const browserVersion = caps.get( - isW3CEnabled || browserType === Browsers.ChromiumEdge ? 'browserVersion' : 'version' - ); + const browserVersion = caps.get(isW3CEnabled ? 'browserVersion' : 'version'); - log.info( - `Remote initialized: ${caps.get( - 'browserName' - )} ${browserVersion}, w3c compliance=${isW3CEnabled}, collectingCoverage=${collectCoverage}` - ); + log.info(`Remote initialized: ${caps.get('browserName')} ${browserVersion}`); - if ([Browsers.Chrome, Browsers.ChromiumEdge].includes(browserType)) { + if (browserType === Browsers.Chrome) { log.info( - `${browserType}driver version: ${caps.get(browserType)[`${browserType}driverVersion`]}` + `Chromedriver version: ${ + caps.get('chrome').chromedriverVersion + }, w3c=${isW3CEnabled}, codeCoverage=${collectCoverage}` ); } diff --git a/test/functional/services/remote/webdriver.ts b/test/functional/services/remote/webdriver.ts index fc0b5bbb787c8..3bf5b865aa7ba 100644 --- a/test/functional/services/remote/webdriver.ts +++ b/test/functional/services/remote/webdriver.ts @@ -31,12 +31,10 @@ import { Builder, Capabilities, By, logging, until } from 'selenium-webdriver'; import chrome from 'selenium-webdriver/chrome'; import firefox from 'selenium-webdriver/firefox'; // @ts-ignore internal modules are not typed -import edge from 'selenium-webdriver/edge'; -import { installDriver } from 'ms-chromium-edge-driver'; -// @ts-ignore internal modules are not typed import { Executor } from 'selenium-webdriver/lib/http'; // @ts-ignore internal modules are not typed import { getLogger } from 'selenium-webdriver/lib/logging'; + import { pollForLogEntry$ } from './poll_for_log_entry'; import { createStdoutSocket } from './create_stdout_stream'; import { preventParallelCalls } from './prevent_parallel_calls'; @@ -65,7 +63,6 @@ Executor.prototype.execute = preventParallelCalls( ); let attemptCounter = 0; -let edgePaths: { driverPath: string | undefined; browserPath: string | undefined }; async function attemptToCreateCommand( log: ToolingLog, browserType: Browsers, @@ -77,46 +74,6 @@ async function attemptToCreateCommand( const buildDriverInstance = async () => { switch (browserType) { - case 'msedge': { - if (edgePaths && edgePaths.browserPath && edgePaths.driverPath) { - const edgeOptions = new edge.Options(); - if (headlessBrowser === '1') { - // @ts-ignore internal modules are not typed - edgeOptions.headless(); - } - // @ts-ignore internal modules are not typed - edgeOptions.setEdgeChromium(true); - // @ts-ignore internal modules are not typed - edgeOptions.setBinaryPath(edgePaths.browserPath); - const session = await new Builder() - .forBrowser('MicrosoftEdge') - .setEdgeOptions(edgeOptions) - .setEdgeService(new edge.ServiceBuilder(edgePaths.driverPath)) - .build(); - return { - session, - consoleLog$: pollForLogEntry$( - session, - logging.Type.BROWSER, - logPollingMs, - lifecycle.cleanup.after$ - ).pipe( - takeUntil(lifecycle.cleanup.after$), - map(({ message, level: { name: level } }) => ({ - message: message.replace(/\\n/g, '\n'), - level, - })) - ), - }; - } else { - throw new Error( - `Chromium Edge session requires browser or driver path to be defined: ${JSON.stringify( - edgePaths - )}` - ); - } - } - case 'chrome': { const chromeCapabilities = Capabilities.chrome(); const chromeOptions = [ @@ -308,11 +265,6 @@ export async function initWebDriver( log.verbose(entry.message); }); - // download Edge driver only in case of usage - if (browserType === Browsers.ChromiumEdge) { - edgePaths = await installDriver(); - } - return await Promise.race([ (async () => { await delay(2 * MINUTE); diff --git a/x-pack/test/functional/config.edge.js b/x-pack/test/functional/config.edge.js deleted file mode 100644 index 882fb6fea3686..0000000000000 --- a/x-pack/test/functional/config.edge.js +++ /dev/null @@ -1,21 +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 default async function({ readConfigFile }) { - const chromeConfig = await readConfigFile(require.resolve('./config')); - - return { - ...chromeConfig.getAll(), - - browser: { - type: 'msedge', - }, - - junit: { - reportName: 'MS Chromium Edge XPack UI Functional Tests', - }, - }; -} diff --git a/yarn.lock b/yarn.lock index 8ca25cc18a8a2..fdfdcada62e2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2562,11 +2562,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== -"@sindresorhus/is@^2.0.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-2.1.0.tgz#6ad4ca610f696098e92954ab431ff83bea0ce13f" - integrity sha512-lXKXfypKo644k4Da4yXkPCrwcvn6SlUW2X2zFbuflKHNjf0w9htru01bo26uMhleMXsDmnZ12eJLdrAZa9MANg== - "@sinonjs/commons@^1", "@sinonjs/commons@^1.3.0", "@sinonjs/commons@^1.4.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.6.0.tgz#ec7670432ae9c8eb710400d112c201a362d83393" @@ -3466,13 +3461,6 @@ "@svgr/plugin-svgo" "^4.2.0" loader-utils "^1.2.3" -"@szmarczak/http-timer@^4.0.0": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152" - integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== - dependencies: - defer-to-connect "^2.0.0" - "@testim/chrome-version@^1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@testim/chrome-version/-/chrome-version-1.0.7.tgz#0cd915785ec4190f08a3a6acc9b61fc38fb5f1a9" @@ -3721,16 +3709,6 @@ resolved "https://registry.yarnpkg.com/@types/browserslist-useragent/-/browserslist-useragent-3.0.0.tgz#d425c9818182ce71ce53866798cee9c7d41d6e53" integrity sha512-ZBvKzg3yyWNYEkwxAzdmUzp27sFvw+1m080/+2lwrt+eltNefn1f4fnpMyrjOla31p8zLleCYqQXw+3EETfn0w== -"@types/cacheable-request@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" - integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "*" - "@types/node" "*" - "@types/responselike" "*" - "@types/caseless@*": version "0.12.2" resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" @@ -4100,11 +4078,6 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" -"@types/http-cache-semantics@*": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" - integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== - "@types/indent-string@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/indent-string/-/indent-string-3.0.0.tgz#9ebb391ceda548926f5819ad16405349641b999f" @@ -4236,13 +4209,6 @@ dependencies: "@types/node" "*" -"@types/keyv@*": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" - integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== - dependencies: - "@types/node" "*" - "@types/license-checker@15.0.0": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/license-checker/-/license-checker-15.0.0.tgz#685d69e2cf61ffd862320434601f51c85e28bba1" @@ -4714,13 +4680,6 @@ "@types/tough-cookie" "*" form-data "^2.5.0" -"@types/responselike@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" - integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== - dependencies: - "@types/node" "*" - "@types/retry@^0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" @@ -4736,10 +4695,10 @@ resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-2.4.28.tgz#9ce8fa048c1e8c85cb71d7fe4d704e000226036f" integrity sha512-SMA+fUwULwK7sd/ZJicUztiPs8F1yCPwF3O23Z9uQ32ME5Ha0NmDK9+QTsYE4O2tHXChzXomSWWeIhCnoN1LqA== -"@types/selenium-webdriver@4.0.9": - version "4.0.9" - resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.0.9.tgz#12621e55b2ef8f6c98bd17fe23fa720c6cba16bd" - integrity sha512-HopIwBE7GUXsscmt/J0DhnFXLSmO04AfxT6b8HAprknwka7pqEWquWDMXxCjd+NUHK9MkCe1SDKKsMiNmCItbQ== +"@types/selenium-webdriver@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.0.5.tgz#23041a4948c82daf2df9836e4d2358fec10d3e24" + integrity sha512-ma1aL1znI3ptEbSQgbywgadrRCJouPIACSfOl/bPwu/TPNSyyE/+o9jZ6+bpDVTtIdksZuVKpq4SR1ip3DRduw== "@types/semver@^5.5.0": version "5.5.0" @@ -7470,18 +7429,13 @@ binaryextensions@2: resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935" integrity sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA== -bindings@1, bindings@^1.5.0: +bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" -bindings@~1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" - integrity sha1-FK1hE4EtLTfXLme0ystLtyZQXxE= - bit-twiddle@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bit-twiddle/-/bit-twiddle-1.0.2.tgz#0c6c1fabe2b23d17173d9a61b7b7093eb9e1769e" @@ -8015,7 +7969,7 @@ buffer@^5.1.0, buffer@^5.2.0: base64-js "^1.0.2" ieee754 "^1.1.4" -builtin-modules@^1.0.0, builtin-modules@^1.1.1: +builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= @@ -8162,13 +8116,6 @@ cache-loader@^4.1.0: neo-async "^2.6.1" schema-utils "^2.0.0" -cacheable-lookup@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-2.0.0.tgz#33b1e56f17507f5cf9bb46075112d65473fb7713" - integrity sha512-s2piO6LvA7xnL1AR03wuEdSx3BZT3tIJpZ56/lcJwzO/6DTJZlTs7X3lrvPxk6d1PlDe6PrVe2TjlUIZNFglAQ== - dependencies: - keyv "^4.0.0" - cacheable-request@^2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" @@ -8182,19 +8129,6 @@ cacheable-request@^2.1.1: normalize-url "2.0.1" responselike "1.0.2" -cacheable-request@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" - integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^2.0.0" - cachedir@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" @@ -9023,7 +8957,7 @@ clone-regexp@^1.0.0: is-regexp "^1.0.0" is-supported-regexp-flag "^1.0.0" -clone-response@1.0.2, clone-response@^1.0.2: +clone-response@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= @@ -9287,16 +9221,16 @@ commander@4.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.0.tgz#545983a0603fe425bc672d66c9e3c89c42121a83" integrity sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw== -commander@^2.12.1, commander@^2.20.0, commander@^2.7.1: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - commander@^2.13.0, commander@^2.15.1, commander@^2.16.0, commander@^2.19.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@^2.20.0, commander@^2.7.1: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^2.8.1: version "2.18.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" @@ -10701,7 +10635,7 @@ debug-fabulous@1.X: memoizee "0.4.X" object-assign "4.X" -debug@2, debug@2.6.9, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -10773,13 +10707,6 @@ decompress-response@^4.2.0: dependencies: mimic-response "^2.0.0" -decompress-response@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-5.0.0.tgz#7849396e80e3d1eba8cb2f75ef4930f76461cb0f" - integrity sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw== - dependencies: - mimic-response "^2.0.0" - decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" @@ -10931,11 +10858,6 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -defer-to-connect@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" - integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg== - define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -13158,7 +13080,7 @@ extract-zip@1.6.7: mkdirp "0.5.1" yauzl "2.4.1" -extract-zip@^1.6.6, extract-zip@^1.6.7, extract-zip@^1.7.0: +extract-zip@^1.6.6, extract-zip@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== @@ -13388,17 +13310,6 @@ fetch-mock@^7.3.9: path-to-regexp "^2.2.1" whatwg-url "^6.5.0" -ffi@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/ffi/-/ffi-2.3.0.tgz#fa1a7b3d85c0fa8c83d96947a64b5192bc47f858" - integrity sha512-vkPA9Hf9CVuQ5HeMZykYvrZF2QNJ/iKGLkyDkisBnoOOFeFXZQhUPxBARPBIZMJVulvBI2R+jgofW03gyPpJcQ== - dependencies: - bindings "~1.2.0" - debug "2" - nan "2" - ref "1" - ref-struct "1" - figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" @@ -14881,27 +14792,6 @@ got@5.6.0: unzip-response "^1.0.0" url-parse-lax "^1.0.0" -got@^10.6.0: - version "10.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-10.6.0.tgz#ac3876261a4d8e5fc4f81186f79955ce7b0501dc" - integrity sha512-3LIdJNTdCFbbJc+h/EH0V5lpNpbJ6Bfwykk21lcQvQsEcrzdi/ltCyQehFHLzJ/ka0UMH4Slg0hkYvAZN9qUDg== - dependencies: - "@sindresorhus/is" "^2.0.0" - "@szmarczak/http-timer" "^4.0.0" - "@types/cacheable-request" "^6.0.1" - cacheable-lookup "^2.0.0" - cacheable-request "^7.0.1" - decompress-response "^5.0.0" - duplexer3 "^0.1.4" - get-stream "^5.0.0" - lowercase-keys "^2.0.0" - mimic-response "^2.1.0" - p-cancelable "^2.0.0" - p-event "^4.0.0" - responselike "^2.0.0" - to-readable-stream "^2.0.0" - type-fest "^0.10.0" - got@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/got/-/got-3.3.1.tgz#e5d0ed4af55fc3eef4d56007769d98192bcb2eca" @@ -16008,11 +15898,6 @@ http-cache-semantics@3.8.1: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -17051,11 +16936,6 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e" integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g== -is-generator-function@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" - integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== - is-glob@4.0.0, is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" @@ -18345,11 +18225,6 @@ json-buffer@3.0.0: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - json-parse-better-errors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" @@ -18585,7 +18460,7 @@ jsx-to-string@^1.4.0: json-stringify-pretty-compact "^1.0.1" react "^0.14.0" -jszip@^3.2.2: +jszip@^3.1.5: version "3.2.2" resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.2.2.tgz#b143816df7e106a9597a94c77493385adca5bd1d" integrity sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA== @@ -18761,13 +18636,6 @@ keyv@3.0.0: dependencies: json-buffer "3.0.0" -keyv@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.0.tgz#2d1dab694926b2d427e4c74804a10850be44c12f" - integrity sha512-U7ioE8AimvRVLfw4LffyOIRhL2xVgmE8T22L6i0BucSnBUyv4w+I7VN/zVZwRKHOI6ZRUcdMdWHQ8KSUvGpEog== - dependencies: - json-buffer "3.0.1" - killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -19736,11 +19604,6 @@ lowercase-keys@^1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - lowlight@~1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.9.1.tgz#ed7c3dffc36f8c1f263735c0fe0c907847c11250" @@ -20394,11 +20257,6 @@ mimic-response@^2.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== -mimic-response@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== - mimos@4.x.x: version "4.0.0" resolved "https://registry.yarnpkg.com/mimos/-/mimos-4.0.0.tgz#76e3d27128431cb6482fd15b20475719ad626a5a" @@ -20827,19 +20685,6 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -ms-chromium-edge-driver@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ms-chromium-edge-driver/-/ms-chromium-edge-driver-0.2.0.tgz#0e0c6fd9fd1d1d36db97b2b3d7e9d4ba4d2de456" - integrity sha512-RkDsBPnMLjRna7q4LlvtLb+CHPei9gZapnlxm3ayWKk3Ab6HmDsz/17xG2eyqkKX5UcKeo04YlLZ345tO7OolA== - dependencies: - extract-zip "^1.6.7" - got "^10.6.0" - lodash "4.17.15" - tslint "^6.1.0" - tslint-config-prettier "^1.18.0" - util "^0.12.2" - windows-registry "^0.1.5" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -20952,7 +20797,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@2, nan@^2.12.1, nan@^2.13.2: +nan@^2.12.1, nan@^2.13.2: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -21462,11 +21307,6 @@ normalize-url@^3.3.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== -normalize-url@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" - integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== - now-and-later@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" @@ -22153,11 +21993,6 @@ p-cancelable@^0.4.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== -p-cancelable@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" - integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== - p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -22170,7 +22005,7 @@ p-each-series@^1.0.0: dependencies: p-reduce "^1.0.0" -p-event@^4.0.0, p-event@^4.1.0: +p-event@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.1.0.tgz#e92bb866d7e8e5b732293b1c8269d38e9982bf8e" integrity sha512-4vAd06GCsgflX4wHN1JqrMzBh/8QZ4j+rzp0cd2scXRwuBEv+QR3wrVA5aLhWDLw4y2WgDKvzWF3CCLmVM1UgA== @@ -25226,31 +25061,6 @@ redux@^4.0.5: loose-envify "^1.4.0" symbol-observable "^1.2.0" -ref-struct@1, ref-struct@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ref-struct/-/ref-struct-1.1.0.tgz#5d5ee65ad41cefc3a5c5feb40587261e479edc13" - integrity sha1-XV7mWtQc78Olxf60BYcmHkee3BM= - dependencies: - debug "2" - ref "1" - -ref-union@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ref-union/-/ref-union-1.0.1.tgz#3a2397f862f1e75171d687268f43b3f17729f120" - integrity sha1-OiOX+GLx51Fx1ocmj0Oz8Xcp8SA= - dependencies: - debug "2" - ref "1" - -ref@1, ref@^1.2.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ref/-/ref-1.3.5.tgz#0e33f080cdb94a3d95312b2b3b1fd0f82044ca0f" - integrity sha512-2cBCniTtxcGUjDpvFfVpw323a83/0RLSGJJY5l5lcomZWhYpU2cuLdsvYqMixvsdLJ9+sTdzEkju8J8ZHDM2nA== - dependencies: - bindings "1" - debug "2" - nan "2" - reflect.ownkeys@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" @@ -25990,13 +25800,6 @@ responselike@1.0.2: dependencies: lowercase-keys "^1.0.0" -responselike@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" - integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw== - dependencies: - lowercase-keys "^2.0.0" - restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -26555,14 +26358,15 @@ select@^1.1.2: resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= -selenium-webdriver@^4.0.0-alpha.7: - version "4.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.7.tgz#e3879d8457fd7ad8e4424094b7dc0540d99e6797" - integrity sha512-D4qnTsyTr91jT8f7MfN+OwY0IlU5+5FmlO5xlgRUV6hDEV8JyYx2NerdTEqDDkNq7RZDYc4VoPALk8l578RBHw== +selenium-webdriver@^4.0.0-alpha.5: + version "4.0.0-alpha.5" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.5.tgz#e4683b3dbf827d70df09a7e43bf02ebad20fa7c1" + integrity sha512-hktl3DSrhzM59yLhWzDGHIX9o56DvA+cVK7Dw6FcJR6qQ4CGzkaHeXQPcdrslkWMTeq0Ci9AmCxq0EMOvm2Rkg== dependencies: - jszip "^3.2.2" - rimraf "^2.7.1" + jszip "^3.1.5" + rimraf "^2.6.3" tmp "0.0.30" + xml2js "^0.4.19" selfsigned@^1.10.7: version "1.10.7" @@ -28962,11 +28766,6 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" -to-readable-stream@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-2.1.0.tgz#82880316121bea662cdc226adb30addb50cb06e8" - integrity sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w== - to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -29246,37 +29045,6 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.2, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== -tslint-config-prettier@^1.18.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37" - integrity sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg== - -tslint@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.0.tgz#c6c611b8ba0eed1549bf5a59ba05a7732133d851" - integrity sha512-fXjYd/61vU6da04E505OZQGb2VCN2Mq3doeWcOIryuG+eqdmFUXTYVwdhnbEu2k46LNLgUYt9bI5icQze/j0bQ== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^4.0.1" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.1" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.10.0" - tsutils "^2.29.0" - -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== - dependencies: - tslib "^1.8.1" - tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -29781,11 +29549,6 @@ type-detect@^1.0.0: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" integrity sha1-diIXzAbbJY7EiQihKY6LlRIejqI= -type-fest@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.10.0.tgz#7f06b2b9fbfc581068d1341ffabd0349ceafc642" - integrity sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw== - type-fest@^0.3.0, type-fest@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -30483,16 +30246,6 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@^0.12.2: - version "0.12.2" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.2.tgz#54adb634c9e7c748707af2bf5a8c7ab640cbba2b" - integrity sha512-XE+MkWQvglYa+IOfBt5UFG93EmncEMP23UqpgDvVZVFBPxwmkK10QRp6pgU4xICPnWRf/t0zPv4noYSUq9gqUQ== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - safe-buffer "^5.1.2" - utila@^0.4.0, utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" @@ -31654,17 +31407,6 @@ window-size@^0.2.0: resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= -windows-registry@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/windows-registry/-/windows-registry-0.1.5.tgz#92c25c960884b0d215e69395f52d8dfaa0ba4ad0" - integrity sha512-gMN3ets1fbdP+TApEbbX2TIfBK3MIH5+p9GMvIFS3CNLr7U0Khe5mRj/T5zvwo/pKdhJgDrCLYyaNSs7HYiBCw== - dependencies: - debug "^2.2.0" - ffi "^2.0.0" - ref "^1.2.0" - ref-struct "^1.0.2" - ref-union "^1.0.0" - windows-release@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f" @@ -31973,6 +31715,14 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha1-qQKekp09vN7RafPG4oI42VpdWig= +xml2js@^0.4.19, xml2js@^0.4.5: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + xml2js@^0.4.22: version "0.4.22" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02" @@ -31982,14 +31732,6 @@ xml2js@^0.4.22: util.promisify "~1.0.0" xmlbuilder "~11.0.0" -xml2js@^0.4.5: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - xml@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" From 040e7b464edfe58de4612278fbb33f21a99c62d1 Mon Sep 17 00:00:00 2001 From: Larry Gregory <larry.gregory@elastic.co> Date: Tue, 14 Apr 2020 07:33:14 -0400 Subject: [PATCH 091/121] Adjust API authorization logging (#63350) --- .../security/server/authorization/api_authorization.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security/server/authorization/api_authorization.ts b/x-pack/plugins/security/server/authorization/api_authorization.ts index cc672fbc69e06..88b3f2c6f7155 100644 --- a/x-pack/plugins/security/server/authorization/api_authorization.ts +++ b/x-pack/plugins/security/server/authorization/api_authorization.ts @@ -24,7 +24,6 @@ export function initAPIAuthorization( // if there are no tags starting with "access:", just continue if (actionTags.length === 0) { - logger.debug('API endpoint is not marked with "access:" tags, skipping.'); return toolkit.next(); } @@ -34,11 +33,11 @@ export function initAPIAuthorization( // we've actually authorized the request if (checkPrivilegesResponse.hasAllRequested) { - logger.debug(`authorized for "${request.url.path}"`); + logger.debug(`User authorized for "${request.url.path}"`); return toolkit.next(); } - logger.debug(`not authorized for "${request.url.path}"`); + logger.warn(`User not authorized for "${request.url.path}": responding with 404`); return response.notFound(); }); } From 1a6398b983ee3645b175009f150c92dc1a8b70cd Mon Sep 17 00:00:00 2001 From: Sandra Gonzales <neptunian@users.noreply.github.com> Date: Tue, 14 Apr 2020 07:56:24 -0400 Subject: [PATCH 092/121] [EPM] add/remove package in package settings page (#63389) * fix bug where assets were not being returned, use archive info for assets * add settings page, add install/remove button and text * check existence of datasources associated with this package * add package title variable to text * update modal text and rename to uninstall --- .../ingest_manager/common/types/models/epm.ts | 2 +- .../common/types/rest_spec/datasource.ts | 15 ++- .../hooks/use_request/datasource.ts | 12 +- .../sections/epm/hooks/index.tsx | 2 +- .../epm/hooks/use_package_install.tsx | 101 +++++++++------ .../screens/detail/confirm_package_delete.tsx | 32 ----- .../detail/confirm_package_install.tsx | 41 +++++- .../detail/confirm_package_uninstall.tsx | 73 +++++++++++ .../sections/epm/screens/detail/content.tsx | 5 +- .../screens/detail/installation_button.tsx | 83 ++++++++---- .../epm/screens/detail/settings_panel.tsx | 118 ++++++++++++++++++ .../epm/screens/detail/side_nav_links.tsx | 1 + .../server/services/epm/packages/get.ts | 4 +- 13 files changed, 381 insertions(+), 108 deletions(-) delete mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index 5524e7505d74b..064341c68a97a 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -19,7 +19,7 @@ export enum InstallStatus { uninstalling = 'uninstalling', } -export type DetailViewPanelName = 'overview' | 'data-sources'; +export type DetailViewPanelName = 'overview' | 'data-sources' | 'settings'; export type ServiceName = 'kibana' | 'elasticsearch'; export type AssetType = KibanaAssetType | ElasticsearchAssetType | AgentAssetType; diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts index f630602503f0a..66f734b904cfc 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts @@ -4,10 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ import { Datasource, NewDatasource } from '../models'; -import { ListWithKuery } from './common'; export interface GetDatasourcesRequest { - query: ListWithKuery; + query: { + page: number; + perPage: number; + kuery?: string; + }; } export interface GetOneDatasourceRequest { @@ -16,6 +19,14 @@ export interface GetOneDatasourceRequest { }; } +export interface GetDatasourcesResponse { + items: Datasource[]; + total: number; + page: number; + perPage: number; + success: boolean; +} + export interface CreateDatasourceRequest { body: NewDatasource; } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts index d0072f0355993..0d19ecd0cb735 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/datasource.ts @@ -3,12 +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 { sendRequest } from './use_request'; +import { sendRequest, useRequest } from './use_request'; import { datasourceRouteService } from '../../services'; import { CreateDatasourceRequest, CreateDatasourceResponse } from '../../types'; import { DeleteDatasourcesRequest, DeleteDatasourcesResponse, + GetDatasourcesRequest, + GetDatasourcesResponse, } from '../../../../../common/types/rest_spec'; export const sendCreateDatasource = (body: CreateDatasourceRequest['body']) => { @@ -26,3 +28,11 @@ export const sendDeleteDatasource = (body: DeleteDatasourcesRequest['body']) => body: JSON.stringify(body), }); }; + +export function useGetDatasources(query: GetDatasourcesRequest['query']) { + return useRequest<GetDatasourcesResponse>({ + method: 'get', + path: datasourceRouteService.getListPath(), + query, + }); +} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx index 48986481b6061..fbc00fbadcfaa 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/index.tsx @@ -7,7 +7,7 @@ export { useLinks } from './use_links'; export { useLocalSearch, searchIdField } from './use_local_search'; export { PackageInstallProvider, - useDeletePackage, + useUninstallPackage, useGetPackageInstallStatus, useInstallPackage, useSetPackageInstallStatus, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx index 537a2616f1786..0c5f45cdc47a7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx @@ -6,8 +6,8 @@ import createContainer from 'constate'; import React, { useCallback, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { NotificationsStart } from 'src/core/public'; -import { useLinks } from '.'; import { toMountPoint } from '../../../../../../../../../src/plugins/kibana_react/public'; import { PackageInfo } from '../../../types'; import { sendInstallPackage, sendRemovePackage } from '../../../hooks'; @@ -25,7 +25,6 @@ type InstallPackageProps = Pick<PackageInfo, 'name' | 'version' | 'title'>; function usePackageInstall({ notifications }: { notifications: NotificationsStart }) { const [packages, setPackage] = useState<PackagesInstall>({}); - const { toDetailView } = useLinks(); const setPackageInstallStatus = useCallback( ({ name, status }: { name: PackageInfo['name']; status: InstallStatus }) => { @@ -46,34 +45,43 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar if (res.error) { setPackageInstallStatus({ name, status: InstallStatus.notInstalled }); notifications.toasts.addWarning({ - title: `Failed to install ${title} package`, - text: - 'Something went wrong while trying to install this package. Please try again later.', + title: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageInstallErrorTitle" + defaultMessage="Failed to install {title} package" + values={{ title }} + /> + ), + text: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageInstallErrorDescription" + defaultMessage="Something went wrong while trying to install this package. Please try again later." + /> + ), iconType: 'alert', }); } else { setPackageInstallStatus({ name, status: InstallStatus.installed }); - const SuccessMsg = <p>Successfully installed {name}</p>; notifications.toasts.addSuccess({ - title: `Installed ${title} package`, - text: toMountPoint(SuccessMsg), + title: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageInstallSuccessTitle" + defaultMessage="Installed {title}" + values={{ title }} + /> + ), + text: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageInstallSuccessDescription" + defaultMessage="Successfully installed {title}" + values={{ title }} + /> + ), }); - - // TODO: this should probably live somewhere else and use <Redirect />, - // this hook could return the request state and a component could - // use that state. the component should be able to unsubscribe to prevent memory leaks - const packageUrl = toDetailView({ name, version }); - const dataSourcesUrl = toDetailView({ - name, - version, - panel: 'data-sources', - withAppRoot: false, - }); - if (window.location.href.includes(packageUrl)) window.location.hash = dataSourcesUrl; } }, - [notifications.toasts, setPackageInstallStatus, toDetailView] + [notifications.toasts, setPackageInstallStatus] ); const getPackageInstallStatus = useCallback( @@ -83,7 +91,7 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar [packages] ); - const deletePackage = useCallback( + const uninstallPackage = useCallback( async ({ name, version, title }: Pick<PackageInfo, 'name' | 'version' | 'title'>) => { setPackageInstallStatus({ name, status: InstallStatus.uninstalling }); const pkgkey = `${name}-${version}`; @@ -92,30 +100,43 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar if (res.error) { setPackageInstallStatus({ name, status: InstallStatus.installed }); notifications.toasts.addWarning({ - title: `Failed to delete ${title} package`, - text: 'Something went wrong while trying to delete this package. Please try again later.', + title: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageUninstallErrorTitle" + defaultMessage="Failed to uninstall {title} package" + values={{ title }} + /> + ), + text: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageUninstallErrorDescription" + defaultMessage="Something went wrong while trying to uninstall this package. Please try again later." + /> + ), iconType: 'alert', }); } else { setPackageInstallStatus({ name, status: InstallStatus.notInstalled }); - const SuccessMsg = <p>Successfully deleted {title}</p>; - notifications.toasts.addSuccess({ - title: `Deleted ${title} package`, - text: toMountPoint(SuccessMsg), - }); - - const packageUrl = toDetailView({ name, version }); - const dataSourcesUrl = toDetailView({ - name, - version, - panel: 'data-sources', + title: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageUninstallSuccessTitle" + defaultMessage="Uninstalled {title}" + values={{ title }} + /> + ), + text: toMountPoint( + <FormattedMessage + id="xpack.ingestManager.integrations.packageUninstallSuccessDescription" + defaultMessage="Successfully uninstalled {title}" + values={{ title }} + /> + ), }); - if (window.location.href.includes(packageUrl)) window.location.href = dataSourcesUrl; } }, - [notifications.toasts, setPackageInstallStatus, toDetailView] + [notifications.toasts, setPackageInstallStatus] ); return { @@ -123,7 +144,7 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar installPackage, setPackageInstallStatus, getPackageInstallStatus, - deletePackage, + uninstallPackage, }; } @@ -132,11 +153,11 @@ export const [ useInstallPackage, useSetPackageInstallStatus, useGetPackageInstallStatus, - useDeletePackage, + useUninstallPackage, ] = createContainer( usePackageInstall, value => value.installPackage, value => value.setPackageInstallStatus, value => value.getPackageInstallStatus, - value => value.deletePackage + value => value.uninstallPackage ); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx deleted file mode 100644 index 2b3be04ac476b..0000000000000 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_delete.tsx +++ /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 { EuiCallOut, EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; -import React from 'react'; - -interface ConfirmPackageDeleteProps { - onCancel: () => void; - onConfirm: () => void; - packageName: string; - numOfAssets: number; -} -export const ConfirmPackageDelete = (props: ConfirmPackageDeleteProps) => { - const { onCancel, onConfirm, packageName, numOfAssets } = props; - return ( - <EuiOverlayMask> - <EuiConfirmModal - title={`Delete ${packageName}?`} - onCancel={onCancel} - onConfirm={onConfirm} - cancelButtonText="Cancel" - confirmButtonText="Delete package" - defaultFocusedButton="confirm" - buttonColor="danger" - > - <EuiCallOut title={`This package will delete ${numOfAssets} assets.`} color="danger" /> - </EuiConfirmModal> - </EuiOverlayMask> - ); -}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx index 137d9cf226b4d..ac30815a941ee 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx @@ -5,6 +5,7 @@ */ import { EuiCallOut, EuiConfirmModal, EuiOverlayMask, EuiSpacer } from '@elastic/eui'; import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; interface ConfirmPackageInstallProps { onCancel: () => void; @@ -17,18 +18,46 @@ export const ConfirmPackageInstall = (props: ConfirmPackageInstallProps) => { return ( <EuiOverlayMask> <EuiConfirmModal - title={`Install ${packageName}?`} + title={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmInstallModal.installTitle" + defaultMessage="Install {packageName}" + values={{ packageName }} + /> + } onCancel={onCancel} onConfirm={onConfirm} - cancelButtonText="Cancel" - confirmButtonText="Install package" + cancelButtonText={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmInstallModal.cancelButtonLabel" + defaultMessage="Cancel" + /> + } + confirmButtonText={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmInstallModal.installButtonLabel" + defaultMessage="Install {packageName}" + values={{ packageName }} + /> + } defaultFocusedButton="confirm" > - <EuiCallOut title={`This package will install ${numOfAssets} assets.`} /> + <EuiCallOut + iconType="iInCircle" + title={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmInstallModal.installCalloutTitle" + defaultMessage="This action will install {numOfAssets} assets" + values={{ numOfAssets }} + /> + } + /> <EuiSpacer size="l" /> <p> - and will only be accessible to users who have permission to view this Space. Elasticsearch - assets are installed globally and will be accessible to all Kibana users. + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmInstallModal.installDescription" + defaultMessage="Kibana assets will be installed in the current Space (Default) and will only be accessible to users who have permission to view this Space. Elasticsearch assets are installed globally and will be accessible to all Kibana users." + /> </p> </EuiConfirmModal> </EuiOverlayMask> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx new file mode 100644 index 0000000000000..14b9bf77c3a00 --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx @@ -0,0 +1,73 @@ +/* + * 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 { EuiCallOut, EuiConfirmModal, EuiOverlayMask, EuiSpacer } from '@elastic/eui'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +interface ConfirmPackageUninstallProps { + onCancel: () => void; + onConfirm: () => void; + packageName: string; + numOfAssets: number; +} +export const ConfirmPackageUninstall = (props: ConfirmPackageUninstallProps) => { + const { onCancel, onConfirm, packageName, numOfAssets } = props; + return ( + <EuiOverlayMask> + <EuiConfirmModal + title={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallTitle" + defaultMessage="Uninstall {packageName}" + values={{ packageName }} + /> + } + onCancel={onCancel} + onConfirm={onConfirm} + cancelButtonText={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmUninstallModal.cancelButtonLabel" + defaultMessage="Cancel" + /> + } + confirmButtonText={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallButtonLabel" + defaultMessage="Uninstall {packageName}" + values={{ packageName }} + /> + } + defaultFocusedButton="confirm" + buttonColor="danger" + > + <EuiCallOut + color="danger" + title={ + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallCallout.title" + defaultMessage="This action will remove {numOfAssets} assets" + values={{ numOfAssets }} + /> + } + > + <p> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallCallout.description" + defaultMessage="Kibana and Elasticsearch assets that were created by this Integration will be removed. Agents configurations and any data sent by your agents will not be effected." + /> + </p> + </EuiCallOut> + <EuiSpacer size="l" /> + <p> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallDescription" + defaultMessage="This action cannot be undone. Are you sure you wish to continue?" + /> + </p> + </EuiConfirmModal> + </EuiOverlayMask> + ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx index 384cbbeed378e..0d4b395895322 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx @@ -15,6 +15,7 @@ import { CenterColumn, LeftColumn, RightColumn } from './layout'; import { OverviewPanel } from './overview_panel'; import { SideNavLinks } from './side_nav_links'; import { DataSourcesPanel } from './data_sources_panel'; +import { SettingsPanel } from './settings_panel'; type ContentProps = PackageInfo & Pick<DetailParams, 'panel'> & { hasIconPanel: boolean }; export function Content(props: ContentProps) { @@ -49,8 +50,10 @@ export function Content(props: ContentProps) { type ContentPanelProps = PackageInfo & Pick<DetailParams, 'panel'>; export function ContentPanel(props: ContentPanelProps) { - const { panel, name, version } = props; + const { panel, name, version, assets, title } = props; switch (panel) { + case 'settings': + return <SettingsPanel name={name} version={version} assets={assets} title={title} />; case 'data-sources': return <DataSourcesPanel name={name} version={version} />; case 'overview': diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx index 8a8afed5570ed..cbbf1ce53c4ea 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx @@ -5,21 +5,21 @@ */ import { EuiButton } from '@elastic/eui'; import React, { Fragment, useCallback, useMemo, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { PackageInfo, InstallStatus } from '../../../../types'; import { useCapabilities } from '../../../../hooks'; -import { useDeletePackage, useGetPackageInstallStatus, useInstallPackage } from '../../hooks'; -import { ConfirmPackageDelete } from './confirm_package_delete'; +import { useUninstallPackage, useGetPackageInstallStatus, useInstallPackage } from '../../hooks'; +import { ConfirmPackageUninstall } from './confirm_package_uninstall'; import { ConfirmPackageInstall } from './confirm_package_install'; -interface InstallationButtonProps { - package: PackageInfo; -} - +type InstallationButtonProps = Pick<PackageInfo, 'assets' | 'name' | 'title' | 'version'> & { + disabled: boolean; +}; export function InstallationButton(props: InstallationButtonProps) { - const { assets, name, title, version } = props.package; + const { assets, name, title, version, disabled = true } = props; const hasWriteCapabilites = useCapabilities().write; const installPackage = useInstallPackage(); - const deletePackage = useDeletePackage(); + const uninstallPackage = useUninstallPackage(); const getPackageInstallStatus = useGetPackageInstallStatus(); const installationStatus = getPackageInstallStatus(name); @@ -36,11 +36,12 @@ export function InstallationButton(props: InstallationButtonProps) { toggleModal(); }, [installPackage, name, title, toggleModal, version]); - const handleClickDelete = useCallback(() => { - deletePackage({ name, version, title }); + const handleClickUninstall = useCallback(() => { + uninstallPackage({ name, version, title }); toggleModal(); - }, [deletePackage, name, title, toggleModal, version]); + }, [uninstallPackage, name, title, toggleModal, version]); + // counts the number of assets in the package const numOfAssets = useMemo( () => Object.entries(assets).reduce( @@ -56,30 +57,68 @@ export function InstallationButton(props: InstallationButtonProps) { ); const installButton = ( - <EuiButton isLoading={isInstalling} fill={true} onClick={toggleModal}> - {isInstalling ? 'Installing' : 'Install package'} + <EuiButton iconType={'importAction'} isLoading={isInstalling} onClick={toggleModal}> + {isInstalling ? ( + <FormattedMessage + id="xpack.ingestManager.integrations.installPackage.installingPackageButtonLabel" + defaultMessage="Installing {title} assets" + values={{ + title, + }} + /> + ) : ( + <FormattedMessage + id="xpack.ingestManager.integrations.installPackage.installPackageButtonLabel" + defaultMessage="Install {title} assets" + values={{ + title, + }} + /> + )} </EuiButton> ); - const installedButton = ( - <EuiButton isLoading={isRemoving} fill={true} onClick={toggleModal} color="danger"> - {isInstalling ? 'Deleting' : 'Delete package'} + const uninstallButton = ( + <EuiButton + iconType={'trash'} + isLoading={isRemoving} + onClick={toggleModal} + color="danger" + disabled={disabled || isRemoving ? true : false} + > + {isRemoving ? ( + <FormattedMessage + id="xpack.ingestManager.integrations.uninstallPackage.uninstallingPackageButtonLabel" + defaultMessage="Uninstalling {title}" + values={{ + title, + }} + /> + ) : ( + <FormattedMessage + id="xpack.ingestManager.integrations.uninstallPackage.uninstallPackageButtonLabel" + defaultMessage="Uninstall {title}" + values={{ + title, + }} + /> + )} </EuiButton> ); - const deletionModal = ( - <ConfirmPackageDelete + const uninstallModal = ( + <ConfirmPackageUninstall // this is number of which would be installed // deleted includes ingest-pipelines etc so could be larger // not sure how to do this at the moment so using same value numOfAssets={numOfAssets} packageName={title} onCancel={toggleModal} - onConfirm={handleClickDelete} + onConfirm={handleClickUninstall} /> ); - const installationModal = ( + const installModal = ( <ConfirmPackageInstall numOfAssets={numOfAssets} packageName={title} @@ -90,8 +129,8 @@ export function InstallationButton(props: InstallationButtonProps) { return hasWriteCapabilites ? ( <Fragment> - {isInstalled ? installedButton : installButton} - {isModalVisible && (isInstalled ? deletionModal : installationModal)} + {isInstalled || isRemoving ? uninstallButton : installButton} + {isModalVisible && (isInstalled ? uninstallModal : installModal)} </Fragment> ) : null; } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx new file mode 100644 index 0000000000000..ff7ecf97714b6 --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -0,0 +1,118 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n/react'; +import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { EuiSpacer } from '@elastic/eui'; +import { useGetPackageInstallStatus } from '../../hooks'; +import { InstallStatus, PackageInfo } from '../../../../types'; +import { InstallationButton } from './installation_button'; +import { useGetDatasources } from '../../../../hooks'; + +export const SettingsPanel = ( + props: Pick<PackageInfo, 'assets' | 'name' | 'title' | 'version'> +) => { + const getPackageInstallStatus = useGetPackageInstallStatus(); + const { data: datasourcesData } = useGetDatasources({ + perPage: 0, + page: 1, + kuery: `datasources.package.name:${props.name}`, + }); + const { name, title } = props; + const packageInstallStatus = getPackageInstallStatus(name); + const packageHasDatasources = !!datasourcesData?.total; + + return ( + <EuiText> + <EuiTitle> + <h3> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.packageSettingsTitle" + defaultMessage="Settings" + /> + </h3> + </EuiTitle> + <EuiSpacer size="s" /> + {packageInstallStatus === InstallStatus.notInstalled || + packageInstallStatus === InstallStatus.installing ? ( + <div> + <EuiTitle> + <h4> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.packageInstallTitle" + defaultMessage="Install {title}" + values={{ + title, + }} + /> + </h4> + </EuiTitle> + <EuiSpacer size="s" /> + <p> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.packageInstallDescription" + defaultMessage="Install this integration to setup Kibana and Elasticsearch assets designed for {title} data." + values={{ + title, + }} + /> + </p> + </div> + ) : ( + <div> + <EuiTitle> + <h4> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.packageUninstallTitle" + defaultMessage="Uninstall {title}" + values={{ + title, + }} + /> + </h4> + </EuiTitle> + <EuiSpacer size="s" /> + <p> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.packageUninstallDescription" + defaultMessage="Remove Kibana and Elasticsearch assets that were installed by this Integration." + /> + </p> + </div> + )} + <EuiFlexGroup> + <EuiFlexItem grow={false}> + <p> + <InstallationButton + {...props} + disabled={!datasourcesData ? true : packageHasDatasources} + /> + </p> + </EuiFlexItem> + </EuiFlexGroup> + {packageHasDatasources && ( + <p> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteDetail" + defaultMessage="{strongNote} {title} cannot be uninstalled because there are active agents that use this integration. To uninstall, remove all {title} data sources from your agent configurations." + values={{ + title, + strongNote: ( + <strong> + <FormattedMessage + id="xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteLabel" + defaultMessage="Note:" + /> + </strong> + ), + }} + /> + </p> + )} + </EuiText> + ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx index 39a6fca2e4318..05729ccfc1af4 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/side_nav_links.tsx @@ -17,6 +17,7 @@ export type NavLinkProps = Pick<PackageInfo, 'name' | 'version'> & { const PanelDisplayNames: Record<DetailViewPanelName, string> = { overview: 'Overview', 'data-sources': 'Data Sources', + settings: 'Settings', }; export function SideNavLinks({ name, version, active }: NavLinkProps) { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts index 0e2c2a3d26073..d76584225877c 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts @@ -67,7 +67,7 @@ export async function getPackageInfo(options: { pkgVersion: string; }): Promise<PackageInfo> { const { savedObjectsClient, pkgName, pkgVersion } = options; - const [item, savedObject] = await Promise.all([ + const [item, savedObject, assets] = await Promise.all([ Registry.fetchInfo(pkgName, pkgVersion), getInstallationObject({ savedObjectsClient, pkgName }), Registry.getArchiveInfo(pkgName, pkgVersion), @@ -80,7 +80,7 @@ export async function getPackageInfo(options: { const updated = { ...item, title: item.title || nameAsTitle(item.name), - assets: Registry.groupPathsByService(item?.assets || []), + assets: Registry.groupPathsByService(assets || []), }; return createInstallableFrom(updated, savedObject); } From 69ed664dd93a2825679a3d1ff920dd7ccc7823d4 Mon Sep 17 00:00:00 2001 From: Matthew Kime <matt@mattki.me> Date: Tue, 14 Apr 2020 06:58:56 -0500 Subject: [PATCH 093/121] Index Pattern Field class - factor out copy_field code for future typescripting (#63083) * Index Pattern Field class - factor out copy_field code for future typescripting --- ...n-plugins-data-public.indexpatternfield.md | 1 - ...ns-data-public.indexpatternfield.routes.md | 11 --- ...ugins-data-public.indexpatternfieldlist.md | 2 +- ...ata-public.indexpatternfieldlist.update.md | 2 +- .../create_edit_field/create_edit_field.js | 1 - .../edit_index_pattern/edit_index_pattern.js | 10 ++- .../indexed_fields_table.test.js.snap | 5 -- .../indexed_fields_table.js | 3 +- .../scripted_fields_table.tsx | 2 +- .../ui/public/field_editor/field_editor.js | 13 +-- .../lib/__tests__/copy_field.test.js | 48 ----------- .../ui/public/field_editor/lib/copy_field.js | 82 ------------------- .../ui/public/field_editor/lib/index.js | 1 - .../public/index_patterns/fields/field.ts | 7 -- .../index_patterns/fields/field_list.ts | 13 +-- src/plugins/data/public/public.api.md | 4 +- 16 files changed, 22 insertions(+), 183 deletions(-) delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md delete mode 100644 src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.js delete mode 100644 src/legacy/ui/public/field_editor/lib/copy_field.js diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md index 430590c7a2505..121ae80734dfd 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.md @@ -29,7 +29,6 @@ export declare class Field implements IFieldType | [format](./kibana-plugin-plugins-data-public.indexpatternfield.format.md) | | <code>any</code> | | | [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | <code>string</code> | | | [name](./kibana-plugin-plugins-data-public.indexpatternfield.name.md) | | <code>string</code> | | -| [routes](./kibana-plugin-plugins-data-public.indexpatternfield.routes.md) | | <code>Record<string, string></code> | | | [script](./kibana-plugin-plugins-data-public.indexpatternfield.script.md) | | <code>string</code> | | | [scripted](./kibana-plugin-plugins-data-public.indexpatternfield.scripted.md) | | <code>boolean</code> | | | [searchable](./kibana-plugin-plugins-data-public.indexpatternfield.searchable.md) | | <code>boolean</code> | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md deleted file mode 100644 index 664a7b7b7ca0e..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfield.routes.md +++ /dev/null @@ -1,11 +0,0 @@ -<!-- Do not edit this file. It is automatically generated by API Documenter. --> - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) > [routes](./kibana-plugin-plugins-data-public.indexpatternfield.routes.md) - -## IndexPatternField.routes property - -<b>Signature:</b> - -```typescript -routes: Record<string, string>; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md index 4b7184b7dc151..478b73f5f8581 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.md @@ -24,5 +24,5 @@ export declare class FieldList extends Array<Field> implements IFieldList | [getByName](./kibana-plugin-plugins-data-public.indexpatternfieldlist.getbyname.md) | | <code>(name: string) => Field | undefined</code> | | | [getByType](./kibana-plugin-plugins-data-public.indexpatternfieldlist.getbytype.md) | | <code>(type: string) => any[]</code> | | | [remove](./kibana-plugin-plugins-data-public.indexpatternfieldlist.remove.md) | | <code>(field: IFieldType) => void</code> | | -| [update](./kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md) | | <code>(field: Field) => void</code> | | +| [update](./kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md) | | <code>(field: Record<string, any>) => void</code> | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md index ca03ec4b72893..d5156ed41e493 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpatternfieldlist.update.md @@ -7,5 +7,5 @@ <b>Signature:</b> ```typescript -update: (field: Field) => void; +update: (field: Record<string, any>) => void; ``` diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js index 0dcf778a5a662..3569e9caf4e27 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js @@ -53,7 +53,6 @@ const renderFieldEditor = ( indexPattern={indexPattern} field={field} helpers={{ - Field: IndexPatternField, getConfig, $http, fieldFormatEditors, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js index 594430ca01f4c..c65054f583ef2 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js @@ -49,6 +49,8 @@ const TAB_INDEXED_FIELDS = 'indexedFields'; const TAB_SCRIPTED_FIELDS = 'scriptedFields'; const TAB_SOURCE_FILTERS = 'sourceFilters'; +const EDIT_FIELD_PATH = '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}'; + function updateSourceFiltersTable($scope) { $scope.$$postDigest(() => { const node = document.getElementById(REACT_SOURCE_FILTERS_DOM_ELEMENT_ID); @@ -97,8 +99,8 @@ function updateScriptedFieldsTable($scope) { fieldFilter={$scope.fieldFilter} scriptedFieldLanguageFilter={$scope.scriptedFieldLanguageFilter} helpers={{ - redirectToRoute: (obj, route) => { - $scope.kbnUrl.changeToRoute(obj, route); + redirectToRoute: field => { + $scope.kbnUrl.changePath(EDIT_FIELD_PATH, field); $scope.$apply(); }, getRouteHref: (obj, route) => $scope.kbnUrl.getRouteHref(obj, route), @@ -140,8 +142,8 @@ function updateIndexedFieldsTable($scope) { fieldWildcardMatcher={$scope.fieldWildcardMatcher} indexedFieldTypeFilter={$scope.indexedFieldTypeFilter} helpers={{ - redirectToRoute: (obj, route) => { - $scope.kbnUrl.changeToRoute(obj, route); + redirectToRoute: field => { + $scope.kbnUrl.changePath(EDIT_FIELD_PATH, field); $scope.$apply(); }, getFieldInfo: $scope.getFieldInfo, diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap index dc77fe6c8a69d..b38036a0c2bf0 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/__jest__/__snapshots__/indexed_fields_table.test.js.snap @@ -18,7 +18,6 @@ exports[`IndexedFieldsTable should filter based on the query bar 1`] = ` "indexPattern": undefined, "info": undefined, "name": "Elastic", - "routes": undefined, "searchable": true, }, ] @@ -45,7 +44,6 @@ exports[`IndexedFieldsTable should filter based on the type filter 1`] = ` "indexPattern": undefined, "info": undefined, "name": "timestamp", - "routes": undefined, "type": "date", }, ] @@ -72,7 +70,6 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "indexPattern": undefined, "info": undefined, "name": "Elastic", - "routes": undefined, "searchable": true, }, Object { @@ -82,7 +79,6 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "indexPattern": undefined, "info": undefined, "name": "timestamp", - "routes": undefined, "type": "date", }, Object { @@ -92,7 +88,6 @@ exports[`IndexedFieldsTable should render normally 1`] = ` "indexPattern": undefined, "info": undefined, "name": "conflictingField", - "routes": undefined, "type": "conflict", }, ] diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js index 652efbe98067f..074e5784f3dae 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/indexed_fields_table/indexed_fields_table.js @@ -65,7 +65,6 @@ export class IndexedFieldsTable extends Component { return { ...field, displayName: field.displayName, - routes: field.routes, indexPattern: field.indexPattern, format: getFieldFormat(indexPattern, field.name), excluded: fieldWildcardMatch ? fieldWildcardMatch(field.name) : false, @@ -104,7 +103,7 @@ export class IndexedFieldsTable extends Component { <Table indexPattern={indexPattern} items={fields} - editField={field => this.props.helpers.redirectToRoute(field, 'edit')} + editField={field => this.props.helpers.redirectToRoute(field)} /> </div> ); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx index ba044296a693a..e8dfbd6496057 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx @@ -155,7 +155,7 @@ export class ScriptedFieldsTable extends Component< <Table indexPattern={indexPattern} items={items} - editField={field => this.props.helpers.redirectToRoute(field, 'edit')} + editField={field => this.props.helpers.redirectToRoute(field)} deleteField={this.startDeleteField} /> diff --git a/src/legacy/ui/public/field_editor/field_editor.js b/src/legacy/ui/public/field_editor/field_editor.js index 43461c4c689be..e90cb110ac304 100644 --- a/src/legacy/ui/public/field_editor/field_editor.js +++ b/src/legacy/ui/public/field_editor/field_editor.js @@ -66,7 +66,7 @@ import { ScriptingHelpFlyout } from './components/scripting_help'; import { FieldFormatEditor } from './components/field_format_editor'; import { FIELD_TYPES_BY_LANG, DEFAULT_FIELD_TYPES } from './constants'; -import { copyField, executeScript, isScriptValid } from './lib'; +import { executeScript, isScriptValid } from './lib'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -100,7 +100,6 @@ export class FieldEditor extends PureComponent { indexPattern: PropTypes.object.isRequired, field: PropTypes.object.isRequired, helpers: PropTypes.shape({ - Field: PropTypes.func.isRequired, getConfig: PropTypes.func.isRequired, $http: PropTypes.func.isRequired, fieldFormatEditors: PropTypes.object.isRequired, @@ -111,11 +110,7 @@ export class FieldEditor extends PureComponent { constructor(props) { super(props); - const { - field, - indexPattern, - helpers: { Field }, - } = props; + const { field, indexPattern } = props; this.state = { isReady: false, @@ -125,7 +120,7 @@ export class FieldEditor extends PureComponent { fieldTypes: [], fieldTypeFormats: [], existingFieldNames: indexPattern.fields.map(f => f.name), - field: copyField(field, indexPattern, Field), + field: { ...field, format: field.format }, fieldFormatId: undefined, fieldFormatParams: {}, showScriptingHelp: false, @@ -730,7 +725,7 @@ export class FieldEditor extends PureComponent { }; saveField = async () => { - const field = this.state.field.toActualField(); + const field = this.state.field; const { indexPattern } = this.props; const { fieldFormatId } = this.state; diff --git a/src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.js b/src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.js deleted file mode 100644 index 2cee45742ab81..0000000000000 --- a/src/legacy/ui/public/field_editor/lib/__tests__/copy_field.test.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 { copyField } from '../copy_field'; - -const field = { - name: 'test_field', - scripted: true, - type: 'number', - lang: 'painless', -}; - -describe('copyField', () => { - it('should copy a field', () => { - const copiedField = copyField(field, {}, {}); - copiedField.name = 'test_name_change'; - - // Check that copied field has `toActualField()` method - expect(typeof copiedField.toActualField).toEqual('function'); - - // Check that we did not modify the original field object when - // modifying copied field - expect(field.toActualField).toEqual(undefined); - expect(field.name).toEqual('test_field'); - - expect(copiedField).not.toEqual(field); - expect(copiedField.name).toEqual('test_name_change'); - expect(copiedField.scripted).toEqual(field.scripted); - expect(copiedField.type).toEqual(field.type); - expect(copiedField.lang).toEqual(field.lang); - }); -}); diff --git a/src/legacy/ui/public/field_editor/lib/copy_field.js b/src/legacy/ui/public/field_editor/lib/copy_field.js deleted file mode 100644 index bfc1cb8480d5d..0000000000000 --- a/src/legacy/ui/public/field_editor/lib/copy_field.js +++ /dev/null @@ -1,82 +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 { has } from 'lodash'; - -/** - * Fully clones a Field object, so that modifications can be performed on - * the copy without affecting original field. Field objects contain - * enumerable and non-eumerable properties that may or may not be writable. - * The function copies all properties as property descriptors into - * `newFieldProps`, overrides getter and setter, and returns a new object - * created from that. - * - * @param {object} field - Field object to copy - * @param {object} indexPattern - index pattern object the field belongs to - * @param {object} Field - Field object type - * @return {object} the cloned object - */ -export const copyField = (field, indexPattern, Field) => { - const changes = {}; - const newFieldProps = { - // When we are ready to save the copied field back into the index pattern, - // we use `toActualField()` to retrieve an actual `Field` type object, using - // its original properties with our "changes" applied. - toActualField: { - value: () => { - return new Field(indexPattern, { - ...field.$$spec, - ...changes, - }); - }, - }, - }; - - // Index pattern `Field` objects are created with custom property - // descriptors using `ObjDefine`. - // - // Each property of a `Field` type object could be enumerable/non-enumerable, - // writable/not writable, configurable/not configurable, and have custom - // getter and setter. We can't use the original `field` object directly for - // creating a new field or editing a new field, since we need all the - // properties to be editable. - // - // A normal copy of `field` (i.e. `const newField = { ...field }`) will only - // copy enumerable properties and copy each property's descriptors (not - // writable, etc). - // - // So we copy `field`'s **property descriptors** into `newFieldProps` - // and modify them so that they are "writable" with a getter/setter that - // stores and retrieves changes into/from another object (`changes`). - Object.getOwnPropertyNames(field).forEach(function(prop) { - const desc = Object.getOwnPropertyDescriptor(field, prop); - - newFieldProps[prop] = { - enumerable: desc.enumerable, - get: function() { - return has(changes, prop) ? changes[prop] : field[prop]; - }, - set: function(v) { - changes[prop] = v; - }, - }; - }); - - return Object.create(null, newFieldProps); -}; diff --git a/src/legacy/ui/public/field_editor/lib/index.js b/src/legacy/ui/public/field_editor/lib/index.js index c74bb0cc2ef8a..c9dd9d03b74f7 100644 --- a/src/legacy/ui/public/field_editor/lib/index.js +++ b/src/legacy/ui/public/field_editor/lib/index.js @@ -17,5 +17,4 @@ * under the License. */ -export { copyField } from './copy_field'; export { executeScript, isScriptValid } from './validate_script'; diff --git a/src/plugins/data/public/index_patterns/fields/field.ts b/src/plugins/data/public/index_patterns/fields/field.ts index 1554565d1403e..6370dcdf2db6f 100644 --- a/src/plugins/data/public/index_patterns/fields/field.ts +++ b/src/plugins/data/public/index_patterns/fields/field.ts @@ -45,9 +45,6 @@ export class Field implements IFieldType { subType?: IFieldSubType; displayName?: string; format: any; - routes: Record<string, string> = { - edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}', - }; $$spec: FieldSpec; constructor( @@ -146,7 +143,3 @@ export class Field implements IFieldType { return obj.create(); } } - -Field.prototype.routes = { - edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}', -}; diff --git a/src/plugins/data/public/index_patterns/fields/field_list.ts b/src/plugins/data/public/index_patterns/fields/field_list.ts index 03214a8c96427..d6067280fd7b6 100644 --- a/src/plugins/data/public/index_patterns/fields/field_list.ts +++ b/src/plugins/data/public/index_patterns/fields/field_list.ts @@ -70,11 +70,12 @@ export class FieldList extends Array<Field> implements IFieldList { this.splice(fieldIndex, 1); }; - update = (field: Field) => { - const index = this.findIndex(f => f.name === field.name); - this.splice(index, 1, field); - this.setByName(field); - this.removeByGroup(field); - this.setByGroup(field); + update = (field: FieldSpec) => { + const newField = new Field(this.indexPattern, field, this.shortDotsEnable); + const index = this.findIndex(f => f.name === newField.name); + this.splice(index, 1, newField); + this.setByName(newField); + this.removeByGroup(newField); + this.setByGroup(newField); }; } diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index cef82b27b1b5b..62967a7071d82 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -947,8 +947,6 @@ export class IndexPatternField implements IFieldType { // (undocumented) name: string; // (undocumented) - routes: Record<string, string>; - // (undocumented) script?: string; // (undocumented) scripted?: boolean; @@ -978,7 +976,7 @@ export class IndexPatternFieldList extends Array<IndexPatternField> implements I // (undocumented) remove: (field: IFieldType) => void; // (undocumented) - update: (field: IndexPatternField) => void; + update: (field: Record<string, any>) => void; } // Warning: (ae-missing-release-tag) "indexPatterns" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) From e6095fcd03120b62c6d65dcdd23ea7a0ba6d3aab Mon Sep 17 00:00:00 2001 From: Justin Kambic <justin.kambic@elastic.co> Date: Tue, 14 Apr 2020 08:35:31 -0400 Subject: [PATCH 094/121] [Uptime] Remove pings graphql (#59392) * WIP replacing GQL with redux/rest. * Finish implementing migration. * Introduce new connected component for ping list. * Replace GraphQL type with io-ts. * Update some broken tests. * Add test for new helper function. * Write test snapshots. * Migrate api tests from graphql to rest. * Update fixtures that rely on pings. * Move ping types to runtime_types folder with rest of io-ts files. * Update Ping type location and imports, type checking. * Remove reliance on fixtures for ping functional API tests. * Fix broken unit tests. * Fix broken types. * Remove local state storage from parent components. * Add functional test to cover Ping List functionality. * Fix monitor page functional test that was broken by merge conflicts. * Fix broken tests. * Fix broken API test. * Replace a test with a describe block that will pre-navigate all tests. * Delete unused reducer keys. * Re-introduce loading to ping list reducer. * Inroduce code that will cause PingList to re-fetch when refresh button is pressed. * Update expanded rows to support multiple concurrent expanded rows. * Modify pingList reducer to have singular optional error field. * Delete unnecessary helper code. * Delete unused interface. * Add runtime_type to parse getPings params, fix pagination index. * Add dedicated monitor type to runtime_types. * Fix broken tests. * Fix broken tests. * Rename '@timestamp' property to 'timestamp' on Ping type. * Fix broken type and key pings list table on document ID instead of timestamp. * Fix broken unit tests. * Fix broken tests and types. * Fix broken functional test. --- .../plugins/uptime/common/graphql/types.ts | 340 ---- .../uptime/common/runtime_types/common.ts | 6 + .../uptime/common/runtime_types/index.ts | 1 + .../ping/histogram.ts | 12 + .../runtime_types/ping}/index.ts | 3 +- .../uptime/common/runtime_types/ping/ping.ts | 181 ++ .../plugins/uptime/common/types/index.ts | 2 - .../connected/charts/ping_histogram.tsx | 2 +- .../public/components/connected/index.ts | 1 + .../monitor/status_bar_container.tsx | 2 +- .../components/connected/pings/index.ts | 7 + .../components/connected/pings/ping_list.tsx | 52 + .../functional/charts/ping_histogram.tsx | 2 +- .../public/components/functional/index.ts | 2 +- .../__test__/monitor_ssl_certificate.test.tsx | 4 +- .../__test__/monitor_status.bar.test.tsx | 6 +- .../monitor_ssl_certificate.tsx | 5 +- .../monitor_status_bar/monitor_status_bar.tsx | 2 +- .../__snapshots__/ping_list.test.tsx.snap | 665 ++++--- .../ping_list/__tests__/expanded_row.test.tsx | 14 +- .../ping_list/__tests__/ping_list.test.tsx | 418 +++-- .../functional/ping_list/expanded_row.tsx | 4 +- .../components/functional/ping_list/index.tsx | 2 +- .../functional/ping_list/ping_list.tsx | 343 ++-- .../plugins/uptime/public/hooks/index.ts | 1 + .../plugins/uptime/public/pages/monitor.tsx | 46 +- .../uptime/public/queries/pings_query.ts | 73 - .../public/state/actions/monitor_status.ts | 2 +- .../uptime/public/state/actions/ping.ts | 11 +- .../uptime/public/state/api/monitor_status.ts | 4 +- .../plugins/uptime/public/state/api/ping.ts | 19 +- .../public/state/effects/fetch_effect.ts | 2 +- .../uptime/public/state/effects/index.ts | 3 +- .../uptime/public/state/effects/ping.ts | 15 +- .../uptime/public/state/reducers/index.ts | 2 + .../public/state/reducers/monitor_status.ts | 2 +- .../uptime/public/state/reducers/ping.ts | 2 +- .../uptime/public/state/reducers/ping_list.ts | 48 + .../state/selectors/__tests__/index.test.ts | 8 + .../uptime/public/state/selectors/index.ts | 5 + x-pack/plugins/uptime/server/graphql/index.ts | 3 +- .../graphql/monitor_states/schema.gql.ts | 2 +- .../uptime/server/graphql/pings/index.ts | 1 - .../uptime/server/graphql/pings/resolvers.ts | 59 - .../uptime/server/graphql/pings/schema.gql.ts | 26 - .../__tests__/get_latest_monitor.test.ts | 25 +- .../lib/requests/__tests__/get_pings.test.ts | 273 ++- .../server/lib/requests/get_latest_monitor.ts | 12 +- .../server/lib/requests/get_ping_histogram.ts | 6 +- .../uptime/server/lib/requests/get_pings.ts | 65 +- .../uptime/server/lib/requests/index.ts | 2 +- .../uptime/server/lib/requests/types.ts | 72 - .../server/lib/requests/uptime_requests.ts | 13 +- .../plugins/uptime/server/rest_api/index.ts | 4 +- .../uptime/server/rest_api/pings/get_all.ts | 47 - .../uptime/server/rest_api/pings/get_pings.ts | 24 +- .../uptime/server/rest_api/pings/index.ts | 1 + .../apis/uptime/feature_controls.ts | 2 +- .../apis/uptime/get_all_pings.ts | 18 +- .../uptime/graphql/fixtures/ping_list.json | 320 ---- .../graphql/fixtures/ping_list_count.json | 1569 ----------------- .../fixtures/ping_list_monitor_id.json | 475 ----- .../graphql/fixtures/ping_list_sort.json | 165 -- .../apis/uptime/graphql/index.ts | 1 - .../apis/uptime/graphql/ping_list.ts | 116 -- .../test/api_integration/apis/uptime/index.ts | 11 +- .../rest/fixtures/monitor_latest_status.json | 15 +- .../api_integration/apis/uptime/rest/index.ts | 5 +- .../apis/uptime/rest/ping_list.ts | 178 ++ x-pack/test/functional/apps/uptime/monitor.ts | 29 +- .../functional/page_objects/uptime_page.ts | 16 +- .../functional/services/uptime/monitor.ts | 17 + 72 files changed, 1695 insertions(+), 4196 deletions(-) rename x-pack/legacy/plugins/uptime/common/{types => runtime_types}/ping/histogram.ts (77%) rename x-pack/legacy/plugins/uptime/{public/queries => common/runtime_types/ping}/index.ts (79%) create mode 100644 x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts create mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/queries/pings_query.ts create mode 100644 x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts delete mode 100644 x-pack/plugins/uptime/server/graphql/pings/resolvers.ts delete mode 100644 x-pack/plugins/uptime/server/lib/requests/types.ts delete mode 100644 x-pack/plugins/uptime/server/rest_api/pings/get_all.ts delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json delete mode 100644 x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts create mode 100644 x-pack/test/api_integration/apis/uptime/rest/ping_list.ts diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts index c8beb91d807d5..506966ec6b5c9 100644 --- a/x-pack/legacy/plugins/uptime/common/graphql/types.ts +++ b/x-pack/legacy/plugins/uptime/common/graphql/types.ts @@ -15,294 +15,15 @@ export type UnsignedInteger = any; // ==================================================== export interface Query { - /** Get a list of all recorded pings for all monitors */ - allPings: PingResults; - /** Fetches the current state of Uptime monitors for the given parameters. */ getMonitorStates?: MonitorSummaryResult | null; } -export interface PingResults { - /** Total number of matching pings */ - total: UnsignedInteger; - /** Unique list of all locations the query matched */ - locations: string[]; - /** List of pings */ - pings: Ping[]; -} -/** A request sent from a monitor to a host */ -export interface Ping { - /** unique ID for this ping */ - id: string; - /** The timestamp of the ping's creation */ - timestamp: string; - /** The agent that recorded the ping */ - beat?: Beat | null; - - container?: Container | null; - - docker?: Docker | null; - - ecs?: Ecs | null; - - error?: Error | null; - - host?: Host | null; - - http?: Http | null; - - icmp?: Icmp | null; - - kubernetes?: Kubernetes | null; - - meta?: Meta | null; - - monitor?: Monitor | null; - - observer?: Observer | null; - - resolve?: Resolve | null; - - socks5?: Socks5 | null; - - summary?: Summary | null; - - tags?: string | null; - - tcp?: Tcp | null; - - tls?: PingTls | null; - - url?: Url | null; -} -/** An agent for recording a beat */ -export interface Beat { - hostname?: string | null; - - name?: string | null; - - timezone?: string | null; - - type?: string | null; -} - -export interface Container { - id?: string | null; - - image?: ContainerImage | null; - - name?: string | null; - - runtime?: string | null; -} - -export interface ContainerImage { - name?: string | null; - - tag?: string | null; -} - -export interface Docker { - id?: string | null; - - image?: string | null; - - name?: string | null; -} - -export interface Ecs { - version?: string | null; -} - -export interface Error { - code?: number | null; - - message?: string | null; - - type?: string | null; -} - -export interface Host { - architecture?: string | null; - - id?: string | null; - - hostname?: string | null; - - ip?: string | null; - - mac?: string | null; - - name?: string | null; - - os?: Os | null; -} - -export interface Os { - family?: string | null; - - kernel?: string | null; - - platform?: string | null; - - version?: string | null; - - name?: string | null; - - build?: string | null; -} - -export interface Http { - response?: HttpResponse | null; - - rtt?: HttpRtt | null; - - url?: string | null; -} - -export interface HttpResponse { - status_code?: UnsignedInteger | null; - - body?: HttpBody | null; -} - -export interface HttpBody { - /** Size of HTTP response body in bytes */ - bytes?: UnsignedInteger | null; - /** Hash of the HTTP response body */ - hash?: string | null; - /** Response body of the HTTP Response. May be truncated based on client settings. */ - content?: string | null; - /** Byte length of the content string, taking into account multibyte chars. */ - content_bytes?: UnsignedInteger | null; -} - -export interface HttpRtt { - content?: Duration | null; - - response_header?: Duration | null; - - total?: Duration | null; - - validate?: Duration | null; - - validate_body?: Duration | null; - - write_request?: Duration | null; -} /** The monitor's status for a ping */ export interface Duration { us?: UnsignedInteger | null; } -export interface Icmp { - requests?: number | null; - - rtt?: number | null; -} - -export interface Kubernetes { - container?: KubernetesContainer | null; - - namespace?: string | null; - - node?: KubernetesNode | null; - - pod?: KubernetesPod | null; -} - -export interface KubernetesContainer { - image?: string | null; - - name?: string | null; -} - -export interface KubernetesNode { - name?: string | null; -} - -export interface KubernetesPod { - name?: string | null; - - uid?: string | null; -} - -export interface Meta { - cloud?: MetaCloud | null; -} - -export interface MetaCloud { - availability_zone?: string | null; - - instance_id?: string | null; - - instance_name?: string | null; - - machine_type?: string | null; - - project_id?: string | null; - - provider?: string | null; - - region?: string | null; -} - -export interface Monitor { - duration?: Duration | null; - - host?: string | null; - /** The id of the monitor */ - id?: string | null; - /** The IP pinged by the monitor */ - ip?: string | null; - /** The name of the protocol being monitored */ - name?: string | null; - /** The protocol scheme of the monitored host */ - scheme?: string | null; - /** The status of the monitored host */ - status?: string | null; - /** The type of host being monitored */ - type?: string | null; - - check_group?: string | null; -} -/** Metadata added by a proccessor, which is specified in its configuration. */ -export interface Observer { - /** Geolocation data for the agent. */ - geo?: Geo | null; -} -/** Geolocation data added via processors to enrich events. */ -export interface Geo { - /** Name of the city in which the agent is running. */ - city_name?: string | null; - /** The name of the continent on which the agent is running. */ - continent_name?: string | null; - /** ISO designation for the agent's country. */ - country_iso_code?: string | null; - /** The name of the agent's country. */ - country_name?: string | null; - /** The lat/long of the agent. */ - location?: string | null; - /** A name for the host's location, e.g. 'us-east-1' or 'LAX'. */ - name?: string | null; - /** ISO designation of the agent's region. */ - region_iso_code?: string | null; - /** Name of the region hosting the agent. */ - region_name?: string | null; -} - -export interface Resolve { - host?: string | null; - - ip?: string | null; - - rtt?: Duration | null; -} - -export interface Socks5 { - rtt?: Rtt | null; -} - export interface Rtt { connect?: Duration | null; @@ -331,53 +52,10 @@ export interface Location { lon?: number | null; } -export interface Tcp { - port?: number | null; - - rtt?: Rtt | null; -} -/** Contains monitor transmission encryption information. */ -export interface PingTls { - /** The date and time after which the certificate is invalid. */ - certificate_not_valid_after?: string | null; - - certificate_not_valid_before?: string | null; - - certificates?: string | null; - - rtt?: Rtt | null; -} - -export interface Url { - full?: string | null; - - scheme?: string | null; - - domain?: string | null; - - port?: number | null; - - path?: string | null; - - query?: string | null; -} - export interface DocCount { count: UnsignedInteger; } -export interface Snapshot { - counts: SnapshotCount; -} - -export interface SnapshotCount { - up: number; - - down: number; - - total: number; -} - /** The primary object returned for monitor states. */ export interface MonitorSummaryResult { /** Used to go to the next page of results */ @@ -521,24 +199,6 @@ export interface SummaryHistogramPoint { down: number; } -export interface AllPingsQueryArgs { - /** Optional: the direction to sort by. Accepts 'asc' and 'desc'. Defaults to 'desc'. */ - sort?: string | null; - /** Optional: the number of results to return. */ - size?: number | null; - /** Optional: the monitor ID filter. */ - monitorId?: string | null; - /** Optional: the check status to filter by. */ - status?: string | null; - /** The lower limit of the date range. */ - dateRangeStart: string; - /** The upper limit of the date range. */ - dateRangeEnd: string; - /** Optional: agent location to filter by. */ - location?: string | null; - page?: number; -} - export interface GetMonitorStatesQueryArgs { dateRangeStart: string; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts index 37101b5b46fd2..9018f4acaa320 100644 --- a/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts @@ -27,7 +27,13 @@ export const StatesIndexStatusType = t.type({ docCount: t.number, }); +export const DateRangeType = t.type({ + from: t.string, + to: t.string, +}); + export type Summary = t.TypeOf<typeof SummaryType>; export type CheckGeo = t.TypeOf<typeof CheckGeoType>; export type Location = t.TypeOf<typeof LocationType>; export type StatesIndexStatus = t.TypeOf<typeof StatesIndexStatusType>; +export type DateRange = t.TypeOf<typeof DateRangeType>; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts index 5e3fb2326bdb9..652d60cbe304d 100644 --- a/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/index.ts @@ -8,5 +8,6 @@ export * from './alerts'; export * from './common'; export * from './monitor'; export * from './overview_filters'; +export * from './ping'; export * from './snapshot'; export * from './dynamic_settings'; diff --git a/x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/histogram.ts similarity index 77% rename from x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts rename to x-pack/legacy/plugins/uptime/common/runtime_types/ping/histogram.ts index 3ae32e15ca55c..2c3b52051be0f 100644 --- a/x-pack/legacy/plugins/uptime/common/types/ping/histogram.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/histogram.ts @@ -28,3 +28,15 @@ export interface HistogramResult { histogram: HistogramDataPoint[]; interval: string; } + +export interface HistogramQueryResult { + key: number; + key_as_string: string; + doc_count: number; + down: { + doc_count: number; + }; + up: { + doc_count: number; + }; +} diff --git a/x-pack/legacy/plugins/uptime/public/queries/index.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/index.ts similarity index 79% rename from x-pack/legacy/plugins/uptime/public/queries/index.ts rename to x-pack/legacy/plugins/uptime/common/runtime_types/ping/index.ts index 283382ec1b7ba..a2fc7c1b243ba 100644 --- a/x-pack/legacy/plugins/uptime/public/queries/index.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/index.ts @@ -4,4 +4,5 @@ * you may not use this file except in compliance with the Elastic License. */ -export { pingsQuery, pingsQueryString } from './pings_query'; +export * from './histogram'; +export * from './ping'; diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts new file mode 100644 index 0000000000000..ee14b298f3810 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/ping/ping.ts @@ -0,0 +1,181 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import * as t from 'io-ts'; +import { DateRangeType } from '../common'; + +export const HttpResponseBodyType = t.partial({ + bytes: t.number, + content: t.string, + content_bytes: t.number, + hash: t.string, +}); + +export type HttpResponseBody = t.TypeOf<typeof HttpResponseBodyType>; + +export const TlsType = t.partial({ + certificate_not_valid_after: t.string, + certificate_not_valid_before: t.string, +}); + +export type Tls = t.TypeOf<typeof TlsType>; + +export const MonitorType = t.intersection([ + t.type({ + duration: t.type({ + us: t.number, + }), + id: t.string, + status: t.string, + type: t.string, + }), + t.partial({ + check_group: t.string, + ip: t.string, + name: t.string, + timespan: t.partial({ + gte: t.string, + lte: t.string, + }), + }), +]); + +export type Monitor = t.TypeOf<typeof MonitorType>; + +export const PingType = t.intersection([ + t.type({ + timestamp: t.string, + monitor: MonitorType, + docId: t.string, + }), + t.partial({ + agent: t.intersection([ + t.type({ + ephemeral_id: t.string, + hostname: t.string, + id: t.string, + type: t.string, + version: t.string, + }), + t.partial({ + name: t.string, + }), + ]), + container: t.partial({ + id: t.string, + image: t.partial({ + name: t.string, + tag: t.string, + }), + name: t.string, + runtime: t.string, + }), + ecs: t.partial({ + version: t.string, + }), + error: t.intersection([ + t.partial({ + code: t.string, + id: t.string, + stack_trace: t.string, + type: t.string, + }), + t.type({ + // this is _always_ on the error field + message: t.string, + }), + ]), + http: t.partial({ + request: t.partial({ + body: t.partial({ + bytes: t.number, + content: t.partial({ + text: t.string, + }), + }), + bytes: t.number, + method: t.string, + referrer: t.string, + }), + response: t.partial({ + body: HttpResponseBodyType, + bytes: t.number, + redirects: t.string, + status_code: t.number, + }), + version: t.string, + }), + icmp: t.partial({ + requests: t.number, + rtt: t.partial({ + us: t.number, + }), + }), + kubernetes: t.partial({ + pod: t.partial({ + name: t.string, + uid: t.string, + }), + }), + observer: t.partial({ + geo: t.partial({ + name: t.string, + }), + }), + resolve: t.partial({ + ip: t.string, + rtt: t.partial({ + us: t.number, + }), + }), + summary: t.partial({ + down: t.number, + up: t.number, + }), + tags: t.array(t.string), + tcp: t.partial({ + rtt: t.partial({ + connect: t.partial({ + us: t.number, + }), + }), + }), + tls: TlsType, + // should this be partial? + url: t.partial({ + domain: t.string, + full: t.string, + port: t.number, + scheme: t.string, + }), + }), +]); + +export type Ping = t.TypeOf<typeof PingType>; + +export const PingsResponseType = t.type({ + total: t.number, + locations: t.array(t.string), + pings: t.array(PingType), +}); + +export type PingsResponse = t.TypeOf<typeof PingsResponseType>; + +export const GetPingsParamsType = t.intersection([ + t.type({ + dateRange: DateRangeType, + }), + t.partial({ + index: t.number, + size: t.number, + location: t.string, + monitorId: t.string, + sort: t.string, + status: t.string, + }), +]); + +export type GetPingsParams = t.TypeOf<typeof GetPingsParamsType>; diff --git a/x-pack/legacy/plugins/uptime/common/types/index.ts b/x-pack/legacy/plugins/uptime/common/types/index.ts index 2c39f2a3b7314..1d0003addd761 100644 --- a/x-pack/legacy/plugins/uptime/common/types/index.ts +++ b/x-pack/legacy/plugins/uptime/common/types/index.ts @@ -41,5 +41,3 @@ export interface MonitorDurationResult { /** The maximum duration value in this chart. */ durationMaxValue: number; } - -export * from './ping/histogram'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx index 6428ddfd10f8c..cf35dbf4e5206 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx @@ -14,7 +14,7 @@ import { import { getPingHistogram } from '../../../state/actions'; import { selectPingHistogram } from '../../../state/selectors'; import { withResponsiveWrapper, ResponsiveWrapperProps } from '../../higher_order'; -import { GetPingHistogramParams, HistogramResult } from '../../../../common/types'; +import { GetPingHistogramParams, HistogramResult } from '../../../../common/runtime_types'; import { useGetUrlParams } from '../../../hooks'; type Props = ResponsiveWrapperProps & diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts index 7e442cbe850ba..be3cc5b65aa0e 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts @@ -13,5 +13,6 @@ export { MonitorStatusDetails } from './monitor/status_details_container'; export { MonitorStatusBar } from './monitor/status_bar_container'; export { MonitorListDrawer } from './monitor/list_drawer_container'; export { MonitorListActionsPopover } from './monitor/drawer_popover_container'; +export { PingList, PingListProps } from './pings'; export { DurationChart } from './charts/monitor_duration'; export { EmptyState } from './empty_state/empty_state'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx index 00cfd02d8dc32..3a96aa7c0275b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx @@ -12,7 +12,7 @@ import { monitorLocationsSelector, monitorStatusSelector } from '../../../state/ import { MonitorStatusBarComponent } from '../../functional/monitor_status_details/monitor_status_bar'; import { getMonitorStatusAction } from '../../../state/actions'; import { useGetUrlParams } from '../../../hooks'; -import { Ping } from '../../../../common/graphql/types'; +import { Ping } from '../../../../common/runtime_types'; import { MonitorLocations } from '../../../../common/runtime_types/monitor'; import { UptimeRefreshContext } from '../../../contexts'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts b/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts new file mode 100644 index 0000000000000..95ced104e5188 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/connected/pings/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 { PingList, PingListProps } from './ping_list'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx new file mode 100644 index 0000000000000..5b32a623495f1 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx @@ -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 { useSelector, useDispatch } from 'react-redux'; +import React, { useContext, useCallback } from 'react'; +import { selectPingList } from '../../../state/selectors'; +import { getPings } from '../../../state/actions'; +import { GetPingsParams } from '../../../../common/runtime_types'; +import { UptimeSettingsContext } from '../../../contexts'; +import { PingListComponent } from '../../functional'; + +export interface PingListProps { + monitorId: string; +} + +export const PingList = (props: PingListProps) => { + const { + lastRefresh, + pings: { + error, + loading, + pingList: { locations, pings, total }, + }, + } = useSelector(selectPingList); + + const { dateRangeStart: drs, dateRangeEnd: dre } = useContext(UptimeSettingsContext); + + const dispatch = useDispatch(); + const getPingsCallback = useCallback((params: GetPingsParams) => dispatch(getPings(params)), [ + dispatch, + ]); + + return ( + <PingListComponent + dateRange={{ + from: drs, + to: dre, + }} + error={error} + getPings={getPingsCallback} + lastRefresh={lastRefresh} + loading={loading} + locations={locations} + pings={pings} + total={total} + {...props} + /> + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx index f988afc7fc84d..66e86d6731236 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx @@ -13,7 +13,7 @@ import moment from 'moment'; import { getChartDateLabel } from '../../../lib/helper'; import { ChartWrapper } from './chart_wrapper'; import { UptimeThemeContext } from '../../../contexts'; -import { HistogramResult } from '../../../../common/types'; +import { HistogramResult } from '../../../../common/runtime_types'; import { useUrlParams } from '../../../hooks'; import { ChartEmptyState } from './chart_empty_state'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts index 8d0352e01d40e..d82912a6216e8 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts @@ -15,6 +15,6 @@ export { KueryBarComponent } from './kuery_bar/kuery_bar'; export { MonitorCharts } from './monitor_charts'; export { MonitorList } from './monitor_list'; export { OverviewPageParsingErrorCallout } from './overview_page_parsing_error_callout'; -export { PingList } from './ping_list'; +export { PingListComponent } from './ping_list'; export { PingHistogramComponent } from './charts'; export { StatusPanel } from './status_panel'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx index 2eae14301fd4d..57ed09cc30ef1 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx @@ -9,11 +9,11 @@ import moment from 'moment'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { EuiBadge } from '@elastic/eui'; import { renderWithIntl } from 'test_utils/enzyme_helpers'; -import { PingTls } from '../../../../../common/graphql/types'; +import { Tls } from '../../../../../common/runtime_types'; import { MonitorSSLCertificate } from '../monitor_status_bar'; describe('MonitorStatusBar component', () => { - let monitorTls: PingTls; + let monitorTls: Tls; beforeEach(() => { const dateInTwoMonths = moment() diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx index 0a53eeb89d793..5fd32c808da42 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/__test__/monitor_status.bar.test.tsx @@ -8,7 +8,7 @@ import moment from 'moment'; import React from 'react'; import { renderWithIntl } from 'test_utils/enzyme_helpers'; import { MonitorStatusBarComponent } from '../monitor_status_bar'; -import { Ping } from '../../../../../common/graphql/types'; +import { Ping } from '../../../../../common/runtime_types'; describe('MonitorStatusBar component', () => { let monitorStatus: Ping; @@ -16,7 +16,7 @@ describe('MonitorStatusBar component', () => { beforeEach(() => { monitorStatus = { - id: 'id1', + docId: 'few213kl', timestamp: moment(new Date()) .subtract(15, 'm') .toString(), @@ -24,7 +24,9 @@ describe('MonitorStatusBar component', () => { duration: { us: 1234567, }, + id: 'id1', status: 'up', + type: 'http', }, url: { full: 'https://www.example.com/', diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx index c57348c4ab4cd..d92534aecd175 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx @@ -9,14 +9,13 @@ import moment from 'moment'; import { EuiSpacer, EuiText, EuiBadge } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; - -import { PingTls } from '../../../../../common/graphql/types'; +import { Tls } from '../../../../../common/runtime_types'; interface Props { /** * TLS information coming from monitor in ES heartbeat index */ - tls: PingTls | null | undefined; + tls: Tls | null | undefined; } export const MonitorSSLCertificate = ({ tls }: Props) => { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx index 22e4377944be1..ac3cedc517995 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx @@ -17,7 +17,7 @@ import { import { MonitorSSLCertificate } from './monitor_ssl_certificate'; import * as labels from './translations'; import { StatusByLocations } from './status_by_location'; -import { Ping } from '../../../../../common/graphql/types'; +import { Ping } from '../../../../../common/runtime_types'; import { MonitorLocations } from '../../../../../common/runtime_types'; interface MonitorStatusBarProps { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap index 2e59ec5e57337..154ab6399452d 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap @@ -1,384 +1,349 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`PingList component renders sorted list without errors 1`] = ` -<Fragment> - <EuiPanel> - <EuiTitle - size="xs" +<EuiPanel> + <EuiTitle + size="xs" + > + <h4> + <FormattedMessage + defaultMessage="History" + id="xpack.uptime.pingList.checkHistoryTitle" + values={Object {}} + /> + </h4> + </EuiTitle> + <EuiSpacer + size="s" + /> + <EuiFlexGroup + justifyContent="spaceBetween" + > + <EuiFlexItem + grow={false} > - <h4> - <FormattedMessage - defaultMessage="History" - id="xpack.uptime.pingList.checkHistoryTitle" - values={Object {}} + <EuiFormRow + aria-label="Status" + describedByIds={Array []} + display="row" + fullWidth={false} + hasChildLabel={true} + hasEmptyLabelSpace={false} + label="Status" + labelType="label" + > + <EuiSelect + aria-label="Status" + data-test-subj="xpack.uptime.pingList.statusSelect" + onChange={[Function]} + options={ + Array [ + Object { + "data-test-subj": "xpack.uptime.pingList.statusOptions.all", + "text": "All", + "value": "", + }, + Object { + "data-test-subj": "xpack.uptime.pingList.statusOptions.up", + "text": "Up", + "value": "up", + }, + Object { + "data-test-subj": "xpack.uptime.pingList.statusOptions.down", + "text": "Down", + "value": "down", + }, + ] + } + value="" /> - </h4> - </EuiTitle> - <EuiSpacer - size="s" - /> - <EuiFlexGroup - justifyContent="spaceBetween" - > - <EuiFlexItem - grow={false} + </EuiFormRow> + </EuiFlexItem> + <EuiFlexItem> + <EuiFormRow + aria-label="Location" + describedByIds={Array []} + display="row" + fullWidth={false} + hasChildLabel={true} + hasEmptyLabelSpace={false} + label="Location" + labelType="label" > - <EuiFlexGroup> - <EuiFlexItem - style={ + <EuiSelect + aria-label="Location" + data-test-subj="xpack.uptime.pingList.locationSelect" + onChange={[Function]} + options={ + Array [ Object { - "minWidth": 200, - } - } - > - <EuiFlexGroup> - <EuiFlexItem> - <EuiFormRow - aria-label="Status" - describedByIds={Array []} - display="row" - fullWidth={false} - hasChildLabel={true} - hasEmptyLabelSpace={false} - label="Status" - labelType="label" - > - <EuiSelect - aria-label="Status" - onChange={[Function]} - options={ - Array [ - Object { - "text": "All", - "value": "", - }, - Object { - "text": "Up", - "value": "up", - }, - Object { - "text": "Down", - "value": "down", - }, - ] - } - value="down" - /> - </EuiFormRow> - </EuiFlexItem> - <EuiFlexItem> - <EuiFormRow - aria-label="Location" - describedByIds={Array []} - display="row" - fullWidth={false} - hasChildLabel={true} - hasEmptyLabelSpace={false} - label="Location" - labelType="label" - > - <EuiSelect - aria-label="Location" - onChange={[Function]} - options={ - Array [ - Object { - "text": "All", - "value": "", - }, - Object { - "text": "nyc", - "value": "nyc", - }, - ] - } - value="" - /> - </EuiFormRow> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - </EuiFlexGroup> - <EuiSpacer - size="s" - /> - <EuiBasicTable - columns={ - Array [ - Object { - "field": "monitor.status", - "name": "Status", - "render": [Function], - }, - Object { - "align": "left", - "field": "observer.geo.name", - "name": "Location", - "render": [Function], + "data-test-subj": "xpack.uptime.pingList.locationOptions.all", + "text": "All", + "value": "", + }, + ] + } + value="" + /> + </EuiFormRow> + </EuiFlexItem> + </EuiFlexGroup> + <EuiSpacer + size="s" + /> + <EuiBasicTable + columns={ + Array [ + Object { + "field": "monitor.status", + "name": "Status", + "render": [Function], + }, + Object { + "align": "left", + "field": "observer.geo.name", + "name": "Location", + "render": [Function], + }, + Object { + "align": "right", + "dataType": "number", + "field": "monitor.ip", + "name": "IP", + }, + Object { + "align": "right", + "field": "monitor.duration.us", + "name": "Duration", + "render": [Function], + }, + Object { + "align": "right", + "field": "error.type", + "name": "Error type", + "render": [Function], + }, + Object { + "align": "right", + "field": "http.response.status_code", + "name": <ForwardRef(styled.span)> + Response code + </ForwardRef(styled.span)>, + "render": [Function], + }, + Object { + "align": "right", + "isExpander": true, + "render": [Function], + "width": "24px", + }, + ] + } + hasActions={true} + isExpandable={true} + itemId="docId" + itemIdToExpandedRowMap={Object {}} + items={ + Array [ + Object { + "docId": "fewjio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "align": "right", - "dataType": "number", - "field": "monitor.ip", - "name": "IP", + "monitor": Object { + "duration": Object { + "us": 1430, + }, + "id": "auto-tcp-0X81440A68E839814F", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "align": "right", - "field": "monitor.duration.us", - "name": "Duration", - "render": [Function], + "timestamp": "2019-01-28T17:47:08.078Z", + }, + Object { + "docId": "fewjoo21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "align": "right", - "field": "error.type", - "name": "Error type", - "render": [Function], + "monitor": Object { + "duration": Object { + "us": 1370, + }, + "id": "auto-tcp-0X81440A68E839814D", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "align": "right", - "field": "http.response.status_code", - "name": <ForwardRef(styled.span)> - Response code - </ForwardRef(styled.span)>, - "render": [Function], + "timestamp": "2019-01-28T17:47:09.075Z", + }, + Object { + "docId": "fejjio21", + "monitor": Object { + "duration": Object { + "us": 1452, + }, + "id": "auto-tcp-0X81440A68E839814D", + "ip": "127.0.0.1", + "name": "", + "status": "up", + "type": "tcp", }, - Object { - "align": "right", - "isExpander": true, - "render": [Function], - "width": "24px", + "timestamp": "2019-01-28T17:47:06.077Z", + }, + Object { + "docId": "fewzio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - ] - } - hasActions={true} - isExpandable={true} - itemId="id" - itemIdToExpandedRowMap={Object {}} - items={ - Array [ - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", + "monitor": Object { + "duration": Object { + "us": 1094, }, - "http": null, - "id": "id1", - "monitor": Object { - "duration": Object { - "us": 1430, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:08.078Z", + "id": "auto-tcp-0X81440A68E839814E", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id2", - "monitor": Object { - "duration": Object { - "us": 1370, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:09.075Z", + "timestamp": "2019-01-28T17:47:07.075Z", + }, + Object { + "docId": "fewpi321", + "error": Object { + "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", + "type": "io", }, - Object { - "error": null, - "http": null, - "id": "id3", - "monitor": Object { - "duration": Object { - "us": 1452, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "tcp", + "monitor": Object { + "duration": Object { + "us": 1597, }, - "timestamp": "2019-01-28T17:47:06.077Z", + "id": "auto-http-0X3675F89EF061209G", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "http", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id4", - "monitor": Object { - "duration": Object { - "us": 1094, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:07.075Z", + "timestamp": "2019-01-28T17:47:07.074Z", + }, + Object { + "docId": "0ewjio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "error": Object { - "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", - "type": "io", + "monitor": Object { + "duration": Object { + "us": 1699, }, - "http": null, - "id": "id5", - "monitor": Object { - "duration": Object { - "us": 1597, - }, - "id": "auto-http-0X3675F89EF0612091", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http", - }, - "timestamp": "2019-01-28T17:47:07.074Z", + "id": "auto-tcp-0X81440A68E839814H", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id6", - "monitor": Object { - "duration": Object { - "us": 1699, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", - }, - "timestamp": "2019-01-28T17:47:18.080Z", + "timestamp": "2019-01-28T17:47:18.080Z", + }, + Object { + "docId": "3ewjio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", }, - Object { - "error": Object { - "message": "dial tcp 127.0.0.1:9200: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id7", - "monitor": Object { - "duration": Object { - "us": 5384, - }, - "id": "auto-tcp-0X81440A68E839814C", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "tcp", + "monitor": Object { + "duration": Object { + "us": 5384, }, - "timestamp": "2019-01-28T17:47:19.076Z", + "id": "auto-tcp-0X81440A68E839814I", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", }, - Object { - "error": Object { - "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", - "type": "io", - }, - "http": null, - "id": "id8", - "monitor": Object { - "duration": Object { - "us": 5397, - }, - "id": "auto-http-0X3675F89EF0612091", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http", + "timestamp": "2019-01-28T17:47:19.076Z", + }, + Object { + "docId": "fewjip21", + "error": Object { + "message": "Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused", + "type": "io", + }, + "monitor": Object { + "duration": Object { + "us": 5397, }, - "timestamp": "2019-01-28T17:47:19.076Z", + "id": "auto-http-0X3675F89EF061209J", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "http", }, - Object { - "error": null, - "http": Object { - "response": Object { - "status_code": 200, - }, + "timestamp": "2019-01-28T17:47:19.076Z", + }, + Object { + "docId": "fewjio21", + "http": Object { + "response": Object { + "status_code": 200, }, - "id": "id9", - "monitor": Object { - "duration": Object { - "us": 127511, - }, - "id": "auto-http-0X131221E73F825974", - "ip": "172.217.7.4", - "name": "", - "scheme": null, - "status": "up", - "type": "http", + }, + "monitor": Object { + "duration": Object { + "us": 127511, }, - "timestamp": "2019-01-28T17:47:19.077Z", + "id": "auto-tcp-0X81440A68E839814C", + "ip": "172.217.7.4", + "name": "", + "status": "up", + "type": "http", }, - Object { - "error": null, - "http": Object { - "response": Object { - "status_code": 200, - }, + "timestamp": "2019-01-28T17:47:19.077Z", + }, + Object { + "docId": "fewjik81", + "http": Object { + "response": Object { + "status_code": 200, }, - "id": "id10", - "monitor": Object { - "duration": Object { - "us": 287543, - }, - "id": "auto-http-0X9CB71300ABD5A2A8", - "ip": "192.30.253.112", - "name": "", - "scheme": null, - "status": "up", - "type": "http", + }, + "monitor": Object { + "duration": Object { + "us": 287543, }, - "timestamp": "2019-01-28T17:47:19.077Z", + "id": "auto-http-0X131221E73F825974", + "ip": "192.30.253.112", + "name": "", + "status": "up", + "type": "http", }, - ] - } - loading={false} - noItemsMessage="No items found" - onChange={[Function]} - pagination={ - Object { - "initialPageSize": 25, - "pageIndex": 0, - "pageSize": 10, - "pageSizeOptions": Array [ - 10, - 25, - 50, - 100, - ], - "totalItemCount": 9231, - } + "timestamp": "2019-01-28T17:47:19.077Z", + }, + ] + } + loading={false} + noItemsMessage="No items found" + onChange={[Function]} + pagination={ + Object { + "initialPageSize": 10, + "pageIndex": 0, + "pageSize": 10, + "pageSizeOptions": Array [ + 10, + 25, + 50, + 100, + ], + "totalItemCount": 10, } - responsive={true} - tableLayout="fixed" - /> - </EuiPanel> -</Fragment> + } + responsive={true} + tableLayout="fixed" + /> +</EuiPanel> `; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx index 9dbe48ec5553a..2c1434cfd64bd 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx @@ -7,15 +7,23 @@ import { mountWithIntl, renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { PingListExpandedRowComponent } from '../expanded_row'; -import { Ping } from '../../../../../common/graphql/types'; +import { Ping } from '../../../../../common/runtime_types'; import { DocLinkForBody } from '../doc_link_body'; describe('PingListExpandedRow', () => { let ping: Ping; beforeEach(() => { ping = { - id: '123', + docId: 'fdeio12', timestamp: '19290310', + monitor: { + duration: { + us: 12345, + }, + id: '123', + status: 'down', + type: 'http', + }, http: { response: { body: { @@ -34,7 +42,7 @@ describe('PingListExpandedRow', () => { it('renders error information when an error field is present', () => { ping.error = { - code: 403, + code: '403', message: 'Forbidden', }; expect(shallowWithIntl(<PingListExpandedRowComponent ping={ping} />)).toMatchSnapshot(); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx index 68d285bd0baf1..ec256a886aa16 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx @@ -6,211 +6,188 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { PingResults, Ping } from '../../../../../common/graphql/types'; -import { PingListComponent, AllLocationOption, toggleDetails } from '../ping_list'; +import { PingListComponent, toggleDetails } from '../ping_list'; import { ExpandedRowMap } from '../../monitor_list/types'; +import { Ping, PingsResponse } from '../../../../../common/runtime_types'; describe('PingList component', () => { - let pingList: { allPings: PingResults }; + let response: PingsResponse; beforeEach(() => { - pingList = { - allPings: { - total: 9231, - pings: [ - { - id: 'id1', - timestamp: '2019-01-28T17:47:08.078Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1430 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id2', - timestamp: '2019-01-28T17:47:09.075Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1370 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id3', - timestamp: '2019-01-28T17:47:06.077Z', - http: null, - error: null, - monitor: { - duration: { us: 1452 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'up', - type: 'tcp', - }, - }, - { - id: 'id4', - timestamp: '2019-01-28T17:47:07.075Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1094 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id5', - timestamp: '2019-01-28T17:47:07.074Z', - http: null, - error: { - message: - 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1597 }, - id: 'auto-http-0X3675F89EF0612091', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'http', - }, - }, - { - id: 'id6', - timestamp: '2019-01-28T17:47:18.080Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 1699 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id7', - timestamp: '2019-01-28T17:47:19.076Z', - http: null, - error: { - message: 'dial tcp 127.0.0.1:9200: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 5384 }, - id: 'auto-tcp-0X81440A68E839814C', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'tcp', - }, - }, - { - id: 'id8', - timestamp: '2019-01-28T17:47:19.076Z', - http: null, - error: { - message: - 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', - type: 'io', - }, - monitor: { - duration: { us: 5397 }, - id: 'auto-http-0X3675F89EF0612091', - ip: '127.0.0.1', - name: '', - scheme: null, - status: 'down', - type: 'http', - }, - }, - { - id: 'id9', - timestamp: '2019-01-28T17:47:19.077Z', - http: { response: { status_code: 200 } }, - error: null, - monitor: { - duration: { us: 127511 }, - id: 'auto-http-0X131221E73F825974', - ip: '172.217.7.4', - name: '', - scheme: null, - status: 'up', - type: 'http', - }, - }, - { - id: 'id10', - timestamp: '2019-01-28T17:47:19.077Z', - http: { response: { status_code: 200 } }, - error: null, - monitor: { - duration: { us: 287543 }, - id: 'auto-http-0X9CB71300ABD5A2A8', - ip: '192.30.253.112', - name: '', - scheme: null, - status: 'up', - type: 'http', - }, - }, - ], - locations: ['nyc'], - }, + response = { + total: 9231, + locations: ['nyc'], + pings: [ + { + docId: 'fewjio21', + timestamp: '2019-01-28T17:47:08.078Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1430 }, + id: 'auto-tcp-0X81440A68E839814F', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fewjoo21', + timestamp: '2019-01-28T17:47:09.075Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1370 }, + id: 'auto-tcp-0X81440A68E839814D', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fejjio21', + timestamp: '2019-01-28T17:47:06.077Z', + monitor: { + duration: { us: 1452 }, + id: 'auto-tcp-0X81440A68E839814D', + ip: '127.0.0.1', + name: '', + status: 'up', + type: 'tcp', + }, + }, + { + docId: 'fewzio21', + timestamp: '2019-01-28T17:47:07.075Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1094 }, + id: 'auto-tcp-0X81440A68E839814E', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fewpi321', + timestamp: '2019-01-28T17:47:07.074Z', + error: { + message: + 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1597 }, + id: 'auto-http-0X3675F89EF061209G', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'http', + }, + }, + { + docId: '0ewjio21', + timestamp: '2019-01-28T17:47:18.080Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 1699 }, + id: 'auto-tcp-0X81440A68E839814H', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: '3ewjio21', + timestamp: '2019-01-28T17:47:19.076Z', + error: { + message: 'dial tcp 127.0.0.1:9200: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 5384 }, + id: 'auto-tcp-0X81440A68E839814I', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'tcp', + }, + }, + { + docId: 'fewjip21', + timestamp: '2019-01-28T17:47:19.076Z', + error: { + message: + 'Get http://localhost:12349/: dial tcp 127.0.0.1:12349: connect: connection refused', + type: 'io', + }, + monitor: { + duration: { us: 5397 }, + id: 'auto-http-0X3675F89EF061209J', + ip: '127.0.0.1', + name: '', + status: 'down', + type: 'http', + }, + }, + { + docId: 'fewjio21', + timestamp: '2019-01-28T17:47:19.077Z', + http: { response: { status_code: 200 } }, + monitor: { + duration: { us: 127511 }, + id: 'auto-tcp-0X81440A68E839814C', + ip: '172.217.7.4', + name: '', + status: 'up', + type: 'http', + }, + }, + { + docId: 'fewjik81', + timestamp: '2019-01-28T17:47:19.077Z', + http: { response: { status_code: 200 } }, + monitor: { + duration: { us: 287543 }, + id: 'auto-http-0X131221E73F825974', + ip: '192.30.253.112', + name: '', + status: 'up', + type: 'http', + }, + }, + ], }; }); it('renders sorted list without errors', () => { - const { allPings } = pingList; const component = shallowWithIntl( <PingListComponent + dateRange={{ + from: 'now-15m', + to: 'now', + }} + getPings={jest.fn()} + lastRefresh={123} loading={false} - data={{ allPings }} - onPageCountChange={jest.fn()} - onPageIndexChange={jest.fn()} - onSelectedLocationChange={(_loc: any[]) => {}} - onSelectedStatusChange={jest.fn()} - pageIndex={0} - pageSize={10} - selectedOption="down" - selectedLocation={AllLocationOption.value} + locations={[]} + monitorId="foo" + pings={response.pings} + total={10} /> ); expect(component).toMatchSnapshot(); @@ -224,13 +201,38 @@ describe('PingList component', () => { beforeEach(() => { itemIdToExpandedRowMap = {}; - pings = pingList.allPings.pings; + pings = response.pings; }); it('should expand an item if empty', () => { const ping = pings[0]; toggleDetails(ping, itemIdToExpandedRowMap, setItemIdToExpandedRowMap); - expect(itemIdToExpandedRowMap).toHaveProperty(ping.id); + expect(itemIdToExpandedRowMap).toMatchInlineSnapshot(` + Object { + "fewjio21": <PingListExpandedRowComponent + ping={ + Object { + "docId": "fewjio21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", + }, + "monitor": Object { + "duration": Object { + "us": 1430, + }, + "id": "auto-tcp-0X81440A68E839814F", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", + }, + "timestamp": "2019-01-28T17:47:08.078Z", + } + } + />, + } + `); }); it('should un-expand an item if clicked again', () => { @@ -245,7 +247,31 @@ describe('PingList component', () => { const pingB = pings[1]; toggleDetails(pingA, itemIdToExpandedRowMap, setItemIdToExpandedRowMap); toggleDetails(pingB, itemIdToExpandedRowMap, setItemIdToExpandedRowMap); - expect(itemIdToExpandedRowMap).toHaveProperty(pingB.id); + expect(pingA.docId).not.toEqual(pingB.docId); + expect(itemIdToExpandedRowMap[pingB.docId]).toMatchInlineSnapshot(` + <PingListExpandedRowComponent + ping={ + Object { + "docId": "fewjoo21", + "error": Object { + "message": "dial tcp 127.0.0.1:9200: connect: connection refused", + "type": "io", + }, + "monitor": Object { + "duration": Object { + "us": 1370, + }, + "id": "auto-tcp-0X81440A68E839814D", + "ip": "127.0.0.1", + "name": "", + "status": "down", + "type": "tcp", + }, + "timestamp": "2019-01-28T17:47:09.075Z", + } + } + /> + `); }); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx index c684235122e34..28b96fcb1bf7b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx @@ -16,14 +16,14 @@ import { } from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; -import { Ping, HttpBody } from '../../../../common/graphql/types'; +import { Ping, HttpResponseBody } from '../../../../common/runtime_types'; import { DocLinkForBody } from './doc_link_body'; interface Props { ping: Ping; } -const BodyDescription = ({ body }: { body: HttpBody }) => { +const BodyDescription = ({ body }: { body: HttpResponseBody }) => { const contentBytes = body.content_bytes || 0; const bodyBytes = body.bytes || 0; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx index e57b229dfd973..808f3f90ef015 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './ping_list'; +export { PingListComponent } from './ping_list'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx index 19768c7104e91..934dfd961f9e0 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx @@ -20,109 +20,127 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { get } from 'lodash'; import moment from 'moment'; -import React, { Fragment, useState } from 'react'; +import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; -import { CriteriaWithPagination } from '@elastic/eui/src/components/basic_table/basic_table'; -import { Ping, PingResults } from '../../../../common/graphql/types'; +import { Ping, GetPingsParams, DateRange } from '../../../../common/runtime_types'; import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../../lib/helper'; -import { UptimeGraphQLQueryProps, withUptimeGraphQL } from '../../higher_order'; -import { pingsQuery } from '../../../queries'; import { LocationName } from './location_name'; import { Pagination } from './../monitor_list'; import { PingListExpandedRowComponent } from './expanded_row'; +import { PingListProps } from '../../connected/pings'; -interface PingListQueryResult { - allPings?: PingResults; -} - -interface PingListProps { - onSelectedStatusChange: (status: string | undefined) => void; - onSelectedLocationChange: (location: any) => void; - onPageCountChange: (itemCount: number) => void; - onPageIndexChange: (index: number) => void; - pageSize: number; - pageIndex: number; - selectedOption: string; - selectedLocation: string | undefined; -} - -type Props = UptimeGraphQLQueryProps<PingListQueryResult> & PingListProps; -interface ExpandedRowMap { - [key: string]: JSX.Element; -} - -export const AllLocationOption = { text: 'All', value: '' }; +export const AllLocationOption = { + 'data-test-subj': 'xpack.uptime.pingList.locationOptions.all', + text: 'All', + value: '', +}; export const toggleDetails = ( ping: Ping, - itemIdToExpandedRowMap: ExpandedRowMap, - setItemIdToExpandedRowMap: (update: ExpandedRowMap) => any + expandedRows: Record<string, JSX.Element>, + setExpandedRows: (update: Record<string, JSX.Element>) => any ) => { - // If the user has clicked on the expanded map, close all expanded rows. - if (itemIdToExpandedRowMap[ping.id]) { - setItemIdToExpandedRowMap({}); + // If already expanded, collapse + if (expandedRows[ping.docId]) { + delete expandedRows[ping.docId]; + setExpandedRows({ ...expandedRows }); return; } // Otherwise expand this row - const newItemIdToExpandedRowMap: ExpandedRowMap = {}; - newItemIdToExpandedRowMap[ping.id] = <PingListExpandedRowComponent ping={ping} />; - setItemIdToExpandedRowMap(newItemIdToExpandedRowMap); + setExpandedRows({ + ...expandedRows, + [ping.docId]: <PingListExpandedRowComponent ping={ping} />, + }); }; const SpanWithMargin = styled.span` margin-right: 16px; `; -export const PingListComponent = ({ - data, - loading, - onPageCountChange, - onPageIndexChange, - onSelectedLocationChange, - onSelectedStatusChange, - pageIndex, - pageSize, - selectedOption, - selectedLocation, -}: Props) => { - const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<ExpandedRowMap>({}); +interface Props extends PingListProps { + dateRange: DateRange; + error?: Error; + getPings: (props: GetPingsParams) => void; + lastRefresh: number; + loading: boolean; + locations: string[]; + pings: Ping[]; + total: number; +} + +const DEFAULT_PAGE_SIZE = 10; + +const statusOptions = [ + { + 'data-test-subj': 'xpack.uptime.pingList.statusOptions.all', + text: i18n.translate('xpack.uptime.pingList.statusOptions.allStatusOptionLabel', { + defaultMessage: 'All', + }), + value: '', + }, + { + 'data-test-subj': 'xpack.uptime.pingList.statusOptions.up', + text: i18n.translate('xpack.uptime.pingList.statusOptions.upStatusOptionLabel', { + defaultMessage: 'Up', + }), + value: 'up', + }, + { + 'data-test-subj': 'xpack.uptime.pingList.statusOptions.down', + text: i18n.translate('xpack.uptime.pingList.statusOptions.downStatusOptionLabel', { + defaultMessage: 'Down', + }), + value: 'down', + }, +]; + +export const PingListComponent = (props: Props) => { + const [selectedLocation, setSelectedLocation] = useState<string>(''); + const [status, setStatus] = useState<string>(''); + const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE); + const [pageIndex, setPageIndex] = useState(0); + const { + dateRange: { from, to }, + error, + getPings, + lastRefresh, + loading, + locations, + monitorId, + pings, + total, + } = props; + + useEffect(() => { + getPings({ + dateRange: { + from, + to, + }, + location: selectedLocation, + monitorId, + index: pageIndex, + size: pageSize, + status: status !== 'all' ? status : '', + }); + }, [from, to, getPings, monitorId, lastRefresh, selectedLocation, pageIndex, pageSize, status]); + + const [expandedRows, setExpandedRows] = useState<Record<string, JSX.Element>>({}); - const statusOptions = [ - { - text: i18n.translate('xpack.uptime.pingList.statusOptions.allStatusOptionLabel', { - defaultMessage: 'All', - }), - value: '', - }, - { - text: i18n.translate('xpack.uptime.pingList.statusOptions.upStatusOptionLabel', { - defaultMessage: 'Up', - }), - value: 'up', - }, - { - text: i18n.translate('xpack.uptime.pingList.statusOptions.downStatusOptionLabel', { - defaultMessage: 'Down', - }), - value: 'down', - }, - ]; - const locations = get<string[]>(data, 'allPings.locations'); const locationOptions = !locations ? [AllLocationOption] : [AllLocationOption].concat( - locations.map(name => { - return { text: name, value: name }; - }) + locations.map(name => ({ + text: name, + 'data-test-subj': `xpack.uptime.pingList.locationOptions.${name}`, + value: name, + })) ); - const pings: Ping[] = data?.allPings?.pings ?? []; - const hasStatus: boolean = pings.reduce( - (hasHttpStatus: boolean, currentPing: Ping) => + (hasHttpStatus: boolean, currentPing) => hasHttpStatus || !!currentPing.http?.response?.status_code, false ); @@ -134,7 +152,7 @@ export const PingListComponent = ({ defaultMessage: 'Status', }), render: (pingStatus: string, item: Ping) => ( - <div> + <div data-test-subj={`xpack.uptime.pingList.ping-${item.docId}`}> <EuiHealth color={pingStatus === 'up' ? 'success' : 'danger'}> {pingStatus === 'up' ? i18n.translate('xpack.uptime.pingList.statusColumnHealthUpLabel', { @@ -189,7 +207,7 @@ export const PingListComponent = ({ name: i18n.translate('xpack.uptime.pingList.errorTypeColumnLabel', { defaultMessage: 'Error type', }), - render: (error: string) => error ?? '-', + render: (errorType: string) => errorType ?? '-', }, // Only add this column is there is any status present in list ...(hasStatus @@ -219,16 +237,16 @@ export const PingListComponent = ({ render: (item: Ping) => { return ( <EuiButtonIcon - onClick={() => toggleDetails(item, itemIdToExpandedRowMap, setItemIdToExpandedRowMap)} - disabled={!item.error && !(item.http?.response?.body?.bytes > 0)} + onClick={() => toggleDetails(item, expandedRows, setExpandedRows)} + disabled={!item.error && !(item.http?.response?.body?.bytes ?? 0 > 0)} aria-label={ - itemIdToExpandedRowMap[item.id] + expandedRows[item.docId] ? i18n.translate('xpack.uptime.pingList.collapseRow', { defaultMessage: 'Collapse', }) : i18n.translate('xpack.uptime.pingList.expandRow', { defaultMessage: 'Expand' }) } - iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'} + iconType={expandedRows[item.docId] ? 'arrowUp' : 'arrowDown'} /> ); }, @@ -236,104 +254,83 @@ export const PingListComponent = ({ ]; const pagination: Pagination = { - initialPageSize: 25, + initialPageSize: DEFAULT_PAGE_SIZE, pageIndex, pageSize, pageSizeOptions: [10, 25, 50, 100], - totalItemCount: data?.allPings?.total ?? pageSize, + /** + * we're not currently supporting pagination in this component + * so the first page is the only page + */ + totalItemCount: total, }; return ( - <Fragment> - <EuiPanel> - <EuiTitle size="xs"> - <h4> - <FormattedMessage - id="xpack.uptime.pingList.checkHistoryTitle" - defaultMessage="History" + <EuiPanel> + <EuiTitle size="xs"> + <h4> + <FormattedMessage id="xpack.uptime.pingList.checkHistoryTitle" defaultMessage="History" /> + </h4> + </EuiTitle> + <EuiSpacer size="s" /> + <EuiFlexGroup justifyContent="spaceBetween"> + <EuiFlexItem grow={false}> + <EuiFormRow + label="Status" + aria-label={i18n.translate('xpack.uptime.pingList.statusLabel', { + defaultMessage: 'Status', + })} + > + <EuiSelect + options={statusOptions} + aria-label={i18n.translate('xpack.uptime.pingList.statusLabel', { + defaultMessage: 'Status', + })} + data-test-subj="xpack.uptime.pingList.statusSelect" + value={status} + onChange={selected => { + setStatus(selected.target.value); + }} /> - </h4> - </EuiTitle> - <EuiSpacer size="s" /> - <EuiFlexGroup justifyContent="spaceBetween"> - <EuiFlexItem grow={false}> - <EuiFlexGroup> - <EuiFlexItem style={{ minWidth: 200 }}> - <EuiFlexGroup> - <EuiFlexItem> - <EuiFormRow - label="Status" - aria-label={i18n.translate('xpack.uptime.pingList.statusLabel', { - defaultMessage: 'Status', - })} - > - <EuiSelect - options={statusOptions} - aria-label={i18n.translate('xpack.uptime.pingList.statusLabel', { - defaultMessage: 'Status', - })} - value={selectedOption} - onChange={selected => { - if (typeof selected.target.value === 'string') { - onSelectedStatusChange( - selected.target && selected.target.value !== '' - ? selected.target.value - : undefined - ); - } - }} - /> - </EuiFormRow> - </EuiFlexItem> - <EuiFlexItem> - <EuiFormRow - label="Location" - aria-label={i18n.translate('xpack.uptime.pingList.locationLabel', { - defaultMessage: 'Location', - })} - > - <EuiSelect - options={locationOptions} - value={selectedLocation} - aria-label={i18n.translate('xpack.uptime.pingList.locationLabel', { - defaultMessage: 'Location', - })} - onChange={selected => { - onSelectedLocationChange( - selected.target && selected.target.value !== '' - ? selected.target.value - : null - ); - }} - /> - </EuiFormRow> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - </EuiFlexGroup> - <EuiSpacer size="s" /> - <EuiBasicTable - loading={loading} - columns={columns} - isExpandable={true} - hasActions={true} - items={pings} - itemId="id" - itemIdToExpandedRowMap={itemIdToExpandedRowMap} - pagination={pagination} - onChange={(criteria: CriteriaWithPagination<Ping>) => { - onPageCountChange(criteria.page!.size); - onPageIndexChange(criteria.page!.index); - }} - /> - </EuiPanel> - </Fragment> + </EuiFormRow> + </EuiFlexItem> + <EuiFlexItem> + <EuiFormRow + label="Location" + aria-label={i18n.translate('xpack.uptime.pingList.locationLabel', { + defaultMessage: 'Location', + })} + > + <EuiSelect + options={locationOptions} + value={selectedLocation} + aria-label={i18n.translate('xpack.uptime.pingList.locationLabel', { + defaultMessage: 'Location', + })} + data-test-subj="xpack.uptime.pingList.locationSelect" + onChange={selected => { + setSelectedLocation(selected.target.value); + }} + /> + </EuiFormRow> + </EuiFlexItem> + </EuiFlexGroup> + <EuiSpacer size="s" /> + <EuiBasicTable + loading={loading} + columns={columns} + error={error?.message} + isExpandable={true} + hasActions={true} + items={pings} + itemId="docId" + itemIdToExpandedRowMap={expandedRows} + pagination={pagination} + onChange={(criteria: any) => { + setPageSize(criteria.page!.size); + setPageIndex(criteria.page!.index); + }} + /> + </EuiPanel> ); }; - -export const PingList = withUptimeGraphQL<PingListQueryResult, PingListProps>( - PingListComponent, - pingsQuery -); diff --git a/x-pack/legacy/plugins/uptime/public/hooks/index.ts b/x-pack/legacy/plugins/uptime/public/hooks/index.ts index e022248df407a..1f50e995eda49 100644 --- a/x-pack/legacy/plugins/uptime/public/hooks/index.ts +++ b/x-pack/legacy/plugins/uptime/public/hooks/index.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +export * from './use_monitor'; export * from './use_url_params'; export * from './use_telemetry'; export * from './update_kuery_string'; diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx index 5016ccebbab54..683af81239c99 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx @@ -5,39 +5,21 @@ */ import { EuiSpacer } from '@elastic/eui'; -import React, { useContext, useState } from 'react'; +import React from 'react'; import { useSelector } from 'react-redux'; -import { MonitorCharts, PingList } from '../components/functional'; -import { UptimeRefreshContext } from '../contexts'; -import { useUptimeTelemetry, useUrlParams, UptimePage } from '../hooks'; import { useTrackPageview } from '../../../../../plugins/observability/public'; -import { MonitorStatusDetails } from '../components/connected'; +import { MonitorStatusDetails, PingList } from '../components/connected'; import { monitorStatusSelector } from '../state/selectors'; import { PageHeader } from './page_header'; +import { MonitorCharts } from '../components/functional'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; -import { useMonitorId } from '../hooks/use_monitor'; +import { useMonitorId, useUptimeTelemetry, UptimePage } from '../hooks'; export const MonitorPage: React.FC = () => { const monitorId = useMonitorId(); - const [pingListPageCount, setPingListPageCount] = useState<number>(10); - const { refreshApp } = useContext(UptimeRefreshContext); - const [getUrlParams, updateUrlParams] = useUrlParams(); - const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams(); - const { dateRangeStart, dateRangeEnd, selectedPingStatus } = params; - - const [selectedLocation, setSelectedLocation] = useState(undefined); - const [pingListIndex, setPingListIndex] = useState(0); - const selectedMonitor = useSelector(monitorStatusSelector); - const sharedVariables = { - dateRangeStart, - dateRangeEnd, - monitorId, - location: selectedLocation, - }; - useUptimeTelemetry(UptimePage.Monitor); useTrackPageview({ app: 'uptime', path: 'monitor' }); @@ -53,25 +35,7 @@ export const MonitorPage: React.FC = () => { <EuiSpacer size="s" /> <MonitorCharts monitorId={monitorId} /> <EuiSpacer size="s" /> - <PingList - onPageCountChange={setPingListPageCount} - onSelectedLocationChange={setSelectedLocation} - onSelectedStatusChange={(selectedStatus: string | undefined) => { - updateUrlParams({ selectedPingStatus: selectedStatus || '' }); - refreshApp(); - }} - onPageIndexChange={(index: number) => setPingListIndex(index)} - pageIndex={pingListIndex} - pageSize={pingListPageCount} - selectedOption={selectedPingStatus} - selectedLocation={selectedLocation} - variables={{ - ...sharedVariables, - page: pingListIndex, - size: pingListPageCount, - status: selectedPingStatus, - }} - /> + <PingList monitorId={monitorId} /> </> ); }; diff --git a/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts b/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts deleted file mode 100644 index ed20fe8eb2931..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/queries/pings_query.ts +++ /dev/null @@ -1,73 +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'; - -export const pingsQueryString = ` -query PingList( - $dateRangeStart: String! - $dateRangeEnd: String! - $monitorId: String - $status: String - $sort: String - $size: Int - $location: String - $page: Int -) { - allPings( - dateRangeStart: $dateRangeStart - dateRangeEnd: $dateRangeEnd - monitorId: $monitorId - status: $status - sort: $sort - size: $size - location: $location - page: $page - ) { - total - locations - pings { - id - timestamp - http { - response { - status_code - body { - bytes - hash - content - content_bytes - } - } - } - error { - message - type - } - monitor { - duration { - us - } - id - ip - name - scheme - status - type - } - observer { - geo { - name - } - } - } - } - } -`; - -export const pingsQuery = gql` - ${pingsQueryString} -`; diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts index a8f37d38ebae6..e8c862e209739 100644 --- a/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/actions/monitor_status.ts @@ -5,7 +5,7 @@ */ import { createAction } from 'redux-actions'; import { QueryParams } from './types'; -import { Ping } from '../../../common/graphql/types'; +import { Ping } from '../../../common/runtime_types'; export const getMonitorStatusAction = createAction<QueryParams>('GET_MONITOR_STATUS'); export const getMonitorStatusActionSuccess = createAction<Ping>('GET_MONITOR_STATUS_SUCCESS'); diff --git a/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts b/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts index bb7258d9a54b2..70918a4cc70e5 100644 --- a/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/actions/ping.ts @@ -5,8 +5,17 @@ */ import { createAction } from 'redux-actions'; -import { GetPingHistogramParams, HistogramResult } from '../../../common/types'; +import { + GetPingHistogramParams, + HistogramResult, + PingsResponse, + GetPingsParams, +} from '../../../common/runtime_types'; export const getPingHistogram = createAction<GetPingHistogramParams>('GET_PING_HISTOGRAM'); export const getPingHistogramSuccess = createAction<HistogramResult>('GET_PING_HISTOGRAM_SUCCESS'); export const getPingHistogramFail = createAction<Error>('GET_PING_HISTOGRAM_FAIL'); + +export const getPings = createAction<GetPingsParams>('GET PINGS'); +export const getPingsSuccess = createAction<PingsResponse>('GET PINGS SUCCESS'); +export const getPingsFail = createAction<Error>('GET PINGS FAIL'); diff --git a/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts index f9e171adda334..7c8ab3518b5a0 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/monitor_status.ts @@ -5,9 +5,9 @@ */ import { QueryParams } from '../actions/types'; -import { Ping } from '../../../common/graphql/types'; -import { apiService } from './utils'; +import { Ping } from '../../../common/runtime_types'; import { API_URLS } from '../../../common/constants'; +import { apiService } from './utils'; export const fetchMonitorStatus = async ({ monitorId, diff --git a/x-pack/legacy/plugins/uptime/public/state/api/ping.ts b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts index df71cc8d67bd0..bbd3ddf399dcc 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts @@ -5,10 +5,21 @@ */ import { APIFn } from './types'; -import { GetPingHistogramParams, HistogramResult } from '../../../common/types'; +import { + PingsResponseType, + PingsResponse, + GetPingsParams, + GetPingHistogramParams, + HistogramResult, +} from '../../../common/runtime_types'; import { apiService } from './utils'; import { API_URLS } from '../../../common/constants/rest_api'; +export const fetchPings: APIFn<GetPingsParams, PingsResponse> = async ({ + dateRange: { from, to }, + ...optional +}) => await apiService.get(API_URLS.PINGS, { from, to, ...optional }, PingsResponseType); + export const fetchPingHistogram: APIFn<GetPingHistogramParams, HistogramResult> = async ({ monitorId, dateStart, @@ -19,9 +30,9 @@ export const fetchPingHistogram: APIFn<GetPingHistogramParams, HistogramResult> const queryParams = { dateStart, dateEnd, - ...(monitorId && { monitorId }), - ...(statusFilter && { statusFilter }), - ...(filters && { filters }), + monitorId, + statusFilter, + filters, }; return await apiService.get(API_URLS.PING_HISTOGRAM, queryParams); diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts b/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts index 49e497952ea44..b0734cb5ccabb 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/fetch_effect.ts @@ -16,7 +16,7 @@ import { IHttpFetchError } from '../../../../../../../target/types/core/public/h * @param fail creates a failure action * @template T the action type expected by the fetch action * @template R the type that the API request should return on success - * @template S tye type of the success action + * @template S the type of the success action * @template F the type of the failure action */ export function fetchEffectFactory<T, R, S, F>( diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/index.ts b/x-pack/legacy/plugins/uptime/public/state/effects/index.ts index 8d457be1d1c78..8df11312b6455 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/index.ts @@ -11,7 +11,7 @@ import { fetchSnapshotCountEffect } from './snapshot'; import { fetchMonitorStatusEffect } from './monitor_status'; import { fetchDynamicSettingsEffect, setDynamicSettingsEffect } from './dynamic_settings'; import { fetchIndexPatternEffect } from './index_pattern'; -import { fetchPingHistogramEffect } from './ping'; +import { fetchPingsEffect, fetchPingHistogramEffect } from './ping'; import { fetchMonitorDurationEffect } from './monitor_duration'; import { fetchMLJobEffect } from './ml_anomaly'; import { fetchIndexStatusEffect } from './index_status'; @@ -24,6 +24,7 @@ export function* rootEffect() { yield fork(fetchDynamicSettingsEffect); yield fork(setDynamicSettingsEffect); yield fork(fetchIndexPatternEffect); + yield fork(fetchPingsEffect); yield fork(fetchPingHistogramEffect); yield fork(fetchMLJobEffect); yield fork(fetchMonitorDurationEffect); diff --git a/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts b/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts index acb9b31915fa9..dec67ed8cf979 100644 --- a/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/effects/ping.ts @@ -5,10 +5,21 @@ */ import { takeLatest } from 'redux-saga/effects'; -import { getPingHistogram, getPingHistogramSuccess, getPingHistogramFail } from '../actions'; -import { fetchPingHistogram } from '../api'; +import { + getPingHistogram, + getPingHistogramSuccess, + getPingHistogramFail, + getPings, + getPingsSuccess, + getPingsFail, +} from '../actions'; +import { fetchPingHistogram, fetchPings } from '../api'; import { fetchEffectFactory } from './fetch_effect'; +export function* fetchPingsEffect() { + yield takeLatest(String(getPings), fetchEffectFactory(fetchPings, getPingsSuccess, getPingsFail)); +} + export function* fetchPingHistogramEffect() { yield takeLatest( String(getPingHistogram), diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts index 7bf8af5dd4d03..0a3ff35df0599 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/index.ts @@ -13,6 +13,7 @@ import { monitorStatusReducer } from './monitor_status'; import { dynamicSettingsReducer } from './dynamic_settings'; import { indexPatternReducer } from './index_pattern'; import { pingReducer } from './ping'; +import { pingListReducer } from './ping_list'; import { monitorDurationReducer } from './monitor_duration'; import { indexStatusReducer } from './index_status'; import { mlJobsReducer } from './ml_anomaly'; @@ -26,6 +27,7 @@ export const rootReducer = combineReducers({ dynamicSettings: dynamicSettingsReducer, indexPattern: indexPatternReducer, ping: pingReducer, + pingList: pingListReducer, ml: mlJobsReducer, monitorDuration: monitorDurationReducer, indexStatus: indexStatusReducer, diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts index 6cfaa9f8f59c1..fa3e377b5ebf4 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts @@ -9,7 +9,7 @@ import { getMonitorStatusActionSuccess, getMonitorStatusActionFail, } from '../actions'; -import { Ping } from '../../../common/graphql/types'; +import { Ping } from '../../../common/runtime_types'; import { QueryParams } from '../actions/types'; export interface MonitorStatusState { diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts index 76775e6a0a355..4c8715038ce36 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/ping.ts @@ -6,7 +6,7 @@ import { handleActions, Action } from 'redux-actions'; import { getPingHistogram, getPingHistogramSuccess, getPingHistogramFail } from '../actions'; -import { HistogramResult } from '../../../common/types'; +import { HistogramResult } from '../../../common/runtime_types'; export interface PingState { pingHistogram: HistogramResult | null; diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts new file mode 100644 index 0000000000000..e3ccb1e663eda --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/ping_list.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { handleActions, Action } from 'redux-actions'; +import { PingsResponse } from '../../../common/runtime_types'; +import { getPings, getPingsSuccess, getPingsFail } from '../actions'; + +export interface PingListState { + pingList: PingsResponse; + error?: Error; + loading: boolean; +} + +const initialState: PingListState = { + pingList: { + total: 0, + locations: [], + pings: [], + }, + loading: false, +}; + +type PingListPayload = PingsResponse & Error; + +export const pingListReducer = handleActions<PingListState, PingListPayload>( + { + [String(getPings)]: state => ({ + ...state, + loading: true, + }), + + [String(getPingsSuccess)]: (state, action: Action<PingsResponse>) => ({ + ...state, + pingList: { ...action.payload }, + loading: false, + }), + + [String(getPingsFail)]: (state, action: Action<Error>) => ({ + ...state, + error: action.payload, + loading: false, + }), + }, + initialState +); diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts index 3b4547514a11e..77902f347f6f9 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/__tests__/index.test.ts @@ -58,6 +58,14 @@ describe('state selectors', () => { loading: false, errors: [], }, + pingList: { + loading: false, + pingList: { + total: 0, + locations: [], + pings: [], + }, + }, monitorDuration: { durationLines: null, loading: false, diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts index 0fc3c7151cb3b..37695e4274306 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts @@ -41,6 +41,11 @@ export const selectPingHistogram = ({ ping, ui }: AppState) => { }; }; +export const selectPingList = ({ pingList, ui: { lastRefresh } }: AppState) => ({ + pings: pingList, + lastRefresh, +}); + const mlCapabilitiesSelector = (state: AppState) => state.ml.mlCapabilities.data; export const hasMLFeatureAvailable = createSelector( diff --git a/x-pack/plugins/uptime/server/graphql/index.ts b/x-pack/plugins/uptime/server/graphql/index.ts index 49ba5583b417b..a88afd7ac769c 100644 --- a/x-pack/plugins/uptime/server/graphql/index.ts +++ b/x-pack/plugins/uptime/server/graphql/index.ts @@ -5,14 +5,13 @@ */ import { createMonitorStatesResolvers, monitorStatesSchema } from './monitor_states'; -import { createPingsResolvers, pingsSchema } from './pings'; +import { pingsSchema } from './pings'; import { CreateUMGraphQLResolvers } from './types'; import { unsignedIntegerResolverFunctions, unsignedIntegerSchema } from './unsigned_int_scalar'; export { DEFAULT_GRAPHQL_PATH } from './constants'; export const resolvers: CreateUMGraphQLResolvers[] = [ createMonitorStatesResolvers, - createPingsResolvers, unsignedIntegerResolverFunctions, ]; export const typeDefs: any[] = [pingsSchema, unsignedIntegerSchema, monitorStatesSchema]; diff --git a/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts index 6ab564fdeb532..040ad99ac0c64 100644 --- a/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts +++ b/x-pack/plugins/uptime/server/graphql/monitor_states/schema.gql.ts @@ -169,7 +169,7 @@ export const monitorStatesSchema = gql` DESC } - extend type Query { + type Query { "Fetches the current state of Uptime monitors for the given parameters." getMonitorStates( dateRangeStart: String! diff --git a/x-pack/plugins/uptime/server/graphql/pings/index.ts b/x-pack/plugins/uptime/server/graphql/pings/index.ts index 57ec3242a7aa9..100ce29c398ec 100644 --- a/x-pack/plugins/uptime/server/graphql/pings/index.ts +++ b/x-pack/plugins/uptime/server/graphql/pings/index.ts @@ -4,5 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { createPingsResolvers } from './resolvers'; export { pingsSchema } from './schema.gql'; diff --git a/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts b/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts deleted file mode 100644 index 2bb1e13bc4b1f..0000000000000 --- a/x-pack/plugins/uptime/server/graphql/pings/resolvers.ts +++ /dev/null @@ -1,59 +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 { UMResolver } from '../../../../../legacy/plugins/uptime/common/graphql/resolver_types'; -import { - AllPingsQueryArgs, - PingResults, -} from '../../../../../legacy/plugins/uptime/common/graphql/types'; -import { UMServerLibs } from '../../lib/lib'; -import { UMContext } from '../types'; -import { CreateUMGraphQLResolvers } from '../types'; -import { savedObjectsAdapter } from '../../lib/saved_objects'; - -export type UMAllPingsResolver = UMResolver< - PingResults | Promise<PingResults>, - any, - AllPingsQueryArgs, - UMContext ->; - -export interface UMPingResolver { - allPings: () => PingResults; -} - -export const createPingsResolvers: CreateUMGraphQLResolvers = ( - libs: UMServerLibs -): { - Query: { - allPings: UMAllPingsResolver; - }; -} => ({ - Query: { - async allPings( - _resolver, - { monitorId, sort, size, status, dateRangeStart, dateRangeEnd, location, page }, - { APICaller, savedObjectsClient } - ): Promise<PingResults> { - const dynamicSettings = await savedObjectsAdapter.getUptimeDynamicSettings( - savedObjectsClient - ); - - return await libs.requests.getPings({ - callES: APICaller, - dynamicSettings, - dateRangeStart, - dateRangeEnd, - monitorId, - status, - sort, - size, - location, - page, - }); - }, - }, -}); diff --git a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts index 25767fb544104..179bca53db161 100644 --- a/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts +++ b/x-pack/plugins/uptime/server/graphql/pings/schema.gql.ts @@ -7,10 +7,6 @@ import gql from 'graphql-tag'; export const pingsSchema = gql` - schema { - query: Query - } - type PingResults { "Total number of matching pings" total: UnsignedInteger! @@ -20,28 +16,6 @@ export const pingsSchema = gql` pings: [Ping!]! } - type Query { - "Get a list of all recorded pings for all monitors" - allPings( - "Optional: the direction to sort by. Accepts 'asc' and 'desc'. Defaults to 'desc'." - sort: String - "Optional: the number of results to return." - size: Int - "Optional: the monitor ID filter." - monitorId: String - "Optional: the check status to filter by." - status: String - "The lower limit of the date range." - dateRangeStart: String! - "The upper limit of the date range." - dateRangeEnd: String! - "Optional: agent location to filter by." - location: String - "Optional: current page." - page: Int - ): PingResults! - } - type ContainerImage { name: String tag: String diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts index 112c8e97d4c00..cf8414a3b0a68 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_latest_monitor.test.ts @@ -42,10 +42,16 @@ describe('getLatestMonitor', () => { hits: { hits: [ { + _id: 'fejwio32', _source: { - timestamp: 123456, + '@timestamp': '123456', monitor: { + duration: { + us: 12345, + }, id: 'testMonitor', + status: 'down', + type: 'http', }, }, }, @@ -64,7 +70,22 @@ describe('getLatestMonitor', () => { monitorId: 'testMonitor', }); - expect(result.timestamp).toBe(123456); + expect(result).toMatchInlineSnapshot(` + Object { + "@timestamp": "123456", + "docId": "fejwio32", + "monitor": Object { + "duration": Object { + "us": 12345, + }, + "id": "testMonitor", + "status": "down", + "type": "http", + }, + "timestamp": "123456", + } + `); + expect(result.timestamp).toBe('123456'); expect(result.monitor).not.toBeFalsy(); expect(result?.monitor?.id).toBe('testMonitor'); expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetLatestSearchParams); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts index 9145ccca1b6d1..fcf773db23de6 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_pings.test.ts @@ -17,16 +17,34 @@ describe('getAll', () => { { _source: { '@timestamp': '2018-10-30T18:51:59.792Z', + monitor: { + duration: { us: 2134 }, + id: 'foo', + status: 'up', + type: 'http', + }, }, }, { _source: { '@timestamp': '2018-10-30T18:53:59.792Z', + monitor: { + duration: { us: 2131 }, + id: 'foo', + status: 'up', + type: 'http', + }, }, }, { _source: { '@timestamp': '2018-10-30T18:55:59.792Z', + monitor: { + duration: { us: 2132 }, + id: 'foo', + status: 'up', + type: 'http', + }, }, }, ]; @@ -48,7 +66,7 @@ describe('getAll', () => { body: { query: { bool: { - filter: [{ range: { '@timestamp': { gte: 'now-1h', lte: 'now' } } }], + filter: [{ range: { timestamp: { gte: 'now-1h', lte: 'now' } } }], }, }, aggregations: { @@ -60,8 +78,7 @@ describe('getAll', () => { }, }, }, - sort: [{ '@timestamp': { order: 'desc' } }], - size: 12, + sort: [{ timestamp: { order: 'desc' } }], }, }; }); @@ -72,8 +89,7 @@ describe('getAll', () => { const result = await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, sort: 'asc', size: 12, }); @@ -95,15 +111,54 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, sort: 'asc', size: 12, }); - set(expectedGetAllParams, 'body.sort[0]', { '@timestamp': { order: 'asc' } }); + set(expectedGetAllParams, 'body.sort[0]', { timestamp: { order: 'asc' } }); expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + ], + }, + }, + "size": 12, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "asc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('omits the sort param when no sort passed', async () => { @@ -112,12 +167,52 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, size: 12, }); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + ], + }, + }, + "size": 12, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('omits the size param when no size passed', async () => { @@ -126,14 +221,52 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, sort: 'desc', }); - delete expectedGetAllParams.body.size; - set(expectedGetAllParams, 'body.sort[0].@timestamp.order', 'desc'); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + ], + }, + }, + "size": 25, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('adds a filter for monitor ID', async () => { @@ -142,14 +275,57 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, monitorId: 'testmonitorid', }); - delete expectedGetAllParams.body.size; - expectedGetAllParams.body.query.bool.filter.push({ term: { 'monitor.id': 'testmonitorid' } }); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + Object { + "term": Object { + "monitor.id": "testmonitorid", + }, + }, + ], + }, + }, + "size": 25, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); it('adds a filter for monitor status', async () => { @@ -158,13 +334,56 @@ describe('getAll', () => { await getPings({ callES: mockEsClient, dynamicSettings: defaultDynamicSettings, - dateRangeStart: 'now-1h', - dateRangeEnd: 'now', + dateRange: { from: 'now-1h', to: 'now' }, status: 'down', }); - delete expectedGetAllParams.body.size; - expectedGetAllParams.body.query.bool.filter.push({ term: { 'monitor.status': 'down' } }); - expect(mockEsClient).toHaveBeenCalledWith('search', expectedGetAllParams); + expect(mockEsClient).toHaveBeenCalledTimes(1); + expect(mockEsClient.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "search", + Object { + "body": Object { + "aggregations": Object { + "locations": Object { + "terms": Object { + "field": "observer.geo.name", + "missing": "N/A", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-1h", + "lte": "now", + }, + }, + }, + Object { + "term": Object { + "monitor.status": "down", + }, + }, + ], + }, + }, + "size": 25, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*", + }, + ] + `); }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts index 299e3eb6ca3cf..a8e9ccb875a08 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts @@ -5,7 +5,7 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Ping } from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { Ping } from '../../../../../legacy/plugins/uptime/common/runtime_types'; export interface GetLatestMonitorParams { /** @member dateRangeStart timestamp bounds */ @@ -53,11 +53,9 @@ export const getLatestMonitor: UMElasticsearchQueryFn<GetLatestMonitorParams, Pi }; const result = await callES('search', params); - const ping: any = result.hits?.hits?.[0] ?? {}; - const { '@timestamp': timestamp, ...monitorResult } = ping?._source ?? {}; + const doc = result.hits?.hits?.[0]; + const source = doc?._source ?? {}; + const docId = doc?._id ?? ''; - return { - timestamp, - ...monitorResult, - }; + return { ...source, docId, timestamp: source['@timestamp'] }; }; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts index a49e4c8931142..5a8927764ea5c 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts @@ -7,8 +7,10 @@ import { UMElasticsearchQueryFn } from '../adapters'; import { QUERY } from '../../../../../legacy/plugins/uptime/common/constants'; import { getFilterClause } from '../helper'; -import { HistogramQueryResult } from './types'; -import { HistogramResult } from '../../../../../legacy/plugins/uptime/common/types'; +import { + HistogramResult, + HistogramQueryResult, +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; export interface GetPingHistogramParams { /** @member dateRangeStart timestamp bounds */ diff --git a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts index c64b5f3ad4af4..6eccfdb13cef7 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts @@ -6,52 +6,28 @@ import { UMElasticsearchQueryFn } from '../adapters/framework'; import { - PingResults, + GetPingsParams, + HttpResponseBody, + PingsResponse, Ping, - HttpBody, -} from '../../../../../legacy/plugins/uptime/common/graphql/types'; +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; -export interface GetPingsParams { - /** @member dateRangeStart timestamp bounds */ - dateRangeStart: string; +const DEFAULT_PAGE_SIZE = 25; - /** @member dateRangeEnd timestamp bounds */ - dateRangeEnd: string; - - /** @member monitorId optional limit by monitorId */ - monitorId?: string | null; - - /** @member status optional limit by check statuses */ - status?: string | null; - - /** @member sort optional sort by timestamp */ - sort?: string | null; - - /** @member size optional limit query size */ - size?: number | null; - - /** @member location optional location value for use in filtering*/ - location?: string | null; - - /** @member page the number to provide to Elasticsearch as the "from" parameter */ - page?: number; -} - -export const getPings: UMElasticsearchQueryFn<GetPingsParams, PingResults> = async ({ +export const getPings: UMElasticsearchQueryFn<GetPingsParams, PingsResponse> = async ({ callES, dynamicSettings, - dateRangeStart, - dateRangeEnd, + dateRange: { from, to }, + index, monitorId, status, sort, - size, + size: sizeParam, location, - page, }) => { + const size = sizeParam ?? DEFAULT_PAGE_SIZE; const sortParam = { sort: [{ '@timestamp': { order: sort ?? 'desc' } }] }; - const sizeParam = size ? { size } : undefined; - const filter: any[] = [{ range: { '@timestamp': { gte: dateRangeStart, lte: dateRangeEnd } } }]; + const filter: any[] = [{ range: { '@timestamp': { gte: from, lte: to } } }]; if (monitorId) { filter.push({ term: { 'monitor.id': monitorId } }); } @@ -71,7 +47,7 @@ export const getPings: UMElasticsearchQueryFn<GetPingsParams, PingResults> = asy ...queryContext, }, ...sortParam, - ...sizeParam, + size, aggregations: { locations: { terms: { @@ -85,8 +61,8 @@ export const getPings: UMElasticsearchQueryFn<GetPingsParams, PingResults> = asy }, }; - if (page) { - params.body.from = page * (size ?? 25); + if (index) { + params.body.from = index * size; } const { @@ -96,25 +72,22 @@ export const getPings: UMElasticsearchQueryFn<GetPingsParams, PingResults> = asy const locations = aggs?.locations ?? { buckets: [{ key: 'N/A', doc_count: 0 }] }; - const pings: Ping[] = hits.map(({ _id, _source }: any) => { - const timestamp = _source['@timestamp']; - + const pings: Ping[] = hits.map((doc: any) => { + const { _id, _source } = doc; // Calculate here the length of the content string in bytes, this is easier than in client JS, where // we don't have access to Buffer.byteLength. There are some hacky ways to do this in the // client but this is cleaner. - const httpBody: HttpBody | undefined = _source?.http?.response?.body; + const httpBody: HttpResponseBody | undefined = _source?.http?.response?.body; if (httpBody && httpBody.content) { httpBody.content_bytes = Buffer.byteLength(httpBody.content); } - return { id: _id, timestamp, ..._source }; + return { ..._source, timestamp: _source['@timestamp'], docId: _id }; }); - const results: PingResults = { + return { total: total.value, locations: locations.buckets.map((bucket: { key: string }) => bucket.key), pings, }; - - return results; }; diff --git a/x-pack/plugins/uptime/server/lib/requests/index.ts b/x-pack/plugins/uptime/server/lib/requests/index.ts index 445adc3c15a93..6317f665d377f 100644 --- a/x-pack/plugins/uptime/server/lib/requests/index.ts +++ b/x-pack/plugins/uptime/server/lib/requests/index.ts @@ -13,7 +13,7 @@ export { getMonitorLocations, GetMonitorLocationsParams } from './get_monitor_lo export { getMonitorStates, GetMonitorStatesParams } from './get_monitor_states'; export { getMonitorStatus, GetMonitorStatusParams } from './get_monitor_status'; export * from './get_monitor_status'; -export { getPings, GetPingsParams } from './get_pings'; +export { getPings } from './get_pings'; export { getPingHistogram, GetPingHistogramParams } from './get_ping_histogram'; export { UptimeRequests } from './uptime_requests'; export { getSnapshotCount, GetSnapshotCountParams } from './get_snapshot_counts'; diff --git a/x-pack/plugins/uptime/server/lib/requests/types.ts b/x-pack/plugins/uptime/server/lib/requests/types.ts deleted file mode 100644 index 53a4e989e3789..0000000000000 --- a/x-pack/plugins/uptime/server/lib/requests/types.ts +++ /dev/null @@ -1,72 +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 { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/graphql/types'; -import { UMElasticsearchQueryFn } from '../adapters'; -import { - GetPingHistogramParams, - HistogramResult, -} from '../../../../../legacy/plugins/uptime/common/types'; - -export interface GetAllParams { - /** @member dateRangeStart timestamp bounds */ - dateRangeStart: string; - - /** @member dateRangeEnd timestamp bounds */ - dateRangeEnd: string; - - /** @member monitorId optional limit by monitorId */ - monitorId?: string | null; - - /** @member status optional limit by check statuses */ - status?: string | null; - - /** @member sort optional sort by timestamp */ - sort?: string | null; - - /** @member size optional limit query size */ - size?: number | null; - - /** @member location optional location value for use in filtering*/ - location?: string | null; -} - -export interface GetLatestMonitorDocsParams { - /** @member dateRangeStart timestamp bounds */ - dateStart?: string; - - /** @member dateRangeEnd timestamp bounds */ - dateEnd?: string; - - /** @member monitorId optional limit to monitorId */ - monitorId?: string | null; -} - -/** - * Count the number of documents in heartbeat indices - */ -export interface UMPingsAdapter { - getAll: UMElasticsearchQueryFn<GetAllParams, PingResults>; - - // Get the monitor meta info regardless of timestamp - getMonitor: UMElasticsearchQueryFn<GetLatestMonitorDocsParams, Ping>; - - getLatestMonitorStatus: UMElasticsearchQueryFn<GetLatestMonitorDocsParams, Ping>; - - getPingHistogram: UMElasticsearchQueryFn<GetPingHistogramParams, HistogramResult>; -} - -export interface HistogramQueryResult { - key: number; - key_as_string: string; - doc_count: number; - down: { - doc_count: number; - }; - up: { - doc_count: number; - }; -} diff --git a/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts index 9d3fa5aa08aed..e9a7aa94dd3aa 100644 --- a/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts +++ b/x-pack/plugins/uptime/server/lib/requests/uptime_requests.ts @@ -5,7 +5,12 @@ */ import { UMElasticsearchQueryFn } from '../adapters'; -import { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/graphql/types'; +import { + HistogramResult, + Ping, + PingsResponse as PingResults, + GetPingsParams, +} from '../../../../../legacy/plugins/uptime/common/runtime_types'; import { GetFilterBarParams, GetLatestMonitorParams, @@ -13,7 +18,6 @@ import { GetMonitorDetailsParams, GetMonitorLocationsParams, GetMonitorStatesParams, - GetPingsParams, GetPingHistogramParams, GetMonitorStatusParams, GetMonitorStatusResult, @@ -27,10 +31,7 @@ import { } from '../../../../../legacy/plugins/uptime/common/runtime_types'; import { GetMonitorStatesResult } from './get_monitor_states'; import { GetSnapshotCountParams } from './get_snapshot_counts'; -import { - HistogramResult, - MonitorDurationResult, -} from '../../../../../legacy/plugins/uptime/common/types'; +import { MonitorDurationResult } from '../../../../../legacy/plugins/uptime/common/types'; type ESQ<P, R> = UMElasticsearchQueryFn<P, R>; diff --git a/x-pack/plugins/uptime/server/rest_api/index.ts b/x-pack/plugins/uptime/server/rest_api/index.ts index c84ea71037953..c0412e588fa93 100644 --- a/x-pack/plugins/uptime/server/rest_api/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/index.ts @@ -5,7 +5,7 @@ */ import { createGetOverviewFilters } from './overview_filters'; -import { createGetPingsRoute } from './pings'; +import { createGetPingHistogramRoute, createGetPingsRoute } from './pings'; import { createGetDynamicSettingsRoute, createPostDynamicSettingsRoute } from './dynamic_settings'; import { createLogPageViewRoute } from './telemetry'; import { createGetSnapshotCount } from './snapshot'; @@ -15,10 +15,8 @@ import { createGetMonitorLocationsRoute, createGetStatusBarRoute, } from './monitors'; -import { createGetPingHistogramRoute } from './pings/get_ping_histogram'; import { createGetMonitorDurationRoute } from './monitors/monitors_durations'; import { createGetIndexPatternRoute, createGetIndexStatusRoute } from './index_state'; - export * from './types'; export { createRouteWithAuth } from './create_route_with_auth'; export { uptimeRouteWrapper } from './uptime_route_wrapper'; diff --git a/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts deleted file mode 100644 index c76892103da6b..0000000000000 --- a/x-pack/plugins/uptime/server/rest_api/pings/get_all.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { schema } from '@kbn/config-schema'; -import { UMServerLibs } from '../../lib/lib'; -import { UMRestApiRouteFactory } from '../types'; -import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants/rest_api'; - -export const createGetAllRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({ - method: 'GET', - path: API_URLS.PINGS, - validate: { - query: schema.object({ - dateRangeStart: schema.string(), - dateRangeEnd: schema.string(), - location: schema.maybe(schema.string()), - monitorId: schema.maybe(schema.string()), - size: schema.maybe(schema.number()), - sort: schema.maybe(schema.string()), - status: schema.maybe(schema.string()), - }), - }, - handler: async ({ callES, dynamicSettings }, _context, request, response): Promise<any> => { - const { dateRangeStart, dateRangeEnd, location, monitorId, size, sort, status } = request.query; - - const result = await libs.requests.getPings({ - callES, - dynamicSettings, - dateRangeStart, - dateRangeEnd, - monitorId, - status, - sort, - size, - location, - }); - - return response.ok({ - body: { - ...result, - }, - }); - }, -}); diff --git a/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts index cde9a8c4e47ea..80a887a7f64a9 100644 --- a/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts +++ b/x-pack/plugins/uptime/server/rest_api/pings/get_pings.ts @@ -5,37 +5,41 @@ */ import { schema } from '@kbn/config-schema'; +import { isLeft } from 'fp-ts/lib/Either'; +import { PathReporter } from 'io-ts/lib/PathReporter'; import { UMServerLibs } from '../../lib/lib'; import { UMRestApiRouteFactory } from '../types'; import { API_URLS } from '../../../../../legacy/plugins/uptime/common/constants/rest_api'; +import { GetPingsParamsType } from '../../../../../legacy/plugins/uptime/common/runtime_types'; export const createGetPingsRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({ method: 'GET', path: API_URLS.PINGS, validate: { query: schema.object({ - dateRangeStart: schema.string(), - dateRangeEnd: schema.string(), + from: schema.string(), + to: schema.string(), location: schema.maybe(schema.string()), monitorId: schema.maybe(schema.string()), + index: schema.maybe(schema.number()), size: schema.maybe(schema.number()), sort: schema.maybe(schema.string()), status: schema.maybe(schema.string()), }), }, handler: async ({ callES, dynamicSettings }, _context, request, response): Promise<any> => { - const { dateRangeStart, dateRangeEnd, location, monitorId, size, sort, status } = request.query; + const { from, to, ...optional } = request.query; + const params = GetPingsParamsType.decode({ dateRange: { from, to }, ...optional }); + if (isLeft(params)) { + // eslint-disable-next-line no-console + console.error(new Error(PathReporter.report(params).join(';'))); + return response.badRequest({ body: { message: 'Received invalid request parameters.' } }); + } const result = await libs.requests.getPings({ callES, dynamicSettings, - dateRangeStart, - dateRangeEnd, - monitorId, - status, - sort, - size, - location, + ...params.right, }); return response.ok({ diff --git a/x-pack/plugins/uptime/server/rest_api/pings/index.ts b/x-pack/plugins/uptime/server/rest_api/pings/index.ts index abb7da26f994f..a10ab435e4b0a 100644 --- a/x-pack/plugins/uptime/server/rest_api/pings/index.ts +++ b/x-pack/plugins/uptime/server/rest_api/pings/index.ts @@ -5,3 +5,4 @@ */ export { createGetPingsRoute } from './get_pings'; +export { createGetPingHistogramRoute } from './get_ping_histogram'; diff --git a/x-pack/test/api_integration/apis/uptime/feature_controls.ts b/x-pack/test/api_integration/apis/uptime/feature_controls.ts index 4c3b7f97c9544..8b82735fc38b0 100644 --- a/x-pack/test/api_integration/apis/uptime/feature_controls.ts +++ b/x-pack/test/api_integration/apis/uptime/feature_controls.ts @@ -40,7 +40,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext) const executePingsRequest = async (username: string, password: string, spaceId?: string) => { const basePath = spaceId ? `/s/${spaceId}` : ''; - const url = `${basePath}${API_URLS.PINGS}?sort=desc&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}`; + const url = `${basePath}${API_URLS.PINGS}?sort=desc&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}`; return await supertest .get(url) .auth(username, password) diff --git a/x-pack/test/api_integration/apis/uptime/get_all_pings.ts b/x-pack/test/api_integration/apis/uptime/get_all_pings.ts index 666986e7008b7..0b3f5faccb044 100644 --- a/x-pack/test/api_integration/apis/uptime/get_all_pings.ts +++ b/x-pack/test/api_integration/apis/uptime/get_all_pings.ts @@ -22,7 +22,7 @@ export default function({ getService }: FtrProviderContext) { it('should get all pings stored in index', async () => { const { body: apiResponse } = await supertest .get( - `/api/uptime/pings?sort=desc&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}` + `/api/uptime/pings?sort=desc&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}` ) .expect(200); @@ -33,21 +33,19 @@ export default function({ getService }: FtrProviderContext) { it('should sort pings according to timestamp', async () => { const { body: apiResponse } = await supertest - .get( - `/api/uptime/pings?sort=asc&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}` - ) + .get(`/api/uptime/pings?sort=asc&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}`) .expect(200); expect(apiResponse.total).to.be(2); expect(apiResponse.pings.length).to.be(2); - expect(apiResponse.pings[0].timestamp).to.be('2018-10-30T14:49:23.889Z'); - expect(apiResponse.pings[1].timestamp).to.be('2018-10-30T18:51:56.792Z'); + expect(apiResponse.pings[0]['@timestamp']).to.be('2018-10-30T14:49:23.889Z'); + expect(apiResponse.pings[1]['@timestamp']).to.be('2018-10-30T18:51:56.792Z'); }); it('should return results of n length', async () => { const { body: apiResponse } = await supertest .get( - `/api/uptime/pings?sort=desc&size=1&dateRangeStart=${PINGS_DATE_RANGE_START}&dateRangeEnd=${PINGS_DATE_RANGE_END}` + `/api/uptime/pings?sort=desc&size=1&from=${PINGS_DATE_RANGE_START}&to=${PINGS_DATE_RANGE_END}` ) .expect(200); @@ -57,10 +55,10 @@ export default function({ getService }: FtrProviderContext) { }); it('should miss pings outside of date range', async () => { - const dateRangeStart = moment('2002-01-01').valueOf(); - const dateRangeEnd = moment('2002-01-02').valueOf(); + const from = moment('2002-01-01').valueOf(); + const to = moment('2002-01-02').valueOf(); const { body: apiResponse } = await supertest - .get(`/api/uptime/pings?dateRangeStart=${dateRangeStart}&dateRangeEnd=${dateRangeEnd}`) + .get(`/api/uptime/pings?from=${from}&to=${to}`) .expect(200); expect(apiResponse.total).to.be(0); diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json deleted file mode 100644 index 330ec83931a62..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list.json +++ /dev/null @@ -1,320 +0,0 @@ -{ - "allPings": { - "total": 2000, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:40:34.410Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 413 - }, - "id": "0074-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 441 - }, - "id": "0073-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 482 - }, - "id": "0099-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 558 - }, - "id": "0098-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 304 - }, - "id": "0075-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 487 - }, - "id": "0097-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 602 - }, - "id": "0049-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.390Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 365 - }, - "id": "0047-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.389Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 870 - }, - "id": "0077-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.387Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2808 - }, - "id": "0076-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json deleted file mode 100644 index 3a619f517626a..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_count.json +++ /dev/null @@ -1,1569 +0,0 @@ -{ - "allPings": { - "total": 2000, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:40:34.410Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 413 - }, - "id": "0074-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 441 - }, - "id": "0073-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 482 - }, - "id": "0099-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 558 - }, - "id": "0098-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.406Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 304 - }, - "id": "0075-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 487 - }, - "id": "0097-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.405Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 602 - }, - "id": "0049-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.390Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 365 - }, - "id": "0047-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.389Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 870 - }, - "id": "0077-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.387Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2808 - }, - "id": "0076-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.386Z", - "http": { - "response": { - "status_code": 400, - "body": { - "bytes": 3, - "hash": "26d228663f13a88592a12d16cf9587caab0388b262d6d9f126ed62f9333aca94", - "content": "400", - "content_bytes": 3 - } - } - }, - "error": { - "message": "400 Bad Request", - "type": "validate" - }, - "monitor": { - "duration": { - "us": 4258 - }, - "id": "0050-down", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.386Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 4784 - }, - "id": "0048-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.376Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14580 - }, - "id": "0072-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.376Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14679 - }, - "id": "0096-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15308 - }, - "id": "0092-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15183 - }, - "id": "0069-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15013 - }, - "id": "0093-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 400, - "body": { - "bytes": 3, - "hash": "26d228663f13a88592a12d16cf9587caab0388b262d6d9f126ed62f9333aca94", - "content": "400", - "content_bytes": 3 - } - } - }, - "error": { - "message": "400 Bad Request", - "type": "validate" - }, - "monitor": { - "duration": { - "us": 15117 - }, - "id": "0070-down", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14875 - }, - "id": "0071-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14801 - }, - "id": "0095-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15065 - }, - "id": "0032-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 14911 - }, - "id": "0094-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 16135 - }, - "id": "0046-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15428 - }, - "id": "0091-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15499 - }, - "id": "0067-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15464 - }, - "id": "0068-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 21736 - }, - "id": "0090-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 21874 - }, - "id": "0031-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.374Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 36584 - }, - "id": "0066-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 3148 - }, - "id": "0084-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 13442 - }, - "id": "0083-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 13666 - }, - "id": "0041-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 16290 - }, - "id": "0045-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 17255 - }, - "id": "0042-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 500, - "body": { - "bytes": 3, - "hash": "0604cd3138feed202ef293e062da2f4720f77a05d25ee036a7a01c9cfcdd1f0a", - "content": "500", - "content_bytes": 3 - } - } - }, - "error": { - "message": "500 Internal Server Error", - "type": "validate" - }, - "monitor": { - "duration": { - "us": 17146 - }, - "id": "0030-intermittent", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "down", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 17770 - }, - "id": "0063-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 18194 - }, - "id": "0061-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 17587 - }, - "id": "0065-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 22666 - }, - "id": "0062-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33311 - }, - "id": "0026-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33506 - }, - "id": "0085-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33974 - }, - "id": "0025-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33693 - }, - "id": "0088-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 33833 - }, - "id": "0089-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 34600 - }, - "id": "0087-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35573 - }, - "id": "0028-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35830 - }, - "id": "0086-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35698 - }, - "id": "0064-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35594 - }, - "id": "0029-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35652 - }, - "id": "0044-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json deleted file mode 100644 index 5826fd9f3f540..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_monitor_id.json +++ /dev/null @@ -1,475 +0,0 @@ -{ - "allPings": { - "total": 20, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:40:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 35534 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:40:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 3080 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:39:34.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 7810 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:39:04.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 1575 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:38:34.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 1787 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:38:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 654 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:37:34.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 15915 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:37:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2679 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:36:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2104 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:36:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 5759 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:35:34.373Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 7166 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:35:04.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 26830 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:34:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 993 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:34:04.381Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 3880 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:33:34.371Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 1604 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json deleted file mode 100644 index b9b8deae2e564..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/ping_list_sort.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "allPings": { - "total": 20, - "locations": [ - "mpls" - ], - "pings": [ - { - "timestamp": "2019-09-11T03:31:04.380Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 56940 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:31:34.366Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 9861 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:32:04.372Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2924 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:32:34.375Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 21665 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - }, - { - "timestamp": "2019-09-11T03:33:04.370Z", - "http": { - "response": { - "status_code": 200, - "body": { - "bytes": 3, - "hash": "27badc983df1780b60c2b3fa9d3a19a00e46aac798451f0febdca52920faaddf", - "content": null, - "content_bytes": null - } - } - }, - "error": null, - "monitor": { - "duration": { - "us": 2128 - }, - "id": "0001-up", - "ip": "127.0.0.1", - "name": "", - "scheme": null, - "status": "up", - "type": "http" - }, - "observer": { - "geo": { - "name": "mpls" - } - } - } - ] - } -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/index.ts b/x-pack/test/api_integration/apis/uptime/graphql/index.ts index 2e0b5e2eea2a5..862cce47f257a 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/index.ts +++ b/x-pack/test/api_integration/apis/uptime/graphql/index.ts @@ -13,6 +13,5 @@ export default function({ loadTestFile }: FtrProviderContext) { // verifying the pre-loaded documents are returned in a way that // matches the snapshots contained in './fixtures' loadTestFile(require.resolve('./monitor_states')); - loadTestFile(require.resolve('./ping_list')); }); } diff --git a/x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts b/x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts deleted file mode 100644 index c84b9c382acdd..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/graphql/ping_list.ts +++ /dev/null @@ -1,116 +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 { pingsQueryString } from '../../../../../legacy/plugins/uptime/public/queries'; -import { expectFixtureEql } from './helpers/expect_fixture_eql'; -import { Ping, PingResults } from '../../../../../legacy/plugins/uptime/common/graphql/types'; - -const expectPingFixtureEql = (data: { allPings: PingResults }, fixtureName: string) => { - expectFixtureEql(data, fixtureName, d => d.allPings.pings.forEach((p: Ping) => delete p.id)); -}; - -export default function({ getService }: any) { - describe('pingList query', () => { - before('load heartbeat data', () => getService('esArchiver').load('uptime/full_heartbeat')); - after('unload heartbeat index', () => getService('esArchiver').unload('uptime/full_heartbeat')); - - const supertest = getService('supertest'); - - it('returns a list of pings for the given date range and default size', async () => { - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - const { - allPings: { pings }, - } = data; - expect(pings).length(10); - - expectPingFixtureEql(data, 'ping_list'); - }); - - it('returns a list of pings for the date range and given size', async () => { - const SIZE = 50; - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - size: SIZE, - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - const { - allPings: { pings }, - } = data; - expect(pings).length(SIZE); - expectPingFixtureEql(data, 'ping_list_count'); - }); - - it('returns a list of pings for a monitor ID', async () => { - const SIZE = 15; - const MONITOR_ID = '0001-up'; - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - monitorId: MONITOR_ID, - size: SIZE, - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - expectPingFixtureEql(data, 'ping_list_monitor_id'); - }); - - it('returns a list of pings sorted ascending', async () => { - const SIZE = 5; - const MONITOR_ID = '0001-up'; - const getPingsQuery = { - operationName: 'PingList', - query: pingsQueryString, - variables: { - dateRangeStart: '2019-01-28T17:40:08.078Z', - dateRangeEnd: '2025-01-28T19:00:16.078Z', - monitorId: MONITOR_ID, - size: SIZE, - sort: 'asc', - }, - }; - const { - body: { data }, - } = await supertest - .post('/api/uptime/graphql') - .set('kbn-xsrf', 'foo') - .send({ ...getPingsQuery }); - - expectPingFixtureEql(data, 'ping_list_sort'); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/uptime/index.ts b/x-pack/test/api_integration/apis/uptime/index.ts index a21db08d58c4d..8def64b71a110 100644 --- a/x-pack/test/api_integration/apis/uptime/index.ts +++ b/x-pack/test/api_integration/apis/uptime/index.ts @@ -10,11 +10,12 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { const es = getService('legacyEs'); describe('uptime', () => { - before(() => - es.indices.delete({ - index: 'heartbeat*', - ignore: [404], - }) + before( + async () => + await es.indices.delete({ + index: 'heartbeat*', + ignore: [404], + }) ); loadTestFile(require.resolve('./feature_controls')); diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json index 2e5854f4d9866..6a832ad8536f7 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/monitor_latest_status.json @@ -1,16 +1,11 @@ { - "timestamp": "2019-09-11T03:40:34.371Z", "observer": { - "geo": { - "name": "mpls", - "location": "37.926868, -78.024902" - }, + "geo": { "name": "mpls", "location": "37.926868, -78.024902" }, "hostname": "avc-x1x" }, + "@timestamp": "2019-09-11T03:40:34.371Z", "monitor": { - "duration": { - "us": 24627 - }, + "duration": { "us": 24627 }, "ip": "127.0.0.1", "name": "", "check_group": "d76f0762-d445-11e9-88e3-3e80641b9c71", @@ -25,5 +20,7 @@ "domain": "localhost", "query": "r=200x1", "full": "http://localhost:5678/pattern?r=200x1" - } + }, + "docId": "h5toHm0B0I9WX_CznN_V", + "timestamp": "2019-09-11T03:40:34.371Z" } diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts index 9b0cd61c22462..3f8df81856f5c 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/index.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts @@ -45,10 +45,11 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./telemetry_collectors')); }); describe('with real-world data', () => { - before('load heartbeat data', async () => await esArchiver.load('uptime/full_heartbeat')); - after('unload', async () => await esArchiver.unload('uptime/full_heartbeat')); + beforeEach('load heartbeat data', async () => await esArchiver.load('uptime/full_heartbeat')); + afterEach('unload', async () => await esArchiver.unload('uptime/full_heartbeat')); loadTestFile(require.resolve('./monitor_latest_status')); loadTestFile(require.resolve('./ping_histogram')); + loadTestFile(require.resolve('./ping_list')); loadTestFile(require.resolve('./monitor_duration')); loadTestFile(require.resolve('./doc_count')); }); diff --git a/x-pack/test/api_integration/apis/uptime/rest/ping_list.ts b/x-pack/test/api_integration/apis/uptime/rest/ping_list.ts new file mode 100644 index 0000000000000..a261763d5991f --- /dev/null +++ b/x-pack/test/api_integration/apis/uptime/rest/ping_list.ts @@ -0,0 +1,178 @@ +/* + * 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 { isLeft } from 'fp-ts/lib/Either'; +import { PathReporter } from 'io-ts/lib/PathReporter'; +import { PingsResponseType } from '../../../../../legacy/plugins/uptime/common/runtime_types'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +function decodePingsResponseData(response: any) { + const decoded = PingsResponseType.decode(response); + if (isLeft(decoded)) { + throw Error(JSON.stringify(PathReporter.report(decoded), null, 2)); + } + return decoded.right; +} + +export default function({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + describe('pingList query', () => { + before('load heartbeat data', () => getService('esArchiver').load('uptime/full_heartbeat')); + after('unload heartbeat index', () => getService('esArchiver').unload('uptime/full_heartbeat')); + + it('returns a list of pings for the given date range and default size', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + + const apiResponse = await supertest.get(`/api/uptime/pings?from=${from}&to=${to}&size=10`); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(2000); + expect(locations).to.eql(['mpls']); + expect(pings).length(10); + expect(pings.map(({ monitor: { id } }) => id)).to.eql([ + '0074-up', + '0073-up', + '0099-up', + '0098-up', + '0075-intermittent', + '0097-up', + '0049-up', + '0047-up', + '0077-up', + '0076-up', + ]); + }); + + it('returns a list of pings for the date range and given size', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + const size = 50; + + const apiResponse = await supertest.get( + `/api/uptime/pings?from=${from}&to=${to}&size=${size}` + ); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(2000); + expect(locations).to.eql(['mpls']); + expect(pings).length(50); + expect(pings.map(({ monitor: { id } }) => id)).to.eql([ + '0074-up', + '0073-up', + '0099-up', + '0098-up', + '0075-intermittent', + '0097-up', + '0049-up', + '0047-up', + '0077-up', + '0076-up', + '0050-down', + '0048-up', + '0072-up', + '0096-up', + '0092-up', + '0069-up', + '0093-up', + '0070-down', + '0071-up', + '0095-up', + '0032-up', + '0094-up', + '0046-up', + '0091-up', + '0067-up', + '0068-up', + '0090-intermittent', + '0031-up', + '0066-up', + '0084-up', + '0083-up', + '0041-up', + '0045-intermittent', + '0042-up', + '0030-intermittent', + '0063-up', + '0061-up', + '0065-up', + '0062-up', + '0026-up', + '0085-up', + '0025-up', + '0088-up', + '0089-up', + '0087-up', + '0028-up', + '0086-up', + '0064-up', + '0029-up', + '0044-up', + ]); + }); + + it('returns a list of pings for a monitor ID', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + const monitorId = '0001-up'; + const size = 15; + + const apiResponse = await supertest.get( + `/api/uptime/pings?from=${from}&to=${to}&monitorId=${monitorId}&size=${size}` + ); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(20); + expect(locations).to.eql(['mpls']); + pings.forEach(({ monitor: { id } }) => expect(id).to.eql('0001-up')); + expect(pings.map(({ timestamp }) => timestamp)).to.eql([ + '2019-09-11T03:40:34.371Z', + '2019-09-11T03:40:04.370Z', + '2019-09-11T03:39:34.370Z', + '2019-09-11T03:39:04.371Z', + '2019-09-11T03:38:34.370Z', + '2019-09-11T03:38:04.370Z', + '2019-09-11T03:37:34.370Z', + '2019-09-11T03:37:04.370Z', + '2019-09-11T03:36:34.371Z', + '2019-09-11T03:36:04.370Z', + '2019-09-11T03:35:34.373Z', + '2019-09-11T03:35:04.371Z', + '2019-09-11T03:34:34.371Z', + '2019-09-11T03:34:04.381Z', + '2019-09-11T03:33:34.371Z', + ]); + }); + + it('returns a list of pings sorted ascending', async () => { + const from = '2019-01-28T17:40:08.078Z'; + const to = '2025-01-28T19:00:16.078Z'; + const monitorId = '0001-up'; + const size = 5; + const sort = 'asc'; + + const apiResponse = await supertest.get( + `/api/uptime/pings?from=${from}&to=${to}&monitorId=${monitorId}&size=${size}&sort=${sort}` + ); + + const { total, locations, pings } = decodePingsResponseData(apiResponse.body); + + expect(total).to.be(20); + expect(locations).to.eql(['mpls']); + expect(pings.map(({ timestamp }) => timestamp)).to.eql([ + '2019-09-11T03:31:04.380Z', + '2019-09-11T03:31:34.366Z', + '2019-09-11T03:32:04.372Z', + '2019-09-11T03:32:34.375Z', + '2019-09-11T03:33:04.370Z', + ]); + }); + }); +} diff --git a/x-pack/test/functional/apps/uptime/monitor.ts b/x-pack/test/functional/apps/uptime/monitor.ts index 90ad1836c69d3..388d660f21eb3 100644 --- a/x-pack/test/functional/apps/uptime/monitor.ts +++ b/x-pack/test/functional/apps/uptime/monitor.ts @@ -23,8 +23,33 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await uptimeService.navigation.goToUptime(); }); - it('loads and displays uptime data based on date range', async () => { - await uptime.loadDataAndGoToMonitorPage(dateStart, dateEnd, monitorId); + after(async () => { + await esArchiver.unload(archive); + }); + + describe('navigation to monitor page', () => { + before(async () => { + await uptime.loadDataAndGoToMonitorPage(dateStart, dateEnd, monitorId); + }); + + it('displays ping data as expected', async () => { + await uptime.checkPingListInteractions( + [ + 'XZtoHm0B0I9WX_CznN-6', + '7ZtoHm0B0I9WX_CzJ96M', + 'pptnHm0B0I9WX_Czst5X', + 'I5tnHm0B0I9WX_CzPd46', + 'y5tmHm0B0I9WX_Czx93x', + 'XZtmHm0B0I9WX_CzUt3H', + '-JtlHm0B0I9WX_Cz3dyX', + 'k5tlHm0B0I9WX_CzaNxm', + 'NZtkHm0B0I9WX_Cz89w9', + 'zJtkHm0B0I9WX_CzftsN', + ], + 'mpls', + 'up' + ); + }); }); }); }; diff --git a/x-pack/test/functional/page_objects/uptime_page.ts b/x-pack/test/functional/page_objects/uptime_page.ts index 7157bbfb3811b..0ebcb5c87deee 100644 --- a/x-pack/test/functional/page_objects/uptime_page.ts +++ b/x-pack/test/functional/page_objects/uptime_page.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../ftr_provider_context'; export function UptimePageProvider({ getPageObjects, getService }: FtrProviderContext) { const pageObjects = getPageObjects(['common', 'timePicker']); - const { common: commonService, navigation, alerts } = getService('uptime'); + const { alerts, common: commonService, monitor, navigation } = getService('uptime'); const retry = getService('retry'); return new (class UptimePage { @@ -137,6 +137,20 @@ export function UptimePageProvider({ getPageObjects, getService }: FtrProviderCo return commonService.clickPageSizeSelectPopoverItem(size); } + public async checkPingListInteractions( + timestamps: string[], + location?: string, + status?: string + ): Promise<void> { + if (location) { + await monitor.setPingListLocation(location); + } + if (status) { + await monitor.setPingListStatus(status); + } + return monitor.checkForPingListTimestamps(timestamps); + } + public async resetFilters() { await this.inputFilterQuery(''); await commonService.resetStatusFilter(); diff --git a/x-pack/test/functional/services/uptime/monitor.ts b/x-pack/test/functional/services/uptime/monitor.ts index 3bdec4b6749d4..a3e3d953e2eb7 100644 --- a/x-pack/test/functional/services/uptime/monitor.ts +++ b/x-pack/test/functional/services/uptime/monitor.ts @@ -27,5 +27,22 @@ export function UptimeMonitorProvider({ getService }: FtrProviderContext) { await find.descendantExistsByCssSelector('canvas.mapboxgl-canvas', mapPanel); }); }, + async setPingListLocation(location: string) { + await testSubjects.click('xpack.uptime.pingList.locationSelect', 5000); + return testSubjects.click(`xpack.uptime.pingList.locationOptions.${location}`, 5000); + }, + async setPingListStatus(status: string) { + await testSubjects.click('xpack.uptime.pingList.statusSelect', 5000); + return testSubjects.click(`xpack.uptime.pingList.statusOptions.${status}`, 5000); + }, + async checkForPingListTimestamps(timestamps: string[]): Promise<void> { + return retry.tryForTime(10000, async () => { + await Promise.all( + timestamps.map(timestamp => + testSubjects.existOrFail(`xpack.uptime.pingList.ping-${timestamp}`) + ) + ); + }); + }, }; } From b38c98a730f4962910e29acf7d8847346ab67e6d Mon Sep 17 00:00:00 2001 From: Alison Goryachev <alison.goryachev@elastic.co> Date: Tue, 14 Apr 2020 09:13:20 -0400 Subject: [PATCH 095/121] =?UTF-8?q?[Remote=20clusters]=20guard=20against?= =?UTF-8?q?=20usageCollection=20plugin=20if=20unav=E2=80=A6=20(#63284)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../public/application/services/ui_metric.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts b/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts index 91354155cacb0..4fc3c438e76d6 100644 --- a/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts +++ b/x-pack/plugins/remote_clusters/public/application/services/ui_metric.ts @@ -3,17 +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 { UiStatsMetricType, METRIC_TYPE } from '@kbn/analytics'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; -import { UiStatsMetricType } from '@kbn/analytics'; import { UIM_APP_NAME } from '../constants'; -export let trackUiMetric: (metricType: UiStatsMetricType, eventName: string) => void; -export let METRIC_TYPE: UsageCollectionSetup['METRIC_TYPE']; +export { METRIC_TYPE }; + +export let usageCollection: UsageCollectionSetup | undefined; + +export function init(_usageCollection: UsageCollectionSetup): void { + usageCollection = _usageCollection; +} -export function init(usageCollection: UsageCollectionSetup): void { - trackUiMetric = usageCollection.reportUiStats.bind(usageCollection, UIM_APP_NAME); - METRIC_TYPE = usageCollection.METRIC_TYPE; +export function trackUiMetric(metricType: UiStatsMetricType, name: string) { + if (!usageCollection) { + return; + } + const { reportUiStats } = usageCollection; + reportUiStats(UIM_APP_NAME, metricType, name); } /** From 11e2e0839627dcd00da39165537fc13bc6b46a39 Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Tue, 14 Apr 2020 10:56:25 -0400 Subject: [PATCH 096/121] Task/linux events (#63400) * linux events for endpoint policy details, additional windows events --- .../applications/endpoint/models/policy.ts | 7 +- .../store/policy_details/index.test.ts | 22 ++++ .../store/policy_details/selectors.ts | 20 ++++ .../public/applications/endpoint/types.ts | 84 +++++++------- .../endpoint/view/policy/policy_details.tsx | 4 +- .../view/policy/policy_forms/events/index.tsx | 1 + .../view/policy/policy_forms/events/linux.tsx | 106 ++++++++++++++++++ .../policy/policy_forms/events/windows.tsx | 41 ++++++- 8 files changed, 240 insertions(+), 45 deletions(-) create mode 100644 x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts index 30f45e54c2005..5269ee72f4039 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/models/policy.ts @@ -15,8 +15,13 @@ export const generatePolicy = (): PolicyConfig => { return { windows: { events: { - process: true, + dll_and_driver_load: true, + dns: true, + file: true, network: true, + process: true, + registry: true, + security: true, }, malware: { mode: ProtectionModes.prevent, diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts index e09a62b235e35..f81852d6a074a 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/index.test.ts @@ -98,4 +98,26 @@ describe('policy details: ', () => { expect(config!.mac.events.file).toEqual(true); }); }); + + describe('when the user has enabled linux process events', () => { + beforeEach(() => { + const config = policyConfig(getState()); + if (!config) { + throw new Error(); + } + + const newPayload1 = clone(config); + newPayload1.linux.events.file = true; + + dispatch({ + type: 'userChangedPolicyConfig', + payload: { policyConfig: newPayload1 }, + }); + }); + + it('linux file events is enabled', () => { + const config = policyConfig(getState()); + expect(config!.linux.events.file).toEqual(true); + }); + }); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts index 4b4dc9d9bee43..a37a06bafcf05 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/selectors.ts @@ -119,6 +119,26 @@ export const selectedMacEvents = (state: PolicyDetailsState): number => { return 0; }; +/** Returns the total number of possible linux eventing configurations */ +export const totalLinuxEvents = (state: PolicyDetailsState): number => { + const config = policyConfig(state); + if (config) { + return Object.keys(config.linux.events).length; + } + return 0; +}; + +/** Returns the number of selected liinux eventing configurations */ +export const selectedLinuxEvents = (state: PolicyDetailsState): number => { + const config = policyConfig(state); + if (config) { + return Object.values(config.linux.events).reduce((count, event) => { + return event === true ? count + 1 : count; + }, 0); + } + return 0; +}; + /** is there an api call in flight */ export const isLoading = (state: PolicyDetailsState) => state.isLoading; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index a625c49bf7d5a..54afbf220944e 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -131,21 +131,42 @@ export interface PolicyListUrlSearchParams { * Endpoint Policy configuration */ export interface PolicyConfig { - windows: UIPolicyConfig['windows'] & { + windows: { + events: { + dll_and_driver_load: boolean; + dns: boolean; + file: boolean; + network: boolean; + process: boolean; + registry: boolean; + security: boolean; + }; + malware: MalwareFields; logging: { stdout: string; file: string; }; advanced: PolicyConfigAdvancedOptions; }; - mac: UIPolicyConfig['mac'] & { + mac: { + events: { + file: boolean; + process: boolean; + network: boolean; + }; + malware: MalwareFields; logging: { stdout: string; file: string; }; advanced: PolicyConfigAdvancedOptions; }; - linux: UIPolicyConfig['linux'] & { + linux: { + events: { + file: boolean; + process: boolean; + network: boolean; + }; logging: { stdout: string; file: string; @@ -169,38 +190,28 @@ interface PolicyConfigAdvancedOptions { } /** - * The set of Policy configuration settings that are show/edited via the UI + * Windows-specific policy configuration that is supported via the UI */ -/* eslint-disable @typescript-eslint/consistent-type-definitions */ -export type UIPolicyConfig = { - windows: { - events: { - process: boolean; - network: boolean; - }; - /** malware mode can be off, detect, prevent or prevent and notify user */ - malware: MalwareFields; - }; - mac: { - events: { - file: boolean; - process: boolean; - network: boolean; - }; - malware: MalwareFields; - }; +type WindowsPolicyConfig = Pick<PolicyConfig['windows'], 'events' | 'malware'>; - /** - * Linux-specific policy configuration that is supported via the UI - */ - linux: { - events: { - file: boolean; - process: boolean; - network: boolean; - }; - }; -}; +/** + * Mac-specific policy configuration that is supported via the UI + */ +type MacPolicyConfig = Pick<PolicyConfig['mac'], 'malware' | 'events'>; + +/** + * Linux-specific policy configuration that is supported via the UI + */ +type LinuxPolicyConfig = Pick<PolicyConfig['linux'], 'events'>; + +/** + * The set of Policy configuration settings that are show/edited via the UI + */ +export interface UIPolicyConfig { + windows: WindowsPolicyConfig; + mac: MacPolicyConfig; + linux: LinuxPolicyConfig; +} /** OS used in Policy */ export enum OS { @@ -209,13 +220,6 @@ export enum OS { linux = 'linux', } -/** Used in Policy */ -export enum EventingFields { - process = 'process', - network = 'network', - file = 'file', -} - /** * Returns the keys of an object whose values meet a criteria. * Ex) interface largeNestedObject = { diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx index 267077da6598c..076de7b57b44b 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_details.tsx @@ -34,7 +34,7 @@ import { AppAction } from '../../types'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { AgentsSummary } from './agents_summary'; import { VerticalDivider } from './vertical_divider'; -import { WindowsEvents, MacEvents } from './policy_forms/events'; +import { WindowsEvents, MacEvents, LinuxEvents } from './policy_forms/events'; import { MalwareProtections } from './policy_forms/protections/malware'; export const PolicyDetails = React.memo(() => { @@ -208,6 +208,8 @@ export const PolicyDetails = React.memo(() => { <WindowsEvents /> <EuiSpacer size="l" /> <MacEvents /> + <EuiSpacer size="l" /> + <LinuxEvents /> </PageView> </> ); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx index 44716d8183041..927456fb671d8 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/index.tsx @@ -6,3 +6,4 @@ export { WindowsEvents } from './windows'; export { MacEvents } from './mac'; +export { LinuxEvents } from './linux'; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx new file mode 100644 index 0000000000000..9d2ce03c20462 --- /dev/null +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx @@ -0,0 +1,106 @@ +/* + * 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, { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; +import { EventsCheckbox } from './checkbox'; +import { OS, UIPolicyConfig } from '../../../../types'; +import { usePolicyDetailsSelector } from '../../policy_hooks'; +import { selectedLinuxEvents, totalLinuxEvents } from '../../../../store/policy_details/selectors'; +import { ConfigForm } from '../config_form'; +import { getIn, setIn } from '../../../../models/policy_details_config'; + +export const LinuxEvents = React.memo(() => { + const selected = usePolicyDetailsSelector(selectedLinuxEvents); + const total = usePolicyDetailsSelector(totalLinuxEvents); + + const checkboxes: Array<{ + name: string; + os: 'linux'; + protectionField: keyof UIPolicyConfig['linux']['events']; + }> = useMemo( + () => [ + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.linux.events.file', { + defaultMessage: 'File', + }), + os: OS.linux, + protectionField: 'file', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.linux.events.process', { + defaultMessage: 'Process', + }), + os: OS.linux, + protectionField: 'process', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.linux.events.network', { + defaultMessage: 'Network', + }), + os: OS.linux, + protectionField: 'network', + }, + ], + [] + ); + + const renderCheckboxes = () => { + return ( + <> + <EuiTitle size="xxs"> + <h5> + <FormattedMessage + id="xpack.endpoint.policyDetailsConfig.eventingEvents" + defaultMessage="Events" + /> + </h5> + </EuiTitle> + <EuiSpacer size="s" /> + {checkboxes.map((item, index) => { + return ( + <EventsCheckbox + name={item.name} + key={index} + setter={(config, checked) => + setIn(config)(item.os)('events')(item.protectionField)(checked) + } + getter={config => getIn(config)(item.os)('events')(item.protectionField)} + /> + ); + })} + </> + ); + }; + + const collectionsEnabled = () => { + return ( + <EuiText size="s" color="subdued"> + <FormattedMessage + id="xpack.endpoint.policy.details.eventCollectionsEnabled" + defaultMessage="{selected} / {total} event collections enabled" + values={{ selected, total }} + /> + </EuiText> + ); + }; + + return ( + <ConfigForm + type={i18n.translate('xpack.endpoint.policy.details.eventCollection', { + defaultMessage: 'Event Collection', + })} + supportedOss={[ + i18n.translate('xpack.endpoint.policy.details.linux', { defaultMessage: 'Linux' }), + ]} + id="linuxEventingForm" + rightCorner={collectionsEnabled()} + children={renderCheckboxes()} + /> + ); +}); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx index 63a140912437d..da675dc1e2393 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx @@ -29,11 +29,25 @@ export const WindowsEvents = React.memo(() => { }> = useMemo( () => [ { - name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.process', { - defaultMessage: 'Process', + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.dllDriverLoad', { + defaultMessage: 'DLL and Driver Load', }), os: OS.windows, - protectionField: 'process', + protectionField: 'dll_and_driver_load', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.dns', { + defaultMessage: 'DNS', + }), + os: OS.windows, + protectionField: 'dns', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.file', { + defaultMessage: 'File', + }), + os: OS.windows, + protectionField: 'file', }, { name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.network', { @@ -42,6 +56,27 @@ export const WindowsEvents = React.memo(() => { os: OS.windows, protectionField: 'network', }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.process', { + defaultMessage: 'Process', + }), + os: OS.windows, + protectionField: 'process', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.registry', { + defaultMessage: 'Registry', + }), + os: OS.windows, + protectionField: 'registry', + }, + { + name: i18n.translate('xpack.endpoint.policyDetailsConfig.windows.events.security', { + defaultMessage: 'Security', + }), + os: OS.windows, + protectionField: 'security', + }, ], [] ); From 48d528ff2ea65405456051d8067e3b265e915379 Mon Sep 17 00:00:00 2001 From: Wylie Conlon <william.conlon@elastic.co> Date: Tue, 14 Apr 2020 10:59:01 -0400 Subject: [PATCH 097/121] [Lens] Fix bug where suggestions didn't use filters (#63293) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../editor_frame/suggestion_panel.test.tsx | 16 ++++++++++++++-- .../editor_frame/suggestion_panel.tsx | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx index b146f2467c46c..0e32f1f053b9d 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx @@ -16,6 +16,7 @@ import { } from '../mocks'; import { act } from 'react-dom/test-utils'; import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; +import { esFilters, IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public'; import { SuggestionPanel, SuggestionPanelProps } from './suggestion_panel'; import { getSuggestions, Suggestion } from './suggestion_helpers'; import { EuiIcon, EuiPanel, EuiToolTip } from '@elastic/eui'; @@ -243,14 +244,25 @@ describe('suggestion_panel', () => { (mockVisualization.toPreviewExpression as jest.Mock).mockReturnValueOnce('test | expression'); mockDatasource.toExpression.mockReturnValue('datasource_expression'); - mount(<SuggestionPanel {...defaultProps} />); + const indexPattern = ({ id: 'index1' } as unknown) as IIndexPattern; + const field = ({ name: 'myfield' } as unknown) as IFieldType; + + mount( + <SuggestionPanel + {...defaultProps} + frame={{ + ...createMockFramePublicAPI(), + filters: [esFilters.buildExistsFilter(field, indexPattern)], + }} + /> + ); expect(expressionRendererMock).toHaveBeenCalledTimes(1); const passedExpression = (expressionRendererMock as jest.Mock).mock.calls[0][0].expression; expect(passedExpression).toMatchInlineSnapshot(` "kibana - | kibana_context timeRange=\\"{\\\\\\"from\\\\\\":\\\\\\"now-7d\\\\\\",\\\\\\"to\\\\\\":\\\\\\"now\\\\\\"}\\" query=\\"{\\\\\\"query\\\\\\":\\\\\\"\\\\\\",\\\\\\"language\\\\\\":\\\\\\"lucene\\\\\\"}\\" filters=\\"[]\\" + | kibana_context timeRange=\\"{\\\\\\"from\\\\\\":\\\\\\"now-7d\\\\\\",\\\\\\"to\\\\\\":\\\\\\"now\\\\\\"}\\" query=\\"{\\\\\\"query\\\\\\":\\\\\\"\\\\\\",\\\\\\"language\\\\\\":\\\\\\"lucene\\\\\\"}\\" filters=\\"[{\\\\\\"meta\\\\\\":{\\\\\\"index\\\\\\":\\\\\\"index1\\\\\\"},\\\\\\"exists\\\\\\":{\\\\\\"field\\\\\\":\\\\\\"myfield\\\\\\"}}]\\" | lens_merge_tables layerIds=\\"first\\" tables={datasource_expression} | test | expression" diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index 93f6ea6ea67ac..76443027ab88a 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -235,6 +235,7 @@ export function SuggestionPanel({ const expressionContext = { query: frame.query, + filters: frame.filters, timeRange: { from: frame.dateRange.fromDate, to: frame.dateRange.toDate, From 8489efc034dddfae18913830f50091eb603100ff Mon Sep 17 00:00:00 2001 From: Wylie Conlon <william.conlon@elastic.co> Date: Tue, 14 Apr 2020 11:04:47 -0400 Subject: [PATCH 098/121] [Lens] Migration from 7.7 (#62879) * [Lens] Migration from 7.7 * Fix types * Fix types in test * Add docs * Commit forgotten file * Remove extra types Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- x-pack/plugins/lens/server/migrations.test.ts | 161 ++++++++++++++++++ x-pack/plugins/lens/server/migrations.ts | 37 ++++ x-pack/plugins/lens/server/saved_objects.ts | 2 + 3 files changed, 200 insertions(+) create mode 100644 x-pack/plugins/lens/server/migrations.test.ts create mode 100644 x-pack/plugins/lens/server/migrations.ts diff --git a/x-pack/plugins/lens/server/migrations.test.ts b/x-pack/plugins/lens/server/migrations.test.ts new file mode 100644 index 0000000000000..e80308cc9acdb --- /dev/null +++ b/x-pack/plugins/lens/server/migrations.test.ts @@ -0,0 +1,161 @@ +/* + * 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 { migrations } from './migrations'; +import { SavedObjectMigrationContext } from 'src/core/server'; + +describe('Lens migrations', () => { + describe('7.7.0 missing dimensions in XY', () => { + const context = {} as SavedObjectMigrationContext; + + const example = { + type: 'lens', + attributes: { + expression: + 'kibana\n| kibana_context query="{\\"language\\":\\"kuery\\",\\"query\\":\\"\\"}" \n| lens_merge_tables layerIds="c61a8afb-a185-4fae-a064-fb3846f6c451" \n tables={esaggs index="logstash-*" metricsAtAllLevels=false partialRows=false includeFormatHints=true aggConfigs="[{\\"id\\":\\"2cd09808-3915-49f4-b3b0-82767eba23f7\\",\\"enabled\\":true,\\"type\\":\\"max\\",\\"schema\\":\\"metric\\",\\"params\\":{\\"field\\":\\"bytes\\"}}]" | lens_rename_columns idMap="{\\"col-0-2cd09808-3915-49f4-b3b0-82767eba23f7\\":\\"2cd09808-3915-49f4-b3b0-82767eba23f7\\"}"}\n| lens_metric_chart title="Maximum of bytes" accessor="2cd09808-3915-49f4-b3b0-82767eba23f7"', + state: { + datasourceMetaData: { + filterableIndexPatterns: [ + { + id: 'logstash-*', + title: 'logstash-*', + }, + ], + }, + datasourceStates: { + indexpattern: { + currentIndexPatternId: 'logstash-*', + layers: { + 'c61a8afb-a185-4fae-a064-fb3846f6c451': { + columnOrder: ['2cd09808-3915-49f4-b3b0-82767eba23f7'], + columns: { + '2cd09808-3915-49f4-b3b0-82767eba23f7': { + dataType: 'number', + isBucketed: false, + label: 'Maximum of bytes', + operationType: 'max', + scale: 'ratio', + sourceField: 'bytes', + }, + 'd3e62a7a-c259-4fff-a2fc-eebf20b7008a': { + dataType: 'number', + isBucketed: false, + label: 'Minimum of bytes', + operationType: 'min', + scale: 'ratio', + sourceField: 'bytes', + }, + 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8': { + dataType: 'date', + isBucketed: true, + label: 'Date Histogram of @timestamp', + operationType: 'date_histogram', + params: { + interval: 'auto', + }, + scale: 'interval', + sourceField: '@timestamp', + }, + }, + indexPatternId: 'logstash-*', + }, + }, + }, + }, + filters: [], + query: { + language: 'kuery', + query: '', + }, + visualization: { + accessor: '2cd09808-3915-49f4-b3b0-82767eba23f7', + isHorizontal: false, + layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451', + layers: [ + { + accessors: [ + 'd3e62a7a-c259-4fff-a2fc-eebf20b7008a', + '26ef70a9-c837-444c-886e-6bd905ee7335', + ], + layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451', + seriesType: 'area', + splitAccessor: '54cd64ed-2a44-4591-af84-b2624504569a', + xAccessor: 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8', + }, + ], + legend: { + isVisible: true, + position: 'right', + }, + preferredSeriesType: 'area', + }, + }, + title: 'Artistpreviouslyknownaslens', + visualizationType: 'lnsXY', + }, + }; + + it('should not change anything by XY visualizations', () => { + const target = { + ...example, + attributes: { + ...example.attributes, + visualizationType: 'lnsMetric', + }, + }; + const result = migrations['7.7.0'](target, context); + expect(result).toEqual(target); + }); + + it('should handle missing layers', () => { + const result = migrations['7.7.0']( + { + ...example, + attributes: { + ...example.attributes, + state: { + ...example.attributes.state, + datasourceStates: { + indexpattern: { + layers: [], + }, + }, + }, + }, + }, + context + ); + + expect(result.attributes.state.visualization.layers).toEqual([ + { + layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451', + seriesType: 'area', + // Removed split accessor + splitAccessor: undefined, + xAccessor: undefined, + // Removed a yAcccessor + accessors: [], + }, + ]); + }); + + it('should remove only missing accessors', () => { + const result = migrations['7.7.0'](example, context); + + expect(result.attributes.state.visualization.layers).toEqual([ + { + layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451', + seriesType: 'area', + xAccessor: 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8', + // Removed split accessor + splitAccessor: undefined, + // Removed a yAcccessor + accessors: ['d3e62a7a-c259-4fff-a2fc-eebf20b7008a'], + }, + ]); + }); + }); +}); diff --git a/x-pack/plugins/lens/server/migrations.ts b/x-pack/plugins/lens/server/migrations.ts new file mode 100644 index 0000000000000..3d238723b7438 --- /dev/null +++ b/x-pack/plugins/lens/server/migrations.ts @@ -0,0 +1,37 @@ +/* + * 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 { cloneDeep } from 'lodash'; +import { SavedObjectMigrationFn } from 'src/core/server'; + +interface XYLayerPre77 { + layerId: string; + xAccessor: string; + splitAccessor: string; + accessors: string[]; +} + +export const migrations: Record<string, SavedObjectMigrationFn> = { + '7.7.0': doc => { + const newDoc = cloneDeep(doc); + if (newDoc.attributes?.visualizationType === 'lnsXY') { + const datasourceState = newDoc.attributes.state?.datasourceStates?.indexpattern; + const datasourceLayers = datasourceState?.layers ?? {}; + const xyState = newDoc.attributes.state?.visualization; + newDoc.attributes.state.visualization.layers = xyState.layers.map((layer: XYLayerPre77) => { + const layerId = layer.layerId; + const datasource = datasourceLayers[layerId]; + return { + ...layer, + xAccessor: datasource?.columns[layer.xAccessor] ? layer.xAccessor : undefined, + splitAccessor: datasource?.columns[layer.splitAccessor] ? layer.splitAccessor : undefined, + accessors: layer.accessors.filter(accessor => !!datasource?.columns[accessor]), + }; + }) as typeof xyState.layers; + } + return newDoc; + }, +}; diff --git a/x-pack/plugins/lens/server/saved_objects.ts b/x-pack/plugins/lens/server/saved_objects.ts index 42dc750878f45..b2eb325c09266 100644 --- a/x-pack/plugins/lens/server/saved_objects.ts +++ b/x-pack/plugins/lens/server/saved_objects.ts @@ -6,6 +6,7 @@ import { CoreSetup } from 'kibana/server'; import { getEditPath } from '../common'; +import { migrations } from './migrations'; export function setupSavedObjects(core: CoreSetup) { core.savedObjects.registerType({ @@ -22,6 +23,7 @@ export function setupSavedObjects(core: CoreSetup) { uiCapabilitiesPath: 'visualize.show', }), }, + migrations, mappings: { properties: { title: { From 4ce2412316624184cb1a3dde3b9e724550fe7659 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa <Uladzislau_Lasitsa@epam.com> Date: Tue, 14 Apr 2020 18:45:21 +0300 Subject: [PATCH 099/121] Clicking cancel in saved query save modal doesn't close it (#62774) * use validation by clicking on save, added autotrim * Fixes form errors. * Fixed comments Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../ui/saved_query_form/save_query_form.tsx | 99 +++++++++---------- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 3 files changed, 48 insertions(+), 55 deletions(-) diff --git a/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx b/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx index 36dcd4a00c05e..5550ea16c22df 100644 --- a/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx +++ b/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useCallback } from 'react'; import { EuiButtonEmpty, EuiOverlayMask, @@ -63,6 +63,7 @@ export function SaveQueryForm({ showTimeFilterOption = true, }: Props) { const [title, setTitle] = useState(savedQuery ? savedQuery.title : ''); + const [enabledSaveButton, setEnabledSaveButton] = useState(Boolean(savedQuery)); const [description, setDescription] = useState(savedQuery ? savedQuery.description : ''); const [savedQueries, setSavedQueries] = useState<SavedQuery[]>([]); const [shouldIncludeFilters, setShouldIncludeFilters] = useState( @@ -76,49 +77,31 @@ export function SaveQueryForm({ ); const [formErrors, setFormErrors] = useState<string[]>([]); - useEffect(() => { - const fetchQueries = async () => { - const allSavedQueries = await savedQueryService.getAllSavedQueries(); - const sortedAllSavedQueries = sortBy(allSavedQueries, 'attributes.title') as SavedQuery[]; - setSavedQueries(sortedAllSavedQueries); - }; - fetchQueries(); - }, [savedQueryService]); - - const savedQueryDescriptionText = i18n.translate( - 'data.search.searchBar.savedQueryDescriptionText', - { - defaultMessage: 'Save query text and filters that you want to use again.', - } - ); - const titleConflictErrorText = i18n.translate( 'data.search.searchBar.savedQueryForm.titleConflictText', { defaultMessage: 'Name conflicts with an existing saved query', } ); - const titleMissingErrorText = i18n.translate( - 'data.search.searchBar.savedQueryForm.titleMissingText', - { - defaultMessage: 'Name is required', - } - ); - const whitespaceErrorText = i18n.translate( - 'data.search.searchBar.savedQueryForm.whitespaceErrorText', + + const savedQueryDescriptionText = i18n.translate( + 'data.search.searchBar.savedQueryDescriptionText', { - defaultMessage: 'Name cannot contain leading or trailing whitespace', + defaultMessage: 'Save query text and filters that you want to use again.', } ); - const validate = () => { + useEffect(() => { + const fetchQueries = async () => { + const allSavedQueries = await savedQueryService.getAllSavedQueries(); + const sortedAllSavedQueries = sortBy(allSavedQueries, 'attributes.title') as SavedQuery[]; + setSavedQueries(sortedAllSavedQueries); + }; + fetchQueries(); + }, [savedQueryService]); + + const validate = useCallback(() => { const errors = []; - if (!title.length) { - errors.push(titleMissingErrorText); - } - if (title.length > title.trim().length) { - errors.push(whitespaceErrorText); - } if ( !!savedQueries.find( existingSavedQuery => !savedQuery && existingSavedQuery.attributes.title === title @@ -129,14 +112,37 @@ export function SaveQueryForm({ if (!isEqual(errors, formErrors)) { setFormErrors(errors); + return false; } - }; - const hasErrors = formErrors.length > 0; + return !formErrors.length; + }, [savedQueries, savedQuery, title, titleConflictErrorText, formErrors]); + + const onClickSave = useCallback(() => { + if (validate()) { + onSave({ + title, + description, + shouldIncludeFilters, + shouldIncludeTimefilter, + }); + } + }, [validate, onSave, title, description, shouldIncludeFilters, shouldIncludeTimefilter]); + + const onInputChange = useCallback(event => { + setEnabledSaveButton(Boolean(event.target.value)); + setFormErrors([]); + setTitle(event.target.value); + }, []); + + const autoTrim = useCallback(() => { + const trimmedTitle = title.trim(); + if (title.length > trimmedTitle.length) { + setTitle(trimmedTitle); + } + }, [title]); - if (hasErrors) { - validate(); - } + const hasErrors = formErrors.length > 0; const saveQueryForm = ( <EuiForm isInvalid={hasErrors} error={formErrors} data-test-subj="saveQueryForm"> @@ -157,12 +163,10 @@ export function SaveQueryForm({ disabled={!!savedQuery} value={title} name="title" - onChange={event => { - setTitle(event.target.value); - }} + onChange={onInputChange} data-test-subj="saveQueryFormTitle" isInvalid={hasErrors} - onBlur={validate} + onBlur={autoTrim} /> </EuiFormRow> @@ -235,17 +239,10 @@ export function SaveQueryForm({ </EuiButtonEmpty> <EuiButton - onClick={() => - onSave({ - title, - description, - shouldIncludeFilters, - shouldIncludeTimefilter, - }) - } + onClick={onClickSave} fill data-test-subj="savedQueryFormSaveButton" - disabled={hasErrors} + disabled={hasErrors || !enabledSaveButton} > {i18n.translate('data.search.searchBar.savedQueryFormSaveButtonText', { defaultMessage: 'Save', diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a8574971426f5..a5d2c20447ad5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -798,8 +798,6 @@ "data.search.searchBar.savedQueryDescriptionLabelText": "説明", "data.search.searchBar.savedQueryDescriptionText": "再度使用するクエリテキストとフィルターを保存します。", "data.search.searchBar.savedQueryForm.titleConflictText": "タイトルが既に保存されているクエリに使用されています", - "data.search.searchBar.savedQueryForm.titleMissingText": "名前が必要です", - "data.search.searchBar.savedQueryForm.whitespaceErrorText": "タイトルの始めと終わりにはスペースを使用できません", "data.search.searchBar.savedQueryFormCancelButtonText": "キャンセル", "data.search.searchBar.savedQueryFormSaveButtonText": "保存", "data.search.searchBar.savedQueryFormTitle": "クエリを保存", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index df5cccf1a9b97..ef749e9218e11 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -799,8 +799,6 @@ "data.search.searchBar.savedQueryDescriptionLabelText": "描述", "data.search.searchBar.savedQueryDescriptionText": "保存想要再次使用的查询文本和筛选。", "data.search.searchBar.savedQueryForm.titleConflictText": "标题与现有已保存查询有冲突", - "data.search.searchBar.savedQueryForm.titleMissingText": "“名称”必填", - "data.search.searchBar.savedQueryForm.whitespaceErrorText": "标题不能包含前导或尾随空格", "data.search.searchBar.savedQueryFormCancelButtonText": "取消", "data.search.searchBar.savedQueryFormSaveButtonText": "保存", "data.search.searchBar.savedQueryFormTitle": "保存查询", From d015c24509d0ed8a2bce5802fea036ae7c910a38 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov <restrry@gmail.com> Date: Tue, 14 Apr 2020 17:45:40 +0200 Subject: [PATCH 100/121] [NP] Migrate logstash server side code to NP (#63135) * convert api_integration test into TS * create logstash NP plugin and move models * move common/constants to NP * type fetch all from scroll * move route declaration to NP * add licence checker wrapper * register logstash route handlers in NP * track logstash NP i18n * address shaunak comment * fix validation * udpdate security tests since for new mock defaults * address Pierres comments * rename upgrade file route --- x-pack/.i18nrc.json | 2 +- x-pack/legacy/plugins/logstash/index.js | 10 +-- .../pipeline_editor/pipeline_editor.js | 2 +- .../public/lib/register_home_feature.ts | 2 +- .../pipeline_list_item/pipeline_list_item.js | 2 +- .../services/cluster/cluster_service.js | 2 +- .../license/logstash_license_service.js | 2 +- .../services/monitoring/monitoring_service.js | 2 +- .../services/pipeline/pipeline_service.js | 2 +- .../services/pipelines/pipelines_service.js | 2 +- .../services/upgrade/upgrade_service.js | 2 +- .../call_with_request_factory.js | 18 ---- .../__tests__/wrap_custom_error.js | 21 ----- .../error_wrappers/__tests__/wrap_es_error.js | 42 --------- .../__tests__/wrap_unknown_error.js | 19 ---- .../lib/error_wrappers/wrap_custom_error.js | 18 ---- .../lib/error_wrappers/wrap_es_error.js | 27 ------ .../lib/error_wrappers/wrap_unknown_error.js | 17 ---- .../__tests__/fetch_all_from_scroll.js | 88 ------------------- .../fetch_all_from_scroll.js | 28 ------ .../__tests__/license_pre_routing_factory.js | 69 --------------- .../license_pre_routing_factory.js | 27 ------ .../register_license_checker.js | 2 +- .../api/cluster/register_cluster_routes.js | 11 --- .../routes/api/cluster/register_load_route.js | 40 --------- .../api/pipeline/register_delete_route.js | 38 -------- .../api/pipeline/register_load_route.js | 47 ---------- .../api/pipeline/register_pipeline_routes.js | 15 ---- .../api/pipeline/register_save_route.js | 48 ---------- .../server/routes/api/pipelines/index.js | 7 -- .../api/pipelines/register_delete_route.js | 51 ----------- .../api/pipelines/register_list_route.js | 52 ----------- .../pipelines/register_pipelines_routes.js | 13 --- .../server/routes/api/upgrade/index.js | 7 -- .../api/upgrade/register_execute_route.js | 56 ------------ .../api/upgrade/register_upgrade_routes.js | 11 --- .../licensing/common/licensing.mock.ts | 1 + x-pack/plugins/licensing/server/index.ts | 1 + .../wrap_route_with_license_check.test.ts | 71 +++++++++++++++ .../server/wrap_route_with_license_check.ts | 40 +++++++++ .../common/constants/es_scroll_settings.ts} | 0 .../logstash/common/constants/index.ts} | 0 .../logstash/common/constants/index_names.ts} | 0 .../logstash/common/constants/monitoring.ts} | 0 .../logstash/common/constants/pagination.ts} | 0 .../logstash/common/constants/pipeline.ts} | 0 .../logstash/common/constants/plugin.ts} | 0 .../logstash/common/constants/routes.ts} | 0 .../logstash/common/constants/tooltips.ts} | 0 x-pack/plugins/logstash/kibana.json | 12 +++ x-pack/plugins/logstash/server/index.ts | 16 ++++ .../lib/check_license/check_license.test.ts | 60 +++++++++++++ .../server/lib/check_license/check_license.ts | 65 ++++++++++++++ .../server/lib/check_license/index.ts} | 2 +- .../fetch_all_from_scroll.test.ts | 71 +++++++++++++++ .../fetch_all_from_scroll.ts | 34 +++++++ .../lib/fetch_all_from_scroll/index.ts} | 0 .../server/models/cluster/cluster.test.ts} | 5 +- .../server/models/cluster/cluster.ts} | 11 +-- .../logstash/server/models/cluster/index.ts} | 0 .../logstash/server/models/pipeline/index.ts} | 0 .../server/models/pipeline/pipeline.test.ts} | 21 +++-- .../server/models/pipeline/pipeline.ts} | 55 ++++++++---- .../models/pipeline_list_item/index.ts} | 0 .../pipeline_list_item.test.ts} | 16 ++-- .../pipeline_list_item/pipeline_list_item.ts} | 25 +++--- x-pack/plugins/logstash/server/plugin.ts | 51 +++++++++++ .../logstash/server/routes/cluster/index.ts} | 3 +- .../logstash/server/routes/cluster/load.ts | 34 +++++++ .../plugins/logstash/server/routes/index.ts | 28 ++++++ .../logstash/server/routes/pipeline/delete.ts | 38 ++++++++ .../logstash/server/routes/pipeline/index.ts} | 7 +- .../logstash/server/routes/pipeline/load.ts | 46 ++++++++++ .../logstash/server/routes/pipeline/save.ts | 69 +++++++++++++++ .../server/routes/pipelines/delete.ts | 54 ++++++++++++ .../server/routes/pipelines/index.ts} | 4 +- .../logstash/server/routes/pipelines/list.ts | 63 +++++++++++++ .../logstash/server/routes/upgrade/index.ts} | 2 +- .../logstash/server/routes/upgrade/upgrade.ts | 46 ++++++++++ x-pack/plugins/logstash/server/types.ts | 27 ++++++ .../common/licensing/license_service.test.ts | 16 ++-- .../logstash/cluster/{index.js => index.ts} | 3 +- .../logstash/cluster/{load.js => load.ts} | 3 +- .../apis/logstash/{index.js => index.ts} | 3 +- .../pipeline/{delete.js => delete.ts} | 3 +- .../logstash/pipeline/{index.js => index.ts} | 4 +- .../logstash/pipeline/{load.js => load.ts} | 6 +- .../logstash/pipeline/{save.js => save.ts} | 3 +- .../pipelines/{delete.js => delete.ts} | 3 +- .../logstash/pipelines/{index.js => index.ts} | 3 +- .../logstash/pipelines/{list.js => list.ts} | 5 +- 91 files changed, 959 insertions(+), 873 deletions(-) delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js create mode 100644 x-pack/plugins/licensing/server/wrap_route_with_license_check.test.ts create mode 100644 x-pack/plugins/licensing/server/wrap_route_with_license_check.ts rename x-pack/{legacy/plugins/logstash/common/constants/es_scroll_settings.js => plugins/logstash/common/constants/es_scroll_settings.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/index.js => plugins/logstash/common/constants/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/index_names.js => plugins/logstash/common/constants/index_names.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/monitoring.js => plugins/logstash/common/constants/monitoring.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/pagination.js => plugins/logstash/common/constants/pagination.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/pipeline.js => plugins/logstash/common/constants/pipeline.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/plugin.js => plugins/logstash/common/constants/plugin.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/routes.js => plugins/logstash/common/constants/routes.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/tooltips.js => plugins/logstash/common/constants/tooltips.ts} (100%) create mode 100644 x-pack/plugins/logstash/kibana.json create mode 100644 x-pack/plugins/logstash/server/index.ts create mode 100755 x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts create mode 100644 x-pack/plugins/logstash/server/lib/check_license/check_license.ts rename x-pack/{legacy/plugins/logstash/server/lib/call_with_request_factory/index.js => plugins/logstash/server/lib/check_license/index.ts} (77%) mode change 100755 => 100644 create mode 100755 x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts create mode 100755 x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts rename x-pack/{legacy/plugins/logstash/server/lib/fetch_all_from_scroll/index.js => plugins/logstash/server/lib/fetch_all_from_scroll/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js => plugins/logstash/server/models/cluster/cluster.test.ts} (81%) rename x-pack/{legacy/plugins/logstash/server/models/cluster/cluster.js => plugins/logstash/server/models/cluster/cluster.ts} (68%) rename x-pack/{legacy/plugins/logstash/server/models/cluster/index.js => plugins/logstash/server/models/cluster/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline/index.js => plugins/logstash/server/models/pipeline/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js => plugins/logstash/server/models/pipeline/pipeline.test.ts} (74%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline/pipeline.js => plugins/logstash/server/models/pipeline/pipeline.ts} (59%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline_list_item/index.js => plugins/logstash/server/models/pipeline_list_item/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js => plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts} (72%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js => plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts} (50%) create mode 100644 x-pack/plugins/logstash/server/plugin.ts rename x-pack/{legacy/plugins/logstash/server/routes/api/cluster/index.js => plugins/logstash/server/routes/cluster/index.ts} (76%) mode change 100755 => 100644 create mode 100644 x-pack/plugins/logstash/server/routes/cluster/load.ts create mode 100644 x-pack/plugins/logstash/server/routes/index.ts create mode 100644 x-pack/plugins/logstash/server/routes/pipeline/delete.ts rename x-pack/{legacy/plugins/logstash/server/lib/error_wrappers/index.js => plugins/logstash/server/routes/pipeline/index.ts} (60%) mode change 100755 => 100644 create mode 100644 x-pack/plugins/logstash/server/routes/pipeline/load.ts create mode 100644 x-pack/plugins/logstash/server/routes/pipeline/save.ts create mode 100644 x-pack/plugins/logstash/server/routes/pipelines/delete.ts rename x-pack/{legacy/plugins/logstash/server/routes/api/pipeline/index.js => plugins/logstash/server/routes/pipelines/index.ts} (68%) mode change 100755 => 100644 create mode 100644 x-pack/plugins/logstash/server/routes/pipelines/list.ts rename x-pack/{legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js => plugins/logstash/server/routes/upgrade/index.ts} (76%) mode change 100755 => 100644 create mode 100644 x-pack/plugins/logstash/server/routes/upgrade/upgrade.ts create mode 100644 x-pack/plugins/logstash/server/types.ts rename x-pack/test/api_integration/apis/logstash/cluster/{index.js => index.ts} (71%) rename x-pack/test/api_integration/apis/logstash/cluster/{load.js => load.ts} (83%) rename x-pack/test/api_integration/apis/logstash/{index.js => index.ts} (76%) rename x-pack/test/api_integration/apis/logstash/pipeline/{delete.js => delete.ts} (90%) rename x-pack/test/api_integration/apis/logstash/pipeline/{index.js => index.ts} (76%) rename x-pack/test/api_integration/apis/logstash/pipeline/{load.js => load.ts} (82%) rename x-pack/test/api_integration/apis/logstash/pipeline/{save.js => save.ts} (90%) rename x-pack/test/api_integration/apis/logstash/pipelines/{delete.js => delete.ts} (90%) rename x-pack/test/api_integration/apis/logstash/pipelines/{index.js => index.ts} (73%) rename x-pack/test/api_integration/apis/logstash/pipelines/{list.js => list.ts} (82%) diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index bbbcc062786b0..b3744f7cf93ab 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -24,7 +24,7 @@ "xpack.lens": "legacy/plugins/lens", "xpack.licenseMgmt": "plugins/license_management", "xpack.licensing": "plugins/licensing", - "xpack.logstash": "legacy/plugins/logstash", + "xpack.logstash": ["plugins/logstash", "legacy/plugins/logstash"], "xpack.main": "legacy/plugins/xpack_main", "xpack.maps": ["plugins/maps", "legacy/plugins/maps"], "xpack.ml": ["plugins/ml", "legacy/plugins/ml"], diff --git a/x-pack/legacy/plugins/logstash/index.js b/x-pack/legacy/plugins/logstash/index.js index ae8571d1c19c3..29f01032f3413 100755 --- a/x-pack/legacy/plugins/logstash/index.js +++ b/x-pack/legacy/plugins/logstash/index.js @@ -5,12 +5,8 @@ */ import { resolve } from 'path'; -import { registerLogstashPipelinesRoutes } from './server/routes/api/pipelines'; -import { registerLogstashPipelineRoutes } from './server/routes/api/pipeline'; -import { registerLogstashUpgradeRoutes } from './server/routes/api/upgrade'; -import { registerLogstashClusterRoutes } from './server/routes/api/cluster'; import { registerLicenseChecker } from './server/lib/register_license_checker'; -import { PLUGIN } from './common/constants'; +import { PLUGIN } from '../../../plugins/logstash/common/constants'; export const logstash = kibana => new kibana.Plugin({ @@ -32,9 +28,5 @@ export const logstash = kibana => }, init: server => { registerLicenseChecker(server); - registerLogstashPipelinesRoutes(server); - registerLogstashPipelineRoutes(server); - registerLogstashUpgradeRoutes(server); - registerLogstashClusterRoutes(server); }, }); diff --git a/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js b/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js index 43ca656e0827c..5e430ccbd8ceb 100644 --- a/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js +++ b/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js @@ -13,7 +13,7 @@ import 'brace/mode/plain_text'; import 'brace/theme/github'; import { isEmpty } from 'lodash'; -import { TOOLTIPS } from '../../../common/constants/tooltips'; +import { TOOLTIPS } from '../../../../../../plugins/logstash/common/constants/tooltips'; import { EuiButton, EuiButtonEmpty, diff --git a/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts b/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts index e943656120d5e..2e1ee2afb9ce6 100644 --- a/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts +++ b/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts @@ -10,7 +10,7 @@ import { npSetup } from 'ui/new_platform'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; import { FeatureCatalogueCategory } from '../../../../../../src/plugins/home/public'; // @ts-ignore -import { PLUGIN } from '../../common/constants'; +import { PLUGIN } from '../../../../../plugins/logstash/common/constants'; const { plugins: { home }, diff --git a/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js b/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js index 14900fdaa7cdc..06d01a05bac27 100755 --- a/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js +++ b/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js @@ -8,7 +8,7 @@ import { pick, capitalize } from 'lodash'; import { getSearchValue } from 'plugins/logstash/lib/get_search_value'; import { getMoment } from 'plugins/logstash/../common/lib/get_moment'; -import { PIPELINE } from '../../../common/constants'; +import { PIPELINE } from '../../../../../../plugins/logstash/common/constants'; /** * Represents the model for listing pipelines in the UI diff --git a/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js b/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js index 4bad4f48cc61d..e89c2fe7d11bf 100755 --- a/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { ROUTES } from '../../../../../../plugins/logstash/common/constants'; import { Cluster } from 'plugins/logstash/models/cluster'; export class ClusterService { diff --git a/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js b/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js index 97b336ec0728b..69cc8614a6ae2 100755 --- a/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js @@ -7,7 +7,7 @@ import React from 'react'; import { toastNotifications } from 'ui/notify'; import { MarkdownSimple } from '../../../../../../../src/plugins/kibana_react/public'; -import { PLUGIN } from '../../../common/constants'; +import { PLUGIN } from '../../../../../../plugins/logstash/common/constants'; export class LogstashLicenseService { constructor(xpackInfoService, kbnUrlService, $timeout) { diff --git a/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js b/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js index 8a267e38db738..6103e730c2171 100755 --- a/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js @@ -6,7 +6,7 @@ import moment from 'moment'; import chrome from 'ui/chrome'; -import { ROUTES, MONITORING } from '../../../common/constants'; +import { ROUTES, MONITORING } from '../../../../../../plugins/logstash/common/constants'; import { PipelineListItem } from 'plugins/logstash/models/pipeline_list_item'; export class MonitoringService { diff --git a/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js b/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js index 0696bf9d83256..b5d0dbeb852d5 100755 --- a/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { ROUTES } from '../../../../../../plugins/logstash/common/constants'; import { Pipeline } from 'plugins/logstash/models/pipeline'; export class PipelineService { diff --git a/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js b/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js index 5a43cf07eba41..d70c8be06fde4 100755 --- a/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES, MONITORING } from '../../../common/constants'; +import { ROUTES, MONITORING } from '../../../../../../plugins/logstash/common/constants'; import { PipelineListItem } from 'plugins/logstash/models/pipeline_list_item'; const RECENTLY_DELETED_PIPELINE_IDS_STORAGE_KEY = 'xpack.logstash.recentlyDeletedPipelines'; diff --git a/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js b/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js index 7870a495d07a3..2019bdc1bf1aa 100755 --- a/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { ROUTES } from '../../../../../../plugins/logstash/common/constants'; export class UpgradeService { constructor($http) { diff --git a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js b/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js deleted file mode 100755 index 8dc09d394e973..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { once } from 'lodash'; - -const callWithRequest = once(server => { - const cluster = server.plugins.elasticsearch.createCluster('logstash'); - return cluster.callWithRequest; -}); - -export const callWithRequestFactory = (server, request) => { - return (...args) => { - return callWithRequest(server)(request, ...args); - }; -}; diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js deleted file mode 100755 index f9c102be7a1ff..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ /dev/null @@ -1,21 +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 { wrapCustomError } from '../wrap_custom_error'; - -describe('wrap_custom_error', () => { - describe('#wrapCustomError', () => { - it('should return a Boom object', () => { - const originalError = new Error('I am an error'); - const statusCode = 404; - const wrappedError = wrapCustomError(originalError, statusCode); - - expect(wrappedError.isBoom).to.be(true); - expect(wrappedError.output.statusCode).to.equal(statusCode); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js deleted file mode 100755 index cab25cd0b1b10..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ /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 expect from '@kbn/expect'; -import { wrapEsError } from '../wrap_es_error'; - -describe('wrap_es_error', () => { - describe('#wrapEsError', () => { - let originalError; - beforeEach(() => { - originalError = new Error('I am an error'); - originalError.statusCode = 404; - }); - - it('should return a Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.isBoom).to.be(true); - }); - - it('should return the correct Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.output.statusCode).to.be(originalError.statusCode); - expect(wrappedError.output.payload.message).to.be(originalError.message); - }); - - it('should return invalid permissions message for 403 errors', () => { - const securityError = new Error('I am an error'); - securityError.statusCode = 403; - const wrappedError = wrapEsError(securityError); - - expect(wrappedError.isBoom).to.be(true); - expect(wrappedError.message).to.be( - 'Insufficient user permissions for managing Logstash pipelines' - ); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js deleted file mode 100755 index 85e0b2b3033ad..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { wrapUnknownError } from '../wrap_unknown_error'; - -describe('wrap_unknown_error', () => { - describe('#wrapUnknownError', () => { - it('should return a Boom object', () => { - const originalError = new Error('I am an error'); - const wrappedError = wrapUnknownError(originalError); - - expect(wrappedError.isBoom).to.be(true); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js deleted file mode 100755 index 3295113d38ee5..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; - -/** - * Wraps a custom error into a Boom error response and returns it - * - * @param err Object error - * @param statusCode Error status code - * @return Object Boom error response - */ -export function wrapCustomError(err, statusCode) { - return Boom.boomify(err, { statusCode }); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js deleted file mode 100755 index 41819179bde55..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js +++ /dev/null @@ -1,27 +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 Boom from 'boom'; -import { i18n } from '@kbn/i18n'; - -/** - * Wraps ES errors into a Boom error response and returns it - * This also handles the permissions issue gracefully - * - * @param err Object ES error - * @return Object Boom error response - */ -export function wrapEsError(err) { - const statusCode = err.statusCode; - if (statusCode === 403) { - return Boom.forbidden( - i18n.translate('xpack.logstash.insufficientUserPermissionsDescription', { - defaultMessage: 'Insufficient user permissions for managing Logstash pipelines', - }) - ); - } - return Boom.boomify(err, { statusCode: err.statusCode }); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js deleted file mode 100755 index ffd915c513362..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js +++ /dev/null @@ -1,17 +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 Boom from 'boom'; - -/** - * Wraps an unknown error into a Boom error response and returns it - * - * @param err Object Unknown error - * @return Object Boom error response - */ -export function wrapUnknownError(err) { - return Boom.boomify(err); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js b/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js deleted file mode 100755 index b1593fb1ba355..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js +++ /dev/null @@ -1,88 +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 sinon from 'sinon'; -import { fetchAllFromScroll } from '../fetch_all_from_scroll'; -import { set } from 'lodash'; - -describe('fetch_all_from_scroll', () => { - let mockResponse; - let stubCallWithRequest; - - beforeEach(() => { - mockResponse = {}; - - stubCallWithRequest = sinon.stub(); - stubCallWithRequest.onCall(0).returns( - new Promise(resolve => { - const mockInnerResponse = { - hits: { - hits: ['newhit'], - }, - _scroll_id: 'newScrollId', - }; - return resolve(mockInnerResponse); - }) - ); - - stubCallWithRequest.onCall(1).returns( - new Promise(resolve => { - const mockInnerResponse = { - hits: { - hits: [], - }, - }; - return resolve(mockInnerResponse); - }) - ); - }); - - describe('#fetchAllFromScroll', () => { - describe('when the passed-in response has no hits', () => { - beforeEach(() => { - set(mockResponse, 'hits.hits', []); - }); - - it('should return an empty array of hits', () => { - return fetchAllFromScroll(mockResponse).then(hits => { - expect(hits).to.eql([]); - }); - }); - - it('should not call callWithRequest', () => { - return fetchAllFromScroll(mockResponse, stubCallWithRequest).then(() => { - expect(stubCallWithRequest.called).to.be(false); - }); - }); - }); - - describe('when the passed-in response has some hits', () => { - beforeEach(() => { - set(mockResponse, 'hits.hits', ['foo', 'bar']); - set(mockResponse, '_scroll_id', 'originalScrollId'); - }); - - it('should return the hits from the response', () => { - return fetchAllFromScroll(mockResponse, stubCallWithRequest).then(hits => { - expect(hits).to.eql(['foo', 'bar', 'newhit']); - }); - }); - - it('should call callWithRequest', () => { - return fetchAllFromScroll(mockResponse, stubCallWithRequest).then(() => { - expect(stubCallWithRequest.calledTwice).to.be(true); - - const firstCallWithRequestCallArgs = stubCallWithRequest.args[0]; - expect(firstCallWithRequestCallArgs[1].body.scroll_id).to.eql('originalScrollId'); - - const secondCallWithRequestCallArgs = stubCallWithRequest.args[1]; - expect(secondCallWithRequestCallArgs[1].body.scroll_id).to.eql('newScrollId'); - }); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js b/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js deleted file mode 100755 index 835ef0090a5d2..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js +++ /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 { get } from 'lodash'; -import { ES_SCROLL_SETTINGS } from '../../../common/constants'; - -export function fetchAllFromScroll(response, callWithRequest, hits = []) { - const newHits = get(response, 'hits.hits', []); - const scrollId = get(response, '_scroll_id'); - - if (newHits.length > 0) { - hits.push(...newHits); - - return callWithRequest('scroll', { - body: { - scroll: ES_SCROLL_SETTINGS.KEEPALIVE, - scroll_id: scrollId, - }, - }).then(innerResponse => { - return fetchAllFromScroll(innerResponse, callWithRequest, hits); - }); - } - - return Promise.resolve(hits); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js deleted file mode 100755 index 1dc1df922acf7..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ /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 expect from '@kbn/expect'; -import { licensePreRoutingFactory } from '../license_pre_routing_factory'; - -describe('license_pre_routing_factory', () => { - describe('#logstashFeaturePreRoutingFactory', () => { - let mockServer; - let mockLicenseCheckResults; - - beforeEach(() => { - mockServer = { - plugins: { - xpack_main: { - info: { - feature: () => ({ - getLicenseCheckResults: () => mockLicenseCheckResults, - }), - }, - }, - }, - }; - }); - - it('only instantiates one instance per server', () => { - const firstInstance = licensePreRoutingFactory(mockServer); - const secondInstance = licensePreRoutingFactory(mockServer); - - expect(firstInstance).to.be(secondInstance); - }); - - describe('isAvailable is false', () => { - beforeEach(() => { - mockLicenseCheckResults = { - isAvailable: false, - }; - }); - - it('replies with 403', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - expect(() => licensePreRouting(stubRequest)).to.throwException(response => { - expect(response).to.be.an(Error); - expect(response.isBoom).to.be(true); - expect(response.output.statusCode).to.be(403); - }); - }); - }); - - describe('isAvailable is true', () => { - beforeEach(() => { - mockLicenseCheckResults = { - isAvailable: true, - }; - }); - - it('replies with nothing', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - const response = licensePreRouting(stubRequest); - expect(response).to.be(null); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js deleted file mode 100755 index 05402a56a52d8..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ /dev/null @@ -1,27 +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 { once } from 'lodash'; -import { wrapCustomError } from '../error_wrappers'; -import { PLUGIN } from '../../../common/constants'; - -export const licensePreRoutingFactory = once(server => { - const xpackMainPlugin = server.plugins.xpack_main; - - // License checking and enable/disable logic - function licensePreRouting() { - const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); - if (!licenseCheckResults.isAvailable) { - const error = new Error(licenseCheckResults.message); - const statusCode = 403; - throw wrapCustomError(error, statusCode); - } - - return null; - } - - return licensePreRouting; -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js b/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js index 8a17fb2eea497..a0d06e77b410d 100755 --- a/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js +++ b/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js @@ -6,7 +6,7 @@ import { mirrorPluginStatus } from '../../../../../server/lib/mirror_plugin_status'; import { checkLicense } from '../check_license'; -import { PLUGIN } from '../../../common/constants'; +import { PLUGIN } from '../../../../../../plugins/logstash/common/constants'; export function registerLicenseChecker(server) { const xpackMainPlugin = server.plugins.xpack_main; diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js deleted file mode 100755 index 86e18b02ddce2..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js +++ /dev/null @@ -1,11 +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 { registerLoadRoute } from './register_load_route'; - -export function registerLogstashClusterRoutes(server) { - registerLoadRoute(server); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js deleted file mode 100755 index 663b60cc8c1d1..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { Cluster } from '../../../models/cluster'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function fetchCluster(callWithRequest) { - return callWithRequest('info'); -} - -export function registerLoadRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/cluster', - method: 'GET', - handler: (request, h) => { - const callWithRequest = callWithRequestFactory(server, request); - - return fetchCluster(callWithRequest) - .then(responseFromES => ({ - cluster: Cluster.fromUpstreamJSON(responseFromES).downstreamJSON, - })) - .catch(e => { - if (e.status === 403) { - return h.response(); - } - throw Boom.internal(e); - }); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js deleted file mode 100755 index 232ee4207541c..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js +++ /dev/null @@ -1,38 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { wrapEsError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function deletePipeline(callWithRequest, pipelineId) { - return callWithRequest('delete', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - refresh: 'wait_for', - }); -} - -export function registerDeleteRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipeline/{id}', - method: 'DELETE', - handler: (request, h) => { - const callWithRequest = callWithRequestFactory(server, request); - const pipelineId = request.params.id; - - return deletePipeline(callWithRequest, pipelineId) - .then(() => h.response().code(204)) - .catch(e => wrapEsError(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js deleted file mode 100755 index 796bf939d747f..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Boom from 'boom'; -import { INDEX_NAMES } from '../../../../common/constants'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { Pipeline } from '../../../models/pipeline'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function fetchPipeline(callWithRequest, pipelineId) { - return callWithRequest('get', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - _source: ['description', 'username', 'pipeline', 'pipeline_settings'], - ignore: [404], - }); -} - -export function registerLoadRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipeline/{id}', - method: 'GET', - handler: request => { - const callWithRequest = callWithRequestFactory(server, request); - const pipelineId = request.params.id; - - return fetchPipeline(callWithRequest, pipelineId) - .then(pipelineResponseFromES => { - if (!pipelineResponseFromES.found) { - throw Boom.notFound(); - } - - const pipeline = Pipeline.fromUpstreamJSON(pipelineResponseFromES); - return pipeline.downstreamJSON; - }) - .catch(e => Boom.boomify(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js deleted file mode 100755 index 9966cd2ca2139..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js +++ /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 { registerLoadRoute } from './register_load_route'; -import { registerDeleteRoute } from './register_delete_route'; -import { registerSaveRoute } from './register_save_route'; - -export function registerLogstashPipelineRoutes(server) { - registerLoadRoute(server); - registerDeleteRoute(server); - registerSaveRoute(server); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js deleted file mode 100755 index 50f62dc0a0ddd..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js +++ /dev/null @@ -1,48 +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 { get } from 'lodash'; -import { wrapEsError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { Pipeline } from '../../../models/pipeline'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function savePipeline(callWithRequest, pipelineId, pipelineBody) { - return callWithRequest('index', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - body: pipelineBody, - refresh: 'wait_for', - }); -} - -export function registerSaveRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipeline/{id}', - method: 'PUT', - handler: async (request, h) => { - let username; - if (server.plugins.security) { - const user = await server.plugins.security.getUser(request); - username = get(user, 'username'); - } - - const callWithRequest = callWithRequestFactory(server, request); - const pipelineId = request.params.id; - - const pipeline = Pipeline.fromDownstreamJSON(request.payload, pipelineId, username); - return savePipeline(callWithRequest, pipeline.id, pipeline.upstreamJSON) - .then(() => h.response().code(204)) - .catch(e => wrapEsError(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js deleted file mode 100755 index db275b5a3ea79..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js +++ /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 { registerLogstashPipelinesRoutes } from './register_pipelines_routes'; diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js deleted file mode 100755 index 8ccd792d5a876..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js +++ /dev/null @@ -1,51 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { wrapUnknownError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function deletePipelines(callWithRequest, pipelineIds) { - const deletePromises = pipelineIds.map(pipelineId => { - return callWithRequest('delete', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - refresh: 'wait_for', - }) - .then(success => ({ success })) - .catch(error => ({ error })); - }); - - return Promise.all(deletePromises).then(results => { - const successes = results.filter(result => Boolean(result.success)); - const errors = results.filter(result => Boolean(result.error)); - - return { - numSuccesses: successes.length, - numErrors: errors.length, - }; - }); -} - -export function registerDeleteRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipelines/delete', - method: 'POST', - handler: request => { - const callWithRequest = callWithRequestFactory(server, request); - - return deletePipelines(callWithRequest, request.payload.pipelineIds) - .then(results => ({ results })) - .catch(err => wrapUnknownError(err)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js deleted file mode 100755 index 43ce1c3e8f6f6..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { wrapEsError } from '../../../lib/error_wrappers'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { fetchAllFromScroll } from '../../../lib/fetch_all_from_scroll'; -import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../common/constants'; -import { PipelineListItem } from '../../../models/pipeline_list_item'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function fetchPipelines(callWithRequest) { - const params = { - index: INDEX_NAMES.PIPELINES, - scroll: ES_SCROLL_SETTINGS.KEEPALIVE, - body: { - size: ES_SCROLL_SETTINGS.PAGE_SIZE, - }, - ignore: [404], - }; - - return callWithRequest('search', params).then(response => - fetchAllFromScroll(response, callWithRequest) - ); -} - -export function registerListRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipelines', - method: 'GET', - handler: request => { - const callWithRequest = callWithRequestFactory(server, request); - - return fetchPipelines(callWithRequest) - .then((pipelinesHits = []) => { - const pipelines = pipelinesHits.map(pipeline => { - return PipelineListItem.fromUpstreamJSON(pipeline).downstreamJSON; - }); - - return { pipelines }; - }) - .catch(e => wrapEsError(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js deleted file mode 100755 index 6d25f3acb9bf9..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js +++ /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 { registerListRoute } from './register_list_route'; -import { registerDeleteRoute } from './register_delete_route'; - -export function registerLogstashPipelinesRoutes(server) { - registerListRoute(server); - registerDeleteRoute(server); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js deleted file mode 100755 index d616349dd6566..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js +++ /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 { registerLogstashUpgradeRoutes } from './register_upgrade_routes'; diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js deleted file mode 100755 index 16f97930ae25e..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js +++ /dev/null @@ -1,56 +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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { wrapUnknownError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function doesIndexExist(callWithRequest) { - return callWithRequest('indices.exists', { - index: INDEX_NAMES.PIPELINES, - }); -} - -async function executeUpgrade(callWithRequest) { - // If index doesn't exist yet, there is no mapping to upgrade - if (!(await doesIndexExist(callWithRequest))) { - return; - } - - return callWithRequest('indices.putMapping', { - index: INDEX_NAMES.PIPELINES, - body: { - properties: { - pipeline_settings: { - dynamic: false, - type: 'object', - }, - }, - }, - }); -} - -export function registerExecuteRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/upgrade', - method: 'POST', - handler: async request => { - const callWithRequest = callWithRequestFactory(server, request); - try { - await executeUpgrade(callWithRequest); - return { is_upgraded: true }; - } catch (err) { - throw wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js deleted file mode 100755 index a198f82613e37..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js +++ /dev/null @@ -1,11 +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 { registerExecuteRoute } from './register_execute_route'; - -export function registerLogstashUpgradeRoutes(server) { - registerExecuteRoute(server); -} diff --git a/x-pack/plugins/licensing/common/licensing.mock.ts b/x-pack/plugins/licensing/common/licensing.mock.ts index bf8b85e3e981b..4a6b27255587a 100644 --- a/x-pack/plugins/licensing/common/licensing.mock.ts +++ b/x-pack/plugins/licensing/common/licensing.mock.ts @@ -53,6 +53,7 @@ const createLicenseMock = () => { }; mock.check.mockReturnValue({ state: 'valid' }); mock.hasAtLeast.mockReturnValue(true); + mock.getFeature.mockReturnValue({ isAvailable: true, isEnabled: true }); return mock; }; export const licenseMock = { diff --git a/x-pack/plugins/licensing/server/index.ts b/x-pack/plugins/licensing/server/index.ts index 0e14ead7c6c57..76e65afc595c4 100644 --- a/x-pack/plugins/licensing/server/index.ts +++ b/x-pack/plugins/licensing/server/index.ts @@ -12,3 +12,4 @@ export const plugin = (context: PluginInitializerContext) => new LicensingPlugin export * from '../common/types'; export * from './types'; export { config } from './licensing_config'; +export { CheckLicense, wrapRouteWithLicenseCheck } from './wrap_route_with_license_check'; diff --git a/x-pack/plugins/licensing/server/wrap_route_with_license_check.test.ts b/x-pack/plugins/licensing/server/wrap_route_with_license_check.test.ts new file mode 100644 index 0000000000000..7abdd3f6190ce --- /dev/null +++ b/x-pack/plugins/licensing/server/wrap_route_with_license_check.test.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { httpServerMock } from 'src/core/server/mocks'; + +import { wrapRouteWithLicenseCheck, CheckLicense } from './wrap_route_with_license_check'; + +const context = { + licensing: { + license: {}, + }, +} as any; +const request = httpServerMock.createKibanaRequest(); + +describe('wrapRouteWithLicenseCheck', () => { + it('calls route handler if checkLicense returns "valid": true', async () => { + const checkLicense: CheckLicense = () => ({ valid: true, message: null }); + const routeHandler = jest.fn(); + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await wrapper(context, request, response); + + expect(routeHandler).toHaveBeenCalledTimes(1); + expect(routeHandler).toHaveBeenCalledWith(context, request, response); + }); + + it('does not call route handler if checkLicense returns "valid": false', async () => { + const checkLicense: CheckLicense = () => ({ valid: false, message: 'reason' }); + const routeHandler = jest.fn(); + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await wrapper(context, request, response); + + expect(routeHandler).toHaveBeenCalledTimes(0); + expect(response.forbidden).toHaveBeenCalledTimes(1); + expect(response.forbidden).toHaveBeenCalledWith({ body: 'reason' }); + }); + + it('allows an exception to bubble up if handler throws', async () => { + const checkLicense: CheckLicense = () => ({ valid: true, message: null }); + const routeHandler = () => { + throw new Error('reason'); + }; + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await expect(wrapper(context, request, response)).rejects.toThrowErrorMatchingInlineSnapshot( + `"reason"` + ); + }); + + it('allows an exception to bubble up if "checkLicense" throws', async () => { + const checkLicense: CheckLicense = () => { + throw new Error('reason'); + }; + const routeHandler = jest.fn(); + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await expect(wrapper(context, request, response)).rejects.toThrowErrorMatchingInlineSnapshot( + `"reason"` + ); + + expect(routeHandler).toHaveBeenCalledTimes(0); + }); +}); diff --git a/x-pack/plugins/licensing/server/wrap_route_with_license_check.ts b/x-pack/plugins/licensing/server/wrap_route_with_license_check.ts new file mode 100644 index 0000000000000..e0cac8d9db208 --- /dev/null +++ b/x-pack/plugins/licensing/server/wrap_route_with_license_check.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + RequestHandler, + RequestHandlerContext, + KibanaRequest, + RouteMethod, + KibanaResponseFactory, +} from 'src/core/server'; + +import { ILicense } from '../common/types'; + +export type CheckLicense = ( + license: ILicense +) => { valid: false; message: string } | { valid: true; message: null }; + +export function wrapRouteWithLicenseCheck<P, Q, B>( + checkLicense: CheckLicense, + handler: RequestHandler<P, Q, B> +): RequestHandler<P, Q, B> { + return async ( + context: RequestHandlerContext, + request: KibanaRequest<P, Q, B, RouteMethod>, + response: KibanaResponseFactory + ) => { + const licenseCheckResult = checkLicense(context.licensing.license); + + if (licenseCheckResult.valid) { + return handler(context, request, response); + } else { + return response.forbidden({ + body: licenseCheckResult.message, + }); + } + }; +} diff --git a/x-pack/legacy/plugins/logstash/common/constants/es_scroll_settings.js b/x-pack/plugins/logstash/common/constants/es_scroll_settings.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/es_scroll_settings.js rename to x-pack/plugins/logstash/common/constants/es_scroll_settings.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/index.js b/x-pack/plugins/logstash/common/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/index.js rename to x-pack/plugins/logstash/common/constants/index.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/index_names.js b/x-pack/plugins/logstash/common/constants/index_names.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/index_names.js rename to x-pack/plugins/logstash/common/constants/index_names.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/monitoring.js b/x-pack/plugins/logstash/common/constants/monitoring.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/monitoring.js rename to x-pack/plugins/logstash/common/constants/monitoring.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/pagination.js b/x-pack/plugins/logstash/common/constants/pagination.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/pagination.js rename to x-pack/plugins/logstash/common/constants/pagination.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/pipeline.js b/x-pack/plugins/logstash/common/constants/pipeline.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/pipeline.js rename to x-pack/plugins/logstash/common/constants/pipeline.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/plugin.js b/x-pack/plugins/logstash/common/constants/plugin.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/plugin.js rename to x-pack/plugins/logstash/common/constants/plugin.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/routes.js b/x-pack/plugins/logstash/common/constants/routes.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/routes.js rename to x-pack/plugins/logstash/common/constants/routes.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/tooltips.js b/x-pack/plugins/logstash/common/constants/tooltips.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/tooltips.js rename to x-pack/plugins/logstash/common/constants/tooltips.ts diff --git a/x-pack/plugins/logstash/kibana.json b/x-pack/plugins/logstash/kibana.json new file mode 100644 index 0000000000000..bcc926535d3c2 --- /dev/null +++ b/x-pack/plugins/logstash/kibana.json @@ -0,0 +1,12 @@ +{ + "id": "logstash", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["xpack", "logstash"], + "requiredPlugins": [ + "licensing" + ], + "optionalPlugins": ["security"], + "server": true, + "ui": false +} diff --git a/x-pack/plugins/logstash/server/index.ts b/x-pack/plugins/logstash/server/index.ts new file mode 100644 index 0000000000000..cc65184a1f3a0 --- /dev/null +++ b/x-pack/plugins/logstash/server/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { schema } from '@kbn/config-schema'; +import { PluginInitializerContext, PluginConfigDescriptor } from 'src/core/server'; +import { LogstashPlugin } from './plugin'; + +export const plugin = (context: PluginInitializerContext) => new LogstashPlugin(context); + +export const config: PluginConfigDescriptor = { + schema: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + }), +}; diff --git a/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts b/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts new file mode 100755 index 0000000000000..324e0a22ff378 --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/check_license/check_license.test.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 { licensingMock } from '../../../../licensing/server/mocks'; +import { checkLicense } from './check_license'; + +describe('check_license', function() { + describe('returns "valid": false & message when', () => { + it('license information is not available', () => { + const license = licensingMock.createLicenseMock(); + license.isAvailable = false; + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + + it('license level is not enough', () => { + const license = licensingMock.createLicenseMock(); + license.hasAtLeast.mockReturnValue(false); + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + + it('license is expired', () => { + const license = licensingMock.createLicenseMock(); + license.isActive = false; + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + + it('elasticsearch security is disabled', () => { + const license = licensingMock.createLicenseMock(); + license.getFeature.mockReturnValue({ isEnabled: false, isAvailable: false }); + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + }); + + it('returns "valid": true without message otherwise', () => { + const license = licensingMock.createLicenseMock(); + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(true); + expect(message).toBe(null); + }); +}); diff --git a/x-pack/plugins/logstash/server/lib/check_license/check_license.ts b/x-pack/plugins/logstash/server/lib/check_license/check_license.ts new file mode 100644 index 0000000000000..4eef2eb9b0681 --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/check_license/check_license.ts @@ -0,0 +1,65 @@ +/* + * 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 { CheckLicense } from '../../../../licensing/server'; + +export const checkLicense: CheckLicense = license => { + if (!license.isAvailable) { + return { + valid: false, + message: i18n.translate( + 'xpack.logstash.managementSection.notPossibleToManagePipelinesMessage', + { + defaultMessage: + 'You cannot manage Logstash pipelines because license information is not available at this time.', + } + ), + }; + } + + if (!license.hasAtLeast('standard')) { + return { + valid: false, + message: i18n.translate('xpack.logstash.managementSection.licenseDoesNotSupportDescription', { + defaultMessage: + 'Your {licenseType} license does not support Logstash pipeline management features. Please upgrade your license.', + values: { licenseType: license.type }, + }), + }; + } + + if (!license.isActive) { + return { + valid: false, + message: i18n.translate( + 'xpack.logstash.managementSection.pipelineCrudOperationsNotAllowedDescription', + { + defaultMessage: + 'You cannot edit, create, or delete your Logstash pipelines because your {licenseType} license has expired.', + values: { licenseType: license.type }, + } + ), + }; + } + + if (!license.getFeature('security').isEnabled) { + return { + valid: false, + message: i18n.translate('xpack.logstash.managementSection.enableSecurityDescription', { + defaultMessage: + 'Security must be enabled in order to use Logstash pipeline management features.' + + ' Please set xpack.security.enabled: true in your elasticsearch.yml.', + }), + }; + } + + return { + valid: true, + message: null, + }; +}; diff --git a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/index.js b/x-pack/plugins/logstash/server/lib/check_license/index.ts old mode 100755 new mode 100644 similarity index 77% rename from x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/index.js rename to x-pack/plugins/logstash/server/lib/check_license/index.ts index 787814d87dff9..f2c070fd44b6e --- a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/index.js +++ b/x-pack/plugins/logstash/server/lib/check_license/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { callWithRequestFactory } from './call_with_request_factory'; +export { checkLicense } from './check_license'; diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts new file mode 100755 index 0000000000000..8cd6b70d47570 --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { fetchAllFromScroll } from './fetch_all_from_scroll'; + +describe('fetch_all_from_scroll', () => { + let stubCallWithRequest: jest.Mock; + + beforeEach(() => { + stubCallWithRequest = jest.fn(); + stubCallWithRequest + .mockResolvedValueOnce({ + hits: { + hits: ['newhit'], + }, + _scroll_id: 'newScrollId', + }) + .mockResolvedValueOnce({ + hits: { + hits: [], + }, + }); + }); + + describe('#fetchAllFromScroll', () => { + describe('when the passed-in response has no hits', () => { + const mockResponse = { + hits: { + hits: [], + }, + }; + + it('should return an empty array of hits', async () => { + const hits = await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); + expect(hits).toEqual([]); + }); + + it('should not call callWithRequest', async () => { + await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); + expect(stubCallWithRequest).toHaveBeenCalledTimes(0); + }); + }); + + describe('when the passed-in response has some hits', () => { + const mockResponse = { + hits: { + hits: ['foo', 'bar'], + }, + _scroll_id: 'originalScrollId', + }; + + it('should return the hits from the response', async () => { + const hits = await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); + expect(hits).toEqual(['foo', 'bar', 'newhit']); + }); + + it('should call callWithRequest', async () => { + await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); + expect(stubCallWithRequest).toHaveBeenCalledTimes(2); + + const firstCallWithRequestCallArgs = stubCallWithRequest.mock.calls[0]; + expect(firstCallWithRequestCallArgs[1].body.scroll_id).toBe('originalScrollId'); + + const secondCallWithRequestCallArgs = stubCallWithRequest.mock.calls[1]; + expect(secondCallWithRequestCallArgs[1].body.scroll_id).toBe('newScrollId'); + }); + }); + }); +}); diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts new file mode 100755 index 0000000000000..060cf188a4c60 --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.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 { APICaller } from 'src/core/server'; +import { SearchResponse } from 'elasticsearch'; + +import { ES_SCROLL_SETTINGS } from '../../../common/constants'; +import { Hits } from '../../types'; + +export async function fetchAllFromScroll( + response: SearchResponse<any>, + callWithRequest: APICaller, + hits: Hits = [] +): Promise<Hits> { + const newHits = response.hits?.hits || []; + const scrollId = response._scroll_id; + + if (newHits.length > 0) { + hits.push(...newHits); + + const innerResponse = await callWithRequest('scroll', { + body: { + scroll: ES_SCROLL_SETTINGS.KEEPALIVE, + scroll_id: scrollId, + }, + }); + + return await fetchAllFromScroll(innerResponse, callWithRequest, hits); + } + + return hits; +} diff --git a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/index.js b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/index.js rename to x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts similarity index 81% rename from x-pack/legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js rename to x-pack/plugins/logstash/server/models/cluster/cluster.test.ts index 08a447a160a1a..63f9f1e58f6ec 100755 --- a/x-pack/legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; -import { Cluster } from '../cluster'; +import { Cluster } from './cluster'; describe('cluster', () => { describe('Cluster', () => { @@ -16,7 +15,7 @@ describe('cluster', () => { it('returns correct Cluster instance', () => { const cluster = Cluster.fromUpstreamJSON(upstreamJSON); - expect(cluster.uuid).to.be(upstreamJSON.cluster_uuid); + expect(cluster.uuid).toEqual(upstreamJSON.cluster_uuid); }); }); }); diff --git a/x-pack/legacy/plugins/logstash/server/models/cluster/cluster.js b/x-pack/plugins/logstash/server/models/cluster/cluster.ts similarity index 68% rename from x-pack/legacy/plugins/logstash/server/models/cluster/cluster.js rename to x-pack/plugins/logstash/server/models/cluster/cluster.ts index b114162fb0986..54f03605e14d6 100755 --- a/x-pack/legacy/plugins/logstash/server/models/cluster/cluster.js +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.ts @@ -10,11 +10,12 @@ import { get } from 'lodash'; * This model deals with a cluster object from ES and converts it to Kibana downstream */ export class Cluster { - constructor(props) { - this.uuid = props.uuid; + public readonly uuid: string; + constructor({ uuid }: { uuid: string }) { + this.uuid = uuid; } - get downstreamJSON() { + public get downstreamJSON() { const json = { uuid: this.uuid, }; @@ -23,8 +24,8 @@ export class Cluster { } // generate Pipeline object from elasticsearch response - static fromUpstreamJSON(upstreamCluster) { - const uuid = get(upstreamCluster, 'cluster_uuid'); + static fromUpstreamJSON(upstreamCluster: Record<string, string>) { + const uuid = get<string>(upstreamCluster, 'cluster_uuid'); return new Cluster({ uuid }); } } diff --git a/x-pack/legacy/plugins/logstash/server/models/cluster/index.js b/x-pack/plugins/logstash/server/models/cluster/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/models/cluster/index.js rename to x-pack/plugins/logstash/server/models/cluster/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline/index.js b/x-pack/plugins/logstash/server/models/pipeline/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/models/pipeline/index.js rename to x-pack/plugins/logstash/server/models/pipeline/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js b/x-pack/plugins/logstash/server/models/pipeline/pipeline.test.ts similarity index 74% rename from x-pack/legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js rename to x-pack/plugins/logstash/server/models/pipeline/pipeline.test.ts index 41869c22271f0..82ce0d72e2052 100755 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js +++ b/x-pack/plugins/logstash/server/models/pipeline/pipeline.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; -import { Pipeline } from '../pipeline'; +import { Pipeline } from './pipeline'; describe('pipeline', () => { describe('Pipeline', () => { @@ -25,10 +24,10 @@ describe('pipeline', () => { it('returns correct Pipeline instance', () => { const pipeline = Pipeline.fromUpstreamJSON(upstreamJSON); - expect(pipeline.id).to.be(upstreamJSON._id); - expect(pipeline.description).to.be(upstreamJSON._source.description); - expect(pipeline.username).to.be(upstreamJSON._source.username); - expect(pipeline.pipeline).to.be(upstreamJSON._source.pipeline); + expect(pipeline.id).toBe(upstreamJSON._id); + expect(pipeline.description).toBe(upstreamJSON._source.description); + expect(pipeline.username).toBe(upstreamJSON._source.username); + expect(pipeline.pipeline).toBe(upstreamJSON._source.pipeline); }); it('throws if pipeline argument does not contain an id property', () => { @@ -39,7 +38,7 @@ describe('pipeline', () => { const testFromUpstreamJsonError = () => { return Pipeline.fromUpstreamJSON(badJSON); }; - expect(testFromUpstreamJsonError).to.throwError( + expect(testFromUpstreamJsonError).toThrowError( /upstreamPipeline argument must contain an id property/i ); }); @@ -64,12 +63,12 @@ describe('pipeline', () => { pipeline: 'input {} filter { grok {} }\n output {}', }; // can't do an object level comparison because modified field is always `now` - expect(pipeline.upstreamJSON.last_modified).to.be.a('string'); - expect(pipeline.upstreamJSON.description).to.be(expectedUpstreamJSON.description); - expect(pipeline.upstreamJSON.pipeline_metadata).to.eql( + expect(pipeline.upstreamJSON.last_modified).toStrictEqual(expect.any(String)); + expect(pipeline.upstreamJSON.description).toBe(expectedUpstreamJSON.description); + expect(pipeline.upstreamJSON.pipeline_metadata).toEqual( expectedUpstreamJSON.pipeline_metadata ); - expect(pipeline.upstreamJSON.pipeline).to.be(expectedUpstreamJSON.pipeline); + expect(pipeline.upstreamJSON.pipeline).toBe(expectedUpstreamJSON.pipeline); }); }); }); diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline/pipeline.js b/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts similarity index 59% rename from x-pack/legacy/plugins/logstash/server/models/pipeline/pipeline.js rename to x-pack/plugins/logstash/server/models/pipeline/pipeline.ts index f02d303cb0380..3f2debeebeb46 100755 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline/pipeline.js +++ b/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts @@ -9,19 +9,38 @@ import { badRequest } from 'boom'; import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; +interface PipelineOptions { + id: string; + description: string; + pipeline: string; + username?: string; + settings?: Record<string, any>; +} + +interface DownstreamPipeline { + description: string; + pipeline: string; + settings?: Record<string, any>; +} /** * This model deals with a pipeline object from ES and converts it to Kibana downstream */ export class Pipeline { - constructor(props) { - this.id = props.id; - this.description = props.description; - this.username = props.username; - this.pipeline = props.pipeline; - this.settings = props.settings || {}; + public readonly id: string; + public readonly description: string; + public readonly username?: string; + public readonly pipeline: string; + private readonly settings: Record<string, any>; + + constructor(options: PipelineOptions) { + this.id = options.id; + this.description = options.description; + this.username = options.username; + this.pipeline = options.pipeline; + this.settings = options.settings || {}; } - get downstreamJSON() { + public get downstreamJSON() { const json = { id: this.id, description: this.description, @@ -41,7 +60,7 @@ export class Pipeline { * pipeline_metadata.type is the Logstash config type (future: LIR, json, etc) * @return {[JSON]} [Elasticsearch JSON] */ - get upstreamJSON() { + public get upstreamJSON() { return { description: this.description, last_modified: moment().toISOString(), @@ -56,7 +75,11 @@ export class Pipeline { } // generate Pipeline object from kibana response - static fromDownstreamJSON(downstreamPipeline, pipelineId, username) { + static fromDownstreamJSON( + downstreamPipeline: DownstreamPipeline, + pipelineId: string, + username?: string + ) { const opts = { id: pipelineId, description: downstreamPipeline.description, @@ -69,7 +92,7 @@ export class Pipeline { } // generate Pipeline object from elasticsearch response - static fromUpstreamJSON(upstreamPipeline) { + static fromUpstreamJSON(upstreamPipeline: Record<string, any>) { if (!upstreamPipeline._id) { throw badRequest( i18n.translate( @@ -80,13 +103,13 @@ export class Pipeline { ) ); } - const id = get(upstreamPipeline, '_id'); - const description = get(upstreamPipeline, '_source.description'); - const username = get(upstreamPipeline, '_source.username'); - const pipeline = get(upstreamPipeline, '_source.pipeline'); - const settings = get(upstreamPipeline, '_source.pipeline_settings'); + const id = get<string>(upstreamPipeline, '_id'); + const description = get<string>(upstreamPipeline, '_source.description'); + const username = get<string>(upstreamPipeline, '_source.username'); + const pipeline = get<string>(upstreamPipeline, '_source.pipeline'); + const settings = get<Record<string, any>>(upstreamPipeline, '_source.pipeline_settings'); - const opts = { id, description, username, pipeline, settings }; + const opts: PipelineOptions = { id, description, username, pipeline, settings }; return new Pipeline(opts); } diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/index.js b/x-pack/plugins/logstash/server/models/pipeline_list_item/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/index.js rename to x-pack/plugins/logstash/server/models/pipeline_list_item/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts similarity index 72% rename from x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js rename to x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts index 4f3a447f030c7..c557e84443b02 100755 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js +++ b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; -import { PipelineListItem } from '../pipeline_list_item'; +import { PipelineListItem } from './pipeline_list_item'; describe('pipeline_list_item', () => { describe('PipelineListItem', () => { @@ -21,15 +20,18 @@ describe('pipeline_list_item', () => { username: 'elastic', pipeline: 'input {} filter { grok {} }\n output {}', }, + _index: 'index', + _type: 'type', + _score: 100, }; describe('fromUpstreamJSON factory method', () => { it('returns correct PipelineListItem instance', () => { const pipelineListItem = PipelineListItem.fromUpstreamJSON(upstreamJSON); - expect(pipelineListItem.id).to.be(upstreamJSON._id); - expect(pipelineListItem.description).to.be(upstreamJSON._source.description); - expect(pipelineListItem.username).to.be(upstreamJSON._source.username); - expect(pipelineListItem.last_modified).to.be(upstreamJSON._source.last_modified); + expect(pipelineListItem.id).toBe(upstreamJSON._id); + expect(pipelineListItem.description).toBe(upstreamJSON._source.description); + expect(pipelineListItem.username).toBe(upstreamJSON._source.username); + expect(pipelineListItem.last_modified).toBe(upstreamJSON._source.last_modified); }); }); @@ -42,7 +44,7 @@ describe('pipeline_list_item', () => { username: 'elastic', last_modified: '2017-05-14T02:50:51.250Z', }; - expect(pipelineListItem.downstreamJSON).to.eql(expectedDownstreamJSON); + expect(pipelineListItem.downstreamJSON).toEqual(expectedDownstreamJSON); }); }); }); diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts similarity index 50% rename from x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js rename to x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts index bbb506766897e..98c91fca1fcca 100755 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js +++ b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts @@ -5,16 +5,21 @@ */ import { get } from 'lodash'; +import { Hit, PipelineListItemOptions } from '../../types'; export class PipelineListItem { - constructor(props) { - this.id = props.id; - this.description = props.description; - this.last_modified = props.last_modified; - this.username = props.username; + public readonly id: string; + public readonly description: string; + public readonly last_modified: string; + public readonly username: string; + constructor(options: PipelineListItemOptions) { + this.id = options.id; + this.description = options.description; + this.last_modified = options.last_modified; + this.username = options.username; } - get downstreamJSON() { + public get downstreamJSON() { const json = { id: this.id, description: this.description, @@ -29,12 +34,12 @@ export class PipelineListItem { * Takes the json GET response from ES and constructs a pipeline model to be used * in Kibana downstream */ - static fromUpstreamJSON(pipeline) { + static fromUpstreamJSON(pipeline: Hit) { const opts = { id: pipeline._id, - description: get(pipeline, '_source.description'), - last_modified: get(pipeline, '_source.last_modified'), - username: get(pipeline, '_source.username'), + description: get<string>(pipeline, '_source.description'), + last_modified: get<string>(pipeline, '_source.last_modified'), + username: get<string>(pipeline, '_source.username'), }; return new PipelineListItem(opts); diff --git a/x-pack/plugins/logstash/server/plugin.ts b/x-pack/plugins/logstash/server/plugin.ts new file mode 100644 index 0000000000000..c048dd13bfb0c --- /dev/null +++ b/x-pack/plugins/logstash/server/plugin.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. + */ +import { + CoreSetup, + CoreStart, + ICustomClusterClient, + Logger, + Plugin, + PluginInitializerContext, +} from 'src/core/server'; +import { LicensingPluginSetup } from '../../licensing/server'; +import { SecurityPluginSetup } from '../../security/server'; + +import { registerRoutes } from './routes'; + +interface SetupDeps { + licensing: LicensingPluginSetup; + security?: SecurityPluginSetup; +} + +export class LogstashPlugin implements Plugin { + private readonly logger: Logger; + private esClient?: ICustomClusterClient; + private coreSetup?: CoreSetup; + constructor(context: PluginInitializerContext) { + this.logger = context.logger.get(); + } + + setup(core: CoreSetup, deps: SetupDeps) { + this.logger.debug('Setting up Logstash plugin'); + + this.coreSetup = core; + registerRoutes(core.http.createRouter(), deps.security); + } + + start(core: CoreStart) { + const esClient = core.elasticsearch.legacy.createClient('logstash'); + + this.coreSetup!.http.registerRouteHandlerContext('logstash', async (context, request) => { + return { esClient: esClient.asScoped(request) }; + }); + } + stop() { + if (this.esClient) { + this.esClient.close(); + } + } +} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/index.js b/x-pack/plugins/logstash/server/routes/cluster/index.ts old mode 100755 new mode 100644 similarity index 76% rename from x-pack/legacy/plugins/logstash/server/routes/api/cluster/index.js rename to x-pack/plugins/logstash/server/routes/cluster/index.ts index b129d8524b573..c43c409cf5a17 --- a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/index.js +++ b/x-pack/plugins/logstash/server/routes/cluster/index.ts @@ -3,5 +3,4 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export { registerLogstashClusterRoutes } from './register_cluster_routes'; +export { registerClusterLoadRoute } from './load'; diff --git a/x-pack/plugins/logstash/server/routes/cluster/load.ts b/x-pack/plugins/logstash/server/routes/cluster/load.ts new file mode 100644 index 0000000000000..18fe21f3da675 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/cluster/load.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 { IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; +import { Cluster } from '../../models/cluster'; +import { checkLicense } from '../../lib/check_license'; + +export function registerClusterLoadRoute(router: IRouter) { + router.get( + { + path: '/api/logstash/cluster', + validate: false, + }, + wrapRouteWithLicenseCheck(checkLicense, async (context, request, response) => { + try { + const client = context.logstash!.esClient; + const info = await client.callAsCurrentUser('info'); + return response.ok({ + body: { + cluster: Cluster.fromUpstreamJSON(info).downstreamJSON, + }, + }); + } catch (err) { + if (err.status === 403) { + return response.ok(); + } + return response.internalError(); + } + }) + ); +} diff --git a/x-pack/plugins/logstash/server/routes/index.ts b/x-pack/plugins/logstash/server/routes/index.ts new file mode 100644 index 0000000000000..0c7183b409055 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { IRouter } from 'src/core/server'; +import { SecurityPluginSetup } from '../../../security/server'; +import { registerClusterLoadRoute } from './cluster'; +import { + registerPipelineDeleteRoute, + registerPipelineLoadRoute, + registerPipelineSaveRoute, +} from './pipeline'; +import { registerPipelinesListRoute, registerPipelinesDeleteRoute } from './pipelines'; +import { registerUpgradeRoute } from './upgrade'; + +export function registerRoutes(router: IRouter, security?: SecurityPluginSetup) { + registerClusterLoadRoute(router); + + registerPipelineDeleteRoute(router); + registerPipelineLoadRoute(router); + registerPipelineSaveRoute(router, security); + + registerPipelinesListRoute(router); + registerPipelinesDeleteRoute(router); + + registerUpgradeRoute(router); +} diff --git a/x-pack/plugins/logstash/server/routes/pipeline/delete.ts b/x-pack/plugins/logstash/server/routes/pipeline/delete.ts new file mode 100644 index 0000000000000..4aeae3e0ae2d5 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipeline/delete.ts @@ -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 { schema } from '@kbn/config-schema'; +import { IRouter } from 'src/core/server'; +import { INDEX_NAMES } from '../../../common/constants'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; + +import { checkLicense } from '../../lib/check_license'; + +export function registerPipelineDeleteRoute(router: IRouter) { + router.delete( + { + path: '/api/logstash/pipeline/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + wrapRouteWithLicenseCheck( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = context.logstash!.esClient; + + await client.callAsCurrentUser('delete', { + index: INDEX_NAMES.PIPELINES, + id: request.params.id, + refresh: 'wait_for', + }); + + return response.noContent(); + }) + ) + ); +} diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/index.js b/x-pack/plugins/logstash/server/routes/pipeline/index.ts old mode 100755 new mode 100644 similarity index 60% rename from x-pack/legacy/plugins/logstash/server/lib/error_wrappers/index.js rename to x-pack/plugins/logstash/server/routes/pipeline/index.ts index f275f15637091..e7db6e18ddaf3 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/index.js +++ b/x-pack/plugins/logstash/server/routes/pipeline/index.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export { wrapCustomError } from './wrap_custom_error'; -export { wrapEsError } from './wrap_es_error'; -export { wrapUnknownError } from './wrap_unknown_error'; +export { registerPipelineDeleteRoute } from './delete'; +export { registerPipelineLoadRoute } from './load'; +export { registerPipelineSaveRoute } from './save'; diff --git a/x-pack/plugins/logstash/server/routes/pipeline/load.ts b/x-pack/plugins/logstash/server/routes/pipeline/load.ts new file mode 100644 index 0000000000000..fec9097114d26 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipeline/load.ts @@ -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 { schema } from '@kbn/config-schema'; +import { IRouter } from 'src/core/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { Pipeline } from '../../models/pipeline'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; +import { checkLicense } from '../../lib/check_license'; + +export function registerPipelineLoadRoute(router: IRouter) { + router.get( + { + path: '/api/logstash/pipeline/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + wrapRouteWithLicenseCheck( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = context.logstash!.esClient; + + const result = await client.callAsCurrentUser('get', { + index: INDEX_NAMES.PIPELINES, + id: request.params.id, + _source: ['description', 'username', 'pipeline', 'pipeline_settings'], + ignore: [404], + }); + + if (!result.found) { + return response.notFound(); + } + + return response.ok({ + body: Pipeline.fromUpstreamJSON(result).downstreamJSON, + }); + }) + ) + ); +} diff --git a/x-pack/plugins/logstash/server/routes/pipeline/save.ts b/x-pack/plugins/logstash/server/routes/pipeline/save.ts new file mode 100644 index 0000000000000..556c281944a85 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipeline/save.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { schema } from '@kbn/config-schema'; +import { i18n } from '@kbn/i18n'; +import { IRouter } from 'src/core/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { Pipeline } from '../../models/pipeline'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; +import { SecurityPluginSetup } from '../../../../security/server'; +import { checkLicense } from '../../lib/check_license'; + +export function registerPipelineSaveRoute(router: IRouter, security?: SecurityPluginSetup) { + router.put( + { + path: '/api/logstash/pipeline/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + body: schema.object({ + id: schema.string(), + description: schema.string(), + pipeline: schema.string(), + username: schema.string(), + settings: schema.maybe(schema.object({}, { unknowns: 'allow' })), + }), + }, + }, + wrapRouteWithLicenseCheck( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + try { + let username: string | undefined; + if (security) { + const user = await security.authc.getCurrentUser(request); + username = user?.username; + } + + const client = context.logstash!.esClient; + const pipeline = Pipeline.fromDownstreamJSON(request.body, request.params.id, username); + + await client.callAsCurrentUser('index', { + index: INDEX_NAMES.PIPELINES, + id: pipeline.id, + body: pipeline.upstreamJSON, + refresh: 'wait_for', + }); + + return response.noContent(); + } catch (err) { + const statusCode = err.statusCode; + // handles the permissions issue of Elasticsearch + if (statusCode === 403) { + return response.forbidden({ + body: i18n.translate('xpack.logstash.insufficientUserPermissionsDescription', { + defaultMessage: 'Insufficient user permissions for managing Logstash pipelines', + }), + }); + } + throw err; + } + }) + ) + ); +} diff --git a/x-pack/plugins/logstash/server/routes/pipelines/delete.ts b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts new file mode 100644 index 0000000000000..ac3097ac0424b --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { schema } from '@kbn/config-schema'; +import { APICaller, IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { checkLicense } from '../../lib/check_license'; + +async function deletePipelines(callWithRequest: APICaller, pipelineIds: string[]) { + const deletePromises = pipelineIds.map(pipelineId => { + return callWithRequest('delete', { + index: INDEX_NAMES.PIPELINES, + id: pipelineId, + refresh: 'wait_for', + }) + .then(success => ({ success })) + .catch(error => ({ error })); + }); + + const results = await Promise.all(deletePromises); + const successes = results.filter(result => Reflect.has(result, 'success')); + const errors = results.filter(result => Reflect.has(result, 'error')); + + return { + numSuccesses: successes.length, + numErrors: errors.length, + }; +} + +export function registerPipelinesDeleteRoute(router: IRouter) { + router.post( + { + path: '/api/logstash/pipelines/delete', + validate: { + body: schema.object({ + pipelineIds: schema.arrayOf(schema.string()), + }), + }, + }, + wrapRouteWithLicenseCheck( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = context.logstash!.esClient; + const results = await deletePipelines(client.callAsCurrentUser, request.body.pipelineIds); + + return response.ok({ body: { results } }); + }) + ) + ); +} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/index.js b/x-pack/plugins/logstash/server/routes/pipelines/index.ts old mode 100755 new mode 100644 similarity index 68% rename from x-pack/legacy/plugins/logstash/server/routes/api/pipeline/index.js rename to x-pack/plugins/logstash/server/routes/pipelines/index.ts index 643a405ced919..36681502cfc70 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/index.js +++ b/x-pack/plugins/logstash/server/routes/pipelines/index.ts @@ -3,5 +3,5 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export { registerLogstashPipelineRoutes } from './register_pipeline_routes'; +export { registerPipelinesListRoute } from './list'; +export { registerPipelinesDeleteRoute } from './delete'; diff --git a/x-pack/plugins/logstash/server/routes/pipelines/list.ts b/x-pack/plugins/logstash/server/routes/pipelines/list.ts new file mode 100644 index 0000000000000..bc477a25a7988 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipelines/list.ts @@ -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 { i18n } from '@kbn/i18n'; +import { SearchResponse } from 'elasticsearch'; +import { APICaller, IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; + +import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../common/constants'; +import { PipelineListItem } from '../../models/pipeline_list_item'; +import { fetchAllFromScroll } from '../../lib/fetch_all_from_scroll'; +import { checkLicense } from '../../lib/check_license'; + +async function fetchPipelines(callWithRequest: APICaller) { + const params = { + index: INDEX_NAMES.PIPELINES, + scroll: ES_SCROLL_SETTINGS.KEEPALIVE, + body: { + size: ES_SCROLL_SETTINGS.PAGE_SIZE, + }, + ignore: [404], + }; + + const response = await callWithRequest<SearchResponse<any>>('search', params); + return fetchAllFromScroll(response, callWithRequest); +} + +export function registerPipelinesListRoute(router: IRouter) { + router.get( + { + path: '/api/logstash/pipelines', + validate: false, + }, + wrapRouteWithLicenseCheck( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + try { + const client = context.logstash!.esClient; + const pipelinesHits = await fetchPipelines(client.callAsCurrentUser); + + const pipelines = pipelinesHits.map(pipeline => { + return PipelineListItem.fromUpstreamJSON(pipeline).downstreamJSON; + }); + + return response.ok({ body: { pipelines } }); + } catch (err) { + const statusCode = err.statusCode; + // handles the permissions issue of Elasticsearch + if (statusCode === 403) { + return response.forbidden({ + body: i18n.translate('xpack.logstash.insufficientUserPermissionsDescription', { + defaultMessage: 'Insufficient user permissions for managing Logstash pipelines', + }), + }); + } + throw err; + } + }) + ) + ); +} diff --git a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js b/x-pack/plugins/logstash/server/routes/upgrade/index.ts old mode 100755 new mode 100644 similarity index 76% rename from x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js rename to x-pack/plugins/logstash/server/routes/upgrade/index.ts index 0743e443955f4..3a5b0868b446b --- a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js +++ b/x-pack/plugins/logstash/server/routes/upgrade/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { licensePreRoutingFactory } from './license_pre_routing_factory'; +export { registerUpgradeRoute } from './upgrade'; diff --git a/x-pack/plugins/logstash/server/routes/upgrade/upgrade.ts b/x-pack/plugins/logstash/server/routes/upgrade/upgrade.ts new file mode 100644 index 0000000000000..2bd2c0f89e190 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/upgrade/upgrade.ts @@ -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 { IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { checkLicense } from '../../lib/check_license'; + +export function registerUpgradeRoute(router: IRouter) { + router.post( + { + path: '/api/logstash/upgrade', + validate: false, + }, + wrapRouteWithLicenseCheck( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = context.logstash!.esClient; + + const doesIndexExist = await client.callAsCurrentUser('indices.exists', { + index: INDEX_NAMES.PIPELINES, + }); + + // If index doesn't exist yet, there is no mapping to upgrade + if (doesIndexExist) { + await client.callAsCurrentUser('indices.putMapping', { + index: INDEX_NAMES.PIPELINES, + body: { + properties: { + pipeline_settings: { + dynamic: false, + type: 'object', + }, + }, + }, + }); + } + + return response.ok({ body: { is_upgraded: true } }); + }) + ) + ); +} diff --git a/x-pack/plugins/logstash/server/types.ts b/x-pack/plugins/logstash/server/types.ts new file mode 100644 index 0000000000000..2b266b2f27708 --- /dev/null +++ b/x-pack/plugins/logstash/server/types.ts @@ -0,0 +1,27 @@ +/* + * 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 { SearchResponse } from 'elasticsearch'; +import { IScopedClusterClient } from 'src/core/server'; + +type UnwrapArray<T> = T extends Array<infer U> ? U : never; + +export type Hits = SearchResponse<any>['hits']['hits']; +export type Hit = UnwrapArray<Hits>; + +export interface PipelineListItemOptions { + id: string; + description: string; + last_modified: string; + username: string; +} + +declare module 'src/core/server' { + interface RequestHandlerContext { + logstash?: { + esClient: IScopedClusterClient; + }; + } +} diff --git a/x-pack/plugins/security/common/licensing/license_service.test.ts b/x-pack/plugins/security/common/licensing/license_service.test.ts index dfc94042ef930..5bdfa7d4886aa 100644 --- a/x-pack/plugins/security/common/licensing/license_service.test.ts +++ b/x-pack/plugins/security/common/licensing/license_service.test.ts @@ -78,14 +78,14 @@ describe('license features', function() { expect(subscriptionHandler.mock.calls[1]).toMatchInlineSnapshot(` Array [ Object { - "allowLogin": false, - "allowRbac": false, - "allowRoleDocumentLevelSecurity": false, - "allowRoleFieldLevelSecurity": false, - "allowSubFeaturePrivileges": false, - "showLinks": false, - "showLogin": false, - "showRoleMappingsManagement": false, + "allowLogin": true, + "allowRbac": true, + "allowRoleDocumentLevelSecurity": true, + "allowRoleFieldLevelSecurity": true, + "allowSubFeaturePrivileges": true, + "showLinks": true, + "showLogin": true, + "showRoleMappingsManagement": true, }, ] `); diff --git a/x-pack/test/api_integration/apis/logstash/cluster/index.js b/x-pack/test/api_integration/apis/logstash/cluster/index.ts similarity index 71% rename from x-pack/test/api_integration/apis/logstash/cluster/index.js rename to x-pack/test/api_integration/apis/logstash/cluster/index.ts index f016fde97ee4b..1d4fbd40b252b 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/index.js +++ b/x-pack/test/api_integration/apis/logstash/cluster/index.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ loadTestFile }) { +export default function({ loadTestFile }: FtrProviderContext) { describe('cluster', () => { loadTestFile(require.resolve('./load')); }); diff --git a/x-pack/test/api_integration/apis/logstash/cluster/load.js b/x-pack/test/api_integration/apis/logstash/cluster/load.ts similarity index 83% rename from x-pack/test/api_integration/apis/logstash/cluster/load.js rename to x-pack/test/api_integration/apis/logstash/cluster/load.ts index a348c6e4857b1..0678c5faf82dc 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/load.js +++ b/x-pack/test/api_integration/apis/logstash/cluster/load.ts @@ -5,8 +5,9 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('legacyEs'); diff --git a/x-pack/test/api_integration/apis/logstash/index.js b/x-pack/test/api_integration/apis/logstash/index.ts similarity index 76% rename from x-pack/test/api_integration/apis/logstash/index.js rename to x-pack/test/api_integration/apis/logstash/index.ts index 53293e5ff9423..582bef5a53bf2 100644 --- a/x-pack/test/api_integration/apis/logstash/index.js +++ b/x-pack/test/api_integration/apis/logstash/index.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../ftr_provider_context'; -export default function({ loadTestFile }) { +export default function({ loadTestFile }: FtrProviderContext) { describe('logstash', () => { loadTestFile(require.resolve('./pipelines')); loadTestFile(require.resolve('./pipeline')); diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/delete.js b/x-pack/test/api_integration/apis/logstash/pipeline/delete.ts similarity index 90% rename from x-pack/test/api_integration/apis/logstash/pipeline/delete.js rename to x-pack/test/api_integration/apis/logstash/pipeline/delete.ts index 85813f4ed04d1..cdbf5a3e6a1fe 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/delete.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/delete.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('delete', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/index.js b/x-pack/test/api_integration/apis/logstash/pipeline/index.ts similarity index 76% rename from x-pack/test/api_integration/apis/logstash/pipeline/index.js rename to x-pack/test/api_integration/apis/logstash/pipeline/index.ts index dcc8a01378e37..2697f7f428f5f 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/index.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/index.ts @@ -3,8 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export default function({ loadTestFile }) { +import { FtrProviderContext } from '../../../ftr_provider_context'; +export default function({ loadTestFile }: FtrProviderContext) { describe('pipeline', () => { loadTestFile(require.resolve('./load')); loadTestFile(require.resolve('./save')); diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/load.js b/x-pack/test/api_integration/apis/logstash/pipeline/load.ts similarity index 82% rename from x-pack/test/api_integration/apis/logstash/pipeline/load.js rename to x-pack/test/api_integration/apis/logstash/pipeline/load.ts index eb2ab6500a9dc..a892f527a6e61 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/load.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/load.ts @@ -5,9 +5,11 @@ */ import expect from '@kbn/expect'; -import pipeline from './fixtures/load'; +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +import pipeline from './fixtures/load.json'; + +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('list', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/save.js b/x-pack/test/api_integration/apis/logstash/pipeline/save.ts similarity index 90% rename from x-pack/test/api_integration/apis/logstash/pipeline/save.js rename to x-pack/test/api_integration/apis/logstash/pipeline/save.ts index ad35ee21f00fc..2ca9fbe7d68e0 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/save.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/save.ts @@ -5,8 +5,9 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('save', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipelines/delete.js b/x-pack/test/api_integration/apis/logstash/pipelines/delete.ts similarity index 90% rename from x-pack/test/api_integration/apis/logstash/pipelines/delete.js rename to x-pack/test/api_integration/apis/logstash/pipelines/delete.ts index 98ff5b99ea744..e71dc7f08ddc9 100644 --- a/x-pack/test/api_integration/apis/logstash/pipelines/delete.js +++ b/x-pack/test/api_integration/apis/logstash/pipelines/delete.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('delete', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipelines/index.js b/x-pack/test/api_integration/apis/logstash/pipelines/index.ts similarity index 73% rename from x-pack/test/api_integration/apis/logstash/pipelines/index.js rename to x-pack/test/api_integration/apis/logstash/pipelines/index.ts index 3abe2ee5ac43d..510bd625b54a0 100644 --- a/x-pack/test/api_integration/apis/logstash/pipelines/index.js +++ b/x-pack/test/api_integration/apis/logstash/pipelines/index.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ loadTestFile }) { +export default function({ loadTestFile }: FtrProviderContext) { describe('pipelines', () => { loadTestFile(require.resolve('./list')); loadTestFile(require.resolve('./delete')); diff --git a/x-pack/test/api_integration/apis/logstash/pipelines/list.js b/x-pack/test/api_integration/apis/logstash/pipelines/list.ts similarity index 82% rename from x-pack/test/api_integration/apis/logstash/pipelines/list.js rename to x-pack/test/api_integration/apis/logstash/pipelines/list.ts index fe5c3222a2ab1..a4ef52791ab70 100644 --- a/x-pack/test/api_integration/apis/logstash/pipelines/list.js +++ b/x-pack/test/api_integration/apis/logstash/pipelines/list.ts @@ -5,9 +5,10 @@ */ import expect from '@kbn/expect'; -import pipelineList from './fixtures/list'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import pipelineList from './fixtures/list.json'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('list', () => { From c2f2a79acb5037078022d939742ed6630b41cca2 Mon Sep 17 00:00:00 2001 From: Chris Cowan <chris@chriscowan.us> Date: Tue, 14 Apr 2020 09:01:41 -0700 Subject: [PATCH 101/121] [Metrics UI] Refactor With* containers to hooks (#59503) * [Metrics UI] Refactor containers to hooks * clean up depends; move useInterval out of useWaffleTime; * converting WithWaffleFilters to useWaffleFilters * Removing WithWaffleOptions * Refactor WithWaffleViewState to useWaffleViewState * Removing obsolete files * Fixing race condition with complext state * Adding undefined to RisonValue; unwinding changes trying to work around bad type * Switching to context * Change assertion to ignore the length of the current URL * Fixing test frameork to accept urls longer then 230 characters * Fixes #59395; Refactor WithMetricsTime to hook; Fixes brushing on metric detail page; fixes refresh button on metric detail page * Fixing tests with adding timeRange Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- test/functional/page_objects/common_page.ts | 24 +- test/typings/rison_node.d.ts | 2 +- typings/rison_node.d.ts | 2 +- .../infra/common/http_api/metadata_api.ts | 4 + .../inventory_models/aws_ec2/layout.tsx | 3 +- .../inventory_models/aws_rds/layout.tsx | 3 +- .../common/inventory_models/aws_s3/layout.tsx | 3 +- .../inventory_models/aws_sqs/layout.tsx | 3 +- .../inventory_models/container/layout.tsx | 3 +- .../common/inventory_models/host/layout.tsx | 8 +- .../common/inventory_models/pod/layout.tsx | 5 +- .../inventory_models/shared/layouts/aws.tsx | 3 +- .../inventory_models/shared/layouts/nginx.tsx | 9 +- .../common/saved_objects/inventory_view.ts | 10 +- .../plugins/infra/public/apps/start_app.tsx | 33 +-- .../public/components/inventory/layout.tsx | 105 ++++--- .../inventory/toolbars/save_views.tsx | 21 ++ .../components/inventory/toolbars/toolbar.tsx | 42 +-- .../inventory/toolbars/toolbar_wrapper.tsx | 74 +++-- .../components/nodes_overview/index.tsx | 6 +- .../infra/public/components/waffle/legend.tsx | 32 ++- .../waffle/lib/create_uptime_link.test.ts | 8 +- .../components/waffle/lib/type_guards.ts | 12 +- .../waffle/waffle_inventory_switcher.tsx | 35 +-- .../waffle/waffle_time_controls.tsx | 128 ++++----- .../containers/metadata/use_metadata.ts | 6 +- .../infra/public/containers/waffle/index.ts | 7 - .../waffle/waffle_nodes.gql_query.ts | 37 --- .../containers/waffle/with_waffle_filters.tsx | 96 ------- .../containers/waffle/with_waffle_options.tsx | 265 ------------------ .../containers/waffle/with_waffle_time.tsx | 96 ------- .../waffle/with_waffle_view_state.tsx | 145 ---------- .../infra/public/containers/with_options.tsx | 4 +- x-pack/plugins/infra/public/lib/lib.ts | 9 +- .../public/pages/infrastructure/index.tsx | 172 ++++++------ .../pages/infrastructure/snapshot/index.tsx | 11 +- .../infrastructure/snapshot/page_content.tsx | 68 ----- .../pages/infrastructure/snapshot/toolbar.tsx | 76 +---- .../inventory_view/compontents/search_bar.tsx | 40 +++ .../hooks/use_waffle_filters.ts | 93 ++++++ .../hooks/use_waffle_options.ts | 147 ++++++++++ .../inventory_view/hooks/use_waffle_time.ts | 76 +++++ .../hooks/use_waffle_view_state.ts | 95 +++++++ .../redirect_to_host_detail_via_ip.tsx | 2 +- .../pages/link_to/redirect_to_node_detail.tsx | 2 +- .../metrics/components/node_details_page.tsx | 4 +- .../pages/metrics/components/page_body.tsx | 8 +- .../pages/metrics/components/section.tsx | 3 + .../metrics/components/time_controls.test.tsx | 2 +- .../metrics/components/time_controls.tsx | 6 +- .../metrics/containers/metrics.gql_query.ts | 38 --- .../metrics/containers/with_metrics_time.tsx | 201 ------------- .../metrics_time.test.tsx | 2 +- .../pages/metrics/hooks/use_metrics_time.ts | 121 ++++++++ .../infra/public/pages/metrics/index.tsx | 101 ++++--- .../public/pages/metrics/page_providers.tsx | 6 +- .../infra/public/pages/metrics/types.ts | 2 +- x-pack/plugins/infra/public/store/actions.ts | 7 - x-pack/plugins/infra/public/store/epics.ts | 11 - x-pack/plugins/infra/public/store/index.ts | 11 - .../infra/public/store/local/actions.ts | 9 - .../plugins/infra/public/store/local/epic.ts | 11 - .../plugins/infra/public/store/local/index.ts | 10 - .../infra/public/store/local/reducer.ts | 33 --- .../infra/public/store/local/selectors.ts | 26 -- .../store/local/waffle_filter/actions.ts | 19 -- .../public/store/local/waffle_filter/index.ts | 11 - .../store/local/waffle_filter/reducer.ts | 43 --- .../store/local/waffle_filter/selectors.ts | 33 --- .../store/local/waffle_options/actions.ts | 29 -- .../store/local/waffle_options/index.ts | 11 - .../store/local/waffle_options/reducer.ts | 113 -------- .../store/local/waffle_options/selector.ts | 18 -- .../public/store/local/waffle_time/actions.ts | 15 - .../public/store/local/waffle_time/epic.ts | 38 --- .../public/store/local/waffle_time/index.ts | 12 - .../public/store/local/waffle_time/reducer.ts | 52 ---- .../store/local/waffle_time/selectors.ts | 23 -- x-pack/plugins/infra/public/store/reducer.ts | 21 -- .../plugins/infra/public/store/selectors.ts | 22 -- x-pack/plugins/infra/public/store/store.ts | 50 ---- .../infra/public/utils/redux_context.tsx | 16 -- .../infra/server/routes/metadata/index.ts | 13 +- .../metadata/lib/get_cloud_metric_metadata.ts | 16 +- .../metadata/lib/get_metric_metadata.ts | 12 +- .../api_integration/apis/infra/metadata.ts | 30 ++ x-pack/typings/rison_node.d.ts | 2 +- 87 files changed, 1087 insertions(+), 2149 deletions(-) create mode 100644 x-pack/plugins/infra/public/components/inventory/toolbars/save_views.tsx delete mode 100644 x-pack/plugins/infra/public/containers/waffle/index.ts delete mode 100644 x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts delete mode 100644 x-pack/plugins/infra/public/containers/waffle/with_waffle_filters.tsx delete mode 100644 x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx delete mode 100644 x-pack/plugins/infra/public/containers/waffle/with_waffle_time.tsx delete mode 100644 x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx delete mode 100644 x-pack/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx create mode 100644 x-pack/plugins/infra/public/pages/inventory_view/compontents/search_bar.tsx create mode 100644 x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_filters.ts create mode 100644 x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_options.ts create mode 100644 x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_time.ts create mode 100644 x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_view_state.ts delete mode 100644 x-pack/plugins/infra/public/pages/metrics/containers/metrics.gql_query.ts delete mode 100644 x-pack/plugins/infra/public/pages/metrics/containers/with_metrics_time.tsx rename x-pack/plugins/infra/public/pages/metrics/{containers => hooks}/metrics_time.test.tsx (96%) create mode 100644 x-pack/plugins/infra/public/pages/metrics/hooks/use_metrics_time.ts delete mode 100644 x-pack/plugins/infra/public/store/actions.ts delete mode 100644 x-pack/plugins/infra/public/store/epics.ts delete mode 100644 x-pack/plugins/infra/public/store/index.ts delete mode 100644 x-pack/plugins/infra/public/store/local/actions.ts delete mode 100644 x-pack/plugins/infra/public/store/local/epic.ts delete mode 100644 x-pack/plugins/infra/public/store/local/index.ts delete mode 100644 x-pack/plugins/infra/public/store/local/reducer.ts delete mode 100644 x-pack/plugins/infra/public/store/local/selectors.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_filter/actions.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_filter/index.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_filter/reducer.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_filter/selectors.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_options/actions.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_options/index.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_options/selector.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_time/actions.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_time/epic.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_time/index.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_time/reducer.ts delete mode 100644 x-pack/plugins/infra/public/store/local/waffle_time/selectors.ts delete mode 100644 x-pack/plugins/infra/public/store/reducer.ts delete mode 100644 x-pack/plugins/infra/public/store/selectors.ts delete mode 100644 x-pack/plugins/infra/public/store/store.ts delete mode 100644 x-pack/plugins/infra/public/utils/redux_context.tsx diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts index f06baeb7a4167..862e5127bb670 100644 --- a/test/functional/page_objects/common_page.ts +++ b/test/functional/page_objects/common_page.ts @@ -247,25 +247,11 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo } currentUrl = (await browser.getCurrentUrl()).replace(/\/\/\w+:\w+@/, '//'); - const maxAdditionalLengthOnNavUrl = 230; - - // On several test failures at the end of the TileMap test we try to navigate back to - // Visualize so we can create the next Vertical Bar Chart, but we can see from the - // logging and the screenshot that it's still on the TileMap page. Why didn't the "get" - // with a new timestamped URL go? I thought that sleep(700) between the get and the - // refresh would solve the problem but didn't seem to always work. - // So this hack fails the navSuccessful check if the currentUrl doesn't match the - // appUrl plus up to 230 other chars. - // Navigating to Settings when there is a default index pattern has a URL length of 196 - // (from debug output). Some other tabs may also be long. But a rather simple configured - // visualization is about 1000 chars long. So at least we catch that case. - - // Browsers don't show the ':port' if it's 80 or 443 so we have to - // remove that part so we can get a match in the tests. - const navSuccessful = new RegExp( - appUrl.replace(':80/', '/').replace(':443/', '/') + - `.{0,${maxAdditionalLengthOnNavUrl}}$` - ).test(currentUrl); + + const navSuccessful = currentUrl + .replace(':80/', '/') + .replace(':443/', '/') + .startsWith(appUrl); if (!navSuccessful) { const msg = `App failed to load: ${appName} in ${defaultFindTimeout}ms appUrl=${appUrl} currentUrl=${currentUrl}`; diff --git a/test/typings/rison_node.d.ts b/test/typings/rison_node.d.ts index 2592c36e8ae9a..a0497f421c3fe 100644 --- a/test/typings/rison_node.d.ts +++ b/test/typings/rison_node.d.ts @@ -18,7 +18,7 @@ */ declare module 'rison-node' { - export type RisonValue = null | boolean | number | string | RisonObject | RisonArray; + export type RisonValue = undefined | null | boolean | number | string | RisonObject | RisonArray; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface RisonArray extends Array<RisonValue> {} diff --git a/typings/rison_node.d.ts b/typings/rison_node.d.ts index 2592c36e8ae9a..a0497f421c3fe 100644 --- a/typings/rison_node.d.ts +++ b/typings/rison_node.d.ts @@ -18,7 +18,7 @@ */ declare module 'rison-node' { - export type RisonValue = null | boolean | number | string | RisonObject | RisonArray; + export type RisonValue = undefined | null | boolean | number | string | RisonObject | RisonArray; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface RisonArray extends Array<RisonValue> {} diff --git a/x-pack/plugins/infra/common/http_api/metadata_api.ts b/x-pack/plugins/infra/common/http_api/metadata_api.ts index 7fc3c3e876f08..5ee96b479be8e 100644 --- a/x-pack/plugins/infra/common/http_api/metadata_api.ts +++ b/x-pack/plugins/infra/common/http_api/metadata_api.ts @@ -11,6 +11,10 @@ export const InfraMetadataRequestRT = rt.type({ nodeId: rt.string, nodeType: ItemTypeRT, sourceId: rt.string, + timeRange: rt.type({ + from: rt.number, + to: rt.number, + }), }); export const InfraMetadataFeatureRT = rt.type({ diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/layout.tsx b/x-pack/plugins/infra/common/inventory_models/aws_ec2/layout.tsx index c8e0680287526..68bfe41fd538e 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_ec2/layout.tsx +++ b/x-pack/plugins/infra/common/inventory_models/aws_ec2/layout.tsx @@ -20,7 +20,7 @@ import { withTheme } from '../../../../observability/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { MetadataDetails } from '../../../public/pages/metrics/components/metadata_details'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, theme, onChangeRangeTime }: LayoutPropsWithTheme) => ( <React.Fragment> <MetadataDetails fields={[ @@ -42,6 +42,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="awsEC2CpuUtilization" diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/layout.tsx b/x-pack/plugins/infra/common/inventory_models/aws_rds/layout.tsx index 4bc4562ab2760..220c6c67f4aea 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_rds/layout.tsx +++ b/x-pack/plugins/infra/common/inventory_models/aws_rds/layout.tsx @@ -18,7 +18,7 @@ import { withTheme } from '../../../../observability/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { LayoutContent } from '../../../public/pages/metrics/components/layout_content'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> <LayoutContent> <Section @@ -30,6 +30,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="awsRDSCpuTotal" diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/layout.tsx b/x-pack/plugins/infra/common/inventory_models/aws_s3/layout.tsx index c40c8e7b8c6d3..805236cf47082 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_s3/layout.tsx +++ b/x-pack/plugins/infra/common/inventory_models/aws_s3/layout.tsx @@ -18,7 +18,7 @@ import { withTheme } from '../../../../observability/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { LayoutContent } from '../../../public/pages/metrics/components/layout_content'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> <LayoutContent> <Section @@ -30,6 +30,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="awsS3BucketSize" diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/layout.tsx b/x-pack/plugins/infra/common/inventory_models/aws_sqs/layout.tsx index 7f2dc92f42205..d581ac751682d 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_sqs/layout.tsx +++ b/x-pack/plugins/infra/common/inventory_models/aws_sqs/layout.tsx @@ -18,7 +18,7 @@ import { withTheme } from '../../../../observability/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { LayoutContent } from '../../../public/pages/metrics/components/layout_content'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> <LayoutContent> <Section @@ -30,6 +30,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="awsSQSMessagesVisible" diff --git a/x-pack/plugins/infra/common/inventory_models/container/layout.tsx b/x-pack/plugins/infra/common/inventory_models/container/layout.tsx index b61e8eed09cce..9956b2c9a2ce4 100644 --- a/x-pack/plugins/infra/common/inventory_models/container/layout.tsx +++ b/x-pack/plugins/infra/common/inventory_models/container/layout.tsx @@ -22,7 +22,7 @@ import { LayoutContent } from '../../../public/pages/metrics/components/layout_c // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { MetadataDetails } from '../../../public/pages/metrics/components/metadata_details'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> <MetadataDetails /> <LayoutContent> @@ -40,6 +40,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="containerOverview"> <GaugesSectionVis diff --git a/x-pack/plugins/infra/common/inventory_models/host/layout.tsx b/x-pack/plugins/infra/common/inventory_models/host/layout.tsx index 15e5530e8db53..6d7d361254220 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/layout.tsx +++ b/x-pack/plugins/infra/common/inventory_models/host/layout.tsx @@ -24,7 +24,7 @@ import { MetadataDetails } from '../../../public/pages/metrics/components/metada // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { LayoutContent } from '../../../public/pages/metrics/components/layout_content'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> <MetadataDetails fields={[ @@ -52,6 +52,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="hostSystemOverview"> <GaugesSectionVis @@ -242,6 +243,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="hostK8sOverview"> <GaugesSectionVis @@ -371,8 +373,8 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( /> </SubSection> </Section> - <Aws.Layout metrics={metrics} /> - <Ngnix.Layout metrics={metrics} /> + <Aws.Layout metrics={metrics} onChangeRangeTime={onChangeRangeTime} /> + <Ngnix.Layout metrics={metrics} onChangeRangeTime={onChangeRangeTime} /> </LayoutContent> </React.Fragment> )); diff --git a/x-pack/plugins/infra/common/inventory_models/pod/layout.tsx b/x-pack/plugins/infra/common/inventory_models/pod/layout.tsx index 43b95d73f6d95..8bc2f3ee8b4b3 100644 --- a/x-pack/plugins/infra/common/inventory_models/pod/layout.tsx +++ b/x-pack/plugins/infra/common/inventory_models/pod/layout.tsx @@ -23,7 +23,7 @@ import { MetadataDetails } from '../../../public/pages/metrics/components/metada // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { LayoutContent } from '../../../public/pages/metrics/components/layout_content'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> <MetadataDetails /> <LayoutContent> @@ -38,6 +38,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="podOverview"> <GaugesSectionVis @@ -161,7 +162,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( /> </SubSection> </Section> - <Nginx.Layout metrics={metrics} /> + <Nginx.Layout metrics={metrics} onChangeRangeTime={onChangeRangeTime} /> </LayoutContent> </React.Fragment> )); diff --git a/x-pack/plugins/infra/common/inventory_models/shared/layouts/aws.tsx b/x-pack/plugins/infra/common/inventory_models/shared/layouts/aws.tsx index fba48c4224e6b..7a0b898d406ce 100644 --- a/x-pack/plugins/infra/common/inventory_models/shared/layouts/aws.tsx +++ b/x-pack/plugins/infra/common/inventory_models/shared/layouts/aws.tsx @@ -18,7 +18,7 @@ import { ChartSectionVis } from '../../../../public/pages/metrics/components/cha // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { withTheme } from '../../../../../observability/public'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> <Section navLabel="AWS" @@ -29,6 +29,7 @@ export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( } )} metrics={metrics} + onChangeRangeTime={onChangeRangeTime} > <SubSection id="awsOverview"> <GaugesSectionVis diff --git a/x-pack/plugins/infra/common/inventory_models/shared/layouts/nginx.tsx b/x-pack/plugins/infra/common/inventory_models/shared/layouts/nginx.tsx index eff0a9bbca85a..79cea5150d498 100644 --- a/x-pack/plugins/infra/common/inventory_models/shared/layouts/nginx.tsx +++ b/x-pack/plugins/infra/common/inventory_models/shared/layouts/nginx.tsx @@ -16,9 +16,14 @@ import { ChartSectionVis } from '../../../../public/pages/metrics/components/cha // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { withTheme } from '../../../../../observability/public'; -export const Layout = withTheme(({ metrics, theme }: LayoutPropsWithTheme) => ( +export const Layout = withTheme(({ metrics, onChangeRangeTime, theme }: LayoutPropsWithTheme) => ( <React.Fragment> - <Section navLabel="Nginx" sectionLabel="Nginx" metrics={metrics}> + <Section + navLabel="Nginx" + sectionLabel="Nginx" + metrics={metrics} + onChangeRangeTime={onChangeRangeTime} + > <SubSection id="nginxHits" label={i18n.translate( diff --git a/x-pack/plugins/infra/common/saved_objects/inventory_view.ts b/x-pack/plugins/infra/common/saved_objects/inventory_view.ts index bccffadc0a1ba..8ae765f379add 100644 --- a/x-pack/plugins/infra/common/saved_objects/inventory_view.ts +++ b/x-pack/plugins/infra/common/saved_objects/inventory_view.ts @@ -7,7 +7,7 @@ // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ElasticsearchMappingOf } from '../../server/utils/typed_elasticsearch_mappings'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { WaffleViewState } from '../../public/containers/waffle/with_waffle_view_state'; +import { WaffleViewState } from '../../public/pages/inventory_view/hooks/use_waffle_view_state'; export const inventoryViewSavedObjectType = 'inventory-view'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths @@ -102,7 +102,7 @@ export const inventoryViewSavedObjectMappings: { type: 'boolean', }, time: { - type: 'integer', + type: 'long', }, autoReload: { type: 'boolean', @@ -117,6 +117,12 @@ export const inventoryViewSavedObjectMappings: { }, }, }, + accountId: { + type: 'keyword', + }, + region: { + type: 'keyword', + }, }, }, }; diff --git a/x-pack/plugins/infra/public/apps/start_app.tsx b/x-pack/plugins/infra/public/apps/start_app.tsx index a986ee6ece352..ebf9562c38d7a 100644 --- a/x-pack/plugins/infra/public/apps/start_app.tsx +++ b/x-pack/plugins/infra/public/apps/start_app.tsx @@ -8,9 +8,6 @@ import { createBrowserHistory } from 'history'; import React from 'react'; import ReactDOM from 'react-dom'; import { ApolloProvider } from 'react-apollo'; -import { Provider as ReduxStoreProvider } from 'react-redux'; -import { BehaviorSubject } from 'rxjs'; -import { pluck } from 'rxjs/operators'; import { CoreStart, AppMountParameters } from 'kibana/public'; // TODO use theme provided from parentApp when kibana supports it @@ -18,9 +15,7 @@ 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 { createStore } from '../store'; import { ApolloClientContext } from '../utils/apollo_context'; -import { ReduxStateContextProvider } from '../utils/redux_context'; import { HistoryContext } from '../utils/history_context'; import { useUiSetting$, @@ -43,12 +38,6 @@ export async function startApp( ) { const { element, appBasePath } = params; const history = createBrowserHistory({ basename: appBasePath }); - const libs$ = new BehaviorSubject(libs); - const store = createStore({ - apolloClient: libs$.pipe(pluck('apolloClient')), - observableApi: libs$.pipe(pluck('observableApi')), - }); - const InfraPluginRoot: React.FunctionComponent = () => { const [darkMode] = useUiSetting$<boolean>('theme:darkMode'); @@ -56,19 +45,15 @@ export async function startApp( <core.i18n.Context> <EuiErrorBoundary> <TriggersActionsProvider triggersActionsUI={triggersActionsUI}> - <ReduxStoreProvider store={store}> - <ReduxStateContextProvider> - <ApolloProvider client={libs.apolloClient}> - <ApolloClientContext.Provider value={libs.apolloClient}> - <EuiThemeProvider darkMode={darkMode}> - <HistoryContext.Provider value={history}> - <Router history={history} /> - </HistoryContext.Provider> - </EuiThemeProvider> - </ApolloClientContext.Provider> - </ApolloProvider> - </ReduxStateContextProvider> - </ReduxStoreProvider> + <ApolloProvider client={libs.apolloClient}> + <ApolloClientContext.Provider value={libs.apolloClient}> + <EuiThemeProvider darkMode={darkMode}> + <HistoryContext.Provider value={history}> + <Router history={history} /> + </HistoryContext.Provider> + </EuiThemeProvider> + </ApolloClientContext.Provider> + </ApolloProvider> </TriggersActionsProvider> </EuiErrorBoundary> </core.i18n.Context> diff --git a/x-pack/plugins/infra/public/components/inventory/layout.tsx b/x-pack/plugins/infra/public/components/inventory/layout.tsx index 4dd9803c7bfce..3c91f9fa5946f 100644 --- a/x-pack/plugins/infra/public/components/inventory/layout.tsx +++ b/x-pack/plugins/infra/public/components/inventory/layout.tsx @@ -5,64 +5,89 @@ */ import React from 'react'; -import { InfraWaffleMapOptions, InfraWaffleMapBounds } from '../../lib/lib'; -import { KueryFilterQuery } from '../../store/local/waffle_filter'; +import { useInterval } from 'react-use'; +import { euiPaletteColorBlind } from '@elastic/eui'; import { NodesOverview } from '../nodes_overview'; import { Toolbar } from './toolbars/toolbar'; import { PageContent } from '../page'; import { useSnapshot } from '../../containers/waffle/use_snaphot'; import { useInventoryMeta } from '../../containers/inventory_metadata/use_inventory_meta'; -import { SnapshotMetricInput, SnapshotGroupBy } from '../../../common/http_api/snapshot_api'; -import { InventoryItemType } from '../../../common/inventory_models/types'; +import { useWaffleTimeContext } from '../../pages/inventory_view/hooks/use_waffle_time'; +import { useWaffleFiltersContext } from '../../pages/inventory_view/hooks/use_waffle_filters'; +import { useWaffleOptionsContext } from '../../pages/inventory_view/hooks/use_waffle_options'; +import { useSourceContext } from '../../containers/source'; +import { InfraFormatterType, InfraWaffleMapGradientLegend } from '../../lib/lib'; -export interface LayoutProps { - options: InfraWaffleMapOptions; - nodeType: InventoryItemType; - onDrilldown: (filter: KueryFilterQuery) => void; - currentTime: number; - onViewChange: (view: string) => void; - view: string; - boundsOverride: InfraWaffleMapBounds; - autoBounds: boolean; +const euiVisColorPalette = euiPaletteColorBlind(); - filterQuery: string | null | undefined; - metric: SnapshotMetricInput; - groupBy: SnapshotGroupBy; - sourceId: string; - accountId: string; - region: string; -} - -export const Layout = (props: LayoutProps) => { - const { accounts, regions } = useInventoryMeta(props.sourceId, props.nodeType); +export const Layout = () => { + const { sourceId, source } = useSourceContext(); + const { + metric, + groupBy, + nodeType, + accountId, + region, + changeView, + view, + autoBounds, + boundsOverride, + } = useWaffleOptionsContext(); + const { accounts, regions } = useInventoryMeta(sourceId, nodeType); + const { currentTime, jumpToTime, isAutoReloading } = useWaffleTimeContext(); + const { filterQueryAsJson, applyFilterQuery } = useWaffleFiltersContext(); const { loading, nodes, reload, interval } = useSnapshot( - props.filterQuery, - props.metric, - props.groupBy, - props.nodeType, - props.sourceId, - props.currentTime, - props.accountId, - props.region + filterQueryAsJson, + metric, + groupBy, + nodeType, + sourceId, + currentTime, + accountId, + region + ); + + const options = { + formatter: InfraFormatterType.percent, + formatTemplate: '{{value}}', + legend: { + type: 'gradient', + rules: [ + { value: 0, color: '#D3DAE6' }, + { value: 1, color: euiVisColorPalette[1] }, + ], + } as InfraWaffleMapGradientLegend, + metric, + fields: source?.configuration?.fields, + groupBy, + }; + + useInterval( + () => { + if (!loading) { + jumpToTime(Date.now()); + } + }, + isAutoReloading ? 5000 : null ); return ( <> - <Toolbar accounts={accounts} regions={regions} nodeType={props.nodeType} /> + <Toolbar accounts={accounts} regions={regions} nodeType={nodeType} /> <PageContent> <NodesOverview nodes={nodes} - options={props.options} - nodeType={props.nodeType} + options={options} + nodeType={nodeType} loading={loading} reload={reload} - onDrilldown={props.onDrilldown} - currentTime={props.currentTime} - onViewChange={props.onViewChange} - view={props.view} - autoBounds={props.autoBounds} - boundsOverride={props.boundsOverride} + onDrilldown={applyFilterQuery} + currentTime={currentTime} + onViewChange={changeView} + view={view} + autoBounds={autoBounds} + boundsOverride={boundsOverride} interval={interval} /> </PageContent> diff --git a/x-pack/plugins/infra/public/components/inventory/toolbars/save_views.tsx b/x-pack/plugins/infra/public/components/inventory/toolbars/save_views.tsx new file mode 100644 index 0000000000000..cb315d3e17b03 --- /dev/null +++ b/x-pack/plugins/infra/public/components/inventory/toolbars/save_views.tsx @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import { SavedViewsToolbarControls } from '../../saved_views/toolbar_control'; +import { inventoryViewSavedObjectType } from '../../../../common/saved_objects/inventory_view'; +import { useWaffleViewState } from '../../../pages/inventory_view/hooks/use_waffle_view_state'; + +export const SavedViews = () => { + const { viewState, defaultViewState, onViewChange } = useWaffleViewState(); + return ( + <SavedViewsToolbarControls + defaultViewState={defaultViewState} + viewState={viewState} + onViewChange={onViewChange} + viewType={inventoryViewSavedObjectType} + /> + ); +}; diff --git a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx index c59ab994a018c..63ab6d2f4465a 100644 --- a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx +++ b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar.tsx @@ -5,7 +5,6 @@ */ import React, { FunctionComponent } from 'react'; -import { Action } from 'typescript-fsa'; import { EuiFlexItem } from '@elastic/eui'; import { SnapshotMetricInput, @@ -16,33 +15,23 @@ import { InventoryCloudAccount } from '../../../../common/http_api/inventory_met import { findToolbar } from '../../../../common/inventory_models/toolbars'; import { ToolbarWrapper } from './toolbar_wrapper'; -import { waffleOptionsSelectors } from '../../../store'; import { InfraGroupByOptions } from '../../../lib/lib'; -import { WithWaffleViewState } from '../../../containers/waffle/with_waffle_view_state'; -import { SavedViewsToolbarControls } from '../../saved_views/toolbar_control'; -import { inventoryViewSavedObjectType } from '../../../../common/saved_objects/inventory_view'; import { IIndexPattern } from '../../../../../../../src/plugins/data/public'; import { InventoryItemType } from '../../../../common/inventory_models/types'; +import { WaffleOptionsState } from '../../../pages/inventory_view/hooks/use_waffle_options'; +import { SavedViews } from './save_views'; -export interface ToolbarProps { +export interface ToolbarProps + extends Omit<WaffleOptionsState, 'view' | 'boundsOverride' | 'autoBounds'> { createDerivedIndexPattern: (type: 'logs' | 'metrics' | 'both') => IIndexPattern; - changeMetric: (payload: SnapshotMetricInput) => Action<SnapshotMetricInput>; - changeGroupBy: (payload: SnapshotGroupBy) => Action<SnapshotGroupBy>; - changeCustomOptions: (payload: InfraGroupByOptions[]) => Action<InfraGroupByOptions[]>; - changeAccount: (id: string) => Action<string>; - changeRegion: (name: string) => Action<string>; - customOptions: ReturnType<typeof waffleOptionsSelectors.selectCustomOptions>; - groupBy: ReturnType<typeof waffleOptionsSelectors.selectGroupBy>; - metric: ReturnType<typeof waffleOptionsSelectors.selectMetric>; - nodeType: ReturnType<typeof waffleOptionsSelectors.selectNodeType>; - accountId: ReturnType<typeof waffleOptionsSelectors.selectAccountId>; - region: ReturnType<typeof waffleOptionsSelectors.selectRegion>; + changeMetric: (payload: SnapshotMetricInput) => void; + changeGroupBy: (payload: SnapshotGroupBy) => void; + changeCustomOptions: (payload: InfraGroupByOptions[]) => void; + changeAccount: (id: string) => void; + changeRegion: (name: string) => void; accounts: InventoryCloudAccount[]; regions: string[]; - customMetrics: ReturnType<typeof waffleOptionsSelectors.selectCustomMetrics>; - changeCustomMetrics: ( - payload: SnapshotCustomMetricInput[] - ) => Action<SnapshotCustomMetricInput[]>; + changeCustomMetrics: (payload: SnapshotCustomMetricInput[]) => void; } const wrapToolbarItems = ( @@ -57,16 +46,7 @@ const wrapToolbarItems = ( <ToolbarItems {...props} accounts={accounts} regions={regions} /> <EuiFlexItem grow={true} /> <EuiFlexItem grow={false}> - <WithWaffleViewState indexPattern={props.createDerivedIndexPattern('metrics')}> - {({ defaultViewState, viewState, onViewChange }) => ( - <SavedViewsToolbarControls - defaultViewState={defaultViewState} - viewState={viewState} - onViewChange={onViewChange} - viewType={inventoryViewSavedObjectType} - /> - )} - </WithWaffleViewState> + <SavedViews /> </EuiFlexItem> </> )} diff --git a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx index 735539d063b01..fefda94372cfb 100644 --- a/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx +++ b/x-pack/plugins/infra/public/components/inventory/toolbars/toolbar_wrapper.tsx @@ -8,58 +8,52 @@ import React from 'react'; import { EuiFlexGroup } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { SnapshotMetricType } from '../../../../common/inventory_models/types'; -import { WithSource } from '../../../containers/with_source'; -import { WithWaffleOptions } from '../../../containers/waffle/with_waffle_options'; import { Toolbar } from '../../eui/toolbar'; import { ToolbarProps } from './toolbar'; import { fieldToName } from '../../waffle/lib/field_to_display_name'; +import { useSourceContext } from '../../../containers/source'; +import { useWaffleOptionsContext } from '../../../pages/inventory_view/hooks/use_waffle_options'; interface Props { children: (props: Omit<ToolbarProps, 'accounts' | 'regions'>) => React.ReactElement; } export const ToolbarWrapper = (props: Props) => { + const { + changeMetric, + changeGroupBy, + changeCustomOptions, + changeAccount, + changeRegion, + customOptions, + groupBy, + metric, + nodeType, + accountId, + region, + customMetrics, + changeCustomMetrics, + } = useWaffleOptionsContext(); + const { createDerivedIndexPattern } = useSourceContext(); return ( <Toolbar> <EuiFlexGroup alignItems="center" gutterSize="m"> - <WithSource> - {({ createDerivedIndexPattern }) => ( - <WithWaffleOptions> - {({ - changeMetric, - changeGroupBy, - changeCustomOptions, - changeAccount, - changeRegion, - customOptions, - groupBy, - metric, - nodeType, - accountId, - region, - customMetrics, - changeCustomMetrics, - }) => - props.children({ - createDerivedIndexPattern, - changeMetric, - changeGroupBy, - changeAccount, - changeRegion, - changeCustomOptions, - customOptions, - groupBy, - metric, - nodeType, - region, - accountId, - customMetrics, - changeCustomMetrics, - }) - } - </WithWaffleOptions> - )} - </WithSource> + {props.children({ + createDerivedIndexPattern, + changeMetric, + changeGroupBy, + changeAccount, + changeRegion, + changeCustomOptions, + customOptions, + groupBy, + metric, + nodeType, + region, + accountId, + customMetrics, + changeCustomMetrics, + })} </EuiFlexGroup> </Toolbar> ); diff --git a/x-pack/plugins/infra/public/components/nodes_overview/index.tsx b/x-pack/plugins/infra/public/components/nodes_overview/index.tsx index 4d61568a63b9f..ef22e0486f892 100644 --- a/x-pack/plugins/infra/public/components/nodes_overview/index.tsx +++ b/x-pack/plugins/infra/public/components/nodes_overview/index.tsx @@ -12,7 +12,6 @@ import React from 'react'; import { euiStyled } from '../../../../observability/public'; import { InfraFormatterType, InfraWaffleMapBounds, InfraWaffleMapOptions } from '../../lib/lib'; -import { KueryFilterQuery } from '../../store/local/waffle_filter'; import { createFormatter } from '../../utils/formatters'; import { NoData } from '../empty_states'; import { InfraLoadingPanel } from '../loading'; @@ -24,6 +23,11 @@ import { convertIntervalToString } from '../../utils/convert_interval_to_string' import { InventoryItemType } from '../../../common/inventory_models/types'; import { createFormatterForMetric } from '../metrics_explorer/helpers/create_formatter_for_metric'; +export interface KueryFilterQuery { + kind: 'kuery'; + expression: string; +} + interface Props { options: InfraWaffleMapOptions; nodeType: InventoryItemType; diff --git a/x-pack/plugins/infra/public/components/waffle/legend.tsx b/x-pack/plugins/infra/public/components/waffle/legend.tsx index de070efb35a1f..13e533b225d4d 100644 --- a/x-pack/plugins/infra/public/components/waffle/legend.tsx +++ b/x-pack/plugins/infra/public/components/waffle/legend.tsx @@ -6,12 +6,12 @@ import React from 'react'; import { euiStyled } from '../../../../observability/public'; -import { WithWaffleOptions } from '../../containers/waffle/with_waffle_options'; import { InfraFormatter, InfraWaffleMapBounds, InfraWaffleMapLegend } from '../../lib/lib'; import { GradientLegend } from './gradient_legend'; import { LegendControls } from './legend_controls'; import { isInfraWaffleMapGradientLegend, isInfraWaffleMapStepLegend } from './lib/type_guards'; import { StepLegend } from './steps_legend'; +import { useWaffleOptionsContext } from '../../pages/inventory_view/hooks/use_waffle_options'; interface Props { legend: InfraWaffleMapLegend; bounds: InfraWaffleMapBounds; @@ -25,22 +25,24 @@ interface LegendControlOptions { } export const Legend: React.FC<Props> = ({ dataBounds, legend, bounds, formatter }) => { + const { + changeBoundsOverride, + changeAutoBounds, + autoBounds, + boundsOverride, + } = useWaffleOptionsContext(); return ( <LegendContainer> - <WithWaffleOptions> - {({ changeBoundsOverride, changeAutoBounds, autoBounds, boundsOverride }) => ( - <LegendControls - dataBounds={dataBounds} - bounds={bounds} - autoBounds={autoBounds} - boundsOverride={boundsOverride} - onChange={(options: LegendControlOptions) => { - changeBoundsOverride(options.bounds); - changeAutoBounds(options.auto); - }} - /> - )} - </WithWaffleOptions> + <LegendControls + dataBounds={dataBounds} + bounds={bounds} + autoBounds={autoBounds} + boundsOverride={boundsOverride} + onChange={(options: LegendControlOptions) => { + changeBoundsOverride(options.bounds); + changeAutoBounds(options.auto); + }} + /> {isInfraWaffleMapGradientLegend(legend) && ( <GradientLegend formatter={formatter} legend={legend} bounds={bounds} /> )} diff --git a/x-pack/plugins/infra/public/components/waffle/lib/create_uptime_link.test.ts b/x-pack/plugins/infra/public/components/waffle/lib/create_uptime_link.test.ts index 18e5838a15b56..902969c83ba39 100644 --- a/x-pack/plugins/infra/public/components/waffle/lib/create_uptime_link.test.ts +++ b/x-pack/plugins/infra/public/components/waffle/lib/create_uptime_link.test.ts @@ -5,11 +5,7 @@ */ import { createUptimeLink } from './create_uptime_link'; -import { - InfraWaffleMapOptions, - InfraWaffleMapLegendMode, - InfraFormatterType, -} from '../../../lib/lib'; +import { InfraWaffleMapOptions, InfraFormatterType } from '../../../lib/lib'; import { SnapshotMetricType } from '../../../../common/inventory_models/types'; const options: InfraWaffleMapOptions = { @@ -26,7 +22,7 @@ const options: InfraWaffleMapOptions = { metric: { type: 'cpu' }, groupBy: [], legend: { - type: InfraWaffleMapLegendMode.gradient, + type: 'gradient', rules: [], }, }; diff --git a/x-pack/plugins/infra/public/components/waffle/lib/type_guards.ts b/x-pack/plugins/infra/public/components/waffle/lib/type_guards.ts index aff16374ae262..f793afee1b948 100644 --- a/x-pack/plugins/infra/public/components/waffle/lib/type_guards.ts +++ b/x-pack/plugins/infra/public/components/waffle/lib/type_guards.ts @@ -4,16 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - InfraWaffleMapGradientLegend, - InfraWaffleMapLegendMode, - InfraWaffleMapStepLegend, -} from '../../../lib/lib'; +import { InfraWaffleMapGradientLegend, InfraWaffleMapStepLegend } from '../../../lib/lib'; + export function isInfraWaffleMapStepLegend(subject: any): subject is InfraWaffleMapStepLegend { - return subject.type && subject.type === InfraWaffleMapLegendMode.step; + return subject.type && subject.type === 'step'; } + export function isInfraWaffleMapGradientLegend( subject: any ): subject is InfraWaffleMapGradientLegend { - return subject.type && subject.type === InfraWaffleMapLegendMode.gradient; + return subject.type && subject.type === 'gradient'; } diff --git a/x-pack/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx b/x-pack/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx index d265b418f010d..21da10a0a7650 100644 --- a/x-pack/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx +++ b/x-pack/plugins/infra/public/components/waffle/waffle_inventory_switcher.tsx @@ -16,36 +16,23 @@ import React, { useCallback, useState, useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { findInventoryModel } from '../../../common/inventory_models'; import { InventoryItemType } from '../../../common/inventory_models/types'; -import { - SnapshotMetricInput, - SnapshotGroupBy, - SnapshotCustomMetricInput, -} from '../../../common/http_api/snapshot_api'; - -interface WaffleInventorySwitcherProps { - nodeType: InventoryItemType; - changeNodeType: (nodeType: InventoryItemType) => void; - changeGroupBy: (groupBy: SnapshotGroupBy) => void; - changeMetric: (metric: SnapshotMetricInput) => void; - changeCustomMetrics: (metrics: SnapshotCustomMetricInput[]) => void; - changeAccount: (id: string) => void; - changeRegion: (name: string) => void; -} +import { useWaffleOptionsContext } from '../../pages/inventory_view/hooks/use_waffle_options'; const getDisplayNameForType = (type: InventoryItemType) => { const inventoryModel = findInventoryModel(type); return inventoryModel.displayName; }; -export const WaffleInventorySwitcher: React.FC<WaffleInventorySwitcherProps> = ({ - changeNodeType, - changeGroupBy, - changeMetric, - changeAccount, - changeRegion, - changeCustomMetrics, - nodeType, -}) => { +export const WaffleInventorySwitcher: React.FC = () => { + const { + changeNodeType, + changeGroupBy, + changeMetric, + changeAccount, + changeRegion, + changeCustomMetrics, + nodeType, + } = useWaffleOptionsContext(); const [isOpen, setIsOpen] = useState(false); const closePopover = useCallback(() => setIsOpen(false), []); const openPopover = useCallback(() => setIsOpen(true), []); diff --git a/x-pack/plugins/infra/public/components/waffle/waffle_time_controls.tsx b/x-pack/plugins/infra/public/components/waffle/waffle_time_controls.tsx index 4f840336de8c3..458bb674afade 100644 --- a/x-pack/plugins/infra/public/components/waffle/waffle_time_controls.tsx +++ b/x-pack/plugins/infra/public/components/waffle/waffle_time_controls.tsx @@ -7,84 +7,60 @@ import { EuiButtonEmpty, EuiDatePicker, EuiFormControlLayout } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import moment, { Moment } from 'moment'; -import React from 'react'; -import { Action } from 'typescript-fsa'; +import React, { useCallback } from 'react'; +import { useWaffleTimeContext } from '../../pages/inventory_view/hooks/use_waffle_time'; -interface WaffleTimeControlsProps { - currentTime: number; - isLiveStreaming?: boolean; - onChangeTime?: (time: number) => void; - startLiveStreaming?: (payload: void) => Action<void>; - stopLiveStreaming?: (payload: void) => Action<void>; -} +export const WaffleTimeControls = () => { + const { + currentTime, + isAutoReloading, + startAutoReload, + stopAutoReload, + jumpToTime, + } = useWaffleTimeContext(); -export class WaffleTimeControls extends React.Component<WaffleTimeControlsProps> { - public render() { - const { currentTime, isLiveStreaming } = this.props; + const currentMoment = moment(currentTime); - const currentMoment = moment(currentTime); + const liveStreamingButton = isAutoReloading ? ( + <EuiButtonEmpty color="primary" iconSide="left" iconType="pause" onClick={stopAutoReload}> + <FormattedMessage + id="xpack.infra.waffleTime.stopRefreshingButtonLabel" + defaultMessage="Stop refreshing" + /> + </EuiButtonEmpty> + ) : ( + <EuiButtonEmpty iconSide="left" iconType="play" onClick={startAutoReload}> + <FormattedMessage + id="xpack.infra.waffleTime.autoRefreshButtonLabel" + defaultMessage="Auto-refresh" + /> + </EuiButtonEmpty> + ); - const liveStreamingButton = isLiveStreaming ? ( - <EuiButtonEmpty - color="primary" - iconSide="left" - iconType="pause" - onClick={this.stopLiveStreaming} - > - <FormattedMessage - id="xpack.infra.waffleTime.stopRefreshingButtonLabel" - defaultMessage="Stop refreshing" - /> - </EuiButtonEmpty> - ) : ( - <EuiButtonEmpty iconSide="left" iconType="play" onClick={this.startLiveStreaming}> - <FormattedMessage - id="xpack.infra.waffleTime.autoRefreshButtonLabel" - defaultMessage="Auto-refresh" - /> - </EuiButtonEmpty> - ); + const handleChangeDate = useCallback( + (time: Moment | null) => { + if (time) { + jumpToTime(time.valueOf()); + } + }, + [jumpToTime] + ); - return ( - <EuiFormControlLayout append={liveStreamingButton} data-test-subj="waffleDatePicker"> - <EuiDatePicker - className="euiFieldText--inGroup" - dateFormat="L LTS" - disabled={isLiveStreaming} - injectTimes={currentMoment ? [currentMoment] : []} - isLoading={isLiveStreaming} - onChange={this.handleChangeDate} - popperPlacement="top-end" - selected={currentMoment} - shouldCloseOnSelect - showTimeSelect - timeFormat="LT" - /> - </EuiFormControlLayout> - ); - } - - private handleChangeDate = (time: Moment | null) => { - const { onChangeTime } = this.props; - - if (onChangeTime && time) { - onChangeTime(time.valueOf()); - } - }; - - private startLiveStreaming = () => { - const { startLiveStreaming } = this.props; - - if (startLiveStreaming) { - startLiveStreaming(); - } - }; - - private stopLiveStreaming = () => { - const { stopLiveStreaming } = this.props; - - if (stopLiveStreaming) { - stopLiveStreaming(); - } - }; -} + return ( + <EuiFormControlLayout append={liveStreamingButton} data-test-subj="waffleDatePicker"> + <EuiDatePicker + className="euiFieldText--inGroup" + dateFormat="L LTS" + disabled={isAutoReloading} + injectTimes={currentMoment ? [currentMoment] : []} + isLoading={isAutoReloading} + onChange={handleChangeDate} + popperPlacement="top-end" + selected={currentMoment} + shouldCloseOnSelect + showTimeSelect + timeFormat="LT" + /> + </EuiFormControlLayout> + ); +}; diff --git a/x-pack/plugins/infra/public/containers/metadata/use_metadata.ts b/x-pack/plugins/infra/public/containers/metadata/use_metadata.ts index 52c522ce8efd4..1ba016195bef4 100644 --- a/x-pack/plugins/infra/public/containers/metadata/use_metadata.ts +++ b/x-pack/plugins/infra/public/containers/metadata/use_metadata.ts @@ -13,17 +13,18 @@ import { useHTTPRequest } from '../../hooks/use_http_request'; import { throwErrors, createPlainError } from '../../../common/runtime_types'; import { InventoryMetric, InventoryItemType } from '../../../common/inventory_models/types'; import { getFilteredMetrics } from './lib/get_filtered_metrics'; +import { MetricsTimeInput } from '../../pages/metrics/hooks/use_metrics_time'; export function useMetadata( nodeId: string, nodeType: InventoryItemType, requiredMetrics: InventoryMetric[], - sourceId: string + sourceId: string, + timeRange: MetricsTimeInput ) { const decodeResponse = (response: any) => { return pipe(InfraMetadataRT.decode(response), fold(throwErrors(createPlainError), identity)); }; - const { error, loading, response, makeRequest } = useHTTPRequest<InfraMetadata>( '/api/infra/metadata', 'POST', @@ -31,6 +32,7 @@ export function useMetadata( nodeId, nodeType, sourceId, + timeRange: { from: timeRange.from, to: timeRange.to }, }), decodeResponse ); diff --git a/x-pack/plugins/infra/public/containers/waffle/index.ts b/x-pack/plugins/infra/public/containers/waffle/index.ts deleted file mode 100644 index 40c4bfc8cf678..0000000000000 --- a/x-pack/plugins/infra/public/containers/waffle/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './with_waffle_filters'; diff --git a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts b/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts deleted file mode 100644 index 1ca6bc8c397e5..0000000000000 --- a/x-pack/plugins/infra/public/containers/waffle/waffle_nodes.gql_query.ts +++ /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 gql from 'graphql-tag'; - -export const waffleNodesQuery = gql` - query WaffleNodesQuery( - $sourceId: ID! - $timerange: InfraTimerangeInput! - $filterQuery: String - $metric: InfraSnapshotMetricInput! - $groupBy: [InfraSnapshotGroupbyInput!]! - $type: InfraNodeType! - ) { - source(id: $sourceId) { - id - snapshot(timerange: $timerange, filterQuery: $filterQuery) { - nodes(groupBy: $groupBy, metric: $metric, type: $type) { - path { - value - label - ip - } - metric { - name - value - avg - max - } - } - } - } - } -`; diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_filters.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_filters.tsx deleted file mode 100644 index 0214237ef52d8..0000000000000 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_filters.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { connect } from 'react-redux'; - -import { IIndexPattern } from 'src/plugins/data/public'; -import { State, waffleFilterActions, waffleFilterSelectors } from '../../store'; -import { FilterQuery } from '../../store/local/waffle_filter'; -import { convertKueryToElasticSearchQuery } from '../../utils/kuery'; -import { asChildFunctionRenderer } from '../../utils/typed_react'; -import { bindPlainActionCreators } from '../../utils/typed_redux'; -import { UrlStateContainer } from '../../utils/url_state'; - -interface WithWaffleFilterProps { - indexPattern: IIndexPattern; -} - -export const withWaffleFilter = connect( - (state: State) => ({ - filterQuery: waffleFilterSelectors.selectWaffleFilterQuery(state), - filterQueryDraft: waffleFilterSelectors.selectWaffleFilterQueryDraft(state), - filterQueryAsJson: waffleFilterSelectors.selectWaffleFilterQueryAsJson(state), - isFilterQueryDraftValid: waffleFilterSelectors.selectIsWaffleFilterQueryDraftValid(state), - }), - (dispatch, ownProps: WithWaffleFilterProps) => - bindPlainActionCreators({ - applyFilterQuery: (query: FilterQuery) => - waffleFilterActions.applyWaffleFilterQuery({ - query, - serializedQuery: convertKueryToElasticSearchQuery( - query.expression, - ownProps.indexPattern - ), - }), - applyFilterQueryFromKueryExpression: (expression: string) => - waffleFilterActions.applyWaffleFilterQuery({ - query: { - kind: 'kuery', - expression, - }, - serializedQuery: convertKueryToElasticSearchQuery(expression, ownProps.indexPattern), - }), - setFilterQueryDraft: waffleFilterActions.setWaffleFilterQueryDraft, - setFilterQueryDraftFromKueryExpression: (expression: string) => - waffleFilterActions.setWaffleFilterQueryDraft({ - kind: 'kuery', - expression, - }), - }) -); - -export const WithWaffleFilter = asChildFunctionRenderer(withWaffleFilter); - -/** - * Url State - */ - -type WaffleFilterUrlState = ReturnType<typeof waffleFilterSelectors.selectWaffleFilterQuery>; - -type WithWaffleFilterUrlStateProps = WithWaffleFilterProps; - -export const WithWaffleFilterUrlState: React.FC<WithWaffleFilterUrlStateProps> = ({ - indexPattern, -}) => ( - <WithWaffleFilter indexPattern={indexPattern}> - {({ applyFilterQuery, filterQuery }) => ( - <UrlStateContainer - urlState={filterQuery} - urlStateKey="waffleFilter" - mapToUrlState={mapToUrlState} - onChange={urlState => { - if (urlState) { - applyFilterQuery(urlState); - } - }} - onInitialize={urlState => { - if (urlState) { - applyFilterQuery(urlState); - } - }} - /> - )} - </WithWaffleFilter> -); - -const mapToUrlState = (value: any): WaffleFilterUrlState | undefined => - value && value.kind === 'kuery' && typeof value.expression === 'string' - ? { - kind: value.kind, - expression: value.expression, - } - : undefined; diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx deleted file mode 100644 index 47dd6a5a73a73..0000000000000 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_options.tsx +++ /dev/null @@ -1,265 +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 { connect } from 'react-redux'; -import { createSelector } from 'reselect'; - -import { isBoolean, isNumber } from 'lodash'; -import { InfraGroupByOptions } from '../../lib/lib'; -import { State, waffleOptionsActions, waffleOptionsSelectors } from '../../store'; -import { asChildFunctionRenderer } from '../../utils/typed_react'; -import { bindPlainActionCreators } from '../../utils/typed_redux'; -import { UrlStateContainer } from '../../utils/url_state'; -import { - SnapshotMetricInput, - SnapshotGroupBy, - SnapshotCustomMetricInputRT, -} from '../../../common/http_api/snapshot_api'; -import { - SnapshotMetricTypeRT, - InventoryItemType, - ItemTypeRT, -} from '../../../common/inventory_models/types'; - -const selectOptionsUrlState = createSelector( - waffleOptionsSelectors.selectMetric, - waffleOptionsSelectors.selectView, - waffleOptionsSelectors.selectGroupBy, - waffleOptionsSelectors.selectNodeType, - waffleOptionsSelectors.selectCustomOptions, - waffleOptionsSelectors.selectBoundsOverride, - waffleOptionsSelectors.selectAutoBounds, - waffleOptionsSelectors.selectAccountId, - waffleOptionsSelectors.selectRegion, - waffleOptionsSelectors.selectCustomMetrics, - ( - metric, - view, - groupBy, - nodeType, - customOptions, - boundsOverride, - autoBounds, - accountId, - region, - customMetrics - ) => ({ - metric, - groupBy, - nodeType, - view, - customOptions, - boundsOverride, - autoBounds, - accountId, - region, - customMetrics, - }) -); - -export const withWaffleOptions = connect( - (state: State) => ({ - metric: waffleOptionsSelectors.selectMetric(state), - groupBy: waffleOptionsSelectors.selectGroupBy(state), - nodeType: waffleOptionsSelectors.selectNodeType(state), - view: waffleOptionsSelectors.selectView(state), - customOptions: waffleOptionsSelectors.selectCustomOptions(state), - boundsOverride: waffleOptionsSelectors.selectBoundsOverride(state), - autoBounds: waffleOptionsSelectors.selectAutoBounds(state), - accountId: waffleOptionsSelectors.selectAccountId(state), - region: waffleOptionsSelectors.selectRegion(state), - urlState: selectOptionsUrlState(state), - customMetrics: waffleOptionsSelectors.selectCustomMetrics(state), - }), - bindPlainActionCreators({ - changeMetric: waffleOptionsActions.changeMetric, - changeGroupBy: waffleOptionsActions.changeGroupBy, - changeNodeType: waffleOptionsActions.changeNodeType, - changeView: waffleOptionsActions.changeView, - changeCustomOptions: waffleOptionsActions.changeCustomOptions, - changeBoundsOverride: waffleOptionsActions.changeBoundsOverride, - changeAutoBounds: waffleOptionsActions.changeAutoBounds, - changeAccount: waffleOptionsActions.changeAccount, - changeRegion: waffleOptionsActions.changeRegion, - changeCustomMetrics: waffleOptionsActions.changeCustomMetrics, - }) -); - -export const WithWaffleOptions = asChildFunctionRenderer(withWaffleOptions); - -/** - * Url State - */ - -interface WaffleOptionsUrlState { - metric?: ReturnType<typeof waffleOptionsSelectors.selectMetric>; - groupBy?: ReturnType<typeof waffleOptionsSelectors.selectGroupBy>; - nodeType?: ReturnType<typeof waffleOptionsSelectors.selectNodeType>; - view?: ReturnType<typeof waffleOptionsSelectors.selectView>; - customOptions?: ReturnType<typeof waffleOptionsSelectors.selectCustomOptions>; - bounds?: ReturnType<typeof waffleOptionsSelectors.selectBoundsOverride>; - auto?: ReturnType<typeof waffleOptionsSelectors.selectAutoBounds>; - accountId?: ReturnType<typeof waffleOptionsSelectors.selectAccountId>; - region?: ReturnType<typeof waffleOptionsSelectors.selectRegion>; - customMetrics?: ReturnType<typeof waffleOptionsSelectors.selectCustomMetrics>; -} - -export const WithWaffleOptionsUrlState = () => ( - <WithWaffleOptions> - {({ - changeMetric, - urlState, - changeGroupBy, - changeNodeType, - changeView, - changeCustomOptions, - changeAutoBounds, - changeBoundsOverride, - changeAccount, - changeRegion, - changeCustomMetrics, - }) => ( - <UrlStateContainer<WaffleOptionsUrlState> - urlState={urlState} - urlStateKey="waffleOptions" - mapToUrlState={mapToUrlState} - onChange={newUrlState => { - if (newUrlState && newUrlState.metric) { - changeMetric(newUrlState.metric); - } - if (newUrlState && newUrlState.groupBy) { - changeGroupBy(newUrlState.groupBy); - } - if (newUrlState && newUrlState.nodeType) { - changeNodeType(newUrlState.nodeType); - } - if (newUrlState && newUrlState.view) { - changeView(newUrlState.view); - } - if (newUrlState && newUrlState.customOptions) { - changeCustomOptions(newUrlState.customOptions); - } - if (newUrlState && newUrlState.bounds) { - changeBoundsOverride(newUrlState.bounds); - } - if (newUrlState && newUrlState.auto) { - changeAutoBounds(newUrlState.auto); - } - if (newUrlState && newUrlState.accountId) { - changeAccount(newUrlState.accountId); - } - if (newUrlState && newUrlState.region) { - changeRegion(newUrlState.region); - } - if (newUrlState && newUrlState.customMetrics) { - changeCustomMetrics(newUrlState.customMetrics); - } - }} - onInitialize={initialUrlState => { - if (initialUrlState && initialUrlState.metric) { - changeMetric(initialUrlState.metric); - } - if (initialUrlState && initialUrlState.groupBy) { - changeGroupBy(initialUrlState.groupBy); - } - if (initialUrlState && initialUrlState.nodeType) { - changeNodeType(initialUrlState.nodeType); - } - if (initialUrlState && initialUrlState.view) { - changeView(initialUrlState.view); - } - if (initialUrlState && initialUrlState.customOptions) { - changeCustomOptions(initialUrlState.customOptions); - } - if (initialUrlState && initialUrlState.bounds) { - changeBoundsOverride(initialUrlState.bounds); - } - if (initialUrlState && initialUrlState.auto) { - changeAutoBounds(initialUrlState.auto); - } - if (initialUrlState && initialUrlState.accountId) { - changeAccount(initialUrlState.accountId); - } - if (initialUrlState && initialUrlState.region) { - changeRegion(initialUrlState.region); - } - if (initialUrlState && initialUrlState.customMetrics) { - changeCustomMetrics(initialUrlState.customMetrics); - } - }} - /> - )} - </WithWaffleOptions> -); - -const mapToUrlState = (value: any): WaffleOptionsUrlState | undefined => - value - ? { - metric: mapToMetricUrlState(value.metric), - groupBy: mapToGroupByUrlState(value.groupBy), - nodeType: mapToNodeTypeUrlState(value.nodeType), - view: mapToViewUrlState(value.view), - customOptions: mapToCustomOptionsUrlState(value.customOptions), - bounds: mapToBoundsOverideUrlState(value.boundsOverride), - auto: mapToAutoBoundsUrlState(value.autoBounds), - accountId: value.accountId, - region: value.region, - customMetrics: mapToCustomMetricsUrlState(value.customMetrics), - } - : undefined; - -const isInfraNodeType = (value: any): value is InventoryItemType => value in ItemTypeRT; - -const isInfraSnapshotMetricInput = (subject: any): subject is SnapshotMetricInput => { - return subject != null && subject.type in SnapshotMetricTypeRT; -}; - -const isInfraSnapshotGroupbyInput = (subject: any): subject is SnapshotGroupBy => { - return subject != null && subject.type != null; -}; - -const isInfraGroupByOption = (subject: any): subject is InfraGroupByOptions => { - return subject != null && subject.text != null && subject.field != null; -}; - -const mapToMetricUrlState = (subject: any) => { - return subject && isInfraSnapshotMetricInput(subject) ? subject : undefined; -}; - -const mapToGroupByUrlState = (subject: any) => { - return subject && Array.isArray(subject) && subject.every(isInfraSnapshotGroupbyInput) - ? subject - : undefined; -}; - -const mapToNodeTypeUrlState = (subject: any) => { - return isInfraNodeType(subject) ? subject : undefined; -}; - -const mapToViewUrlState = (subject: any) => { - return subject && ['map', 'table'].includes(subject) ? subject : undefined; -}; - -const mapToCustomOptionsUrlState = (subject: any) => { - return subject && Array.isArray(subject) && subject.every(isInfraGroupByOption) - ? subject - : undefined; -}; - -const mapToCustomMetricsUrlState = (subject: any) => { - return subject && Array.isArray(subject) && subject.every(s => SnapshotCustomMetricInputRT.is(s)) - ? subject - : []; -}; - -const mapToBoundsOverideUrlState = (subject: any) => { - return subject != null && isNumber(subject.max) && isNumber(subject.min) ? subject : undefined; -}; - -const mapToAutoBoundsUrlState = (subject: any) => { - return subject != null && isBoolean(subject) ? subject : undefined; -}; diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_time.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_time.tsx deleted file mode 100644 index 293f6184af21b..0000000000000 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_time.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; - -import { State, waffleTimeActions, waffleTimeSelectors } from '../../store'; -import { asChildFunctionRenderer } from '../../utils/typed_react'; -import { bindPlainActionCreators } from '../../utils/typed_redux'; -import { UrlStateContainer } from '../../utils/url_state'; - -export const withWaffleTime = connect( - (state: State) => ({ - currentTime: waffleTimeSelectors.selectCurrentTime(state), - currentTimeRange: waffleTimeSelectors.selectCurrentTimeRange(state), - isAutoReloading: waffleTimeSelectors.selectIsAutoReloading(state), - urlState: selectTimeUrlState(state), - }), - bindPlainActionCreators({ - jumpToTime: waffleTimeActions.jumpToTime, - startAutoReload: waffleTimeActions.startAutoReload, - stopAutoReload: waffleTimeActions.stopAutoReload, - }) -); - -export const WithWaffleTime = asChildFunctionRenderer(withWaffleTime, { - onCleanup: ({ stopAutoReload }) => stopAutoReload(), -}); - -/** - * Url State - */ - -interface WaffleTimeUrlState { - time?: ReturnType<typeof waffleTimeSelectors.selectCurrentTime>; - autoReload?: ReturnType<typeof waffleTimeSelectors.selectIsAutoReloading>; -} - -export const WithWaffleTimeUrlState = () => ( - <WithWaffleTime> - {({ jumpToTime, startAutoReload, stopAutoReload, urlState }) => ( - <UrlStateContainer - urlState={urlState} - urlStateKey="waffleTime" - mapToUrlState={mapToUrlState} - onChange={newUrlState => { - if (newUrlState && newUrlState.time) { - jumpToTime(newUrlState.time); - } - if (newUrlState && newUrlState.autoReload) { - startAutoReload(); - } else if ( - newUrlState && - typeof newUrlState.autoReload !== 'undefined' && - !newUrlState.autoReload - ) { - stopAutoReload(); - } - }} - onInitialize={initialUrlState => { - if (initialUrlState) { - jumpToTime(initialUrlState.time ? initialUrlState.time : Date.now()); - } - if (initialUrlState && initialUrlState.autoReload) { - startAutoReload(); - } - }} - /> - )} - </WithWaffleTime> -); - -const selectTimeUrlState = createSelector( - waffleTimeSelectors.selectCurrentTime, - waffleTimeSelectors.selectIsAutoReloading, - (time, autoReload) => ({ - time, - autoReload, - }) -); - -const mapToUrlState = (value: any): WaffleTimeUrlState | undefined => - value - ? { - time: mapToTimeUrlState(value.time), - autoReload: mapToAutoReloadUrlState(value.autoReload), - } - : undefined; - -const mapToTimeUrlState = (value: any) => (value && typeof value === 'number' ? value : undefined); - -const mapToAutoReloadUrlState = (value: any) => (typeof value === 'boolean' ? value : undefined); diff --git a/x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx b/x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx deleted file mode 100644 index 421c506166d04..0000000000000 --- a/x-pack/plugins/infra/public/containers/waffle/with_waffle_view_state.tsx +++ /dev/null @@ -1,145 +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 { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { IIndexPattern } from 'src/plugins/data/public'; -import { - State, - waffleOptionsActions, - waffleOptionsSelectors, - waffleTimeSelectors, - waffleTimeActions, - waffleFilterActions, - waffleFilterSelectors, - initialState, -} from '../../store'; -import { asChildFunctionRenderer } from '../../utils/typed_react'; -import { convertKueryToElasticSearchQuery } from '../../utils/kuery'; - -const selectViewState = createSelector( - waffleOptionsSelectors.selectMetric, - waffleOptionsSelectors.selectView, - waffleOptionsSelectors.selectGroupBy, - waffleOptionsSelectors.selectNodeType, - waffleOptionsSelectors.selectCustomOptions, - waffleOptionsSelectors.selectBoundsOverride, - waffleOptionsSelectors.selectAutoBounds, - waffleTimeSelectors.selectCurrentTime, - waffleTimeSelectors.selectIsAutoReloading, - waffleFilterSelectors.selectWaffleFilterQuery, - waffleOptionsSelectors.selectCustomMetrics, - ( - metric, - view, - groupBy, - nodeType, - customOptions, - boundsOverride, - autoBounds, - time, - autoReload, - filterQuery, - customMetrics - ) => ({ - time, - autoReload, - metric, - groupBy, - nodeType, - view, - customOptions, - boundsOverride, - autoBounds, - filterQuery, - customMetrics, - }) -); - -interface Props { - indexPattern: IIndexPattern; -} - -export const withWaffleViewState = connect( - (state: State) => ({ - viewState: selectViewState(state), - defaultViewState: selectViewState(initialState), - }), - (dispatch, ownProps: Props) => { - return { - onViewChange: (viewState: WaffleViewState) => { - if (viewState.time) { - dispatch(waffleTimeActions.jumpToTime(viewState.time)); - } - if (viewState.autoReload) { - dispatch(waffleTimeActions.startAutoReload()); - } else if (typeof viewState.autoReload !== 'undefined' && !viewState.autoReload) { - dispatch(waffleTimeActions.stopAutoReload()); - } - if (viewState.metric) { - dispatch(waffleOptionsActions.changeMetric(viewState.metric)); - } - if (viewState.groupBy) { - dispatch(waffleOptionsActions.changeGroupBy(viewState.groupBy)); - } - if (viewState.nodeType) { - dispatch(waffleOptionsActions.changeNodeType(viewState.nodeType)); - } - if (viewState.view) { - dispatch(waffleOptionsActions.changeView(viewState.view)); - } - if (viewState.customOptions) { - dispatch(waffleOptionsActions.changeCustomOptions(viewState.customOptions)); - } - if (viewState.customMetrics) { - dispatch(waffleOptionsActions.changeCustomMetrics(viewState.customMetrics)); - } - if (viewState.boundsOverride) { - dispatch(waffleOptionsActions.changeBoundsOverride(viewState.boundsOverride)); - } - if (viewState.autoBounds) { - dispatch(waffleOptionsActions.changeAutoBounds(viewState.autoBounds)); - } - if (viewState.filterQuery) { - dispatch( - waffleFilterActions.applyWaffleFilterQuery({ - query: viewState.filterQuery, - serializedQuery: convertKueryToElasticSearchQuery( - viewState.filterQuery.expression, - ownProps.indexPattern - ), - }) - ); - } else { - dispatch( - waffleFilterActions.applyWaffleFilterQuery({ - query: null, - serializedQuery: null, - }) - ); - } - }, - }; - } -); - -export const WithWaffleViewState = asChildFunctionRenderer(withWaffleViewState); - -/** - * View State - */ -export interface WaffleViewState { - metric?: ReturnType<typeof waffleOptionsSelectors.selectMetric>; - groupBy?: ReturnType<typeof waffleOptionsSelectors.selectGroupBy>; - nodeType?: ReturnType<typeof waffleOptionsSelectors.selectNodeType>; - view?: ReturnType<typeof waffleOptionsSelectors.selectView>; - customOptions?: ReturnType<typeof waffleOptionsSelectors.selectCustomOptions>; - customMetrics?: ReturnType<typeof waffleOptionsSelectors.selectCustomMetrics>; - boundsOverride?: ReturnType<typeof waffleOptionsSelectors.selectBoundsOverride>; - autoBounds?: ReturnType<typeof waffleOptionsSelectors.selectAutoBounds>; - time?: ReturnType<typeof waffleTimeSelectors.selectCurrentTime>; - autoReload?: ReturnType<typeof waffleTimeSelectors.selectIsAutoReloading>; - filterQuery?: ReturnType<typeof waffleFilterSelectors.selectWaffleFilterQuery>; -} diff --git a/x-pack/plugins/infra/public/containers/with_options.tsx b/x-pack/plugins/infra/public/containers/with_options.tsx index 972722890ffef..e18fc85a68d60 100644 --- a/x-pack/plugins/infra/public/containers/with_options.tsx +++ b/x-pack/plugins/infra/public/containers/with_options.tsx @@ -8,7 +8,7 @@ import moment from 'moment'; import React from 'react'; import { euiPaletteColorBlind } from '@elastic/eui'; -import { InfraFormatterType, InfraOptions, InfraWaffleMapLegendMode } from '../lib/lib'; +import { InfraFormatterType, InfraOptions } from '../lib/lib'; import { RendererFunction } from '../utils/typed_react'; const euiVisColorPalette = euiPaletteColorBlind(); @@ -29,7 +29,7 @@ const initialState = { metric: { type: 'cpu' }, groupBy: [], legend: { - type: InfraWaffleMapLegendMode.gradient, + type: 'gradient', rules: [ { value: 0, diff --git a/x-pack/plugins/infra/public/lib/lib.ts b/x-pack/plugins/infra/public/lib/lib.ts index 9f851e185018b..e4de0caf9bb8b 100644 --- a/x-pack/plugins/infra/public/lib/lib.ts +++ b/x-pack/plugins/infra/public/lib/lib.ts @@ -136,18 +136,13 @@ export interface InfraWaffleMapGradientRule { color: string; } -export enum InfraWaffleMapLegendMode { - step = 'step', - gradient = 'gradient', -} - export interface InfraWaffleMapStepLegend { - type: InfraWaffleMapLegendMode.step; + type: 'step'; rules: InfraWaffleMapStepRule[]; } export interface InfraWaffleMapGradientLegend { - type: InfraWaffleMapLegendMode.gradient; + type: 'gradient'; rules: InfraWaffleMapGradientRule[]; } diff --git a/x-pack/plugins/infra/public/pages/infrastructure/index.tsx b/x-pack/plugins/infra/public/pages/infrastructure/index.tsx index 422eb53148fe6..d592ae3480fc9 100644 --- a/x-pack/plugins/infra/public/pages/infrastructure/index.tsx +++ b/x-pack/plugins/infra/public/pages/infrastructure/index.tsx @@ -25,6 +25,9 @@ import { MetricsSettingsPage } from './settings'; import { AppNavigation } from '../../components/navigation/app_navigation'; import { SourceLoadingPage } from '../../components/source_loading_page'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { WaffleOptionsProvider } from '../inventory_view/hooks/use_waffle_options'; +import { WaffleTimeProvider } from '../inventory_view/hooks/use_waffle_time'; +import { WaffleFiltersProvider } from '../inventory_view/hooks/use_waffle_filters'; import { AlertDropdown } from '../../components/alerting/metrics/alert_dropdown'; export const InfrastructurePage = ({ match }: RouteComponentProps) => { @@ -32,96 +35,101 @@ export const InfrastructurePage = ({ match }: RouteComponentProps) => { return ( <Source.Provider sourceId="default"> - <ColumnarPage> - <DocumentTitle - title={i18n.translate('xpack.infra.homePage.documentTitle', { - defaultMessage: 'Metrics', - })} - /> - - <HelpCenterContent - feedbackLink="https://discuss.elastic.co/c/metrics" - appName={i18n.translate('xpack.infra.header.infrastructureHelpAppName', { - defaultMessage: 'Metrics', - })} - /> + <WaffleOptionsProvider> + <WaffleTimeProvider> + <WaffleFiltersProvider> + <ColumnarPage> + <DocumentTitle + title={i18n.translate('xpack.infra.homePage.documentTitle', { + defaultMessage: 'Metrics', + })} + /> - <Header - breadcrumbs={[ - { - text: i18n.translate('xpack.infra.header.infrastructureTitle', { - defaultMessage: 'Metrics', - }), - }, - ]} - readOnlyBadge={!uiCapabilities?.infrastructure?.save} - /> + <HelpCenterContent + feedbackLink="https://discuss.elastic.co/c/metrics" + appName={i18n.translate('xpack.infra.header.infrastructureHelpAppName', { + defaultMessage: 'Metrics', + })} + /> - <AppNavigation - aria-label={i18n.translate('xpack.infra.header.infrastructureNavigationTitle', { - defaultMessage: 'Metrics', - })} - > - <EuiFlexGroup gutterSize={'none'} alignItems={'center'}> - <EuiFlexItem> - <RoutedTabs - tabs={[ - { - app: 'metrics', - title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', { - defaultMessage: 'Inventory', - }), - pathname: '/inventory', - }, - { - app: 'metrics', - title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', { - defaultMessage: 'Metrics Explorer', - }), - pathname: '/explorer', - }, + <Header + breadcrumbs={[ { - app: 'metrics', - title: i18n.translate('xpack.infra.homePage.settingsTabTitle', { - defaultMessage: 'Settings', + text: i18n.translate('xpack.infra.header.infrastructureTitle', { + defaultMessage: 'Metrics', }), - pathname: '/settings', }, ]} + readOnlyBadge={!uiCapabilities?.infrastructure?.save} /> - </EuiFlexItem> - <EuiFlexItem grow={false}> - <Route path={'/explorer'} component={AlertDropdown} /> - </EuiFlexItem> - </EuiFlexGroup> - </AppNavigation> + <AppNavigation + aria-label={i18n.translate('xpack.infra.header.infrastructureNavigationTitle', { + defaultMessage: 'Metrics', + })} + > + <EuiFlexGroup gutterSize={'none'} alignItems={'center'}> + <EuiFlexItem> + <RoutedTabs + tabs={[ + { + app: 'metrics', + title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', { + defaultMessage: 'Inventory', + }), + pathname: '/inventory', + }, + { + app: 'metrics', + title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', { + defaultMessage: 'Metrics Explorer', + }), + pathname: '/explorer', + }, + { + app: 'metrics', + title: i18n.translate('xpack.infra.homePage.settingsTabTitle', { + defaultMessage: 'Settings', + }), + pathname: '/settings', + }, + ]} + /> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <Route path={'/explorer'} component={AlertDropdown} /> + </EuiFlexItem> + </EuiFlexGroup> + </AppNavigation> - <Switch> - <Route path={'/inventory'} component={SnapshotPage} /> - <Route - path={'/explorer'} - render={props => ( - <WithSource> - {({ configuration, createDerivedIndexPattern }) => ( - <MetricsExplorerOptionsContainer.Provider> - <WithMetricsExplorerOptionsUrlState /> - {configuration ? ( - <MetricsExplorerPage - derivedIndexPattern={createDerivedIndexPattern('metrics')} - source={configuration} - {...props} - /> - ) : ( - <SourceLoadingPage /> - )} - </MetricsExplorerOptionsContainer.Provider> - )} - </WithSource> - )} - /> - <Route path={'/settings'} component={MetricsSettingsPage} /> - </Switch> - </ColumnarPage> + <Switch> + <Route path={'/inventory'} component={SnapshotPage} /> + <Route + path={'/explorer'} + render={props => ( + <WithSource> + {({ configuration, createDerivedIndexPattern }) => ( + <MetricsExplorerOptionsContainer.Provider> + <WithMetricsExplorerOptionsUrlState /> + {configuration ? ( + <MetricsExplorerPage + derivedIndexPattern={createDerivedIndexPattern('metrics')} + source={configuration} + {...props} + /> + ) : ( + <SourceLoadingPage /> + )} + </MetricsExplorerOptionsContainer.Provider> + )} + </WithSource> + )} + /> + <Route path={'/settings'} component={MetricsSettingsPage} /> + </Switch> + </ColumnarPage> + </WaffleFiltersProvider> + </WaffleTimeProvider> + </WaffleOptionsProvider> </Source.Provider> ); }; diff --git a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/index.tsx b/x-pack/plugins/infra/public/pages/infrastructure/snapshot/index.tsx index dbb8b2d8e2952..48cc56388c0f2 100644 --- a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/index.tsx +++ b/x-pack/plugins/infra/public/pages/infrastructure/snapshot/index.tsx @@ -8,7 +8,6 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useContext } from 'react'; -import { SnapshotPageContent } from './page_content'; import { SnapshotToolbar } from './toolbar'; import { DocumentTitle } from '../../../components/document_title'; @@ -19,17 +18,14 @@ import { SourceErrorPage } from '../../../components/source_error_page'; import { SourceLoadingPage } from '../../../components/source_loading_page'; import { ViewSourceConfigurationButton } from '../../../components/source_configuration'; import { Source } from '../../../containers/source'; -import { WithWaffleFilterUrlState } from '../../../containers/waffle/with_waffle_filters'; -import { WithWaffleOptionsUrlState } from '../../../containers/waffle/with_waffle_options'; -import { WithWaffleTimeUrlState } from '../../../containers/waffle/with_waffle_time'; import { useTrackPageview } from '../../../../../observability/public'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { Layout } from '../../../components/inventory/layout'; import { useLinkProps } from '../../../hooks/use_link_props'; export const SnapshotPage = () => { const uiCapabilities = useKibana().services.application?.capabilities; const { - createDerivedIndexPattern, hasFailedLoadingSource, isLoading, loadSourceFailureMessage, @@ -60,11 +56,8 @@ export const SnapshotPage = () => { <SourceLoadingPage /> ) : metricIndicesExist ? ( <> - <WithWaffleTimeUrlState /> - <WithWaffleFilterUrlState indexPattern={createDerivedIndexPattern('metrics')} /> - <WithWaffleOptionsUrlState /> <SnapshotToolbar /> - <SnapshotPageContent /> + <Layout /> </> ) : hasFailedLoadingSource ? ( <SourceErrorPage errorMessage={loadSourceFailureMessage || ''} retry={loadSource} /> diff --git a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx b/x-pack/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx deleted file mode 100644 index 83a4c8d3a497f..0000000000000 --- a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/page_content.tsx +++ /dev/null @@ -1,68 +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 { WithWaffleFilter } from '../../../containers/waffle/with_waffle_filters'; -import { WithWaffleOptions } from '../../../containers/waffle/with_waffle_options'; -import { WithWaffleTime } from '../../../containers/waffle/with_waffle_time'; -import { WithOptions } from '../../../containers/with_options'; -import { WithSource } from '../../../containers/with_source'; -import { Layout } from '../../../components/inventory/layout'; - -export const SnapshotPageContent: React.FC = () => ( - <WithSource> - {({ configuration, createDerivedIndexPattern, sourceId }) => ( - <WithOptions> - {({ wafflemap }) => ( - <WithWaffleFilter indexPattern={createDerivedIndexPattern('metrics')}> - {({ filterQueryAsJson, applyFilterQuery }) => ( - <WithWaffleTime> - {({ currentTime }) => ( - <WithWaffleOptions> - {({ - metric, - groupBy, - nodeType, - view, - changeView, - autoBounds, - boundsOverride, - accountId, - region, - }) => ( - <Layout - currentTime={currentTime} - filterQuery={filterQueryAsJson} - metric={metric} - groupBy={groupBy} - nodeType={nodeType} - sourceId={sourceId} - options={{ - ...wafflemap, - metric, - fields: configuration && configuration.fields, - groupBy, - }} - onDrilldown={applyFilterQuery} - view={view} - onViewChange={changeView} - autoBounds={autoBounds} - boundsOverride={boundsOverride} - accountId={accountId} - region={region} - /> - )} - </WithWaffleOptions> - )} - </WithWaffleTime> - )} - </WithWaffleFilter> - )} - </WithOptions> - )} - </WithSource> -); diff --git a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx b/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx index 3606580e86504..ccdaa5e8dc785 100644 --- a/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/infrastructure/snapshot/toolbar.tsx @@ -5,92 +5,24 @@ */ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import React from 'react'; -import { AutocompleteField } from '../../../components/autocomplete_field'; import { Toolbar } from '../../../components/eui/toolbar'; import { WaffleTimeControls } from '../../../components/waffle/waffle_time_controls'; -import { WithWaffleFilter } from '../../../containers/waffle/with_waffle_filters'; -import { WithWaffleTime } from '../../../containers/waffle/with_waffle_time'; -import { WithKueryAutocompletion } from '../../../containers/with_kuery_autocompletion'; -import { WithSource } from '../../../containers/with_source'; -import { WithWaffleOptions } from '../../../containers/waffle/with_waffle_options'; import { WaffleInventorySwitcher } from '../../../components/waffle/waffle_inventory_switcher'; +import { SearchBar } from '../../inventory_view/compontents/search_bar'; export const SnapshotToolbar = () => ( <Toolbar> <EuiFlexGroup alignItems="center" justifyContent="spaceBetween" gutterSize="m"> <EuiFlexItem grow={false}> - <WithWaffleOptions> - {({ - changeMetric, - changeNodeType, - changeGroupBy, - changeAccount, - changeRegion, - changeCustomMetrics, - nodeType, - }) => ( - <WaffleInventorySwitcher - nodeType={nodeType} - changeNodeType={changeNodeType} - changeMetric={changeMetric} - changeGroupBy={changeGroupBy} - changeAccount={changeAccount} - changeRegion={changeRegion} - changeCustomMetrics={changeCustomMetrics} - /> - )} - </WithWaffleOptions> + <WaffleInventorySwitcher /> </EuiFlexItem> <EuiFlexItem> - <WithSource> - {({ createDerivedIndexPattern }) => ( - <WithKueryAutocompletion indexPattern={createDerivedIndexPattern('metrics')}> - {({ isLoadingSuggestions, loadSuggestions, suggestions }) => ( - <WithWaffleFilter indexPattern={createDerivedIndexPattern('metrics')}> - {({ - applyFilterQueryFromKueryExpression, - filterQueryDraft, - isFilterQueryDraftValid, - setFilterQueryDraftFromKueryExpression, - }) => ( - <AutocompleteField - isLoadingSuggestions={isLoadingSuggestions} - isValid={isFilterQueryDraftValid} - loadSuggestions={loadSuggestions} - onChange={setFilterQueryDraftFromKueryExpression} - onSubmit={applyFilterQueryFromKueryExpression} - placeholder={i18n.translate( - 'xpack.infra.homePage.toolbar.kqlSearchFieldPlaceholder', - { - defaultMessage: 'Search for infrastructure data… (e.g. host.name:host-1)', - } - )} - suggestions={suggestions} - value={filterQueryDraft ? filterQueryDraft.expression : ''} - autoFocus={true} - /> - )} - </WithWaffleFilter> - )} - </WithKueryAutocompletion> - )} - </WithSource> + <SearchBar /> </EuiFlexItem> <EuiFlexItem grow={false}> - <WithWaffleTime resetOnUnmount> - {({ currentTime, isAutoReloading, jumpToTime, startAutoReload, stopAutoReload }) => ( - <WaffleTimeControls - currentTime={currentTime} - isLiveStreaming={isAutoReloading} - onChangeTime={jumpToTime} - startLiveStreaming={startAutoReload} - stopLiveStreaming={stopAutoReload} - /> - )} - </WithWaffleTime> + <WaffleTimeControls /> </EuiFlexItem> </EuiFlexGroup> </Toolbar> diff --git a/x-pack/plugins/infra/public/pages/inventory_view/compontents/search_bar.tsx b/x-pack/plugins/infra/public/pages/inventory_view/compontents/search_bar.tsx new file mode 100644 index 0000000000000..f4fde46d434f8 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/inventory_view/compontents/search_bar.tsx @@ -0,0 +1,40 @@ +/* + * 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, { useContext } from 'react'; +import { i18n } from '@kbn/i18n'; +import { Source } from '../../../containers/source'; +import { AutocompleteField } from '../../../components/autocomplete_field'; +import { WithKueryAutocompletion } from '../../../containers/with_kuery_autocompletion'; +import { useWaffleFiltersContext } from '../hooks/use_waffle_filters'; + +export const SearchBar = () => { + const { createDerivedIndexPattern } = useContext(Source.Context); + const { + applyFilterQueryFromKueryExpression, + filterQueryDraft, + isFilterQueryDraftValid, + setFilterQueryDraftFromKueryExpression, + } = useWaffleFiltersContext(); + return ( + <WithKueryAutocompletion indexPattern={createDerivedIndexPattern('metrics')}> + {({ isLoadingSuggestions, loadSuggestions, suggestions }) => ( + <AutocompleteField + isLoadingSuggestions={isLoadingSuggestions} + isValid={isFilterQueryDraftValid} + loadSuggestions={loadSuggestions} + onChange={setFilterQueryDraftFromKueryExpression} + onSubmit={applyFilterQueryFromKueryExpression} + placeholder={i18n.translate('xpack.infra.homePage.toolbar.kqlSearchFieldPlaceholder', { + defaultMessage: 'Search for infrastructure data… (e.g. host.name:host-1)', + })} + suggestions={suggestions} + value={filterQueryDraft ? filterQueryDraft : ''} + autoFocus={true} + /> + )} + </WithKueryAutocompletion> + ); +}; diff --git a/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_filters.ts b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_filters.ts new file mode 100644 index 0000000000000..02c079dcaddc4 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_filters.ts @@ -0,0 +1,93 @@ +/* + * 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 { useState, useMemo, useCallback, useEffect } from 'react'; +import * as rt from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { fold } from 'fp-ts/lib/Either'; +import { constant, identity } from 'fp-ts/lib/function'; +import createContainter from 'constate'; +import { useUrlState } from '../../../utils/use_url_state'; +import { useSourceContext } from '../../../containers/source'; +import { convertKueryToElasticSearchQuery } from '../../../utils/kuery'; +import { esKuery } from '../../../../../../../src/plugins/data/public'; + +const validateKuery = (expression: string) => { + try { + esKuery.fromKueryExpression(expression); + } catch (err) { + return false; + } + return true; +}; + +export const DEFAULT_WAFFLE_FILTERS_STATE: WaffleFiltersState = { kind: 'kuery', expression: '' }; + +export const useWaffleFilters = () => { + const { createDerivedIndexPattern } = useSourceContext(); + const indexPattern = createDerivedIndexPattern('metrics'); + + const [urlState, setUrlState] = useUrlState<WaffleFiltersState>({ + defaultState: DEFAULT_WAFFLE_FILTERS_STATE, + decodeUrlState, + encodeUrlState, + urlStateKey: 'waffleFilter', + }); + + const [state, setState] = useState<WaffleFiltersState>(urlState); + + useEffect(() => setUrlState(state), [setUrlState, state]); + + const [filterQueryDraft, setFilterQueryDraft] = useState<string>(urlState.expression); + + const filterQueryAsJson = useMemo( + () => convertKueryToElasticSearchQuery(urlState.expression, indexPattern), + [indexPattern, urlState.expression] + ); + + const applyFilterQueryFromKueryExpression = useCallback( + (expression: string) => { + setState(previous => ({ + ...previous, + kind: 'kuery', + expression, + })); + }, + [setState] + ); + + const applyFilterQuery = useCallback((filterQuery: WaffleFiltersState) => { + setState(filterQuery); + setFilterQueryDraft(filterQuery.expression); + }, []); + + const isFilterQueryDraftValid = useMemo(() => validateKuery(filterQueryDraft), [ + filterQueryDraft, + ]); + + return { + filterQuery: urlState, + filterQueryDraft, + filterQueryAsJson, + applyFilterQuery, + setFilterQueryDraftFromKueryExpression: setFilterQueryDraft, + applyFilterQueryFromKueryExpression, + isFilterQueryDraftValid, + setWaffleFiltersState: applyFilterQuery, + }; +}; + +export const WaffleFiltersStateRT = rt.type({ + kind: rt.literal('kuery'), + expression: rt.string, +}); + +export type WaffleFiltersState = rt.TypeOf<typeof WaffleFiltersStateRT>; +const encodeUrlState = WaffleFiltersStateRT.encode; +const decodeUrlState = (value: unknown) => + pipe(WaffleFiltersStateRT.decode(value), fold(constant(undefined), identity)); +export const WaffleFilters = createContainter(useWaffleFilters); +export const [WaffleFiltersProvider, useWaffleFiltersContext] = WaffleFilters; diff --git a/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_options.ts b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_options.ts new file mode 100644 index 0000000000000..2853917d5f683 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_options.ts @@ -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 { useCallback, useState, useEffect } from 'react'; +import * as rt from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { fold } from 'fp-ts/lib/Either'; +import { constant, identity } from 'fp-ts/lib/function'; +import createContainer from 'constate'; +import { + SnapshotMetricInput, + SnapshotGroupBy, + SnapshotCustomMetricInput, + SnapshotMetricInputRT, + SnapshotGroupByRT, + SnapshotCustomMetricInputRT, +} from '../../../../common/http_api/snapshot_api'; +import { useUrlState } from '../../../utils/use_url_state'; +import { InventoryItemType, ItemTypeRT } from '../../../../common/inventory_models/types'; + +export const DEFAULT_WAFFLE_OPTIONS_STATE: WaffleOptionsState = { + metric: { type: 'cpu' }, + groupBy: [], + nodeType: 'host', + view: 'map', + customOptions: [], + boundsOverride: { max: 1, min: 0 }, + autoBounds: true, + accountId: '', + region: '', + customMetrics: [], +}; + +export const useWaffleOptions = () => { + const [urlState, setUrlState] = useUrlState<WaffleOptionsState>({ + defaultState: DEFAULT_WAFFLE_OPTIONS_STATE, + decodeUrlState, + encodeUrlState, + urlStateKey: 'waffleOptions', + }); + + const [state, setState] = useState<WaffleOptionsState>(urlState); + + useEffect(() => setUrlState(state), [setUrlState, state]); + + const changeMetric = useCallback( + (metric: SnapshotMetricInput) => setState(previous => ({ ...previous, metric })), + [setState] + ); + + const changeGroupBy = useCallback( + (groupBy: SnapshotGroupBy) => setState(previous => ({ ...previous, groupBy })), + [setState] + ); + + const changeNodeType = useCallback( + (nodeType: InventoryItemType) => setState(previous => ({ ...previous, nodeType })), + [setState] + ); + + const changeView = useCallback((view: string) => setState(previous => ({ ...previous, view })), [ + setState, + ]); + + const changeCustomOptions = useCallback( + (customOptions: Array<{ text: string; field: string }>) => + setState(previous => ({ ...previous, customOptions })), + [setState] + ); + + const changeAutoBounds = useCallback( + (autoBounds: boolean) => setState(previous => ({ ...previous, autoBounds })), + [setState] + ); + + const changeBoundsOverride = useCallback( + (boundsOverride: { min: number; max: number }) => + setState(previous => ({ ...previous, boundsOverride })), + [setState] + ); + + const changeAccount = useCallback( + (accountId: string) => setState(previous => ({ ...previous, accountId })), + [setState] + ); + + const changeRegion = useCallback( + (region: string) => setState(previous => ({ ...previous, region })), + [setState] + ); + + const changeCustomMetrics = useCallback( + (customMetrics: SnapshotCustomMetricInput[]) => { + setState(previous => ({ ...previous, customMetrics })); + }, + [setState] + ); + + return { + ...state, + changeMetric, + changeGroupBy, + changeNodeType, + changeView, + changeCustomOptions, + changeAutoBounds, + changeBoundsOverride, + changeAccount, + changeRegion, + changeCustomMetrics, + setWaffleOptionsState: setState, + }; +}; + +export const WaffleOptionsStateRT = rt.type({ + metric: SnapshotMetricInputRT, + groupBy: SnapshotGroupByRT, + nodeType: ItemTypeRT, + view: rt.string, + customOptions: rt.array( + rt.type({ + text: rt.string, + field: rt.string, + }) + ), + boundsOverride: rt.type({ + min: rt.number, + max: rt.number, + }), + autoBounds: rt.boolean, + accountId: rt.string, + region: rt.string, + customMetrics: rt.array(SnapshotCustomMetricInputRT), +}); + +export type WaffleOptionsState = rt.TypeOf<typeof WaffleOptionsStateRT>; +const encodeUrlState = (state: WaffleOptionsState) => { + return WaffleOptionsStateRT.encode(state); +}; +const decodeUrlState = (value: unknown) => + pipe(WaffleOptionsStateRT.decode(value), fold(constant(undefined), identity)); + +export const WaffleOptions = createContainer(useWaffleOptions); +export const [WaffleOptionsProvider, useWaffleOptionsContext] = WaffleOptions; diff --git a/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_time.ts b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_time.ts new file mode 100644 index 0000000000000..051b5e598cb75 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_time.ts @@ -0,0 +1,76 @@ +/* + * 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 { useCallback, useState, useEffect } from 'react'; +import * as rt from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { fold } from 'fp-ts/lib/Either'; +import { constant, identity } from 'fp-ts/lib/function'; +import createContainer from 'constate'; +import { useUrlState } from '../../../utils/use_url_state'; + +export const DEFAULT_WAFFLE_TIME_STATE: WaffleTimeState = { + currentTime: Date.now(), + isAutoReloading: false, +}; + +export const useWaffleTime = () => { + const [urlState, setUrlState] = useUrlState<WaffleTimeState>({ + defaultState: DEFAULT_WAFFLE_TIME_STATE, + decodeUrlState, + encodeUrlState, + urlStateKey: 'waffleTime', + }); + + const [state, setState] = useState<WaffleTimeState>(urlState); + + useEffect(() => setUrlState(state), [setUrlState, state]); + + const { currentTime, isAutoReloading } = urlState; + + const startAutoReload = useCallback(() => { + setState(previous => ({ ...previous, isAutoReloading: true })); + }, [setState]); + + const stopAutoReload = useCallback(() => { + setState(previous => ({ ...previous, isAutoReloading: false })); + }, [setState]); + + const jumpToTime = useCallback( + (time: number) => { + setState(previous => ({ ...previous, currentTime: time })); + }, + [setState] + ); + + const currentTimeRange = { + from: currentTime - 1000 * 60 * 5, + interval: '1m', + to: currentTime, + }; + + return { + currentTime, + currentTimeRange, + isAutoReloading, + startAutoReload, + stopAutoReload, + jumpToTime, + setWaffleTimeState: setState, + }; +}; + +export const WaffleTimeStateRT = rt.type({ + currentTime: rt.number, + isAutoReloading: rt.boolean, +}); + +export type WaffleTimeState = rt.TypeOf<typeof WaffleTimeStateRT>; +const encodeUrlState = WaffleTimeStateRT.encode; +const decodeUrlState = (value: unknown) => + pipe(WaffleTimeStateRT.decode(value), fold(constant(undefined), identity)); + +export const WaffleTime = createContainer(useWaffleTime); +export const [WaffleTimeProvider, useWaffleTimeContext] = WaffleTime; diff --git a/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_view_state.ts b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_view_state.ts new file mode 100644 index 0000000000000..869560b2b8709 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/inventory_view/hooks/use_waffle_view_state.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 { useCallback } from 'react'; +import { + useWaffleOptionsContext, + DEFAULT_WAFFLE_OPTIONS_STATE, + WaffleOptionsState, +} from './use_waffle_options'; +import { useWaffleTimeContext, DEFAULT_WAFFLE_TIME_STATE } from './use_waffle_time'; +import { + useWaffleFiltersContext, + DEFAULT_WAFFLE_FILTERS_STATE, + WaffleFiltersState, +} from './use_waffle_filters'; + +export const useWaffleViewState = () => { + const { + metric, + groupBy, + nodeType, + view, + customOptions, + customMetrics, + boundsOverride, + autoBounds, + accountId, + region, + setWaffleOptionsState, + } = useWaffleOptionsContext(); + const { currentTime, isAutoReloading, setWaffleTimeState } = useWaffleTimeContext(); + const { filterQuery, setWaffleFiltersState } = useWaffleFiltersContext(); + + const viewState: WaffleViewState = { + metric, + groupBy, + nodeType, + view, + customOptions, + customMetrics, + boundsOverride, + autoBounds, + accountId, + region, + time: currentTime, + autoReload: isAutoReloading, + filterQuery, + }; + + const defaultViewState: WaffleViewState = { + ...DEFAULT_WAFFLE_OPTIONS_STATE, + filterQuery: DEFAULT_WAFFLE_FILTERS_STATE, + time: DEFAULT_WAFFLE_TIME_STATE.currentTime, + autoReload: DEFAULT_WAFFLE_TIME_STATE.isAutoReloading, + }; + + const onViewChange = useCallback( + (newState: WaffleViewState) => { + setWaffleOptionsState({ + metric: newState.metric, + groupBy: newState.groupBy, + nodeType: newState.nodeType, + view: newState.view, + customOptions: newState.customOptions, + customMetrics: newState.customMetrics, + boundsOverride: newState.boundsOverride, + autoBounds: newState.autoBounds, + accountId: newState.accountId, + region: newState.region, + }); + if (newState.time) { + setWaffleTimeState({ + currentTime: newState.time, + isAutoReloading: newState.autoReload, + }); + } + setWaffleFiltersState(newState.filterQuery); + }, + [setWaffleOptionsState, setWaffleTimeState, setWaffleFiltersState] + ); + + return { + viewState, + defaultViewState, + onViewChange, + }; +}; + +export type WaffleViewState = WaffleOptionsState & { + time: number; + autoReload: boolean; + filterQuery: WaffleFiltersState; +}; diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx index 01b02f1acbbf2..b1dab3bd3f673 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_host_detail_via_ip.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { Redirect, RouteComponentProps } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; -import { replaceMetricTimeInQueryString } from '../metrics/containers/with_metrics_time'; +import { replaceMetricTimeInQueryString } from '../metrics/hooks/use_metrics_time'; import { useHostIpToName } from './use_host_ip_to_name'; import { getFromFromLocation, getToFromLocation } from './query_params'; import { LoadingPage } from '../../components/loading_page'; diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx index 9eae632756a3f..72a41f5264244 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { Redirect, RouteComponentProps } from 'react-router-dom'; -import { replaceMetricTimeInQueryString } from '../metrics/containers/with_metrics_time'; +import { replaceMetricTimeInQueryString } from '../metrics/hooks/use_metrics_time'; import { getFromFromLocation, getToFromLocation } from './query_params'; import { InventoryItemType } from '../../../common/inventory_models/types'; import { LinkDescriptor } from '../../hooks/use_link_props'; diff --git a/x-pack/plugins/infra/public/pages/metrics/components/node_details_page.tsx b/x-pack/plugins/infra/public/pages/metrics/components/node_details_page.tsx index ea91c53faf675..dd2a5f2bdb39e 100644 --- a/x-pack/plugins/infra/public/pages/metrics/components/node_details_page.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/components/node_details_page.tsx @@ -22,7 +22,7 @@ import { MetricsTimeControls } from './time_controls'; import { SideNavContext, NavItem } from '../lib/side_nav_context'; import { PageBody } from './page_body'; import { euiStyled } from '../../../../../observability/public'; -import { MetricsTimeInput } from '../containers/with_metrics_time'; +import { MetricsTimeInput } from '../hooks/use_metrics_time'; import { InfraMetadata } from '../../../../common/http_api/metadata_api'; import { PageError } from './page_error'; import { MetadataContext } from '../../../pages/metrics/containers/metadata_context'; @@ -94,7 +94,7 @@ export const NodeDetailsPage = (props: Props) => { setRefreshInterval={props.setRefreshInterval} onChangeTimeRange={props.setTimeRange} setAutoReload={props.setAutoReload} - onRefresh={props.triggerRefresh} + onRefresh={refetch} /> </MetricsTitleTimeRangeContainer> </EuiPageHeaderSection> diff --git a/x-pack/plugins/infra/public/pages/metrics/components/page_body.tsx b/x-pack/plugins/infra/public/pages/metrics/components/page_body.tsx index 414b9c60adee3..e651d6b92d981 100644 --- a/x-pack/plugins/infra/public/pages/metrics/components/page_body.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/components/page_body.tsx @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { findLayout } from '../../../../common/inventory_models/layouts'; import { InventoryItemType } from '../../../../common/inventory_models/types'; -import { MetricsTimeInput } from '../containers/with_metrics_time'; +import { MetricsTimeInput } from '../hooks/use_metrics_time'; import { InfraLoadingPanel } from '../../../components/loading'; import { NoData } from '../../../components/empty_states'; import { NodeDetailsMetricData } from '../../../../common/http_api/node_details_api'; @@ -19,9 +19,9 @@ interface Props { refetch: () => void; type: InventoryItemType; metrics: NodeDetailsMetricData[]; - onChangeRangeTime?: (time: MetricsTimeInput) => void; - isLiveStreaming?: boolean; - stopLiveStreaming?: () => void; + onChangeRangeTime: (time: MetricsTimeInput) => void; + isLiveStreaming: boolean; + stopLiveStreaming: () => void; } export const PageBody = ({ diff --git a/x-pack/plugins/infra/public/pages/metrics/components/section.tsx b/x-pack/plugins/infra/public/pages/metrics/components/section.tsx index 2f9ed9f54df82..68003737a1f14 100644 --- a/x-pack/plugins/infra/public/pages/metrics/components/section.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/components/section.tsx @@ -41,6 +41,9 @@ export const Section: FunctionComponent<SectionProps> = ({ if (metric === null) { return accumulatedChildren; } + if (!child.props.label) { + return accumulatedChildren; + } return [ ...accumulatedChildren, { diff --git a/x-pack/plugins/infra/public/pages/metrics/components/time_controls.test.tsx b/x-pack/plugins/infra/public/pages/metrics/components/time_controls.test.tsx index 91e25fd8ef585..02ba506e8abe1 100644 --- a/x-pack/plugins/infra/public/pages/metrics/components/time_controls.test.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/components/time_controls.test.tsx @@ -19,7 +19,7 @@ jest.mock('../../../utils/use_kibana_ui_setting', () => ({ import React from 'react'; import { MetricsTimeControls } from './time_controls'; import { mount } from 'enzyme'; -import { MetricsTimeInput } from '../containers/with_metrics_time'; +import { MetricsTimeInput } from '../hooks/use_metrics_time'; describe('MetricsTimeControls', () => { it('should set a valid from and to value for Today', () => { diff --git a/x-pack/plugins/infra/public/pages/metrics/components/time_controls.tsx b/x-pack/plugins/infra/public/pages/metrics/components/time_controls.tsx index b1daaa0320fab..cdbdc9bb7ecdb 100644 --- a/x-pack/plugins/infra/public/pages/metrics/components/time_controls.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/components/time_controls.tsx @@ -7,7 +7,7 @@ import { EuiSuperDatePicker, OnRefreshChangeProps, OnTimeChangeProps } from '@elastic/eui'; import React, { useCallback } from 'react'; import { euiStyled } from '../../../../../observability/public'; -import { MetricsTimeInput } from '../containers/with_metrics_time'; +import { MetricsTimeInput } from '../hooks/use_metrics_time'; import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; import { mapKibanaQuickRangesToDatePickerRanges } from '../../../utils/map_timepicker_quickranges_to_datepicker_ranges'; @@ -61,8 +61,8 @@ export const MetricsTimeControls = (props: MetricsTimeControlsProps) => { return ( <MetricsTimeControlsContainer> <EuiSuperDatePicker - start={currentTimeRange.from} - end={currentTimeRange.to} + start={currentTimeRange.from.toString()} + end={currentTimeRange.to.toString()} isPaused={!isLiveStreaming} refreshInterval={refreshInterval ? refreshInterval : 0} onTimeChange={handleTimeChange} diff --git a/x-pack/plugins/infra/public/pages/metrics/containers/metrics.gql_query.ts b/x-pack/plugins/infra/public/pages/metrics/containers/metrics.gql_query.ts deleted file mode 100644 index 1241c0d771382..0000000000000 --- a/x-pack/plugins/infra/public/pages/metrics/containers/metrics.gql_query.ts +++ /dev/null @@ -1,38 +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'; - -export const metricsQuery = gql` - query MetricsQuery( - $sourceId: ID! - $timerange: InfraTimerangeInput! - $metrics: [InfraMetric!]! - $nodeId: ID! - $cloudId: ID - $nodeType: InfraNodeType! - ) { - source(id: $sourceId) { - id - metrics( - nodeIds: { nodeId: $nodeId, cloudId: $cloudId } - timerange: $timerange - metrics: $metrics - nodeType: $nodeType - ) { - id - series { - id - label - data { - timestamp - value - } - } - } - } - } -`; diff --git a/x-pack/plugins/infra/public/pages/metrics/containers/with_metrics_time.tsx b/x-pack/plugins/infra/public/pages/metrics/containers/with_metrics_time.tsx deleted file mode 100644 index 64d2ddb67139d..0000000000000 --- a/x-pack/plugins/infra/public/pages/metrics/containers/with_metrics_time.tsx +++ /dev/null @@ -1,201 +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 createContainer from 'constate'; -import React, { useContext, useState, useCallback } from 'react'; -import { isNumber } from 'lodash'; -import moment from 'moment'; -import dateMath from '@elastic/datemath'; -import * as rt from 'io-ts'; -import { isRight } from 'fp-ts/lib/Either'; -import { replaceStateKeyInQueryString, UrlStateContainer } from '../../../utils/url_state'; -import { InfraTimerangeInput } from '../../../graphql/types'; - -export interface MetricsTimeInput { - from: string; - to: string; - interval: string; -} - -interface MetricsTimeState { - timeRange: MetricsTimeInput; - parsedTimeRange: InfraTimerangeInput; - setTimeRange: (timeRange: MetricsTimeInput) => void; - refreshInterval: number; - setRefreshInterval: (refreshInterval: number) => void; - isAutoReloading: boolean; - setAutoReload: (isAutoReloading: boolean) => void; - lastRefresh: number; - triggerRefresh: () => void; -} - -const parseRange = (range: MetricsTimeInput) => { - const parsedFrom = dateMath.parse(range.from); - const parsedTo = dateMath.parse(range.to, { roundUp: true }); - return { - ...range, - from: - (parsedFrom && parsedFrom.valueOf()) || - moment() - .subtract(1, 'hour') - .valueOf(), - to: (parsedTo && parsedTo.valueOf()) || moment().valueOf(), - }; -}; - -export const useMetricsTime = () => { - const defaultRange = { - from: 'now-1h', - to: 'now', - interval: '>=1m', - }; - const [isAutoReloading, setAutoReload] = useState(false); - const [refreshInterval, setRefreshInterval] = useState(5000); - const [lastRefresh, setLastRefresh] = useState<number>(moment().valueOf()); - const [timeRange, setTimeRange] = useState(defaultRange); - - const [parsedTimeRange, setParsedTimeRange] = useState(parseRange(defaultRange)); - - const updateTimeRange = useCallback((range: MetricsTimeInput) => { - setTimeRange(range); - setParsedTimeRange(parseRange(range)); - }, []); - - return { - timeRange, - setTimeRange: updateTimeRange, - parsedTimeRange, - refreshInterval, - setRefreshInterval, - isAutoReloading, - setAutoReload, - lastRefresh, - triggerRefresh: useCallback(() => setLastRefresh(moment().valueOf()), [setLastRefresh]), - }; -}; - -export const MetricsTimeContainer = createContainer(useMetricsTime); - -interface WithMetricsTimeProps { - children: (args: MetricsTimeState) => React.ReactElement; -} -export const WithMetricsTime: React.FunctionComponent<WithMetricsTimeProps> = ({ - children, -}: WithMetricsTimeProps) => { - const metricsTimeState = useContext(MetricsTimeContainer.Context); - return children({ ...metricsTimeState }); -}; - -/** - * Url State - */ - -interface MetricsTimeUrlState { - time?: MetricsTimeState['timeRange']; - autoReload?: boolean; - refreshInterval?: number; -} - -export const WithMetricsTimeUrlState = () => ( - <WithMetricsTime> - {({ - timeRange, - setTimeRange, - refreshInterval, - setRefreshInterval, - isAutoReloading, - setAutoReload, - }) => ( - <UrlStateContainer - urlState={{ - time: timeRange, - autoReload: isAutoReloading, - refreshInterval, - }} - urlStateKey="metricTime" - mapToUrlState={mapToUrlState} - onChange={newUrlState => { - if (newUrlState && newUrlState.time) { - setTimeRange(newUrlState.time); - } - if (newUrlState && newUrlState.autoReload) { - setAutoReload(true); - } else if ( - newUrlState && - typeof newUrlState.autoReload !== 'undefined' && - !newUrlState.autoReload - ) { - setAutoReload(false); - } - if (newUrlState && newUrlState.refreshInterval) { - setRefreshInterval(newUrlState.refreshInterval); - } - }} - onInitialize={initialUrlState => { - if (initialUrlState && initialUrlState.time) { - if ( - timeRange.from !== initialUrlState.time.from || - timeRange.to !== initialUrlState.time.to || - timeRange.interval !== initialUrlState.time.interval - ) { - setTimeRange(initialUrlState.time); - } - } - if (initialUrlState && initialUrlState.autoReload) { - setAutoReload(true); - } - if (initialUrlState && initialUrlState.refreshInterval) { - setRefreshInterval(initialUrlState.refreshInterval); - } - }} - /> - )} - </WithMetricsTime> -); - -const mapToUrlState = (value: any): MetricsTimeUrlState | undefined => - value - ? { - time: mapToTimeUrlState(value.time), - autoReload: mapToAutoReloadUrlState(value.autoReload), - refreshInterval: mapToRefreshInterval(value.refreshInterval), - } - : undefined; - -const MetricsTimeRT = rt.type({ - from: rt.union([rt.string, rt.number]), - to: rt.union([rt.string, rt.number]), - interval: rt.string, -}); - -const mapToTimeUrlState = (value: any) => { - const result = MetricsTimeRT.decode(value); - if (isRight(result)) { - const resultValue = result.right; - const to = isNumber(resultValue.to) ? moment(resultValue.to).toISOString() : resultValue.to; - const from = isNumber(resultValue.from) - ? moment(resultValue.from).toISOString() - : resultValue.from; - return { ...resultValue, from, to }; - } - return undefined; -}; - -const mapToAutoReloadUrlState = (value: any) => (typeof value === 'boolean' ? value : undefined); - -const mapToRefreshInterval = (value: any) => (typeof value === 'number' ? value : undefined); - -export const replaceMetricTimeInQueryString = (from: number, to: number) => - Number.isNaN(from) || Number.isNaN(to) - ? (value: string) => value - : replaceStateKeyInQueryString<MetricsTimeUrlState>('metricTime', { - autoReload: false, - time: { - interval: '>=1m', - from: moment(from).toISOString(), - to: moment(to).toISOString(), - }, - }); diff --git a/x-pack/plugins/infra/public/pages/metrics/containers/metrics_time.test.tsx b/x-pack/plugins/infra/public/pages/metrics/hooks/metrics_time.test.tsx similarity index 96% rename from x-pack/plugins/infra/public/pages/metrics/containers/metrics_time.test.tsx rename to x-pack/plugins/infra/public/pages/metrics/hooks/metrics_time.test.tsx index 350fa90810935..17fcc05406470 100644 --- a/x-pack/plugins/infra/public/pages/metrics/containers/metrics_time.test.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hooks/metrics_time.test.tsx @@ -6,7 +6,7 @@ import { mountHook } from 'test_utils/enzyme_helpers'; -import { useMetricsTime } from './with_metrics_time'; +import { useMetricsTime } from './use_metrics_time'; describe('useMetricsTime hook', () => { describe('timeRange state', () => { diff --git a/x-pack/plugins/infra/public/pages/metrics/hooks/use_metrics_time.ts b/x-pack/plugins/infra/public/pages/metrics/hooks/use_metrics_time.ts new file mode 100644 index 0000000000000..2ed86863535ff --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/hooks/use_metrics_time.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import createContainer from 'constate'; +import { useState, useCallback, useEffect } from 'react'; +import moment from 'moment'; +import dateMath from '@elastic/datemath'; +import * as rt from 'io-ts'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { fold } from 'fp-ts/lib/Either'; +import { constant, identity } from 'fp-ts/lib/function'; +import { useUrlState } from '../../../utils/use_url_state'; +import { replaceStateKeyInQueryString } from '../../../utils/url_state'; + +const parseRange = (range: MetricsTimeInput) => { + const parsedFrom = dateMath.parse(range.from.toString()); + const parsedTo = dateMath.parse(range.to.toString(), { roundUp: true }); + return { + ...range, + from: + (parsedFrom && parsedFrom.valueOf()) || + moment() + .subtract(1, 'hour') + .valueOf(), + to: (parsedTo && parsedTo.valueOf()) || moment().valueOf(), + }; +}; + +const DEFAULT_TIMERANGE: MetricsTimeInput = { + from: 'now-1h', + to: 'now', + interval: '>=1m', +}; + +const DEFAULT_URL_STATE: MetricsTimeUrlState = { + time: DEFAULT_TIMERANGE, + autoReload: false, + refreshInterval: 5000, +}; + +export const useMetricsTime = () => { + const [urlState, setUrlState] = useUrlState<MetricsTimeUrlState>({ + defaultState: DEFAULT_URL_STATE, + decodeUrlState, + encodeUrlState, + urlStateKey: 'metricTime', + }); + + const [isAutoReloading, setAutoReload] = useState(urlState.autoReload || false); + const [refreshInterval, setRefreshInterval] = useState(urlState.refreshInterval || 5000); + const [lastRefresh, setLastRefresh] = useState<number>(moment().valueOf()); + const [timeRange, setTimeRange] = useState(urlState.time || DEFAULT_TIMERANGE); + + useEffect(() => { + const newState = { + time: timeRange, + autoReload: isAutoReloading, + refreshInterval, + }; + return setUrlState(newState); + }, [isAutoReloading, refreshInterval, setUrlState, timeRange]); + + const [parsedTimeRange, setParsedTimeRange] = useState( + parseRange(urlState.time || DEFAULT_TIMERANGE) + ); + + const updateTimeRange = useCallback((range: MetricsTimeInput) => { + setTimeRange(range); + setParsedTimeRange(parseRange(range)); + }, []); + + return { + timeRange, + setTimeRange: updateTimeRange, + parsedTimeRange, + refreshInterval, + setRefreshInterval, + isAutoReloading, + setAutoReload, + lastRefresh, + triggerRefresh: useCallback(() => { + return setLastRefresh(moment().valueOf()); + }, [setLastRefresh]), + }; +}; + +export const MetricsTimeInputRT = rt.type({ + from: rt.union([rt.string, rt.number]), + to: rt.union([rt.string, rt.number]), + interval: rt.string, +}); +export type MetricsTimeInput = rt.TypeOf<typeof MetricsTimeInputRT>; + +export const MetricsTimeUrlStateRT = rt.partial({ + time: MetricsTimeInputRT, + autoReload: rt.boolean, + refreshInterval: rt.number, +}); +export type MetricsTimeUrlState = rt.TypeOf<typeof MetricsTimeUrlStateRT>; + +const encodeUrlState = MetricsTimeUrlStateRT.encode; +const decodeUrlState = (value: unknown) => + pipe(MetricsTimeUrlStateRT.decode(value), fold(constant(undefined), identity)); + +export const replaceMetricTimeInQueryString = (from: number, to: number) => + Number.isNaN(from) || Number.isNaN(to) + ? (value: string) => value + : replaceStateKeyInQueryString<MetricsTimeUrlState>('metricTime', { + autoReload: false, + time: { + interval: '>=1m', + from: moment(from).toISOString(), + to: moment(to).toISOString(), + }, + }); + +export const MetricsTimeContainer = createContainer(useMetricsTime); +export const [MetricsTimeProvider, useMetricsTimeContext] = MetricsTimeContainer; diff --git a/x-pack/plugins/infra/public/pages/metrics/index.tsx b/x-pack/plugins/infra/public/pages/metrics/index.tsx index 52c9825a4d614..531be40d2dc43 100644 --- a/x-pack/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/index.tsx @@ -9,7 +9,6 @@ import { euiStyled, EuiTheme, withTheme } from '../../../../observability/public import { DocumentTitle } from '../../components/document_title'; import { Header } from '../../components/header'; import { ColumnarPage, PageContent } from '../../components/page'; -import { WithMetricsTime, WithMetricsTimeUrlState } from './containers/with_metrics_time'; import { withMetricPageProviders } from './page_providers'; import { useMetadata } from '../../containers/metadata/use_metadata'; import { Source } from '../../containers/source'; @@ -19,6 +18,7 @@ import { NavItem } from './lib/side_nav_context'; import { NodeDetailsPage } from './components/node_details_page'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import { InventoryItemType } from '../../../common/inventory_models/types'; +import { useMetricsTimeContext } from './hooks/use_metrics_time'; import { useLinkProps } from '../../hooks/use_link_props'; const DetailPageContent = euiStyled(PageContent)` @@ -37,19 +37,29 @@ interface Props { } export const MetricDetail = withMetricPageProviders( - withTheme(({ match, theme }: Props) => { + withTheme(({ match }: Props) => { const uiCapabilities = useKibana().services.application?.capabilities; const nodeId = match.params.node; const nodeType = match.params.type as InventoryItemType; const inventoryModel = findInventoryModel(nodeType); const { sourceId } = useContext(Source.Context); + const { + timeRange, + parsedTimeRange, + setTimeRange, + refreshInterval, + setRefreshInterval, + isAutoReloading, + setAutoReload, + triggerRefresh, + } = useMetricsTimeContext(); const { name, filteredRequiredMetrics, loading: metadataLoading, cloudId, metadata, - } = useMetadata(nodeId, nodeType, inventoryModel.requiredMetrics, sourceId); + } = useMetadata(nodeId, nodeType, inventoryModel.requiredMetrics, sourceId, parsedTimeRange); const [sideNav, setSideNav] = useState<NavItem[]>([]); @@ -90,58 +100,41 @@ export const MetricDetail = withMetricPageProviders( } return ( - <WithMetricsTime> - {({ - timeRange, - parsedTimeRange, - setTimeRange, - refreshInterval, - setRefreshInterval, - isAutoReloading, - setAutoReload, - triggerRefresh, - }) => ( - <ColumnarPage> - <Header - breadcrumbs={breadcrumbs} - readOnlyBadge={!uiCapabilities?.infrastructure?.save} - /> - <WithMetricsTimeUrlState /> - <DocumentTitle - title={i18n.translate('xpack.infra.metricDetailPage.documentTitle', { - defaultMessage: 'Infrastructure | Metrics | {name}', - values: { - name, - }, - })} + <ColumnarPage> + <Header breadcrumbs={breadcrumbs} readOnlyBadge={!uiCapabilities?.infrastructure?.save} /> + <DocumentTitle + title={i18n.translate('xpack.infra.metricDetailPage.documentTitle', { + defaultMessage: 'Infrastructure | Metrics | {name}', + values: { + name, + }, + })} + /> + <DetailPageContent data-test-subj="infraMetricsPage"> + {metadata ? ( + <NodeDetailsPage + name={name} + requiredMetrics={filteredRequiredMetrics} + sourceId={sourceId} + timeRange={timeRange} + parsedTimeRange={parsedTimeRange} + nodeType={nodeType} + nodeId={nodeId} + cloudId={cloudId} + metadataLoading={metadataLoading} + isAutoReloading={isAutoReloading} + refreshInterval={refreshInterval} + sideNav={sideNav} + metadata={metadata} + addNavItem={addNavItem} + setRefreshInterval={setRefreshInterval} + setAutoReload={setAutoReload} + triggerRefresh={triggerRefresh} + setTimeRange={setTimeRange} /> - <DetailPageContent data-test-subj="infraMetricsPage"> - {metadata ? ( - <NodeDetailsPage - name={name} - requiredMetrics={filteredRequiredMetrics} - sourceId={sourceId} - timeRange={timeRange} - parsedTimeRange={parsedTimeRange} - nodeType={nodeType} - nodeId={nodeId} - cloudId={cloudId} - metadataLoading={metadataLoading} - isAutoReloading={isAutoReloading} - refreshInterval={refreshInterval} - sideNav={sideNav} - metadata={metadata} - addNavItem={addNavItem} - setRefreshInterval={setRefreshInterval} - setAutoReload={setAutoReload} - triggerRefresh={triggerRefresh} - setTimeRange={setTimeRange} - /> - ) : null} - </DetailPageContent> - </ColumnarPage> - )} - </WithMetricsTime> + ) : null} + </DetailPageContent> + </ColumnarPage> ); }) ); diff --git a/x-pack/plugins/infra/public/pages/metrics/page_providers.tsx b/x-pack/plugins/infra/public/pages/metrics/page_providers.tsx index 0abbd597dd65c..d3f10adec06ed 100644 --- a/x-pack/plugins/infra/public/pages/metrics/page_providers.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/page_providers.tsx @@ -6,15 +6,15 @@ import React from 'react'; -import { MetricsTimeContainer } from './containers/with_metrics_time'; import { Source } from '../../containers/source'; +import { MetricsTimeProvider } from './hooks/use_metrics_time'; export const withMetricPageProviders = <T extends object>(Component: React.ComponentType<T>) => ( props: T ) => ( <Source.Provider sourceId="default"> - <MetricsTimeContainer.Provider> + <MetricsTimeProvider> <Component {...props} /> - </MetricsTimeContainer.Provider> + </MetricsTimeProvider> </Source.Provider> ); diff --git a/x-pack/plugins/infra/public/pages/metrics/types.ts b/x-pack/plugins/infra/public/pages/metrics/types.ts index fd6243292ec07..2cc261df28977 100644 --- a/x-pack/plugins/infra/public/pages/metrics/types.ts +++ b/x-pack/plugins/infra/public/pages/metrics/types.ts @@ -7,7 +7,7 @@ import rt from 'io-ts'; import { EuiTheme } from '../../../../observability/public'; import { InventoryFormatterTypeRT } from '../../../common/inventory_models/types'; -import { MetricsTimeInput } from './containers/with_metrics_time'; +import { MetricsTimeInput } from './hooks/use_metrics_time'; import { NodeDetailsMetricData } from '../../../common/http_api/node_details_api'; export interface LayoutProps { diff --git a/x-pack/plugins/infra/public/store/actions.ts b/x-pack/plugins/infra/public/store/actions.ts deleted file mode 100644 index 8a5d1f6c668d0..0000000000000 --- a/x-pack/plugins/infra/public/store/actions.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 { waffleFilterActions, waffleTimeActions, waffleOptionsActions } from './local'; diff --git a/x-pack/plugins/infra/public/store/epics.ts b/x-pack/plugins/infra/public/store/epics.ts deleted file mode 100644 index b5e48a4ec6214..0000000000000 --- a/x-pack/plugins/infra/public/store/epics.ts +++ /dev/null @@ -1,11 +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 { combineEpics } from 'redux-observable'; - -import { createLocalEpic } from './local'; - -export const createRootEpic = <State>() => combineEpics(createLocalEpic<State>()); diff --git a/x-pack/plugins/infra/public/store/index.ts b/x-pack/plugins/infra/public/store/index.ts deleted file mode 100644 index 025da41ec40d5..0000000000000 --- a/x-pack/plugins/infra/public/store/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './actions'; -export * from './epics'; -export * from './reducer'; -export * from './selectors'; -export { createStore } from './store'; diff --git a/x-pack/plugins/infra/public/store/local/actions.ts b/x-pack/plugins/infra/public/store/local/actions.ts deleted file mode 100644 index 1c79d5a515cd4..0000000000000 --- a/x-pack/plugins/infra/public/store/local/actions.ts +++ /dev/null @@ -1,9 +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 { waffleFilterActions } from './waffle_filter'; -export { waffleTimeActions } from './waffle_time'; -export { waffleOptionsActions } from './waffle_options'; diff --git a/x-pack/plugins/infra/public/store/local/epic.ts b/x-pack/plugins/infra/public/store/local/epic.ts deleted file mode 100644 index e1a051355576f..0000000000000 --- a/x-pack/plugins/infra/public/store/local/epic.ts +++ /dev/null @@ -1,11 +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 { combineEpics } from 'redux-observable'; - -import { createWaffleTimeEpic } from './waffle_time'; - -export const createLocalEpic = <State>() => combineEpics(createWaffleTimeEpic<State>()); diff --git a/x-pack/plugins/infra/public/store/local/index.ts b/x-pack/plugins/infra/public/store/local/index.ts deleted file mode 100644 index c2843320bfd0c..0000000000000 --- a/x-pack/plugins/infra/public/store/local/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './actions'; -export * from './epic'; -export * from './reducer'; -export * from './selectors'; diff --git a/x-pack/plugins/infra/public/store/local/reducer.ts b/x-pack/plugins/infra/public/store/local/reducer.ts deleted file mode 100644 index 9e194a5d37f49..0000000000000 --- a/x-pack/plugins/infra/public/store/local/reducer.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 { combineReducers } from 'redux'; - -import { initialWaffleFilterState, waffleFilterReducer, WaffleFilterState } from './waffle_filter'; -import { - initialWaffleOptionsState, - waffleOptionsReducer, - WaffleOptionsState, -} from './waffle_options'; -import { initialWaffleTimeState, waffleTimeReducer, WaffleTimeState } from './waffle_time'; - -export interface LocalState { - waffleFilter: WaffleFilterState; - waffleTime: WaffleTimeState; - waffleMetrics: WaffleOptionsState; -} - -export const initialLocalState: LocalState = { - waffleFilter: initialWaffleFilterState, - waffleTime: initialWaffleTimeState, - waffleMetrics: initialWaffleOptionsState, -}; - -export const localReducer = combineReducers<LocalState>({ - waffleFilter: waffleFilterReducer, - waffleTime: waffleTimeReducer, - waffleMetrics: waffleOptionsReducer, -}); diff --git a/x-pack/plugins/infra/public/store/local/selectors.ts b/x-pack/plugins/infra/public/store/local/selectors.ts deleted file mode 100644 index 56ffc53c2bc72..0000000000000 --- a/x-pack/plugins/infra/public/store/local/selectors.ts +++ /dev/null @@ -1,26 +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 { globalizeSelectors } from '../../utils/typed_redux'; -import { LocalState } from './reducer'; -import { waffleFilterSelectors as innerWaffleFilterSelectors } from './waffle_filter'; -import { waffleOptionsSelectors as innerWaffleOptionsSelectors } from './waffle_options'; -import { waffleTimeSelectors as innerWaffleTimeSelectors } from './waffle_time'; - -export const waffleFilterSelectors = globalizeSelectors( - (state: LocalState) => state.waffleFilter, - innerWaffleFilterSelectors -); - -export const waffleTimeSelectors = globalizeSelectors( - (state: LocalState) => state.waffleTime, - innerWaffleTimeSelectors -); - -export const waffleOptionsSelectors = globalizeSelectors( - (state: LocalState) => state.waffleMetrics, - innerWaffleOptionsSelectors -); diff --git a/x-pack/plugins/infra/public/store/local/waffle_filter/actions.ts b/x-pack/plugins/infra/public/store/local/waffle_filter/actions.ts deleted file mode 100644 index a23f9b3108b5b..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_filter/actions.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import actionCreatorFactory from 'typescript-fsa'; - -import { FilterQuery, SerializedFilterQuery } from './reducer'; - -const actionCreator = actionCreatorFactory('x-pack/infra/local/waffle_filter'); - -export const setWaffleFilterQueryDraft = actionCreator<FilterQuery>( - 'SET_WAFFLE_FILTER_QUERY_DRAFT' -); - -export const applyWaffleFilterQuery = actionCreator<SerializedFilterQuery>( - 'APPLY_WAFFLE_FILTER_QUERY' -); diff --git a/x-pack/plugins/infra/public/store/local/waffle_filter/index.ts b/x-pack/plugins/infra/public/store/local/waffle_filter/index.ts deleted file mode 100644 index 558314f2aeda8..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_filter/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as waffleFilterActions from './actions'; -import * as waffleFilterSelectors from './selectors'; - -export { waffleFilterActions, waffleFilterSelectors }; -export * from './reducer'; diff --git a/x-pack/plugins/infra/public/store/local/waffle_filter/reducer.ts b/x-pack/plugins/infra/public/store/local/waffle_filter/reducer.ts deleted file mode 100644 index 912ad96357334..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_filter/reducer.ts +++ /dev/null @@ -1,43 +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 { reducerWithInitialState } from 'typescript-fsa-reducers/dist'; - -import { applyWaffleFilterQuery, setWaffleFilterQueryDraft } from './actions'; - -export interface KueryFilterQuery { - kind: 'kuery'; - expression: string; -} - -export type FilterQuery = KueryFilterQuery; - -export interface SerializedFilterQuery { - query: FilterQuery | null; - serializedQuery: string | null; -} - -export interface WaffleFilterState { - filterQuery: SerializedFilterQuery | null; - filterQueryDraft: KueryFilterQuery | null; -} - -export const initialWaffleFilterState: WaffleFilterState = { - filterQuery: null, - filterQueryDraft: null, -}; - -export const waffleFilterReducer = reducerWithInitialState(initialWaffleFilterState) - .case(setWaffleFilterQueryDraft, (state, filterQueryDraft) => ({ - ...state, - filterQueryDraft, - })) - .case(applyWaffleFilterQuery, (state, filterQuery) => ({ - ...state, - filterQuery, - filterQueryDraft: filterQuery.query, - })) - .build(); diff --git a/x-pack/plugins/infra/public/store/local/waffle_filter/selectors.ts b/x-pack/plugins/infra/public/store/local/waffle_filter/selectors.ts deleted file mode 100644 index 047dabd3f0dd3..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_filter/selectors.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 { createSelector } from 'reselect'; - -import { esKuery } from '../../../../../../../src/plugins/data/public'; -import { WaffleFilterState } from './reducer'; - -export const selectWaffleFilterQuery = (state: WaffleFilterState) => - state.filterQuery ? state.filterQuery.query : null; - -export const selectWaffleFilterQueryAsJson = (state: WaffleFilterState) => - state.filterQuery ? state.filterQuery.serializedQuery : null; - -export const selectWaffleFilterQueryDraft = (state: WaffleFilterState) => state.filterQueryDraft; - -export const selectIsWaffleFilterQueryDraftValid = createSelector( - selectWaffleFilterQueryDraft, - filterQueryDraft => { - if (filterQueryDraft && filterQueryDraft.kind === 'kuery') { - try { - esKuery.fromKueryExpression(filterQueryDraft.expression); - } catch (err) { - return false; - } - } - - return true; - } -); diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/actions.ts b/x-pack/plugins/infra/public/store/local/waffle_options/actions.ts deleted file mode 100644 index 88229c31b2056..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_options/actions.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 actionCreatorFactory from 'typescript-fsa'; -import { - SnapshotGroupBy, - SnapshotMetricInput, - SnapshotCustomMetricInput, -} from '../../../../common/http_api/snapshot_api'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; -import { InfraGroupByOptions, InfraWaffleMapBounds } from '../../../lib/lib'; - -const actionCreator = actionCreatorFactory('x-pack/infra/local/waffle_options'); - -export const changeMetric = actionCreator<SnapshotMetricInput>('CHANGE_METRIC'); -export const changeGroupBy = actionCreator<SnapshotGroupBy>('CHANGE_GROUP_BY'); -export const changeCustomOptions = actionCreator<InfraGroupByOptions[]>('CHANGE_CUSTOM_OPTIONS'); -export const changeNodeType = actionCreator<InventoryItemType>('CHANGE_NODE_TYPE'); -export const changeView = actionCreator<string>('CHANGE_VIEW'); -export const changeBoundsOverride = actionCreator<InfraWaffleMapBounds>('CHANGE_BOUNDS_OVERRIDE'); -export const changeAutoBounds = actionCreator<boolean>('CHANGE_AUTO_BOUNDS'); -export const changeAccount = actionCreator<string>('CHANGE_ACCOUNT'); -export const changeRegion = actionCreator<string>('CHANGE_REGION'); -export const changeCustomMetrics = actionCreator<SnapshotCustomMetricInput[]>( - 'CHANGE_CUSTOM_METRICS' -); diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/index.ts b/x-pack/plugins/infra/public/store/local/waffle_options/index.ts deleted file mode 100644 index 3ecf108eb49d4..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_options/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as waffleOptionsActions from './actions'; -import * as waffleOptionsSelectors from './selector'; - -export { waffleOptionsActions, waffleOptionsSelectors }; -export * from './reducer'; diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts b/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts deleted file mode 100644 index 3789228a7c16b..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_options/reducer.ts +++ /dev/null @@ -1,113 +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 { combineReducers } from 'redux'; -import { reducerWithInitialState } from 'typescript-fsa-reducers'; -import { - SnapshotMetricInput, - SnapshotGroupBy, - SnapshotCustomMetricInput, -} from '../../../../common/http_api/snapshot_api'; -import { InfraGroupByOptions, InfraWaffleMapBounds } from '../../../lib/lib'; -import { - changeAutoBounds, - changeBoundsOverride, - changeCustomOptions, - changeGroupBy, - changeMetric, - changeNodeType, - changeView, - changeAccount, - changeRegion, - changeCustomMetrics, -} from './actions'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; - -export interface WaffleOptionsState { - metric: SnapshotMetricInput; - groupBy: SnapshotGroupBy; - nodeType: InventoryItemType; - view: string; - customOptions: InfraGroupByOptions[]; - boundsOverride: InfraWaffleMapBounds; - autoBounds: boolean; - accountId: string; - region: string; - customMetrics: SnapshotCustomMetricInput[]; -} - -export const initialWaffleOptionsState: WaffleOptionsState = { - metric: { type: 'cpu' }, - groupBy: [], - nodeType: 'host', - view: 'map', - customOptions: [], - boundsOverride: { max: 1, min: 0 }, - autoBounds: true, - accountId: '', - region: '', - customMetrics: [], -}; - -const currentMetricReducer = reducerWithInitialState(initialWaffleOptionsState.metric).case( - changeMetric, - (current, target) => target -); - -const currentCustomOptionsReducer = reducerWithInitialState( - initialWaffleOptionsState.customOptions -).case(changeCustomOptions, (current, target) => target); - -const currentGroupByReducer = reducerWithInitialState(initialWaffleOptionsState.groupBy).case( - changeGroupBy, - (current, target) => target -); - -const currentNodeTypeReducer = reducerWithInitialState(initialWaffleOptionsState.nodeType).case( - changeNodeType, - (current, target) => target -); - -const currentViewReducer = reducerWithInitialState(initialWaffleOptionsState.view).case( - changeView, - (current, target) => target -); - -const currentBoundsOverrideReducer = reducerWithInitialState( - initialWaffleOptionsState.boundsOverride -).case(changeBoundsOverride, (current, target) => target); - -const currentAutoBoundsReducer = reducerWithInitialState(initialWaffleOptionsState.autoBounds).case( - changeAutoBounds, - (current, target) => target -); - -const currentAccountIdReducer = reducerWithInitialState(initialWaffleOptionsState.accountId).case( - changeAccount, - (current, target) => target -); - -const currentRegionReducer = reducerWithInitialState(initialWaffleOptionsState.region).case( - changeRegion, - (current, target) => target -); - -const currentCustomMetricsReducer = reducerWithInitialState( - initialWaffleOptionsState.customMetrics -).case(changeCustomMetrics, (current, target) => target); - -export const waffleOptionsReducer = combineReducers<WaffleOptionsState>({ - metric: currentMetricReducer, - groupBy: currentGroupByReducer, - nodeType: currentNodeTypeReducer, - view: currentViewReducer, - customOptions: currentCustomOptionsReducer, - boundsOverride: currentBoundsOverrideReducer, - autoBounds: currentAutoBoundsReducer, - accountId: currentAccountIdReducer, - region: currentRegionReducer, - customMetrics: currentCustomMetricsReducer, -}); diff --git a/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts b/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts deleted file mode 100644 index 4487af156df97..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_options/selector.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { WaffleOptionsState } from './reducer'; - -export const selectMetric = (state: WaffleOptionsState) => state.metric; -export const selectGroupBy = (state: WaffleOptionsState) => state.groupBy; -export const selectCustomOptions = (state: WaffleOptionsState) => state.customOptions; -export const selectNodeType = (state: WaffleOptionsState) => state.nodeType; -export const selectView = (state: WaffleOptionsState) => state.view; -export const selectBoundsOverride = (state: WaffleOptionsState) => state.boundsOverride; -export const selectAutoBounds = (state: WaffleOptionsState) => state.autoBounds; -export const selectAccountId = (state: WaffleOptionsState) => state.accountId; -export const selectRegion = (state: WaffleOptionsState) => state.region; -export const selectCustomMetrics = (state: WaffleOptionsState) => state.customMetrics; diff --git a/x-pack/plugins/infra/public/store/local/waffle_time/actions.ts b/x-pack/plugins/infra/public/store/local/waffle_time/actions.ts deleted file mode 100644 index fe79f2f536a93..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_time/actions.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 actionCreatorFactory from 'typescript-fsa'; - -const actionCreator = actionCreatorFactory('x-pack/infra/local/waffle_time'); - -export const jumpToTime = actionCreator<number>('JUMP_TO_TIME'); - -export const startAutoReload = actionCreator('START_AUTO_RELOAD'); - -export const stopAutoReload = actionCreator('STOP_AUTO_RELOAD'); diff --git a/x-pack/plugins/infra/public/store/local/waffle_time/epic.ts b/x-pack/plugins/infra/public/store/local/waffle_time/epic.ts deleted file mode 100644 index 986d6b17a2424..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_time/epic.ts +++ /dev/null @@ -1,38 +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 { Action } from 'redux'; -import { Epic } from 'redux-observable'; -import { timer } from 'rxjs'; -import { exhaustMap, filter, map, takeUntil, withLatestFrom } from 'rxjs/operators'; - -import { jumpToTime, startAutoReload, stopAutoReload } from './actions'; - -interface WaffleTimeEpicDependencies<State> { - selectWaffleTimeUpdatePolicyInterval: (state: State) => number | null; -} - -export const createWaffleTimeEpic = <State>(): Epic< - Action, - Action, - State, - WaffleTimeEpicDependencies<State> -> => (action$, state$, { selectWaffleTimeUpdatePolicyInterval }) => { - const updateInterval$ = state$.pipe(map(selectWaffleTimeUpdatePolicyInterval), filter(isNotNull)); - - return action$.pipe( - filter(startAutoReload.match), - withLatestFrom(updateInterval$), - exhaustMap(([action, updateInterval]) => - timer(0, updateInterval).pipe( - map(() => jumpToTime(Date.now())), - takeUntil(action$.pipe(filter(stopAutoReload.match))) - ) - ) - ); -}; - -const isNotNull = <T>(value: T | null): value is T => value !== null; diff --git a/x-pack/plugins/infra/public/store/local/waffle_time/index.ts b/x-pack/plugins/infra/public/store/local/waffle_time/index.ts deleted file mode 100644 index 2b99a6d6d5760..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_time/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as waffleTimeActions from './actions'; -import * as waffleTimeSelectors from './selectors'; - -export { waffleTimeActions, waffleTimeSelectors }; -export * from './epic'; -export * from './reducer'; diff --git a/x-pack/plugins/infra/public/store/local/waffle_time/reducer.ts b/x-pack/plugins/infra/public/store/local/waffle_time/reducer.ts deleted file mode 100644 index 026e5decf5d37..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_time/reducer.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { combineReducers } from 'redux'; -import { reducerWithInitialState } from 'typescript-fsa-reducers/dist'; - -import { jumpToTime, startAutoReload, stopAutoReload } from './actions'; - -interface ManualTimeUpdatePolicy { - policy: 'manual'; -} - -interface IntervalTimeUpdatePolicy { - policy: 'interval'; - interval: number; -} - -type TimeUpdatePolicy = ManualTimeUpdatePolicy | IntervalTimeUpdatePolicy; - -export interface WaffleTimeState { - currentTime: number; - updatePolicy: TimeUpdatePolicy; -} - -export const initialWaffleTimeState: WaffleTimeState = { - currentTime: Date.now(), - updatePolicy: { - policy: 'manual', - }, -}; - -const currentTimeReducer = reducerWithInitialState(initialWaffleTimeState.currentTime).case( - jumpToTime, - (currentTime, targetTime) => targetTime -); - -const updatePolicyReducer = reducerWithInitialState(initialWaffleTimeState.updatePolicy) - .case(startAutoReload, () => ({ - policy: 'interval', - interval: 5000, - })) - .case(stopAutoReload, () => ({ - policy: 'manual', - })); - -export const waffleTimeReducer = combineReducers<WaffleTimeState>({ - currentTime: currentTimeReducer, - updatePolicy: updatePolicyReducer, -}); diff --git a/x-pack/plugins/infra/public/store/local/waffle_time/selectors.ts b/x-pack/plugins/infra/public/store/local/waffle_time/selectors.ts deleted file mode 100644 index 0b6d01bdf5288..0000000000000 --- a/x-pack/plugins/infra/public/store/local/waffle_time/selectors.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 { createSelector } from 'reselect'; - -import { WaffleTimeState } from './reducer'; - -export const selectCurrentTime = (state: WaffleTimeState) => state.currentTime; - -export const selectIsAutoReloading = (state: WaffleTimeState) => - state.updatePolicy.policy === 'interval'; - -export const selectTimeUpdatePolicyInterval = (state: WaffleTimeState) => - state.updatePolicy.policy === 'interval' ? state.updatePolicy.interval : null; - -export const selectCurrentTimeRange = createSelector(selectCurrentTime, currentTime => ({ - from: currentTime - 1000 * 60 * 5, - interval: '1m', - to: currentTime, -})); diff --git a/x-pack/plugins/infra/public/store/reducer.ts b/x-pack/plugins/infra/public/store/reducer.ts deleted file mode 100644 index 2536ddbee401b..0000000000000 --- a/x-pack/plugins/infra/public/store/reducer.ts +++ /dev/null @@ -1,21 +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 { combineReducers } from 'redux'; - -import { initialLocalState, localReducer, LocalState } from './local'; - -export interface State { - local: LocalState; -} - -export const initialState: State = { - local: initialLocalState, -}; - -export const reducer = combineReducers<State>({ - local: localReducer, -}); diff --git a/x-pack/plugins/infra/public/store/selectors.ts b/x-pack/plugins/infra/public/store/selectors.ts deleted file mode 100644 index f4011c232cba4..0000000000000 --- a/x-pack/plugins/infra/public/store/selectors.ts +++ /dev/null @@ -1,22 +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 { globalizeSelectors } from '../utils/typed_redux'; -import { - waffleFilterSelectors as localWaffleFilterSelectors, - waffleOptionsSelectors as localWaffleOptionsSelectors, - waffleTimeSelectors as localWaffleTimeSelectors, -} from './local'; -import { State } from './reducer'; -/** - * local selectors - */ - -const selectLocal = (state: State) => state.local; - -export const waffleFilterSelectors = globalizeSelectors(selectLocal, localWaffleFilterSelectors); -export const waffleTimeSelectors = globalizeSelectors(selectLocal, localWaffleTimeSelectors); -export const waffleOptionsSelectors = globalizeSelectors(selectLocal, localWaffleOptionsSelectors); diff --git a/x-pack/plugins/infra/public/store/store.ts b/x-pack/plugins/infra/public/store/store.ts deleted file mode 100644 index cae0622c5e4a1..0000000000000 --- a/x-pack/plugins/infra/public/store/store.ts +++ /dev/null @@ -1,50 +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 { Action, applyMiddleware, compose, createStore as createBasicStore } from 'redux'; -import { createEpicMiddleware } from 'redux-observable'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; - -import { createRootEpic, initialState, reducer, State, waffleTimeSelectors } from '.'; -import { InfraApolloClient, InfraObservableApi } from '../lib/lib'; - -declare global { - interface Window { - __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: typeof compose; - } -} - -export interface StoreDependencies { - apolloClient: Observable<InfraApolloClient>; - observableApi: Observable<InfraObservableApi>; -} - -export function createStore({ apolloClient, observableApi }: StoreDependencies) { - const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; - - const middlewareDependencies = { - postToApi$: observableApi.pipe(map(({ post }) => post)), - apolloClient$: apolloClient, - selectWaffleTimeUpdatePolicyInterval: waffleTimeSelectors.selectTimeUpdatePolicyInterval, - }; - - const epicMiddleware = createEpicMiddleware<Action, Action, State, typeof middlewareDependencies>( - { - dependencies: middlewareDependencies, - } - ); - - const store = createBasicStore( - reducer, - initialState, - composeEnhancers(applyMiddleware(epicMiddleware)) - ); - - epicMiddleware.run(createRootEpic<State>()); - - return store; -} diff --git a/x-pack/plugins/infra/public/utils/redux_context.tsx b/x-pack/plugins/infra/public/utils/redux_context.tsx deleted file mode 100644 index f249d72a6b56f..0000000000000 --- a/x-pack/plugins/infra/public/utils/redux_context.tsx +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { useSelector } from 'react-redux'; -import React, { createContext } from 'react'; -import { State, initialState } from '../store'; - -export const ReduxStateContext = createContext(initialState); - -export const ReduxStateContextProvider = ({ children }: { children: JSX.Element }) => { - const state = useSelector((store: State) => store); - return <ReduxStateContext.Provider value={state}>{children}</ReduxStateContext.Provider>; -}; diff --git a/x-pack/plugins/infra/server/routes/metadata/index.ts b/x-pack/plugins/infra/server/routes/metadata/index.ts index 03d28110d612a..c45f191b1130d 100644 --- a/x-pack/plugins/infra/server/routes/metadata/index.ts +++ b/x-pack/plugins/infra/server/routes/metadata/index.ts @@ -38,7 +38,7 @@ export const initMetadataRoute = (libs: InfraBackendLibs) => { }, async (requestContext, request, response) => { try { - const { nodeId, nodeType, sourceId } = pipe( + const { nodeId, nodeType, sourceId, timeRange } = pipe( InfraMetadataRequestRT.decode(request.body), fold(throwErrors(Boom.badRequest), identity) ); @@ -52,7 +52,8 @@ export const initMetadataRoute = (libs: InfraBackendLibs) => { requestContext, configuration, nodeId, - nodeType + nodeType, + timeRange ); const metricFeatures = pickFeatureName(metricsMetadata.buckets).map( nameToFeature('metrics') @@ -62,7 +63,13 @@ export const initMetadataRoute = (libs: InfraBackendLibs) => { const cloudInstanceId = get<string>(info, 'cloud.instance.id'); const cloudMetricsMetadata = cloudInstanceId - ? await getCloudMetricsMetadata(framework, requestContext, configuration, cloudInstanceId) + ? await getCloudMetricsMetadata( + framework, + requestContext, + configuration, + cloudInstanceId, + timeRange + ) : { buckets: [] }; const cloudMetricsFeatures = pickFeatureName(cloudMetricsMetadata.buckets).map( nameToFeature('metrics') diff --git a/x-pack/plugins/infra/server/routes/metadata/lib/get_cloud_metric_metadata.ts b/x-pack/plugins/infra/server/routes/metadata/lib/get_cloud_metric_metadata.ts index 75ca3ae3caee2..54a1ca0aaa7e0 100644 --- a/x-pack/plugins/infra/server/routes/metadata/lib/get_cloud_metric_metadata.ts +++ b/x-pack/plugins/infra/server/routes/metadata/lib/get_cloud_metric_metadata.ts @@ -21,7 +21,8 @@ export const getCloudMetricsMetadata = async ( framework: KibanaFramework, requestContext: RequestHandlerContext, sourceConfiguration: InfraSourceConfiguration, - instanceId: string + instanceId: string, + timeRange: { from: number; to: number } ): Promise<InfraCloudMetricsAdapterResponse> => { const metricQuery = { allowNoIndices: true, @@ -30,7 +31,18 @@ export const getCloudMetricsMetadata = async ( body: { query: { bool: { - filter: [{ match: { 'cloud.instance.id': instanceId } }], + filter: [ + { match: { 'cloud.instance.id': instanceId } }, + { + range: { + [sourceConfiguration.fields.timestamp]: { + gte: timeRange.from, + lte: timeRange.to, + format: 'epoch_millis', + }, + }, + }, + ], should: CLOUD_METRICS_MODULES.map(module => ({ match: { 'event.module': module } })), }, }, diff --git a/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts b/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts index 191339565b813..7753d3161039b 100644 --- a/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts +++ b/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts @@ -26,7 +26,8 @@ export const getMetricMetadata = async ( requestContext: RequestHandlerContext, sourceConfiguration: InfraSourceConfiguration, nodeId: string, - nodeType: InventoryItemType + nodeType: InventoryItemType, + timeRange: { from: number; to: number } ): Promise<InfraMetricsAdapterResponse> => { const fields = findInventoryFields(nodeType, sourceConfiguration.fields); const metricQuery = { @@ -41,6 +42,15 @@ export const getMetricMetadata = async ( { match: { [fields.id]: nodeId }, }, + { + range: { + [sourceConfiguration.fields.timestamp]: { + gte: timeRange.from, + lte: timeRange.to, + format: 'epoch_millis', + }, + }, + }, ], }, }, diff --git a/x-pack/test/api_integration/apis/infra/metadata.ts b/x-pack/test/api_integration/apis/infra/metadata.ts index b693881abcdf7..5187cc5e3ec26 100644 --- a/x-pack/test/api_integration/apis/infra/metadata.ts +++ b/x-pack/test/api_integration/apis/infra/metadata.ts @@ -12,6 +12,28 @@ import { } from '../../../../plugins/infra/common/http_api/metadata_api'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { DATES } from './constants'; + +const timeRange700 = { + from: DATES['7.0.0'].hosts.min, + to: DATES[`7.0.0`].hosts.max, +}; + +const timeRange660 = { + from: DATES['6.6.0'].docker.min, + to: DATES[`6.6.0`].docker.max, +}; + +const timeRange800withAws = { + from: DATES['8.0.0'].logs_and_metrics_with_aws.min, + to: DATES[`8.0.0`].logs_and_metrics_with_aws.max, +}; + +const timeRange800 = { + from: DATES['8.0.0'].logs_and_metrics.min, + to: DATES[`8.0.0`].logs_and_metrics.max, +}; + export default function({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); @@ -34,6 +56,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: 'demo-stack-mysql-01', nodeType: InfraNodeType.host, + timeRange: timeRange700, }); if (metadata) { expect(metadata.features.length).to.be(12); @@ -53,6 +76,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: '631f36a845514442b93c3fdd2dc91bcd8feb680b8ac5832c7fb8fdc167bb938e', nodeType: InfraNodeType.container, + timeRange: timeRange660, }); if (metadata) { expect(metadata.features.length).to.be(10); @@ -74,6 +98,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: 'gke-observability-8--observability-8--bc1afd95-f0zc', nodeType: InfraNodeType.host, + timeRange: timeRange800withAws, }); if (metadata) { expect(metadata.features.length).to.be(58); @@ -114,6 +139,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: 'ip-172-31-47-9.us-east-2.compute.internal', nodeType: InfraNodeType.host, + timeRange: timeRange800withAws, }); if (metadata) { expect(metadata.features.length).to.be(19); @@ -155,6 +181,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: '14887487-99f8-11e9-9a96-42010a84004d', nodeType: InfraNodeType.pod, + timeRange: timeRange800withAws, }); if (metadata) { expect(metadata.features.length).to.be(29); @@ -200,6 +227,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: 'c74b04834c6d7cc1800c3afbe31d0c8c0c267f06e9eb45c2b0c2df3e6cee40c5', nodeType: InfraNodeType.container, + timeRange: timeRange800withAws, }); if (metadata) { expect(metadata.features.length).to.be(26); @@ -251,6 +279,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: 'gke-observability-8--observability-8--bc1afd95-f0zc', nodeType: 'host', + timeRange: timeRange800, }); if (metadata) { expect( @@ -265,6 +294,7 @@ export default function({ getService }: FtrProviderContext) { sourceId: 'default', nodeId: 'c1031331-9ae0-11e9-9a96-42010a84004d', nodeType: 'pod', + timeRange: timeRange800, }); if (metadata) { expect( diff --git a/x-pack/typings/rison_node.d.ts b/x-pack/typings/rison_node.d.ts index ec8e5c1f407ad..f830adc897445 100644 --- a/x-pack/typings/rison_node.d.ts +++ b/x-pack/typings/rison_node.d.ts @@ -5,7 +5,7 @@ */ declare module 'rison-node' { - export type RisonValue = null | boolean | number | string | RisonObject | RisonArray; + export type RisonValue = undefined | null | boolean | number | string | RisonObject | RisonArray; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface RisonArray extends Array<RisonValue> {} From 3e2665441633472fc57ba41b1a11bcf9b45db049 Mon Sep 17 00:00:00 2001 From: Pete Harverson <peteharverson@users.noreply.github.com> Date: Tue, 14 Apr 2020 17:49:46 +0100 Subject: [PATCH 102/121] [ML] Converts utils Mocha tests to Jest (#63132) * [ML] Converts utils Mocha tests to Jest * [ML] Remove unused imports * [ML] Switch out enzyme mount for react testing library render Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../ml/common/util/__tests__/anomaly_utils.js | 443 ------------- .../plugins/ml/common/util/anomaly_utils.d.ts | 11 - .../ml/common/util/anomaly_utils.test.ts | 444 +++++++++++++ .../{anomaly_utils.js => anomaly_utils.ts} | 54 +- .../{__tests__/utils.js => utils.test.js} | 45 +- .../util/__tests__/calc_auto_interval.js | 140 ---- .../application/util/__tests__/chart_utils.js | 297 --------- .../util/__tests__/string_utils.js | 229 ------- .../util/calc_auto_interval.test.js | 139 ++++ .../application/util/chart_utils.test.js | 624 ++++++++++++------ .../public/application/util/string_utils.d.ts | 4 + .../public/application/util/string_utils.js | 205 ------ .../application/util/string_utils.test.ts | 193 ++++++ 13 files changed, 1271 insertions(+), 1557 deletions(-) delete mode 100644 x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js delete mode 100644 x-pack/plugins/ml/common/util/anomaly_utils.d.ts create mode 100644 x-pack/plugins/ml/common/util/anomaly_utils.test.ts rename x-pack/plugins/ml/common/util/{anomaly_utils.js => anomaly_utils.ts} (87%) rename x-pack/plugins/ml/public/application/components/rule_editor/{__tests__/utils.js => utils.test.js} (66%) delete mode 100644 x-pack/plugins/ml/public/application/util/__tests__/calc_auto_interval.js delete mode 100644 x-pack/plugins/ml/public/application/util/__tests__/chart_utils.js delete mode 100644 x-pack/plugins/ml/public/application/util/__tests__/string_utils.js create mode 100644 x-pack/plugins/ml/public/application/util/calc_auto_interval.test.js create mode 100644 x-pack/plugins/ml/public/application/util/string_utils.test.ts diff --git a/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js b/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js deleted file mode 100644 index 515304d222c8c..0000000000000 --- a/x-pack/plugins/ml/common/util/__tests__/anomaly_utils.js +++ /dev/null @@ -1,443 +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 { - getSeverity, - getSeverityWithLow, - getSeverityColor, - getMultiBucketImpactLabel, - getEntityFieldName, - getEntityFieldValue, - getEntityFieldList, - showActualForFunction, - showTypicalForFunction, - isRuleSupported, - aggregationTypeTransform, -} from '../anomaly_utils'; - -describe('ML - anomaly utils', () => { - const partitionEntityRecord = { - job_id: 'farequote', - result_type: 'record', - probability: 0.012818, - record_score: 0.0162059, - bucket_span: 300, - detector_index: 0, - timestamp: 1455047400000, - partition_field_name: 'airline', - partition_field_value: 'AAL', - function: 'mean', - function_description: 'mean', - field_name: 'responsetime', - }; - - const byEntityRecord = { - job_id: 'farequote', - result_type: 'record', - probability: 0.012818, - record_score: 0.0162059, - bucket_span: 300, - detector_index: 0, - timestamp: 1455047400000, - by_field_name: 'airline', - by_field_value: 'JZA', - function: 'mean', - function_description: 'mean', - field_name: 'responsetime', - }; - - const overEntityRecord = { - job_id: 'gallery', - result_type: 'record', - probability: 2.81806e-9, - record_score: 59.055, - bucket_span: 3600, - detector_index: 4, - timestamp: 1420552800000, - function: 'sum', - function_description: 'sum', - field_name: 'bytes', - by_field_name: 'method', - over_field_name: 'clientip', - over_field_value: '37.157.32.164', - }; - - const noEntityRecord = { - job_id: 'farequote_no_by', - result_type: 'record', - probability: 0.0191711, - record_score: 4.38431, - initial_record_score: 19.654, - bucket_span: 300, - detector_index: 0, - timestamp: 1454890500000, - function: 'mean', - function_description: 'mean', - field_name: 'responsetime', - }; - - const metricNoEntityRecord = { - job_id: 'farequote_metric', - result_type: 'record', - probability: 0.030133495093182184, - record_score: 0.024881740359975164, - initial_record_score: 0.024881740359975164, - bucket_span: 900, - detector_index: 0, - is_interim: false, - timestamp: 1486845000000, - function: 'metric', - function_description: 'mean', - typical: [545.7764658569108], - actual: [758.8220213274412], - field_name: 'responsetime', - influencers: [ - { - influencer_field_name: 'airline', - influencer_field_values: ['NKS'], - }, - ], - airline: ['NKS'], - }; - - const rareEntityRecord = { - job_id: 'gallery', - result_type: 'record', - probability: 0.02277014211908481, - record_score: 4.545378107075983, - initial_record_score: 4.545378107075983, - bucket_span: 3600, - detector_index: 0, - is_interim: false, - timestamp: 1495879200000, - by_field_name: 'status', - function: 'rare', - function_description: 'rare', - over_field_name: 'clientip', - over_field_value: '173.252.74.112', - causes: [ - { - probability: 0.02277014211908481, - by_field_name: 'status', - by_field_value: '206', - function: 'rare', - function_description: 'rare', - typical: [0.00014832458182211878], - actual: [1], - over_field_name: 'clientip', - over_field_value: '173.252.74.112', - }, - ], - influencers: [ - { - influencer_field_name: 'uri', - influencer_field_values: [ - '/wp-content/uploads/2013/06/dune_house_oil_on_canvas_24x20-298x298.jpg', - '/wp-content/uploads/2013/10/Case-dAste-1-11-298x298.png', - ], - }, - { - influencer_field_name: 'status', - influencer_field_values: ['206'], - }, - { - influencer_field_name: 'clientip', - influencer_field_values: ['173.252.74.112'], - }, - ], - clientip: ['173.252.74.112'], - uri: [ - '/wp-content/uploads/2013/06/dune_house_oil_on_canvas_24x20-298x298.jpg', - '/wp-content/uploads/2013/10/Case-dAste-1-11-298x298.png', - ], - status: ['206'], - }; - - describe('getSeverity', () => { - it('returns warning for 0 <= score < 25', () => { - expect(getSeverity(0).id).to.be('warning'); - expect(getSeverity(0.001).id).to.be('warning'); - expect(getSeverity(24.99).id).to.be('warning'); - }); - - it('returns minor for 25 <= score < 50', () => { - expect(getSeverity(25).id).to.be('minor'); - expect(getSeverity(49.99).id).to.be('minor'); - }); - - it('returns minor for 50 <= score < 75', () => { - expect(getSeverity(50).id).to.be('major'); - expect(getSeverity(74.99).id).to.be('major'); - }); - - it('returns critical for score >= 75', () => { - expect(getSeverity(75).id).to.be('critical'); - expect(getSeverity(100).id).to.be('critical'); - expect(getSeverity(1000).id).to.be('critical'); - }); - - it('returns unknown for scores less than 0 or string input', () => { - expect(getSeverity(-10).id).to.be('unknown'); - expect(getSeverity('value').id).to.be('unknown'); - }); - }); - - describe('getSeverityWithLow', () => { - it('returns low for 0 <= score < 3', () => { - expect(getSeverityWithLow(0).id).to.be('low'); - expect(getSeverityWithLow(0.001).id).to.be('low'); - expect(getSeverityWithLow(2.99).id).to.be('low'); - }); - - it('returns warning for 3 <= score < 25', () => { - expect(getSeverityWithLow(3).id).to.be('warning'); - expect(getSeverityWithLow(24.99).id).to.be('warning'); - }); - - it('returns minor for 25 <= score < 50', () => { - expect(getSeverityWithLow(25).id).to.be('minor'); - expect(getSeverityWithLow(49.99).id).to.be('minor'); - }); - - it('returns minor for 50 <= score < 75', () => { - expect(getSeverityWithLow(50).id).to.be('major'); - expect(getSeverityWithLow(74.99).id).to.be('major'); - }); - - it('returns critical for score >= 75', () => { - expect(getSeverityWithLow(75).id).to.be('critical'); - expect(getSeverityWithLow(100).id).to.be('critical'); - expect(getSeverityWithLow(1000).id).to.be('critical'); - }); - - it('returns unknown for scores less than 0 or string input', () => { - expect(getSeverityWithLow(-10).id).to.be('unknown'); - expect(getSeverityWithLow('value').id).to.be('unknown'); - }); - }); - - describe('getSeverityColor', () => { - it('returns correct hex code for low for 0 <= score < 3', () => { - expect(getSeverityColor(0)).to.be('#d2e9f7'); - expect(getSeverityColor(0.001)).to.be('#d2e9f7'); - expect(getSeverityColor(2.99)).to.be('#d2e9f7'); - }); - - it('returns correct hex code for warning for 3 <= score < 25', () => { - expect(getSeverityColor(3)).to.be('#8bc8fb'); - expect(getSeverityColor(24.99)).to.be('#8bc8fb'); - }); - - it('returns correct hex code for minor for 25 <= score < 50', () => { - expect(getSeverityColor(25)).to.be('#fdec25'); - expect(getSeverityColor(49.99)).to.be('#fdec25'); - }); - - it('returns correct hex code for major for 50 <= score < 75', () => { - expect(getSeverityColor(50)).to.be('#fba740'); - expect(getSeverityColor(74.99)).to.be('#fba740'); - }); - - it('returns correct hex code for critical for score >= 75', () => { - expect(getSeverityColor(75)).to.be('#fe5050'); - expect(getSeverityColor(100)).to.be('#fe5050'); - expect(getSeverityColor(1000)).to.be('#fe5050'); - }); - - it('returns correct hex code for unknown for scores less than 0 or string input', () => { - expect(getSeverityColor(-10)).to.be('#ffffff'); - expect(getSeverityColor('value')).to.be('#ffffff'); - }); - }); - - describe('getMultiBucketImpactLabel', () => { - it('returns high for 3 <= score <= 5', () => { - expect(getMultiBucketImpactLabel(3)).to.be('high'); - expect(getMultiBucketImpactLabel(5)).to.be('high'); - }); - - it('returns medium for 2 <= score < 3', () => { - expect(getMultiBucketImpactLabel(2)).to.be('medium'); - expect(getMultiBucketImpactLabel(2.99)).to.be('medium'); - }); - - it('returns low for 1 <= score < 2', () => { - expect(getMultiBucketImpactLabel(1)).to.be('low'); - expect(getMultiBucketImpactLabel(1.99)).to.be('low'); - }); - - it('returns none for -5 <= score < 1', () => { - expect(getMultiBucketImpactLabel(-5)).to.be('none'); - expect(getMultiBucketImpactLabel(0.99)).to.be('none'); - }); - - it('returns expected label when impact outside normal bounds', () => { - expect(getMultiBucketImpactLabel(10)).to.be('high'); - expect(getMultiBucketImpactLabel(-10)).to.be('none'); - }); - }); - - describe('getEntityFieldName', () => { - it('returns the by field name', () => { - expect(getEntityFieldName(byEntityRecord)).to.be('airline'); - }); - - it('returns the partition field name', () => { - expect(getEntityFieldName(partitionEntityRecord)).to.be('airline'); - }); - - it('returns the over field name', () => { - expect(getEntityFieldName(overEntityRecord)).to.be('clientip'); - }); - - it('returns undefined if no by, over or partition fields', () => { - expect(getEntityFieldName(noEntityRecord)).to.be(undefined); - }); - }); - - describe('getEntityFieldValue', () => { - it('returns the by field value', () => { - expect(getEntityFieldValue(byEntityRecord)).to.be('JZA'); - }); - - it('returns the partition field value', () => { - expect(getEntityFieldValue(partitionEntityRecord)).to.be('AAL'); - }); - - it('returns the over field value', () => { - expect(getEntityFieldValue(overEntityRecord)).to.be('37.157.32.164'); - }); - - it('returns undefined if no by, over or partition fields', () => { - expect(getEntityFieldValue(noEntityRecord)).to.be(undefined); - }); - }); - - describe('getEntityFieldList', () => { - it('returns an empty list for a record with no by, over or partition fields', () => { - expect(getEntityFieldList(noEntityRecord)).to.be.empty(); - }); - - it('returns correct list for a record with a by field', () => { - expect(getEntityFieldList(byEntityRecord)).to.eql([ - { - fieldName: 'airline', - fieldValue: 'JZA', - fieldType: 'by', - }, - ]); - }); - - it('returns correct list for a record with a partition field', () => { - expect(getEntityFieldList(partitionEntityRecord)).to.eql([ - { - fieldName: 'airline', - fieldValue: 'AAL', - fieldType: 'partition', - }, - ]); - }); - - it('returns correct list for a record with an over field', () => { - expect(getEntityFieldList(overEntityRecord)).to.eql([ - { - fieldName: 'clientip', - fieldValue: '37.157.32.164', - fieldType: 'over', - }, - ]); - }); - - it('returns correct list for a record with a by and over field', () => { - expect(getEntityFieldList(rareEntityRecord)).to.eql([ - { - fieldName: 'clientip', - fieldValue: '173.252.74.112', - fieldType: 'over', - }, - ]); - }); - }); - - describe('showActualForFunction', () => { - it('returns true for expected function descriptions', () => { - expect(showActualForFunction('count')).to.be(true); - expect(showActualForFunction('distinct_count')).to.be(true); - expect(showActualForFunction('lat_long')).to.be(true); - expect(showActualForFunction('mean')).to.be(true); - expect(showActualForFunction('max')).to.be(true); - expect(showActualForFunction('min')).to.be(true); - expect(showActualForFunction('sum')).to.be(true); - expect(showActualForFunction('median')).to.be(true); - expect(showActualForFunction('varp')).to.be(true); - expect(showActualForFunction('info_content')).to.be(true); - expect(showActualForFunction('time')).to.be(true); - }); - - it('returns false for expected function descriptions', () => { - expect(showActualForFunction('rare')).to.be(false); - }); - }); - - describe('showTypicalForFunction', () => { - it('returns true for expected function descriptions', () => { - expect(showTypicalForFunction('count')).to.be(true); - expect(showTypicalForFunction('distinct_count')).to.be(true); - expect(showTypicalForFunction('lat_long')).to.be(true); - expect(showTypicalForFunction('mean')).to.be(true); - expect(showTypicalForFunction('max')).to.be(true); - expect(showTypicalForFunction('min')).to.be(true); - expect(showTypicalForFunction('sum')).to.be(true); - expect(showTypicalForFunction('median')).to.be(true); - expect(showTypicalForFunction('varp')).to.be(true); - expect(showTypicalForFunction('info_content')).to.be(true); - expect(showTypicalForFunction('time')).to.be(true); - }); - - it('returns false for expected function descriptions', () => { - expect(showTypicalForFunction('rare')).to.be(false); - }); - }); - - describe('isRuleSupported', () => { - it('returns true for anomalies supporting rules', () => { - expect(isRuleSupported(partitionEntityRecord)).to.be(true); - expect(isRuleSupported(byEntityRecord)).to.be(true); - expect(isRuleSupported(overEntityRecord)).to.be(true); - expect(isRuleSupported(rareEntityRecord)).to.be(true); - expect(isRuleSupported(noEntityRecord)).to.be(true); - }); - - it('returns false for anomaly not supporting rules', () => { - expect(isRuleSupported(metricNoEntityRecord)).to.be(false); - }); - }); - - describe('aggregationTypeTransform', () => { - it('returns correct ES aggregation type for ML function description', () => { - expect(aggregationTypeTransform.toES('count')).to.be('count'); - expect(aggregationTypeTransform.toES('distinct_count')).to.be('cardinality'); - expect(aggregationTypeTransform.toES('distinct_count')).to.not.be('distinct_count'); - expect(aggregationTypeTransform.toES('mean')).to.be('avg'); - expect(aggregationTypeTransform.toES('mean')).to.not.be('mean'); - expect(aggregationTypeTransform.toES('max')).to.be('max'); - expect(aggregationTypeTransform.toES('min')).to.be('min'); - expect(aggregationTypeTransform.toES('sum')).to.be('sum'); - }); - - it('returns correct ML function description for ES aggregation type', () => { - expect(aggregationTypeTransform.toML('count')).to.be('count'); - expect(aggregationTypeTransform.toML('cardinality')).to.be('distinct_count'); - expect(aggregationTypeTransform.toML('cardinality')).to.not.be('cardinality'); - expect(aggregationTypeTransform.toML('avg')).to.be('mean'); - expect(aggregationTypeTransform.toML('avg')).to.not.be('avg'); - expect(aggregationTypeTransform.toML('max')).to.be('max'); - expect(aggregationTypeTransform.toML('min')).to.be('min'); - expect(aggregationTypeTransform.toML('sum')).to.be('sum'); - }); - }); -}); diff --git a/x-pack/plugins/ml/common/util/anomaly_utils.d.ts b/x-pack/plugins/ml/common/util/anomaly_utils.d.ts deleted file mode 100644 index adeb6dc7dd5b9..0000000000000 --- a/x-pack/plugins/ml/common/util/anomaly_utils.d.ts +++ /dev/null @@ -1,11 +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 { ANOMALY_SEVERITY } from '../constants/anomalies'; - -export function getSeverity(normalizedScore: number): string; -export function getSeverityType(normalizedScore: number): ANOMALY_SEVERITY; -export function getSeverityColor(normalizedScore: number): string; diff --git a/x-pack/plugins/ml/common/util/anomaly_utils.test.ts b/x-pack/plugins/ml/common/util/anomaly_utils.test.ts new file mode 100644 index 0000000000000..1343e4611c215 --- /dev/null +++ b/x-pack/plugins/ml/common/util/anomaly_utils.test.ts @@ -0,0 +1,444 @@ +/* + * 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 { AnomalyRecordDoc } from '../types/anomalies'; + +import { + aggregationTypeTransform, + getEntityFieldList, + getEntityFieldName, + getEntityFieldValue, + getMultiBucketImpactLabel, + getSeverity, + getSeverityWithLow, + getSeverityColor, + isRuleSupported, + showActualForFunction, + showTypicalForFunction, +} from './anomaly_utils'; + +describe('ML - anomaly utils', () => { + const partitionEntityRecord: AnomalyRecordDoc = { + job_id: 'farequote', + result_type: 'record', + probability: 0.012818, + record_score: 0.0162059, + initial_record_score: 0.0162059, + bucket_span: 300, + detector_index: 0, + is_interim: false, + timestamp: 1455047400000, + partition_field_name: 'airline', + partition_field_value: 'AAL', + function: 'mean', + function_description: 'mean', + field_name: 'responsetime', + }; + + const byEntityRecord: AnomalyRecordDoc = { + job_id: 'farequote', + result_type: 'record', + probability: 0.012818, + record_score: 0.0162059, + initial_record_score: 0.0162059, + bucket_span: 300, + detector_index: 0, + is_interim: false, + timestamp: 1455047400000, + by_field_name: 'airline', + by_field_value: 'JZA', + function: 'mean', + function_description: 'mean', + field_name: 'responsetime', + }; + + const overEntityRecord: AnomalyRecordDoc = { + job_id: 'gallery', + result_type: 'record', + probability: 2.81806e-9, + record_score: 59.055, + initial_record_score: 59.055, + bucket_span: 3600, + detector_index: 4, + is_interim: false, + timestamp: 1420552800000, + function: 'sum', + function_description: 'sum', + field_name: 'bytes', + by_field_name: 'method', + over_field_name: 'clientip', + over_field_value: '37.157.32.164', + }; + + const noEntityRecord: AnomalyRecordDoc = { + job_id: 'farequote_no_by', + result_type: 'record', + probability: 0.0191711, + record_score: 4.38431, + initial_record_score: 19.654, + bucket_span: 300, + detector_index: 0, + is_interim: false, + timestamp: 1454890500000, + function: 'mean', + function_description: 'mean', + field_name: 'responsetime', + }; + + const metricNoEntityRecord: AnomalyRecordDoc = { + job_id: 'farequote_metric', + result_type: 'record', + probability: 0.030133495093182184, + record_score: 0.024881740359975164, + initial_record_score: 0.024881740359975164, + bucket_span: 900, + detector_index: 0, + is_interim: false, + timestamp: 1486845000000, + function: 'metric', + function_description: 'mean', + typical: [545.7764658569108], + actual: [758.8220213274412], + field_name: 'responsetime', + influencers: [ + { + influencer_field_name: 'airline', + influencer_field_values: ['NKS'], + }, + ], + airline: ['NKS'], + }; + + const rareEntityRecord: AnomalyRecordDoc = { + job_id: 'gallery', + result_type: 'record', + probability: 0.02277014211908481, + record_score: 4.545378107075983, + initial_record_score: 4.545378107075983, + bucket_span: 3600, + detector_index: 0, + is_interim: false, + timestamp: 1495879200000, + by_field_name: 'status', + function: 'rare', + function_description: 'rare', + over_field_name: 'clientip', + over_field_value: '173.252.74.112', + causes: [ + { + probability: 0.02277014211908481, + by_field_name: 'status', + by_field_value: '206', + function: 'rare', + function_description: 'rare', + typical: [0.00014832458182211878], + actual: [1], + over_field_name: 'clientip', + over_field_value: '173.252.74.112', + }, + ], + influencers: [ + { + influencer_field_name: 'uri', + influencer_field_values: [ + '/wp-content/uploads/2013/06/dune_house_oil_on_canvas_24x20-298x298.jpg', + '/wp-content/uploads/2013/10/Case-dAste-1-11-298x298.png', + ], + }, + { + influencer_field_name: 'status', + influencer_field_values: ['206'], + }, + { + influencer_field_name: 'clientip', + influencer_field_values: ['173.252.74.112'], + }, + ], + clientip: ['173.252.74.112'], + uri: [ + '/wp-content/uploads/2013/06/dune_house_oil_on_canvas_24x20-298x298.jpg', + '/wp-content/uploads/2013/10/Case-dAste-1-11-298x298.png', + ], + status: ['206'], + }; + + describe('getSeverity', () => { + test('returns warning for 0 <= score < 25', () => { + expect(getSeverity(0).id).toBe('warning'); + expect(getSeverity(0.001).id).toBe('warning'); + expect(getSeverity(24.99).id).toBe('warning'); + }); + + test('returns minor for 25 <= score < 50', () => { + expect(getSeverity(25).id).toBe('minor'); + expect(getSeverity(49.99).id).toBe('minor'); + }); + + test('returns minor for 50 <= score < 75', () => { + expect(getSeverity(50).id).toBe('major'); + expect(getSeverity(74.99).id).toBe('major'); + }); + + test('returns critical for score >= 75', () => { + expect(getSeverity(75).id).toBe('critical'); + expect(getSeverity(100).id).toBe('critical'); + expect(getSeverity(1000).id).toBe('critical'); + }); + + test('returns unknown for scores less than 0', () => { + expect(getSeverity(-10).id).toBe('unknown'); + }); + }); + + describe('getSeverityWithLow', () => { + test('returns low for 0 <= score < 3', () => { + expect(getSeverityWithLow(0).id).toBe('low'); + expect(getSeverityWithLow(0.001).id).toBe('low'); + expect(getSeverityWithLow(2.99).id).toBe('low'); + }); + + test('returns warning for 3 <= score < 25', () => { + expect(getSeverityWithLow(3).id).toBe('warning'); + expect(getSeverityWithLow(24.99).id).toBe('warning'); + }); + + test('returns minor for 25 <= score < 50', () => { + expect(getSeverityWithLow(25).id).toBe('minor'); + expect(getSeverityWithLow(49.99).id).toBe('minor'); + }); + + test('returns minor for 50 <= score < 75', () => { + expect(getSeverityWithLow(50).id).toBe('major'); + expect(getSeverityWithLow(74.99).id).toBe('major'); + }); + + test('returns critical for score >= 75', () => { + expect(getSeverityWithLow(75).id).toBe('critical'); + expect(getSeverityWithLow(100).id).toBe('critical'); + expect(getSeverityWithLow(1000).id).toBe('critical'); + }); + + test('returns unknown for scores less than 0 ', () => { + expect(getSeverityWithLow(-10).id).toBe('unknown'); + }); + }); + + describe('getSeverityColor', () => { + test('returns correct hex code for low for 0 <= score < 3', () => { + expect(getSeverityColor(0)).toBe('#d2e9f7'); + expect(getSeverityColor(0.001)).toBe('#d2e9f7'); + expect(getSeverityColor(2.99)).toBe('#d2e9f7'); + }); + + test('returns correct hex code for warning for 3 <= score < 25', () => { + expect(getSeverityColor(3)).toBe('#8bc8fb'); + expect(getSeverityColor(24.99)).toBe('#8bc8fb'); + }); + + test('returns correct hex code for minor for 25 <= score < 50', () => { + expect(getSeverityColor(25)).toBe('#fdec25'); + expect(getSeverityColor(49.99)).toBe('#fdec25'); + }); + + test('returns correct hex code for major for 50 <= score < 75', () => { + expect(getSeverityColor(50)).toBe('#fba740'); + expect(getSeverityColor(74.99)).toBe('#fba740'); + }); + + test('returns correct hex code for critical for score >= 75', () => { + expect(getSeverityColor(75)).toBe('#fe5050'); + expect(getSeverityColor(100)).toBe('#fe5050'); + expect(getSeverityColor(1000)).toBe('#fe5050'); + }); + + test('returns correct hex code for unknown for scores less than 0', () => { + expect(getSeverityColor(-10)).toBe('#ffffff'); + }); + }); + + describe('getMultiBucketImpactLabel', () => { + test('returns high for 3 <= score <= 5', () => { + expect(getMultiBucketImpactLabel(3)).toBe('high'); + expect(getMultiBucketImpactLabel(5)).toBe('high'); + }); + + test('returns medium for 2 <= score < 3', () => { + expect(getMultiBucketImpactLabel(2)).toBe('medium'); + expect(getMultiBucketImpactLabel(2.99)).toBe('medium'); + }); + + test('returns low for 1 <= score < 2', () => { + expect(getMultiBucketImpactLabel(1)).toBe('low'); + expect(getMultiBucketImpactLabel(1.99)).toBe('low'); + }); + + test('returns none for -5 <= score < 1', () => { + expect(getMultiBucketImpactLabel(-5)).toBe('none'); + expect(getMultiBucketImpactLabel(0.99)).toBe('none'); + }); + + test('returns expected label when impact outside normal bounds', () => { + expect(getMultiBucketImpactLabel(10)).toBe('high'); + expect(getMultiBucketImpactLabel(-10)).toBe('none'); + }); + }); + + describe('getEntityFieldName', () => { + it('returns the by field name', () => { + expect(getEntityFieldName(byEntityRecord)).toBe('airline'); + }); + + it('returns the partition field name', () => { + expect(getEntityFieldName(partitionEntityRecord)).toBe('airline'); + }); + + it('returns the over field name', () => { + expect(getEntityFieldName(overEntityRecord)).toBe('clientip'); + }); + + it('returns undefined if no by, over or partition fields', () => { + expect(getEntityFieldName(noEntityRecord)).toBe(undefined); + }); + }); + + describe('getEntityFieldValue', () => { + test('returns the by field value', () => { + expect(getEntityFieldValue(byEntityRecord)).toBe('JZA'); + }); + + test('returns the partition field value', () => { + expect(getEntityFieldValue(partitionEntityRecord)).toBe('AAL'); + }); + + test('returns the over field value', () => { + expect(getEntityFieldValue(overEntityRecord)).toBe('37.157.32.164'); + }); + + test('returns undefined if no by, over or partition fields', () => { + expect(getEntityFieldValue(noEntityRecord)).toBe(undefined); + }); + }); + + describe('getEntityFieldList', () => { + test('returns an empty list for a record with no by, over or partition fields', () => { + expect(getEntityFieldList(noEntityRecord)).toHaveLength(0); + }); + + test('returns correct list for a record with a by field', () => { + expect(getEntityFieldList(byEntityRecord)).toEqual([ + { + fieldName: 'airline', + fieldValue: 'JZA', + fieldType: 'by', + }, + ]); + }); + + test('returns correct list for a record with a partition field', () => { + expect(getEntityFieldList(partitionEntityRecord)).toEqual([ + { + fieldName: 'airline', + fieldValue: 'AAL', + fieldType: 'partition', + }, + ]); + }); + + test('returns correct list for a record with an over field', () => { + expect(getEntityFieldList(overEntityRecord)).toEqual([ + { + fieldName: 'clientip', + fieldValue: '37.157.32.164', + fieldType: 'over', + }, + ]); + }); + + test('returns correct list for a record with a by and over field', () => { + expect(getEntityFieldList(rareEntityRecord)).toEqual([ + { + fieldName: 'clientip', + fieldValue: '173.252.74.112', + fieldType: 'over', + }, + ]); + }); + }); + + describe('showActualForFunction', () => { + test('returns true for expected function descriptions', () => { + expect(showActualForFunction('count')).toBe(true); + expect(showActualForFunction('distinct_count')).toBe(true); + expect(showActualForFunction('lat_long')).toBe(true); + expect(showActualForFunction('mean')).toBe(true); + expect(showActualForFunction('max')).toBe(true); + expect(showActualForFunction('min')).toBe(true); + expect(showActualForFunction('sum')).toBe(true); + expect(showActualForFunction('median')).toBe(true); + expect(showActualForFunction('varp')).toBe(true); + expect(showActualForFunction('info_content')).toBe(true); + expect(showActualForFunction('time')).toBe(true); + }); + + test('returns false for expected function descriptions', () => { + expect(showActualForFunction('rare')).toBe(false); + }); + }); + + describe('showTypicalForFunction', () => { + test('returns true for expected function descriptions', () => { + expect(showTypicalForFunction('count')).toBe(true); + expect(showTypicalForFunction('distinct_count')).toBe(true); + expect(showTypicalForFunction('lat_long')).toBe(true); + expect(showTypicalForFunction('mean')).toBe(true); + expect(showTypicalForFunction('max')).toBe(true); + expect(showTypicalForFunction('min')).toBe(true); + expect(showTypicalForFunction('sum')).toBe(true); + expect(showTypicalForFunction('median')).toBe(true); + expect(showTypicalForFunction('varp')).toBe(true); + expect(showTypicalForFunction('info_content')).toBe(true); + expect(showTypicalForFunction('time')).toBe(true); + }); + + test('returns false for expected function descriptions', () => { + expect(showTypicalForFunction('rare')).toBe(false); + }); + }); + + describe('isRuleSupported', () => { + test('returns true for anomalies supporting rules', () => { + expect(isRuleSupported(partitionEntityRecord)).toBe(true); + expect(isRuleSupported(byEntityRecord)).toBe(true); + expect(isRuleSupported(overEntityRecord)).toBe(true); + expect(isRuleSupported(rareEntityRecord)).toBe(true); + expect(isRuleSupported(noEntityRecord)).toBe(true); + }); + + it('returns false for anomaly not supporting rules', () => { + expect(isRuleSupported(metricNoEntityRecord)).toBe(false); + }); + }); + + describe('aggregationTypeTransform', () => { + test('returns correct ES aggregation type for ML function description', () => { + expect(aggregationTypeTransform.toES('count')).toBe('count'); + expect(aggregationTypeTransform.toES('distinct_count')).toBe('cardinality'); + expect(aggregationTypeTransform.toES('mean')).toBe('avg'); + expect(aggregationTypeTransform.toES('max')).toBe('max'); + expect(aggregationTypeTransform.toES('min')).toBe('min'); + expect(aggregationTypeTransform.toES('sum')).toBe('sum'); + }); + + test('returns correct ML function description for ES aggregation type', () => { + expect(aggregationTypeTransform.toML('count')).toBe('count'); + expect(aggregationTypeTransform.toML('cardinality')).toBe('distinct_count'); + expect(aggregationTypeTransform.toML('avg')).toBe('mean'); + expect(aggregationTypeTransform.toML('max')).toBe('max'); + expect(aggregationTypeTransform.toML('min')).toBe('min'); + expect(aggregationTypeTransform.toML('sum')).toBe('sum'); + }); + }); +}); diff --git a/x-pack/plugins/ml/common/util/anomaly_utils.js b/x-pack/plugins/ml/common/util/anomaly_utils.ts similarity index 87% rename from x-pack/plugins/ml/common/util/anomaly_utils.js rename to x-pack/plugins/ml/common/util/anomaly_utils.ts index 16c27b6af869d..36b91f5580b39 100644 --- a/x-pack/plugins/ml/common/util/anomaly_utils.js +++ b/x-pack/plugins/ml/common/util/anomaly_utils.ts @@ -13,6 +13,24 @@ import { i18n } from '@kbn/i18n'; import { CONDITIONS_NOT_SUPPORTED_FUNCTIONS } from '../constants/detector_rule'; import { MULTI_BUCKET_IMPACT } from '../constants/multi_bucket_impact'; import { ANOMALY_SEVERITY, ANOMALY_THRESHOLD } from '../constants/anomalies'; +import { AnomalyRecordDoc } from '../types/anomalies'; + +export interface SeverityType { + id: ANOMALY_SEVERITY; + label: string; +} + +export enum ENTITY_FIELD_TYPE { + BY = 'by', + OVER = 'over', + PARTITON = 'partition', +} + +export interface EntityField { + fieldName: string; + fieldValue: string | number | undefined; + fieldType: ENTITY_FIELD_TYPE; +} // List of function descriptions for which actual values from record level results should be displayed. const DISPLAY_ACTUAL_FUNCTIONS = [ @@ -44,7 +62,7 @@ const DISPLAY_TYPICAL_FUNCTIONS = [ 'time', ]; -let severityTypes; +let severityTypes: Record<string, SeverityType>; function getSeverityTypes() { if (severityTypes) { @@ -93,7 +111,7 @@ function getSeverityTypes() { // Returns a severity label (one of critical, major, minor, warning or unknown) // for the supplied normalized anomaly score (a value between 0 and 100). -export function getSeverity(normalizedScore) { +export function getSeverity(normalizedScore: number): SeverityType { const severityTypesList = getSeverityTypes(); if (normalizedScore >= ANOMALY_THRESHOLD.CRITICAL) { @@ -109,7 +127,7 @@ export function getSeverity(normalizedScore) { } } -export function getSeverityType(normalizedScore) { +export function getSeverityType(normalizedScore: number): ANOMALY_SEVERITY { if (normalizedScore >= 75) { return ANOMALY_SEVERITY.CRITICAL; } else if (normalizedScore >= 50) { @@ -128,7 +146,7 @@ export function getSeverityType(normalizedScore) { // Returns a severity label (one of critical, major, minor, warning, low or unknown) // for the supplied normalized anomaly score (a value between 0 and 100), where scores // less than 3 are assigned a severity of 'low'. -export function getSeverityWithLow(normalizedScore) { +export function getSeverityWithLow(normalizedScore: number): SeverityType { const severityTypesList = getSeverityTypes(); if (normalizedScore >= ANOMALY_THRESHOLD.CRITICAL) { @@ -148,7 +166,7 @@ export function getSeverityWithLow(normalizedScore) { // Returns a severity RGB color (one of critical, major, minor, warning, low_warning or unknown) // for the supplied normalized anomaly score (a value between 0 and 100). -export function getSeverityColor(normalizedScore) { +export function getSeverityColor(normalizedScore: number): string { if (normalizedScore >= ANOMALY_THRESHOLD.CRITICAL) { return '#fe5050'; } else if (normalizedScore >= ANOMALY_THRESHOLD.MAJOR) { @@ -167,7 +185,7 @@ export function getSeverityColor(normalizedScore) { // Returns a label to use for the multi-bucket impact of an anomaly // according to the value of the multi_bucket_impact field of a record, // which ranges from -5 to +5. -export function getMultiBucketImpactLabel(multiBucketImpact) { +export function getMultiBucketImpactLabel(multiBucketImpact: number): string { if (multiBucketImpact >= MULTI_BUCKET_IMPACT.HIGH) { return i18n.translate('xpack.ml.anomalyUtils.multiBucketImpact.highLabel', { defaultMessage: 'high', @@ -190,7 +208,7 @@ export function getMultiBucketImpactLabel(multiBucketImpact) { // Returns the name of the field to use as the entity name from the source record // obtained from Elasticsearch. The function looks first for a by_field, then over_field, // then partition_field, returning undefined if none of these fields are present. -export function getEntityFieldName(record) { +export function getEntityFieldName(record: AnomalyRecordDoc): string | undefined { // Analyses with by and over fields, will have a top-level by_field_name, but // the by_field_value(s) will be in the nested causes array. if (record.by_field_name !== undefined && record.by_field_value !== undefined) { @@ -211,7 +229,7 @@ export function getEntityFieldName(record) { // Returns the value of the field to use as the entity value from the source record // obtained from Elasticsearch. The function looks first for a by_field, then over_field, // then partition_field, returning undefined if none of these fields are present. -export function getEntityFieldValue(record) { +export function getEntityFieldValue(record: AnomalyRecordDoc): string | number | undefined { if (record.by_field_value !== undefined) { return record.by_field_value; } @@ -229,13 +247,13 @@ export function getEntityFieldValue(record) { // Returns the list of partitioning entity fields for the source record as a list // of objects in the form { fieldName: airline, fieldValue: AAL, fieldType: partition } -export function getEntityFieldList(record) { - const entityFields = []; +export function getEntityFieldList(record: AnomalyRecordDoc): EntityField[] { + const entityFields: EntityField[] = []; if (record.partition_field_name !== undefined) { entityFields.push({ fieldName: record.partition_field_name, fieldValue: record.partition_field_value, - fieldType: 'partition', + fieldType: ENTITY_FIELD_TYPE.PARTITON, }); } @@ -243,7 +261,7 @@ export function getEntityFieldList(record) { entityFields.push({ fieldName: record.over_field_name, fieldValue: record.over_field_value, - fieldType: 'over', + fieldType: ENTITY_FIELD_TYPE.OVER, }); } @@ -254,7 +272,7 @@ export function getEntityFieldList(record) { entityFields.push({ fieldName: record.by_field_name, fieldValue: record.by_field_value, - fieldType: 'by', + fieldType: ENTITY_FIELD_TYPE.BY, }); } @@ -264,19 +282,19 @@ export function getEntityFieldList(record) { // Returns whether actual values should be displayed for a record with the specified function description. // Note that the 'function' field in a record contains what the user entered e.g. 'high_count', // whereas the 'function_description' field holds a ML-built display hint for function e.g. 'count'. -export function showActualForFunction(functionDescription) { +export function showActualForFunction(functionDescription: string): boolean { return DISPLAY_ACTUAL_FUNCTIONS.indexOf(functionDescription) > -1; } // Returns whether typical values should be displayed for a record with the specified function description. // Note that the 'function' field in a record contains what the user entered e.g. 'high_count', // whereas the 'function_description' field holds a ML-built display hint for function e.g. 'count'. -export function showTypicalForFunction(functionDescription) { +export function showTypicalForFunction(functionDescription: string): boolean { return DISPLAY_TYPICAL_FUNCTIONS.indexOf(functionDescription) > -1; } // Returns whether a rule can be configured against the specified anomaly. -export function isRuleSupported(record) { +export function isRuleSupported(record: AnomalyRecordDoc): boolean { // A rule can be configured with a numeric condition if the function supports it, // and/or with scope if there is a partitioning fields. return ( @@ -303,7 +321,7 @@ export function isRuleSupported(record) { // The input to toES and the output from toML correspond to the value of the // function_description field of anomaly records. export const aggregationTypeTransform = { - toES: function(oldAggType) { + toES(oldAggType: string): string { let newAggType = oldAggType; if (newAggType === 'mean') { @@ -316,7 +334,7 @@ export const aggregationTypeTransform = { return newAggType; }, - toML: function(oldAggType) { + toML(oldAggType: string): string { let newAggType = oldAggType; if (newAggType === 'avg') { diff --git a/x-pack/plugins/ml/public/application/components/rule_editor/__tests__/utils.js b/x-pack/plugins/ml/public/application/components/rule_editor/utils.test.js similarity index 66% rename from x-pack/plugins/ml/public/application/components/rule_editor/__tests__/utils.js rename to x-pack/plugins/ml/public/application/components/rule_editor/utils.test.js index b5f9bdeaa12aa..18e382f8fe5e8 100644 --- a/x-pack/plugins/ml/public/application/components/rule_editor/__tests__/utils.js +++ b/x-pack/plugins/ml/public/application/components/rule_editor/utils.test.js @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; -import { isValidRule, buildRuleDescription, getAppliesToValueFromAnomaly } from '../utils'; +import { isValidRule, buildRuleDescription, getAppliesToValueFromAnomaly } from './utils'; import { ACTION, APPLIES_TO, OPERATOR, FILTER_TYPE, -} from '../../../../../common/constants/detector_rule'; +} from '../../../../common/constants/detector_rule'; describe('ML - rule editor utils', () => { const ruleWithCondition = { @@ -55,19 +54,19 @@ describe('ML - rule editor utils', () => { }; describe('isValidRule', () => { - it('returns true for a rule with an action and a condition', () => { - expect(isValidRule(ruleWithCondition)).to.be(true); + test('returns true for a rule with an action and a condition', () => { + expect(isValidRule(ruleWithCondition)).toBe(true); }); - it('returns true for a rule with an action and scope', () => { - expect(isValidRule(ruleWithScope)).to.be(true); + test('returns true for a rule with an action and scope', () => { + expect(isValidRule(ruleWithScope)).toBe(true); }); - it('returns true for a rule with an action, scope and condition', () => { - expect(isValidRule(ruleWithConditionAndScope)).to.be(true); + test('returns true for a rule with an action, scope and condition', () => { + expect(isValidRule(ruleWithConditionAndScope)).toBe(true); }); - it('returns false for a rule with no action', () => { + test('returns false for a rule with no action', () => { const ruleWithNoAction = { actions: [], conditions: [ @@ -79,27 +78,27 @@ describe('ML - rule editor utils', () => { ], }; - expect(isValidRule(ruleWithNoAction)).to.be(false); + expect(isValidRule(ruleWithNoAction)).toBe(false); }); - it('returns false for a rule with no scope or conditions', () => { + test('returns false for a rule with no scope or conditions', () => { const ruleWithNoScopeOrCondition = { actions: [ACTION.SKIP_RESULT], }; - expect(isValidRule(ruleWithNoScopeOrCondition)).to.be(false); + expect(isValidRule(ruleWithNoScopeOrCondition)).toBe(false); }); }); describe('buildRuleDescription', () => { - it('returns expected rule descriptions', () => { - expect(buildRuleDescription(ruleWithCondition)).to.be( + test('returns expected rule descriptions', () => { + expect(buildRuleDescription(ruleWithCondition)).toBe( 'skip result when actual is greater than 10' ); - expect(buildRuleDescription(ruleWithScope)).to.be( + expect(buildRuleDescription(ruleWithScope)).toBe( 'skip result when instance is in test_aws_instances' ); - expect(buildRuleDescription(ruleWithConditionAndScope)).to.be( + expect(buildRuleDescription(ruleWithConditionAndScope)).toBe( 'skip result when typical is less than 100 AND instance is not in test_aws_instances' ); }); @@ -111,16 +110,16 @@ describe('ML - rule editor utils', () => { typical: [1.23], }; - it('returns expected actual value from an anomaly', () => { - expect(getAppliesToValueFromAnomaly(anomaly, APPLIES_TO.ACTUAL)).to.be(210); + test('returns expected actual value from an anomaly', () => { + expect(getAppliesToValueFromAnomaly(anomaly, APPLIES_TO.ACTUAL)).toBe(210); }); - it('returns expected typical value from an anomaly', () => { - expect(getAppliesToValueFromAnomaly(anomaly, APPLIES_TO.TYPICAL)).to.be(1.23); + test('returns expected typical value from an anomaly', () => { + expect(getAppliesToValueFromAnomaly(anomaly, APPLIES_TO.TYPICAL)).toBe(1.23); }); - it('returns expected diff from typical value from an anomaly', () => { - expect(getAppliesToValueFromAnomaly(anomaly, APPLIES_TO.DIFF_FROM_TYPICAL)).to.be(208.77); + test('returns expected diff from typical value from an anomaly', () => { + expect(getAppliesToValueFromAnomaly(anomaly, APPLIES_TO.DIFF_FROM_TYPICAL)).toBe(208.77); }); }); }); diff --git a/x-pack/plugins/ml/public/application/util/__tests__/calc_auto_interval.js b/x-pack/plugins/ml/public/application/util/__tests__/calc_auto_interval.js deleted file mode 100644 index 0553cec5cd7d4..0000000000000 --- a/x-pack/plugins/ml/public/application/util/__tests__/calc_auto_interval.js +++ /dev/null @@ -1,140 +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 moment from 'moment'; - -import { timeBucketsCalcAutoIntervalProvider } from '../calc_auto_interval'; - -describe('ML - calc auto intervals', () => { - const calcAuto = timeBucketsCalcAutoIntervalProvider(); - - describe('near interval', () => { - it('returns 0ms buckets for undefined / 0 bars', () => { - const interval = calcAuto.near(0, undefined); - expect(interval.asMilliseconds()).to.be(0); - }); - - it('returns 1000ms buckets for 60s / 100 bars', () => { - const interval = calcAuto.near(100, moment.duration(60, 's')); - expect(interval.asMilliseconds()).to.be(1000); - }); - - it('returns 5m buckets for 8h / 100 bars', () => { - const interval = calcAuto.near(100, moment.duration(8, 'h')); - expect(interval.asMinutes()).to.be(5); - }); - - it('returns 15m buckets for 1d / 100 bars', () => { - const interval = calcAuto.near(100, moment.duration(1, 'd')); - expect(interval.asMinutes()).to.be(15); - }); - - it('returns 1h buckets for 20d / 500 bars', () => { - const interval = calcAuto.near(500, moment.duration(20, 'd')); - expect(interval.asHours()).to.be(1); - }); - - it('returns 6h buckets for 100d / 500 bars', () => { - const interval = calcAuto.near(500, moment.duration(100, 'd')); - expect(interval.asHours()).to.be(6); - }); - - it('returns 24h buckets for 1y / 500 bars', () => { - const interval = calcAuto.near(500, moment.duration(1, 'y')); - expect(interval.asHours()).to.be(24); - }); - - it('returns 12h buckets for 1y / 1000 bars', () => { - const interval = calcAuto.near(1000, moment.duration(1, 'y')); - expect(interval.asHours()).to.be(12); - }); - }); - - describe('lessThan interval', () => { - it('returns 0ms buckets for undefined / 0 bars', () => { - const interval = calcAuto.lessThan(0, undefined); - expect(interval.asMilliseconds()).to.be(0); - }); - - it('returns 500ms buckets for 60s / 100 bars', () => { - const interval = calcAuto.lessThan(100, moment.duration(60, 's')); - expect(interval.asMilliseconds()).to.be(500); - }); - - it('returns 5m buckets for 8h / 100 bars', () => { - const interval = calcAuto.lessThan(100, moment.duration(8, 'h')); - expect(interval.asMinutes()).to.be(5); - }); - - it('returns 30m buckets for 1d / 100 bars', () => { - const interval = calcAuto.lessThan(100, moment.duration(1, 'd')); - expect(interval.asMinutes()).to.be(30); - }); - - it('returns 1h buckets for 20d / 500 bars', () => { - const interval = calcAuto.lessThan(500, moment.duration(20, 'd')); - expect(interval.asHours()).to.be(1); - }); - - it('returns 6h buckets for 100d / 500 bars', () => { - const interval = calcAuto.lessThan(500, moment.duration(100, 'd')); - expect(interval.asHours()).to.be(6); - }); - - it('returns 24h buckets for 1y / 500 bars', () => { - const interval = calcAuto.lessThan(500, moment.duration(1, 'y')); - expect(interval.asHours()).to.be(24); - }); - - it('returns 12h buckets for 1y / 1000 bars', () => { - const interval = calcAuto.lessThan(1000, moment.duration(1, 'y')); - expect(interval.asHours()).to.be(12); - }); - }); - - describe('atLeast interval', () => { - it('returns 0ms buckets for undefined / 0 bars', () => { - const interval = calcAuto.atLeast(0, undefined); - expect(interval.asMilliseconds()).to.be(0); - }); - - it('returns 100ms buckets for 60s / 100 bars', () => { - const interval = calcAuto.atLeast(100, moment.duration(60, 's')); - expect(interval.asMilliseconds()).to.be(100); - }); - - it('returns 1m buckets for 8h / 100 bars', () => { - const interval = calcAuto.atLeast(100, moment.duration(8, 'h')); - expect(interval.asMinutes()).to.be(1); - }); - - it('returns 10m buckets for 1d / 100 bars', () => { - const interval = calcAuto.atLeast(100, moment.duration(1, 'd')); - expect(interval.asMinutes()).to.be(10); - }); - - it('returns 30m buckets for 20d / 500 bars', () => { - const interval = calcAuto.atLeast(500, moment.duration(20, 'd')); - expect(interval.asMinutes()).to.be(30); - }); - - it('returns 4h buckets for 100d / 500 bars', () => { - const interval = calcAuto.atLeast(500, moment.duration(100, 'd')); - expect(interval.asHours()).to.be(4); - }); - - it('returns 12h buckets for 1y / 500 bars', () => { - const interval = calcAuto.atLeast(500, moment.duration(1, 'y')); - expect(interval.asHours()).to.be(12); - }); - - it('returns 8h buckets for 1y / 1000 bars', () => { - const interval = calcAuto.atLeast(1000, moment.duration(1, 'y')); - expect(interval.asHours()).to.be(8); - }); - }); -}); diff --git a/x-pack/plugins/ml/public/application/util/__tests__/chart_utils.js b/x-pack/plugins/ml/public/application/util/__tests__/chart_utils.js deleted file mode 100644 index 89df5946abe76..0000000000000 --- a/x-pack/plugins/ml/public/application/util/__tests__/chart_utils.js +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import $ from 'jquery'; -import d3 from 'd3'; -import expect from '@kbn/expect'; -import { - chartLimits, - filterAxisLabels, - getChartType, - numTicks, - showMultiBucketAnomalyMarker, - showMultiBucketAnomalyTooltip, -} from '../chart_utils'; -import { MULTI_BUCKET_IMPACT } from '../../../../common/constants/multi_bucket_impact'; -import { CHART_TYPE } from '../../explorer/explorer_constants'; - -describe('ML - chart utils', () => { - describe('chartLimits', () => { - it('returns NaN when called without data', () => { - const limits = chartLimits(); - expect(limits.min).to.be.NaN; - expect(limits.max).to.be.NaN; - }); - - it('returns {max: 625736376, min: 201039318} for some test data', () => { - const data = [ - { - date: new Date('2017-02-23T08:00:00.000Z'), - value: 228243469, - anomalyScore: 63.32916, - numberOfCauses: 1, - actual: [228243469], - typical: [133107.7703441773], - }, - { date: new Date('2017-02-23T09:00:00.000Z'), value: null }, - { date: new Date('2017-02-23T10:00:00.000Z'), value: null }, - { date: new Date('2017-02-23T11:00:00.000Z'), value: null }, - { - date: new Date('2017-02-23T12:00:00.000Z'), - value: 625736376, - anomalyScore: 97.32085, - numberOfCauses: 1, - actual: [625736376], - typical: [132830.424736973], - }, - { - date: new Date('2017-02-23T13:00:00.000Z'), - value: 201039318, - anomalyScore: 59.83488, - numberOfCauses: 1, - actual: [201039318], - typical: [132739.5267403542], - }, - ]; - - const limits = chartLimits(data); - - // {max: 625736376, min: 201039318} - expect(limits.min).to.be(201039318); - expect(limits.max).to.be(625736376); - }); - - it("adds 5% padding when min/max are the same, e.g. when there's only one data point", () => { - const data = [ - { - date: new Date('2017-02-23T08:00:00.000Z'), - value: 100, - anomalyScore: 50, - numberOfCauses: 1, - actual: [100], - typical: [100], - }, - ]; - - const limits = chartLimits(data); - expect(limits.min).to.be(95); - expect(limits.max).to.be(105); - }); - - it('returns minimum of 0 when data includes an anomaly for missing data', () => { - const data = [ - { date: new Date('2017-02-23T09:00:00.000Z'), value: 22.2 }, - { date: new Date('2017-02-23T10:00:00.000Z'), value: 23.3 }, - { date: new Date('2017-02-23T11:00:00.000Z'), value: 24.4 }, - { - date: new Date('2017-02-23T12:00:00.000Z'), - value: null, - anomalyScore: 97.32085, - actual: [0], - typical: [22.2], - }, - { date: new Date('2017-02-23T13:00:00.000Z'), value: 21.3 }, - { date: new Date('2017-02-23T14:00:00.000Z'), value: 21.2 }, - { date: new Date('2017-02-23T15:00:00.000Z'), value: 21.1 }, - ]; - - const limits = chartLimits(data); - expect(limits.min).to.be(0); - expect(limits.max).to.be(24.4); - }); - }); - - describe('filterAxisLabels', () => { - it('throws an error when called without arguments', () => { - expect(() => filterAxisLabels()).to.throwError(); - }); - - it('filters axis labels', () => { - // this provides a dummy structure of axis labels. - // the first one should always be filtered because it overflows on the - // left side of the axis. the last one should be filtered based on the - // given width parameter when doing the test calls. - $('body').append(` - <svg id="filterAxisLabels"> - <g class="x axis"> - <g class="tick" transform="translate(5,0)"> - <text dy=".71em" y="10" x="0" style="text-anchor: middle;">06:00</text> - </g> - <g class="tick" transform="translate(187.24137931034485,0)"> - <text dy=".71em" y="10" x="0" style="text-anchor: middle;">12:00</text> - </g> - <g class="tick" transform="translate(486.82758620689657,0)"> - <text dy=".71em" y="10" x="0" style="text-anchor: middle;">18:00</text> - </g> - <g class="tick" transform="translate(786.4137931034483,0)"> - <text dy=".71em" y="10" x="0" style="text-anchor: middle;">00:00</text> - </g> - </g> - </svg> - `); - - const selector = '#filterAxisLabels .x.axis'; - - // given this width, the last tick should not be removed - filterAxisLabels(d3.selectAll(selector), 1000); - expect(d3.selectAll(selector + ' .tick text').size()).to.be(3); - - // given this width, the last tick should be removed - filterAxisLabels(d3.selectAll(selector), 790); - expect(d3.selectAll(selector + ' .tick text').size()).to.be(2); - - // clean up - $('#filterAxisLabels').remove(); - }); - }); - - describe('getChartType', () => { - const singleMetricConfig = { - metricFunction: 'avg', - functionDescription: 'mean', - fieldName: 'responsetime', - entityFields: [], - }; - - const multiMetricConfig = { - metricFunction: 'avg', - functionDescription: 'mean', - fieldName: 'responsetime', - entityFields: [ - { - fieldName: 'airline', - fieldValue: 'AAL', - fieldType: 'partition', - }, - ], - }; - - const populationConfig = { - metricFunction: 'avg', - functionDescription: 'mean', - fieldName: 'http.response.body.bytes', - entityFields: [ - { - fieldName: 'source.ip', - fieldValue: '10.11.12.13', - fieldType: 'over', - }, - ], - }; - - const rareConfig = { - metricFunction: 'count', - functionDescription: 'rare', - entityFields: [ - { - fieldName: 'http.response.status_code', - fieldValue: '404', - fieldType: 'by', - }, - ], - }; - - const varpModelPlotConfig = { - metricFunction: null, - functionDescription: 'varp', - fieldName: 'NetworkOut', - entityFields: [ - { - fieldName: 'instance', - fieldValue: 'i-ef74d410', - fieldType: 'over', - }, - ], - }; - - const overScriptFieldModelPlotConfig = { - metricFunction: 'count', - functionDescription: 'count', - fieldName: 'highest_registered_domain', - entityFields: [ - { - fieldName: 'highest_registered_domain', - fieldValue: 'elastic.co', - fieldType: 'over', - }, - ], - datafeedConfig: { - script_fields: { - highest_registered_domain: { - script: { - source: "return domainSplit(doc['query'].value, params).get(1);", - lang: 'painless', - }, - ignore_failure: false, - }, - }, - }, - }; - - it('returns single metric chart type as expected for configs', () => { - expect(getChartType(singleMetricConfig)).to.be(CHART_TYPE.SINGLE_METRIC); - expect(getChartType(multiMetricConfig)).to.be(CHART_TYPE.SINGLE_METRIC); - expect(getChartType(varpModelPlotConfig)).to.be(CHART_TYPE.SINGLE_METRIC); - expect(getChartType(overScriptFieldModelPlotConfig)).to.be(CHART_TYPE.SINGLE_METRIC); - }); - - it('returns event distribution chart type as expected for configs', () => { - expect(getChartType(rareConfig)).to.be(CHART_TYPE.EVENT_DISTRIBUTION); - }); - - it('returns population distribution chart type as expected for configs', () => { - expect(getChartType(populationConfig)).to.be(CHART_TYPE.POPULATION_DISTRIBUTION); - }); - }); - - describe('numTicks', () => { - it('returns 10 for 1000', () => { - expect(numTicks(1000)).to.be(10); - }); - }); - - describe('showMultiBucketAnomalyMarker', () => { - it('returns true for points with multiBucketImpact at or above medium impact', () => { - expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.HIGH })).to.be( - true - ); - expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.MEDIUM })).to.be( - true - ); - }); - - it('returns false for points with multiBucketImpact missing or below medium impact', () => { - expect(showMultiBucketAnomalyMarker({})).to.be(false); - expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.LOW })).to.be( - false - ); - expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.NONE })).to.be( - false - ); - }); - }); - - describe('showMultiBucketAnomalyTooltip', () => { - it('returns true for points with multiBucketImpact at or above low impact', () => { - expect(showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.HIGH })).to.be( - true - ); - expect( - showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.MEDIUM }) - ).to.be(true); - expect(showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.LOW })).to.be( - true - ); - }); - - it('returns false for points with multiBucketImpact missing or below medium impact', () => { - expect(showMultiBucketAnomalyTooltip({})).to.be(false); - expect(showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.NONE })).to.be( - false - ); - }); - }); -}); diff --git a/x-pack/plugins/ml/public/application/util/__tests__/string_utils.js b/x-pack/plugins/ml/public/application/util/__tests__/string_utils.js deleted file mode 100644 index 702e9dfd96205..0000000000000 --- a/x-pack/plugins/ml/public/application/util/__tests__/string_utils.js +++ /dev/null @@ -1,229 +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 { - replaceStringTokens, - detectorToString, - sortByKey, - guessTimeFormat, - toLocaleString, - mlEscape, - escapeForElasticsearchQuery, -} from '../string_utils'; - -describe('ML - string utils', () => { - describe('replaceStringTokens', () => { - const testRecord = { - job_id: 'test_job', - result_type: 'record', - probability: 0.0191711, - record_score: 4.3, - bucket_span: 300, - detector_index: 0, - timestamp: 1454890500000, - function: 'mean', - function_description: 'mean', - field_name: 'responsetime', - user: "Des O'Connor", - testfield1: 'test$tring=[+-?]', - testfield2: '{<()>}', - testfield3: 'host=\\\\test@uk.dev', - }; - - it('returns correct values without URI encoding', () => { - const result = replaceStringTokens('user=$user$,time=$timestamp$', testRecord, false); - expect(result).to.be("user=Des O'Connor,time=1454890500000"); - }); - - it('returns correct values for missing token without URI encoding', () => { - const result = replaceStringTokens('user=$username$,time=$timestamp$', testRecord, false); - expect(result).to.be('user=$username$,time=1454890500000'); - }); - - it('returns correct values with URI encoding', () => { - const testString1 = 'https://www.google.co.uk/webhp#q=$testfield1$'; - const testString2 = 'https://www.google.co.uk/webhp#q=$testfield2$'; - const testString3 = 'https://www.google.co.uk/webhp#q=$testfield3$'; - const testString4 = 'https://www.google.co.uk/webhp#q=$user$'; - - const result1 = replaceStringTokens(testString1, testRecord, true); - const result2 = replaceStringTokens(testString2, testRecord, true); - const result3 = replaceStringTokens(testString3, testRecord, true); - const result4 = replaceStringTokens(testString4, testRecord, true); - - expect(result1).to.be('https://www.google.co.uk/webhp#q=test%24tring%3D%5B%2B-%3F%5D'); - expect(result2).to.be('https://www.google.co.uk/webhp#q=%7B%3C()%3E%7D'); - expect(result3).to.be('https://www.google.co.uk/webhp#q=host%3D%5C%5Ctest%40uk.dev'); - expect(result4).to.be("https://www.google.co.uk/webhp#q=Des%20O'Connor"); - }); - - it('returns correct values for missing token with URI encoding', () => { - const testString = 'https://www.google.co.uk/webhp#q=$username$&time=$timestamp$'; - const result = replaceStringTokens(testString, testRecord, true); - expect(result).to.be('https://www.google.co.uk/webhp#q=$username$&time=1454890500000'); - }); - }); - - describe('detectorToString', () => { - it('returns the correct descriptions for detectors', () => { - const detector1 = { - function: 'count', - }; - - const detector2 = { - function: 'count', - by_field_name: 'airline', - use_null: false, - }; - - const detector3 = { - function: 'mean', - field_name: 'CPUUtilization', - partition_field_name: 'region', - by_field_name: 'host', - over_field_name: 'user', - exclude_frequent: 'all', - }; - - expect(detectorToString(detector1)).to.be('count'); - expect(detectorToString(detector2)).to.be('count by airline use_null=false'); - expect(detectorToString(detector3)).to.be( - 'mean(CPUUtilization) by host over user partition_field_name=region exclude_frequent=all' - ); - }); - }); - - describe('sortByKey', () => { - const obj = { - zebra: 'stripes', - giraffe: 'neck', - elephant: 'trunk', - }; - - const valueComparator = function(value) { - return value; - }; - - it('returns correct ordering with default comparator', () => { - const result = sortByKey(obj, false); - const keys = Object.keys(result); - expect(keys[0]).to.be('elephant'); - expect(keys[1]).to.be('giraffe'); - expect(keys[2]).to.be('zebra'); - }); - - it('returns correct ordering with default comparator and order reversed', () => { - const result = sortByKey(obj, true); - const keys = Object.keys(result); - expect(keys[0]).to.be('zebra'); - expect(keys[1]).to.be('giraffe'); - expect(keys[2]).to.be('elephant'); - }); - - it('returns correct ordering with comparator', () => { - const result = sortByKey(obj, false, valueComparator); - const keys = Object.keys(result); - expect(keys[0]).to.be('giraffe'); - expect(keys[1]).to.be('zebra'); - expect(keys[2]).to.be('elephant'); - }); - - it('returns correct ordering with comparator and order reversed', () => { - const result = sortByKey(obj, true, valueComparator); - const keys = Object.keys(result); - expect(keys[0]).to.be('elephant'); - expect(keys[1]).to.be('zebra'); - expect(keys[2]).to.be('giraffe'); - }); - }); - - describe('guessTimeFormat', () => { - it('returns correct format for various dates', () => { - expect(guessTimeFormat('2017-03-24T00:00')).to.be("yyyy-MM-dd'T'HH:mm"); - expect(guessTimeFormat('2017-03-24 00:00')).to.be('yyyy-MM-dd HH:mm'); - expect(guessTimeFormat('2017-03-24 00:00:00')).to.be('yyyy-MM-dd HH:mm:ss'); - expect(guessTimeFormat('2017-03-24 00:00:00Z')).to.be('yyyy-MM-dd HH:mm:ssX'); - expect(guessTimeFormat('2017-03-24 00:00:00.000')).to.be('yyyy-MM-dd HH:mm:ss.SSS'); - expect(guessTimeFormat('2017-03-24 00:00:00:000')).to.be('yyyy-MM-dd HH:mm:ss:SSS'); - expect(guessTimeFormat('2017-03-24 00:00:00.000+00:00:00')).to.be( - 'yyyy-MM-dd HH:mm:ss.SSSXXXXX' - ); - expect(guessTimeFormat('2017-03-24 00:00:00.000+00:00')).to.be('yyyy-MM-dd HH:mm:ss.SSSXXX'); - expect(guessTimeFormat('2017-03-24 00:00:00.000+000000')).to.be( - 'yyyy-MM-dd HH:mm:ss.SSSXXXX' - ); - expect(guessTimeFormat('2017-03-24 00:00:00.000+0000')).to.be('yyyy-MM-dd HH:mm:ss.SSSZ'); - expect(guessTimeFormat('2017-03-24 00:00:00.000+00')).to.be('yyyy-MM-dd HH:mm:ss.SSSX'); - expect(guessTimeFormat('2017-03-24 00:00:00.000Z')).to.be('yyyy-MM-dd HH:mm:ss.SSSX'); - expect(guessTimeFormat('2017-03-24 00:00:00.000 GMT')).to.be('yyyy-MM-dd HH:mm:ss.SSS zzz'); - expect(guessTimeFormat('2017-03-24 00:00:00 GMT')).to.be('yyyy-MM-dd HH:mm:ss zzz'); - expect(guessTimeFormat('2017 03 24 00:00:00.000')).to.be('yyyy MM dd HH:mm:ss.SSS'); - expect(guessTimeFormat('2017.03.24 00:00:00.000')).to.be('yyyy.MM.dd HH:mm:ss.SSS'); - expect(guessTimeFormat('2017/03/24 00:00:00.000')).to.be('yyyy/MM/dd HH:mm:ss.SSS'); - expect(guessTimeFormat('24/03/2017 00:00:00.000')).to.be('dd/MM/yyyy HH:mm:ss.SSS'); - expect(guessTimeFormat('03 24 2017 00:00:00.000')).to.be('MM dd yyyy HH:mm:ss.SSS'); - expect(guessTimeFormat('03/24/2017 00:00:00.000')).to.be('MM/dd/yyyy HH:mm:ss.SSS'); - expect(guessTimeFormat('2017 Mar 24 00:00:00.000')).to.be('yyyy MMM dd HH:mm:ss.SSS'); - expect(guessTimeFormat('Mar 24 2017 00:00:00.000')).to.be('MMM dd yyyy HH:mm:ss.SSS'); - expect(guessTimeFormat('24 Mar 2017 00:00:00.000')).to.be('dd MMM yyyy HH:mm:ss.SSS'); - expect(guessTimeFormat('1490313600')).to.be('epoch'); - expect(guessTimeFormat('1490313600000')).to.be('epoch_ms'); - }); - }); - - describe('toLocaleString', () => { - it('returns correct comma placement for large numbers', () => { - expect(toLocaleString(1)).to.be('1'); - expect(toLocaleString(10)).to.be('10'); - expect(toLocaleString(100)).to.be('100'); - expect(toLocaleString(1000)).to.be('1,000'); - expect(toLocaleString(10000)).to.be('10,000'); - expect(toLocaleString(100000)).to.be('100,000'); - expect(toLocaleString(1000000)).to.be('1,000,000'); - expect(toLocaleString(10000000)).to.be('10,000,000'); - expect(toLocaleString(100000000)).to.be('100,000,000'); - expect(toLocaleString(1000000000)).to.be('1,000,000,000'); - }); - }); - - describe('mlEscape', () => { - it('returns correct escaping of characters', () => { - expect(mlEscape('foo&bar')).to.be('foo&bar'); - expect(mlEscape('foo<bar')).to.be('foo<bar'); - expect(mlEscape('foo>bar')).to.be('foo>bar'); - expect(mlEscape('foo"bar')).to.be('foo"bar'); - expect(mlEscape("foo'bar")).to.be('foo'bar'); - expect(mlEscape('foo/bar')).to.be('foo/bar'); - }); - }); - - describe('escapeForElasticsearchQuery', () => { - it('returns correct escaping of reserved elasticsearch characters', () => { - expect(escapeForElasticsearchQuery('foo+bar')).to.be('foo\\+bar'); - expect(escapeForElasticsearchQuery('foo-bar')).to.be('foo\\-bar'); - expect(escapeForElasticsearchQuery('foo=bar')).to.be('foo\\=bar'); - expect(escapeForElasticsearchQuery('foo&&bar')).to.be('foo\\&\\&bar'); - expect(escapeForElasticsearchQuery('foo||bar')).to.be('foo\\|\\|bar'); - expect(escapeForElasticsearchQuery('foo>bar')).to.be('foo\\>bar'); - expect(escapeForElasticsearchQuery('foo<bar')).to.be('foo\\<bar'); - expect(escapeForElasticsearchQuery('foo!bar')).to.be('foo\\!bar'); - expect(escapeForElasticsearchQuery('foo(bar')).to.be('foo\\(bar'); - expect(escapeForElasticsearchQuery('foo)bar')).to.be('foo\\)bar'); - expect(escapeForElasticsearchQuery('foo{bar')).to.be('foo\\{bar'); - expect(escapeForElasticsearchQuery('foo[bar')).to.be('foo\\[bar'); - expect(escapeForElasticsearchQuery('foo]bar')).to.be('foo\\]bar'); - expect(escapeForElasticsearchQuery('foo^bar')).to.be('foo\\^bar'); - expect(escapeForElasticsearchQuery('foo"bar')).to.be('foo\\"bar'); - expect(escapeForElasticsearchQuery('foo~bar')).to.be('foo\\~bar'); - expect(escapeForElasticsearchQuery('foo*bar')).to.be('foo\\*bar'); - expect(escapeForElasticsearchQuery('foo?bar')).to.be('foo\\?bar'); - expect(escapeForElasticsearchQuery('foo:bar')).to.be('foo\\:bar'); - expect(escapeForElasticsearchQuery('foo\\bar')).to.be('foo\\\\bar'); - expect(escapeForElasticsearchQuery('foo/bar')).to.be('foo\\/bar'); - }); - }); -}); diff --git a/x-pack/plugins/ml/public/application/util/calc_auto_interval.test.js b/x-pack/plugins/ml/public/application/util/calc_auto_interval.test.js new file mode 100644 index 0000000000000..c36557a0e6951 --- /dev/null +++ b/x-pack/plugins/ml/public/application/util/calc_auto_interval.test.js @@ -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 moment from 'moment'; + +import { timeBucketsCalcAutoIntervalProvider } from './calc_auto_interval'; + +describe('ML - calc auto intervals', () => { + const calcAuto = timeBucketsCalcAutoIntervalProvider(); + + describe('near interval', () => { + test('returns 0ms buckets for undefined / 0 bars', () => { + const interval = calcAuto.near(0, undefined); + expect(interval.asMilliseconds()).toBe(0); + }); + + test('returns 1000ms buckets for 60s / 100 bars', () => { + const interval = calcAuto.near(100, moment.duration(60, 's')); + expect(interval.asMilliseconds()).toBe(1000); + }); + + test('returns 5m buckets for 8h / 100 bars', () => { + const interval = calcAuto.near(100, moment.duration(8, 'h')); + expect(interval.asMinutes()).toBe(5); + }); + + test('returns 15m buckets for 1d / 100 bars', () => { + const interval = calcAuto.near(100, moment.duration(1, 'd')); + expect(interval.asMinutes()).toBe(15); + }); + + test('returns 1h buckets for 20d / 500 bars', () => { + const interval = calcAuto.near(500, moment.duration(20, 'd')); + expect(interval.asHours()).toBe(1); + }); + + test('returns 6h buckets for 100d / 500 bars', () => { + const interval = calcAuto.near(500, moment.duration(100, 'd')); + expect(interval.asHours()).toBe(6); + }); + + test('returns 24h buckets for 1y / 500 bars', () => { + const interval = calcAuto.near(500, moment.duration(1, 'y')); + expect(interval.asHours()).toBe(24); + }); + + test('returns 12h buckets for 1y / 1000 bars', () => { + const interval = calcAuto.near(1000, moment.duration(1, 'y')); + expect(interval.asHours()).toBe(12); + }); + }); + + describe('lessThan interval', () => { + test('returns 0ms buckets for undefined / 0 bars', () => { + const interval = calcAuto.lessThan(0, undefined); + expect(interval.asMilliseconds()).toBe(0); + }); + + test('returns 500ms buckets for 60s / 100 bars', () => { + const interval = calcAuto.lessThan(100, moment.duration(60, 's')); + expect(interval.asMilliseconds()).toBe(500); + }); + + test('returns 5m buckets for 8h / 100 bars', () => { + const interval = calcAuto.lessThan(100, moment.duration(8, 'h')); + expect(interval.asMinutes()).toBe(5); + }); + + test('returns 30m buckets for 1d / 100 bars', () => { + const interval = calcAuto.lessThan(100, moment.duration(1, 'd')); + expect(interval.asMinutes()).toBe(30); + }); + + test('returns 1h buckets for 20d / 500 bars', () => { + const interval = calcAuto.lessThan(500, moment.duration(20, 'd')); + expect(interval.asHours()).toBe(1); + }); + + test('returns 6h buckets for 100d / 500 bars', () => { + const interval = calcAuto.lessThan(500, moment.duration(100, 'd')); + expect(interval.asHours()).toBe(6); + }); + + test('returns 24h buckets for 1y / 500 bars', () => { + const interval = calcAuto.lessThan(500, moment.duration(1, 'y')); + expect(interval.asHours()).toBe(24); + }); + + test('returns 12h buckets for 1y / 1000 bars', () => { + const interval = calcAuto.lessThan(1000, moment.duration(1, 'y')); + expect(interval.asHours()).toBe(12); + }); + }); + + describe('atLeast interval', () => { + test('returns 0ms buckets for undefined / 0 bars', () => { + const interval = calcAuto.atLeast(0, undefined); + expect(interval.asMilliseconds()).toBe(0); + }); + + test('returns 100ms buckets for 60s / 100 bars', () => { + const interval = calcAuto.atLeast(100, moment.duration(60, 's')); + expect(interval.asMilliseconds()).toBe(100); + }); + + test('returns 1m buckets for 8h / 100 bars', () => { + const interval = calcAuto.atLeast(100, moment.duration(8, 'h')); + expect(interval.asMinutes()).toBe(1); + }); + + test('returns 10m buckets for 1d / 100 bars', () => { + const interval = calcAuto.atLeast(100, moment.duration(1, 'd')); + expect(interval.asMinutes()).toBe(10); + }); + + test('returns 30m buckets for 20d / 500 bars', () => { + const interval = calcAuto.atLeast(500, moment.duration(20, 'd')); + expect(interval.asMinutes()).toBe(30); + }); + + test('returns 4h buckets for 100d / 500 bars', () => { + const interval = calcAuto.atLeast(500, moment.duration(100, 'd')); + expect(interval.asHours()).toBe(4); + }); + + test('returns 12h buckets for 1y / 500 bars', () => { + const interval = calcAuto.atLeast(500, moment.duration(1, 'y')); + expect(interval.asHours()).toBe(12); + }); + + test('returns 8h buckets for 1y / 1000 bars', () => { + const interval = calcAuto.atLeast(1000, moment.duration(1, 'y')); + expect(interval.asHours()).toBe(8); + }); + }); +}); diff --git a/x-pack/plugins/ml/public/application/util/chart_utils.test.js b/x-pack/plugins/ml/public/application/util/chart_utils.test.js index 4b33cb131be7f..57aea3c0ab5aa 100644 --- a/x-pack/plugins/ml/public/application/util/chart_utils.test.js +++ b/x-pack/plugins/ml/public/application/util/chart_utils.test.js @@ -29,246 +29,488 @@ const timefilter = getTimefilter(); import d3 from 'd3'; import moment from 'moment'; -import { mount } from 'enzyme'; import React from 'react'; +import { render } from '@testing-library/react'; import { + chartLimits, + getChartType, getExploreSeriesLink, getTickValues, - isLabelLengthAboveThreshold, getXTransform, + isLabelLengthAboveThreshold, + numTicks, removeLabelOverlap, + showMultiBucketAnomalyMarker, + showMultiBucketAnomalyTooltip, } from './chart_utils'; +import { MULTI_BUCKET_IMPACT } from '../../../common/constants/multi_bucket_impact'; +import { CHART_TYPE } from '../explorer/explorer_constants'; + timefilter.setTime({ from: moment(seriesConfig.selectedEarliest).toISOString(), to: moment(seriesConfig.selectedLatest).toISOString(), }); -describe('getExploreSeriesLink', () => { - test('get timeseriesexplorer link', () => { - const link = getExploreSeriesLink(seriesConfig); - const expectedLink = - `#/timeseriesexplorer?_g=(ml:(jobIds:!(population-03)),` + - `refreshInterval:(display:Off,pause:!f,value:0),time:(from:'2017-02-23T00:00:00.000Z',mode:absolute,` + - `to:'2017-02-23T23:59:59.999Z'))&_a=(mlTimeSeriesExplorer%3A(detectorIndex%3A0%2Centities%3A` + - `(nginx.access.remote_ip%3A'72.57.0.53')%2Czoom%3A(from%3A'2017-02-19T20%3A00%3A00.000Z'%2Cto%3A'2017-02-27T04%3A00%3A00.000Z'))` + - `%2Cquery%3A(query_string%3A(analyze_wildcard%3A!t%2Cquery%3A'*')))`; - - expect(link).toBe(expectedLink); - }); -}); +describe('ML - chart utils', () => { + describe('chartLimits', () => { + test('returns NaN when called without data', () => { + const limits = chartLimits(); + expect(limits.min).toBeNaN(); + expect(limits.max).toBeNaN(); + }); -describe('getTickValues', () => { - test('farequote sample data', () => { - const tickValues = getTickValues(1486656000000, 14400000, 1486606500000, 1486719900000); - - expect(tickValues).toEqual([ - 1486612800000, - 1486627200000, - 1486641600000, - 1486656000000, - 1486670400000, - 1486684800000, - 1486699200000, - 1486713600000, - ]); - }); + test('returns {max: 625736376, min: 201039318} for some test data', () => { + const data = [ + { + date: new Date('2017-02-23T08:00:00.000Z'), + value: 228243469, + anomalyScore: 63.32916, + numberOfCauses: 1, + actual: [228243469], + typical: [133107.7703441773], + }, + { date: new Date('2017-02-23T09:00:00.000Z'), value: null }, + { date: new Date('2017-02-23T10:00:00.000Z'), value: null }, + { date: new Date('2017-02-23T11:00:00.000Z'), value: null }, + { + date: new Date('2017-02-23T12:00:00.000Z'), + value: 625736376, + anomalyScore: 97.32085, + numberOfCauses: 1, + actual: [625736376], + typical: [132830.424736973], + }, + { + date: new Date('2017-02-23T13:00:00.000Z'), + value: 201039318, + anomalyScore: 59.83488, + numberOfCauses: 1, + actual: [201039318], + typical: [132739.5267403542], + }, + ]; + + const limits = chartLimits(data); + + // {max: 625736376, min: 201039318} + expect(limits.min).toBe(201039318); + expect(limits.max).toBe(625736376); + }); - test('filebeat sample data', () => { - const tickValues = getTickValues(1486080000000, 14400000, 1485860400000, 1486314000000); - expect(tickValues).toEqual([ - 1485864000000, - 1485878400000, - 1485892800000, - 1485907200000, - 1485921600000, - 1485936000000, - 1485950400000, - 1485964800000, - 1485979200000, - 1485993600000, - 1486008000000, - 1486022400000, - 1486036800000, - 1486051200000, - 1486065600000, - 1486080000000, - 1486094400000, - 1486108800000, - 1486123200000, - 1486137600000, - 1486152000000, - 1486166400000, - 1486180800000, - 1486195200000, - 1486209600000, - 1486224000000, - 1486238400000, - 1486252800000, - 1486267200000, - 1486281600000, - 1486296000000, - 1486310400000, - ]); + test("adds 5% padding when min/max are the same, e.g. when there's only one data point", () => { + const data = [ + { + date: new Date('2017-02-23T08:00:00.000Z'), + value: 100, + anomalyScore: 50, + numberOfCauses: 1, + actual: [100], + typical: [100], + }, + ]; + + const limits = chartLimits(data); + expect(limits.min).toBe(95); + expect(limits.max).toBe(105); + }); + + test('returns minimum of 0 when data includes an anomaly for missing data', () => { + const data = [ + { date: new Date('2017-02-23T09:00:00.000Z'), value: 22.2 }, + { date: new Date('2017-02-23T10:00:00.000Z'), value: 23.3 }, + { date: new Date('2017-02-23T11:00:00.000Z'), value: 24.4 }, + { + date: new Date('2017-02-23T12:00:00.000Z'), + value: null, + anomalyScore: 97.32085, + actual: [0], + typical: [22.2], + }, + { date: new Date('2017-02-23T13:00:00.000Z'), value: 21.3 }, + { date: new Date('2017-02-23T14:00:00.000Z'), value: 21.2 }, + { date: new Date('2017-02-23T15:00:00.000Z'), value: 21.1 }, + ]; + + const limits = chartLimits(data); + expect(limits.min).toBe(0); + expect(limits.max).toBe(24.4); + }); }); - test('gallery sample data', () => { - const tickValues = getTickValues(1518652800000, 604800000, 1518274800000, 1519635600000); - expect(tickValues).toEqual([1518652800000, 1519257600000]); + describe('getChartType', () => { + const singleMetricConfig = { + metricFunction: 'avg', + functionDescription: 'mean', + fieldName: 'responsetime', + entityFields: [], + }; + + const multiMetricConfig = { + metricFunction: 'avg', + functionDescription: 'mean', + fieldName: 'responsetime', + entityFields: [ + { + fieldName: 'airline', + fieldValue: 'AAL', + fieldType: 'partition', + }, + ], + }; + + const populationConfig = { + metricFunction: 'avg', + functionDescription: 'mean', + fieldName: 'http.response.body.bytes', + entityFields: [ + { + fieldName: 'source.ip', + fieldValue: '10.11.12.13', + fieldType: 'over', + }, + ], + }; + + const rareConfig = { + metricFunction: 'count', + functionDescription: 'rare', + entityFields: [ + { + fieldName: 'http.response.status_code', + fieldValue: '404', + fieldType: 'by', + }, + ], + }; + + const varpModelPlotConfig = { + metricFunction: null, + functionDescription: 'varp', + fieldName: 'NetworkOut', + entityFields: [ + { + fieldName: 'instance', + fieldValue: 'i-ef74d410', + fieldType: 'over', + }, + ], + }; + + const overScriptFieldModelPlotConfig = { + metricFunction: 'count', + functionDescription: 'count', + fieldName: 'highest_registered_domain', + entityFields: [ + { + fieldName: 'highest_registered_domain', + fieldValue: 'elastic.co', + fieldType: 'over', + }, + ], + datafeedConfig: { + script_fields: { + highest_registered_domain: { + script: { + source: "return domainSplit(doc['query'].value, params).get(1);", + lang: 'painless', + }, + ignore_failure: false, + }, + }, + }, + }; + + test('returns single metric chart type as expected for configs', () => { + expect(getChartType(singleMetricConfig)).toBe(CHART_TYPE.SINGLE_METRIC); + expect(getChartType(multiMetricConfig)).toBe(CHART_TYPE.SINGLE_METRIC); + expect(getChartType(varpModelPlotConfig)).toBe(CHART_TYPE.SINGLE_METRIC); + expect(getChartType(overScriptFieldModelPlotConfig)).toBe(CHART_TYPE.SINGLE_METRIC); + }); + + test('returns event distribution chart type as expected for configs', () => { + expect(getChartType(rareConfig)).toBe(CHART_TYPE.EVENT_DISTRIBUTION); + }); + + test('returns population distribution chart type as expected for configs', () => { + expect(getChartType(populationConfig)).toBe(CHART_TYPE.POPULATION_DISTRIBUTION); + }); }); - test('invalid tickIntervals trigger an error', () => { - expect(() => { - getTickValues(1518652800000, 0, 1518274800000, 1519635600000); - }).toThrow(); - expect(() => { - getTickValues(1518652800000, -604800000, 1518274800000, 1519635600000); - }).toThrow(); + describe('getExploreSeriesLink', () => { + test('get timeseriesexplorer link', () => { + const link = getExploreSeriesLink(seriesConfig); + const expectedLink = + `#/timeseriesexplorer?_g=(ml:(jobIds:!(population-03)),` + + `refreshInterval:(display:Off,pause:!f,value:0),time:(from:'2017-02-23T00:00:00.000Z',mode:absolute,` + + `to:'2017-02-23T23:59:59.999Z'))&_a=(mlTimeSeriesExplorer%3A(detectorIndex%3A0%2Centities%3A` + + `(nginx.access.remote_ip%3A'72.57.0.53')%2Czoom%3A(from%3A'2017-02-19T20%3A00%3A00.000Z'%2Cto%3A'2017-02-27T04%3A00%3A00.000Z'))` + + `%2Cquery%3A(query_string%3A(analyze_wildcard%3A!t%2Cquery%3A'*')))`; + + expect(link).toBe(expectedLink); + }); }); -}); -describe('isLabelLengthAboveThreshold', () => { - test('short label', () => { - const isLongLabel = isLabelLengthAboveThreshold({ - detectorLabel: 'count', - entityFields: seriesConfig.entityFields, + describe('numTicks', () => { + test('returns 10 for 1000', () => { + expect(numTicks(1000)).toBe(10); }); - expect(isLongLabel).toBeFalsy(); }); - test('long label', () => { - const isLongLabel = isLabelLengthAboveThreshold(seriesConfig); - expect(isLongLabel).toBeTruthy(); + describe('showMultiBucketAnomalyMarker', () => { + test('returns true for points with multiBucketImpact at or above medium impact', () => { + expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.HIGH })).toBe( + true + ); + expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.MEDIUM })).toBe( + true + ); + }); + + test('returns false for points with multiBucketImpact missing or below medium impact', () => { + expect(showMultiBucketAnomalyMarker({})).toBe(false); + expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.LOW })).toBe( + false + ); + expect(showMultiBucketAnomalyMarker({ multiBucketImpact: MULTI_BUCKET_IMPACT.NONE })).toBe( + false + ); + }); }); -}); -describe('getXTransform', () => { - const expectedXTransform = 0.007167499999999999; + describe('showMultiBucketAnomalyTooltip', () => { + test('returns true for points with multiBucketImpact at or above low impact', () => { + expect(showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.HIGH })).toBe( + true + ); + expect(showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.MEDIUM })).toBe( + true + ); + expect(showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.LOW })).toBe( + true + ); + }); - test('Chrome/Safari/Firefox String variant.', () => { - const transformStr = 'translate(0.007167499999999999,0)'; - const xTransform = getXTransform(transformStr); - expect(xTransform).toEqual(expectedXTransform); + test('returns false for points with multiBucketImpact missing or below medium impact', () => { + expect(showMultiBucketAnomalyTooltip({})).toBe(false); + expect(showMultiBucketAnomalyTooltip({ multiBucketImpact: MULTI_BUCKET_IMPACT.NONE })).toBe( + false + ); + }); }); - test('IE11 String variant.', () => { - const transformStr = 'translate(0.007167499999999999)'; - const xTransform = getXTransform(transformStr); - expect(xTransform).toEqual(expectedXTransform); + describe('getTickValues', () => { + test('farequote sample data', () => { + const tickValues = getTickValues(1486656000000, 14400000, 1486606500000, 1486719900000); + + expect(tickValues).toEqual([ + 1486612800000, + 1486627200000, + 1486641600000, + 1486656000000, + 1486670400000, + 1486684800000, + 1486699200000, + 1486713600000, + ]); + }); + + test('filebeat sample data', () => { + const tickValues = getTickValues(1486080000000, 14400000, 1485860400000, 1486314000000); + expect(tickValues).toEqual([ + 1485864000000, + 1485878400000, + 1485892800000, + 1485907200000, + 1485921600000, + 1485936000000, + 1485950400000, + 1485964800000, + 1485979200000, + 1485993600000, + 1486008000000, + 1486022400000, + 1486036800000, + 1486051200000, + 1486065600000, + 1486080000000, + 1486094400000, + 1486108800000, + 1486123200000, + 1486137600000, + 1486152000000, + 1486166400000, + 1486180800000, + 1486195200000, + 1486209600000, + 1486224000000, + 1486238400000, + 1486252800000, + 1486267200000, + 1486281600000, + 1486296000000, + 1486310400000, + ]); + }); + + test('gallery sample data', () => { + const tickValues = getTickValues(1518652800000, 604800000, 1518274800000, 1519635600000); + expect(tickValues).toEqual([1518652800000, 1519257600000]); + }); + + test('invalid tickIntervals trigger an error', () => { + expect(() => { + getTickValues(1518652800000, 0, 1518274800000, 1519635600000); + }).toThrow(); + expect(() => { + getTickValues(1518652800000, -604800000, 1518274800000, 1519635600000); + }).toThrow(); + }); }); - test('Invalid String.', () => { - const transformStr = 'translate()'; - const xTransform = getXTransform(transformStr); - expect(xTransform).toEqual(NaN); + describe('isLabelLengthAboveThreshold', () => { + test('short label', () => { + const isLongLabel = isLabelLengthAboveThreshold({ + detectorLabel: 'count', + entityFields: seriesConfig.entityFields, + }); + expect(isLongLabel).toBeFalsy(); + }); + + test('long label', () => { + const isLongLabel = isLabelLengthAboveThreshold(seriesConfig); + expect(isLongLabel).toBeTruthy(); + }); }); -}); -describe('removeLabelOverlap', () => { - const originalGetBBox = SVGElement.prototype.getBBox; - - // This resembles how ExplorerChart renders its x axis. - // We set up this boilerplate so we can then run removeLabelOverlap() - // on some "real" structure. - function axisSetup({ interval, plotEarliest, plotLatest, startTimeMs, xAxisTickFormat }) { - const wrapper = mount(<div className="content-wrapper" />); - const node = wrapper.getDOMNode(); - - const chartHeight = 170; - const margin = { top: 10, right: 0, bottom: 30, left: 60 }; - const svgWidth = 500; - const svgHeight = chartHeight + margin.top + margin.bottom; - const vizWidth = 500; - - const chartElement = d3.select(node); - - const lineChartXScale = d3.time - .scale() - .range([0, vizWidth]) - .domain([plotEarliest, plotLatest]); - - const xAxis = d3.svg - .axis() - .scale(lineChartXScale) - .orient('bottom') - .innerTickSize(-chartHeight) - .outerTickSize(0) - .tickPadding(10) - .tickFormat(d => moment(d).format(xAxisTickFormat)); - - const tickValues = getTickValues(startTimeMs, interval, plotEarliest, plotLatest); - xAxis.tickValues(tickValues); - - const svg = chartElement - .append('svg') - .attr('width', svgWidth) - .attr('height', svgHeight); - - const axes = svg.append('g'); - - const gAxis = axes - .append('g') - .attr('class', 'x axis') - .attr('transform', 'translate(0,' + chartHeight + ')') - .call(xAxis); - - return { - gAxis, - node, - vizWidth, - }; - } + describe('getXTransform', () => { + const expectedXTransform = 0.007167499999999999; - test('farequote sample data', () => { - const mockedGetBBox = { width: 27.21875 }; - SVGElement.prototype.getBBox = () => mockedGetBBox; + test('Chrome/Safari/Firefox String variant.', () => { + const transformStr = 'translate(0.007167499999999999,0)'; + const xTransform = getXTransform(transformStr); + expect(xTransform).toEqual(expectedXTransform); + }); - const startTimeMs = 1486656000000; - const interval = 14400000; + test('IE11 String variant.', () => { + const transformStr = 'translate(0.007167499999999999)'; + const xTransform = getXTransform(transformStr); + expect(xTransform).toEqual(expectedXTransform); + }); - const { gAxis, node, vizWidth } = axisSetup({ - interval, - plotEarliest: 1486606500000, - plotLatest: 1486719900000, - startTimeMs, - xAxisTickFormat: 'HH:mm', + test('Invalid String.', () => { + const transformStr = 'translate()'; + const xTransform = getXTransform(transformStr); + expect(xTransform).toEqual(NaN); }); + }); - expect(node.getElementsByTagName('text')).toHaveLength(8); + describe('removeLabelOverlap', () => { + const originalGetBBox = SVGElement.prototype.getBBox; + + // This resembles how ExplorerChart renders its x axis. + // We set up this boilerplate so we can then run removeLabelOverlap() + // on some "real" structure. + function axisSetup({ interval, plotEarliest, plotLatest, startTimeMs, xAxisTickFormat }) { + const { container } = render(<div className="content-wrapper" />); + const node = container.querySelector('.content-wrapper'); + + const chartHeight = 170; + const margin = { top: 10, right: 0, bottom: 30, left: 60 }; + const svgWidth = 500; + const svgHeight = chartHeight + margin.top + margin.bottom; + const vizWidth = 500; + + const chartElement = d3.select(node); + + const lineChartXScale = d3.time + .scale() + .range([0, vizWidth]) + .domain([plotEarliest, plotLatest]); + + const xAxis = d3.svg + .axis() + .scale(lineChartXScale) + .orient('bottom') + .innerTickSize(-chartHeight) + .outerTickSize(0) + .tickPadding(10) + .tickFormat(d => moment(d).format(xAxisTickFormat)); + + const tickValues = getTickValues(startTimeMs, interval, plotEarliest, plotLatest); + xAxis.tickValues(tickValues); + + const svg = chartElement + .append('svg') + .attr('width', svgWidth) + .attr('height', svgHeight); + + const axes = svg.append('g'); + + const gAxis = axes + .append('g') + .attr('class', 'x axis') + .attr('transform', 'translate(0,' + chartHeight + ')') + .call(xAxis); - removeLabelOverlap(gAxis, startTimeMs, interval, vizWidth); + return { + gAxis, + node, + vizWidth, + }; + } - // at the vizWidth of 500, the most left and right tick label - // will get removed because it overflows the chart area - expect(node.getElementsByTagName('text')).toHaveLength(6); + test('farequote sample data', () => { + const mockedGetBBox = { width: 27.21875 }; + SVGElement.prototype.getBBox = () => mockedGetBBox; - SVGElement.prototype.getBBox = originalGetBBox; - }); + const startTimeMs = 1486656000000; + const interval = 14400000; + + const { gAxis, node, vizWidth } = axisSetup({ + interval, + plotEarliest: 1486606500000, + plotLatest: 1486719900000, + startTimeMs, + xAxisTickFormat: 'HH:mm', + }); - test('filebeat sample data', () => { - const mockedGetBBox = { width: 85.640625 }; - SVGElement.prototype.getBBox = () => mockedGetBBox; + expect(node.getElementsByTagName('text')).toHaveLength(8); - const startTimeMs = 1486080000000; - const interval = 14400000; + removeLabelOverlap(gAxis, startTimeMs, interval, vizWidth); - const { gAxis, node, vizWidth } = axisSetup({ - interval, - plotEarliest: 1485860400000, - plotLatest: 1486314000000, - startTimeMs, - xAxisTickFormat: 'YYYY-MM-DD HH:mm', + // at the vizWidth of 500, the most left and right tick label + // will get removed because it overflows the chart area + expect(node.getElementsByTagName('text')).toHaveLength(6); + + SVGElement.prototype.getBBox = originalGetBBox; }); - expect(node.getElementsByTagName('text')).toHaveLength(32); + test('filebeat sample data', () => { + const mockedGetBBox = { width: 85.640625 }; + SVGElement.prototype.getBBox = () => mockedGetBBox; + + const startTimeMs = 1486080000000; + const interval = 14400000; - removeLabelOverlap(gAxis, startTimeMs, interval, vizWidth); + const { gAxis, node, vizWidth } = axisSetup({ + interval, + plotEarliest: 1485860400000, + plotLatest: 1486314000000, + startTimeMs, + xAxisTickFormat: 'YYYY-MM-DD HH:mm', + }); - // In this case labels get reduced significantly because of the wider - // labels (full dates + time) and the narrow interval. - expect(node.getElementsByTagName('text')).toHaveLength(3); + expect(node.getElementsByTagName('text')).toHaveLength(32); - SVGElement.prototype.getBBox = originalGetBBox; + removeLabelOverlap(gAxis, startTimeMs, interval, vizWidth); + + // In this case labels get reduced significantly because of the wider + // labels (full dates + time) and the narrow interval. + expect(node.getElementsByTagName('text')).toHaveLength(3); + + SVGElement.prototype.getBBox = originalGetBBox; + }); }); }); diff --git a/x-pack/plugins/ml/public/application/util/string_utils.d.ts b/x-pack/plugins/ml/public/application/util/string_utils.d.ts index b5063907e1fdf..531e44e3e78c1 100644 --- a/x-pack/plugins/ml/public/application/util/string_utils.d.ts +++ b/x-pack/plugins/ml/public/application/util/string_utils.d.ts @@ -14,4 +14,8 @@ export function replaceStringTokens( export function detectorToString(dtr: any): string; +export function sortByKey(list: any, reverse: boolean, comparator?: any): any; + export function toLocaleString(x: number): string; + +export function mlEscape(str: string): string; diff --git a/x-pack/plugins/ml/public/application/util/string_utils.js b/x-pack/plugins/ml/public/application/util/string_utils.js index 172d334099b3d..66835984df5e5 100644 --- a/x-pack/plugins/ml/public/application/util/string_utils.js +++ b/x-pack/plugins/ml/public/application/util/string_utils.js @@ -99,211 +99,6 @@ export function sortByKey(list, reverse, comparator) { ); } -// guess the time format for a given time string -export function guessTimeFormat(time) { - let format = ''; - let matched = false; - if (isNaN(time)) { - let match; - - // match date format - if (!matched) { - let reg = ''; - - reg += '('; // 1 ( date - - reg += '('; // 2 ( yyyy-MM-dd - reg += '(\\d{4})'; // 3 yyyy - reg += '([-/.\\s])'; // 4 - or . or \s - reg += '('; // 5 ( month - reg += '([01]\\d)'; // 6 MM - reg += '|'; // or - reg += '(\\w{3})'; // 7 MMM - reg += ')'; // ) end month - reg += '([-/.\\s])'; // 8 - or . or \s - reg += '([0-3]\\d)'; // 9 dd 0-3 and 0-9 - reg += ')'; // ) end yyyy-MM-dd - - reg += '|'; // or - - reg += '('; // 10 ( d[d]-MM[M]-yyyy or MM[M]-d[d]-yyyy - - reg += '('; // 11 ( day or month - reg += '(\\d{1,2})'; // 12 d or M or dd or MM - reg += '|'; // or - reg += '(\\w{3})'; // 13 MMM - reg += ')'; // ) end day or month - - reg += '([-/.\\s])'; // 14 - or . or \s - - reg += '('; // 15 ( day or month - reg += '(\\d{1,2})'; // 12 d or M or dd or MM - reg += '|'; // or - reg += '(\\w{3})'; // 17 MMM - reg += ')'; // ) end day or month - - reg += '([-/.\\s])'; // 18 - or . or \s - reg += '(\\d{4})'; // 19 yyyy - reg += ')'; // ) end d[d]-MM[M]-yyyy or MM[M]-d[d]-yyyy - - reg += ')'; // ) end date - - reg += '([T\\s])?'; // 20 T or space - - reg += '([0-2]\\d)'; // 21 HH 0-2 and 0-9 - reg += '([:.])'; // 22 :. - reg += '([0-5]\\d)'; // 23 mm 0-5 and 0-9 - reg += '('; // 24 ( optional secs - reg += '([:.])'; // 25 :. - reg += '([0-5]\\d)'; // 26 ss 0-5 and 0-9 - reg += ')?'; // ) end optional secs - reg += '('; // 27 ( optional millisecs - reg += '([:.])'; // 28 :. - reg += '(\\d{3})'; // 29 3 * 0-9 - reg += ')?'; // ) end optional millisecs - reg += '('; // 30 ( optional timezone matches - reg += '([+-]\\d{2}[:.]\\d{2}[:.]\\d{2})'; // 31 +- 0-9 0-9 :. 0-9 0-9 :. 0-9 0-9 e.g. +00:00:00 - reg += '|'; // or - reg += '([+-]\\d{2}[:.]\\d{2})'; // 32 +- 0-9 0-9 :. 0-9 0-9 e.g. +00:00 - reg += '|'; // or - reg += '([+-]\\d{6})'; // 33 +- 6 * 0-9 e.g. +000000 - reg += '|'; // or - reg += '([+-]\\d{4})'; // 34 +- 4 * 0-9 e.g. +0000 - reg += '|'; // or - reg += '(Z)'; // 35 Z - reg += '|'; // or - reg += '([+-]\\d{2})'; // 36 +- 0-9 0-9 e.g. +00 - reg += '|'; // or - reg += '('; // 37 ( string timezone - reg += '(\\s)'; // 38 optional space - reg += '(\\w{1,4})'; // 39 1-4 letters e.g UTC - reg += ')'; // ) end string timezone - reg += ')?'; // ) end optional timezone - - console.log('guessTimeFormat: time format regex: ' + reg); - - match = time.match(new RegExp(reg)); - // console.log(match); - if (match) { - // add the standard data and time - if (match[2] !== undefined) { - // match yyyy-[MM MMM]-dd - format += 'yyyy'; - format += match[4]; - if (match[6] !== undefined) { - format += 'MM'; - } else if (match[7] !== undefined) { - format += 'MMM'; - } - format += match[8]; - format += 'dd'; - } else if (match[10] !== undefined) { - // match dd-MM[M]-yyyy or MM[M]-dd-yyyy - - if (match[13] !== undefined) { - // found a word as the first part - // e.g., Jan 01 2000 - format += 'MMM'; - format += match[14]; - format += 'dd'; - } else if (match[17] !== undefined) { - // found a word as the second part - // e.g., 01 Jan 2000 - format += 'dd'; - format += match[14]; - format += 'MMM'; - } else { - // check to see if the first number is greater than 12 - // e.g., 24/03/1981 - // this is a guess, but is only thing we can do - // with one line from the data set - if (match[12] !== undefined && +match[12] > 12) { - format += 'dd'; - format += match[14]; - format += 'MM'; - } else { - // default to US format. - format += 'MM'; - format += match[14]; - format += 'dd'; - } - } - - format += match[18]; - format += 'yyyy'; - } - - // optional T or space splitter - // wrap T in single quotes - format += match[20] === 'T' ? "'" + match[20] + "'" : match[20]; - format += 'HH'; - format += match[22]; - format += 'mm'; - - // add optional secs - if (match[24] !== undefined) { - format += match[25]; - format += 'ss'; - } - - // add optional millisecs - if (match[27] !== undefined) { - // .000 - format += match[28]; - format += 'SSS'; - } - - // add optional time zone - if (match[31] !== undefined) { - // +00:00:00 - format += 'XXXXX'; - } else if (match[32] !== undefined) { - // +00:00 - format += 'XXX'; - } else if (match[33] !== undefined) { - // +000000 - format += 'XXXX'; - } else if (match[34] !== undefined) { - // +0000 - format += 'Z'; - } else if (match[35] !== undefined || match[36] !== undefined) { - // Z or +00 - format += 'X'; - } else if (match[37] !== undefined) { - // UTC - if (match[38] !== undefined) { - // add optional space char - format += match[38]; - } - // add time zone name, up to 4 chars - for (let i = 0; i < match[39].length; i++) { - format += 'z'; - } - } - matched = true; - } - } - } else { - // time field is a number, so probably epoch or epoch_ms - if (time > 10000000000) { - // probably milliseconds - format = 'epoch_ms'; - } else { - // probably seconds - format = 'epoch'; - } - matched = true; - } - - if (matched) { - console.log('guessTimeFormat: guessed time format: ', format); - } else { - console.log('guessTimeFormat: time format could not be guessed from: ' + time); - } - - return format; -} - // add commas to large numbers // Number.toLocaleString is not supported on safari export function toLocaleString(x) { diff --git a/x-pack/plugins/ml/public/application/util/string_utils.test.ts b/x-pack/plugins/ml/public/application/util/string_utils.test.ts new file mode 100644 index 0000000000000..d940fce2ee1d5 --- /dev/null +++ b/x-pack/plugins/ml/public/application/util/string_utils.test.ts @@ -0,0 +1,193 @@ +/* + * 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 { + replaceStringTokens, + detectorToString, + sortByKey, + toLocaleString, + mlEscape, + escapeForElasticsearchQuery, +} from './string_utils'; + +describe('ML - string utils', () => { + describe('replaceStringTokens', () => { + const testRecord = { + job_id: 'test_job', + result_type: 'record', + probability: 0.0191711, + record_score: 4.3, + bucket_span: 300, + detector_index: 0, + timestamp: 1454890500000, + function: 'mean', + function_description: 'mean', + field_name: 'responsetime', + user: "Des O'Connor", + testfield1: 'test$tring=[+-?]', + testfield2: '{<()>}', + testfield3: 'host=\\\\test@uk.dev', + }; + + test('returns correct values without URI encoding', () => { + const result = replaceStringTokens('user=$user$,time=$timestamp$', testRecord, false); + expect(result).toBe("user=Des O'Connor,time=1454890500000"); + }); + + test('returns correct values for missing token without URI encoding', () => { + const result = replaceStringTokens('user=$username$,time=$timestamp$', testRecord, false); + expect(result).toBe('user=$username$,time=1454890500000'); + }); + + test('returns correct values with URI encoding', () => { + const testString1 = 'https://www.google.co.uk/webhp#q=$testfield1$'; + const testString2 = 'https://www.google.co.uk/webhp#q=$testfield2$'; + const testString3 = 'https://www.google.co.uk/webhp#q=$testfield3$'; + const testString4 = 'https://www.google.co.uk/webhp#q=$user$'; + + const result1 = replaceStringTokens(testString1, testRecord, true); + const result2 = replaceStringTokens(testString2, testRecord, true); + const result3 = replaceStringTokens(testString3, testRecord, true); + const result4 = replaceStringTokens(testString4, testRecord, true); + + expect(result1).toBe('https://www.google.co.uk/webhp#q=test%24tring%3D%5B%2B-%3F%5D'); + expect(result2).toBe('https://www.google.co.uk/webhp#q=%7B%3C()%3E%7D'); + expect(result3).toBe('https://www.google.co.uk/webhp#q=host%3D%5C%5Ctest%40uk.dev'); + expect(result4).toBe("https://www.google.co.uk/webhp#q=Des%20O'Connor"); + }); + + test('returns correct values for missing token with URI encoding', () => { + const testString = 'https://www.google.co.uk/webhp#q=$username$&time=$timestamp$'; + const result = replaceStringTokens(testString, testRecord, true); + expect(result).toBe('https://www.google.co.uk/webhp#q=$username$&time=1454890500000'); + }); + }); + + describe('detectorToString', () => { + test('returns the correct descriptions for detectors', () => { + const detector1 = { + function: 'count', + }; + + const detector2 = { + function: 'count', + by_field_name: 'airline', + use_null: false, + }; + + const detector3 = { + function: 'mean', + field_name: 'CPUUtilization', + partition_field_name: 'region', + by_field_name: 'host', + over_field_name: 'user', + exclude_frequent: 'all', + }; + + expect(detectorToString(detector1)).toBe('count'); + expect(detectorToString(detector2)).toBe('count by airline use_null=false'); + expect(detectorToString(detector3)).toBe( + 'mean(CPUUtilization) by host over user partition_field_name=region exclude_frequent=all' + ); + }); + }); + + describe('sortByKey', () => { + const obj = { + zebra: 'stripes', + giraffe: 'neck', + elephant: 'trunk', + }; + + const valueComparator = function(value: string) { + return value; + }; + + test('returns correct ordering with default comparator', () => { + const result = sortByKey(obj, false); + const keys = Object.keys(result); + expect(keys[0]).toBe('elephant'); + expect(keys[1]).toBe('giraffe'); + expect(keys[2]).toBe('zebra'); + }); + + test('returns correct ordering with default comparator and order reversed', () => { + const result = sortByKey(obj, true); + const keys = Object.keys(result); + expect(keys[0]).toBe('zebra'); + expect(keys[1]).toBe('giraffe'); + expect(keys[2]).toBe('elephant'); + }); + + test('returns correct ordering with comparator', () => { + const result = sortByKey(obj, false, valueComparator); + const keys = Object.keys(result); + expect(keys[0]).toBe('giraffe'); + expect(keys[1]).toBe('zebra'); + expect(keys[2]).toBe('elephant'); + }); + + test('returns correct ordering with comparator and order reversed', () => { + const result = sortByKey(obj, true, valueComparator); + const keys = Object.keys(result); + expect(keys[0]).toBe('elephant'); + expect(keys[1]).toBe('zebra'); + expect(keys[2]).toBe('giraffe'); + }); + }); + + describe('toLocaleString', () => { + test('returns correct comma placement for large numbers', () => { + expect(toLocaleString(1)).toBe('1'); + expect(toLocaleString(10)).toBe('10'); + expect(toLocaleString(100)).toBe('100'); + expect(toLocaleString(1000)).toBe('1,000'); + expect(toLocaleString(10000)).toBe('10,000'); + expect(toLocaleString(100000)).toBe('100,000'); + expect(toLocaleString(1000000)).toBe('1,000,000'); + expect(toLocaleString(10000000)).toBe('10,000,000'); + expect(toLocaleString(100000000)).toBe('100,000,000'); + expect(toLocaleString(1000000000)).toBe('1,000,000,000'); + }); + }); + + describe('mlEscape', () => { + test('returns correct escaping of characters', () => { + expect(mlEscape('foo&bar')).toBe('foo&bar'); + expect(mlEscape('foo<bar')).toBe('foo<bar'); + expect(mlEscape('foo>bar')).toBe('foo>bar'); + expect(mlEscape('foo"bar')).toBe('foo"bar'); + expect(mlEscape("foo'bar")).toBe('foo'bar'); + expect(mlEscape('foo/bar')).toBe('foo/bar'); + }); + }); + + describe('escapeForElasticsearchQuery', () => { + test('returns correct escaping of reserved elasticsearch characters', () => { + expect(escapeForElasticsearchQuery('foo+bar')).toBe('foo\\+bar'); + expect(escapeForElasticsearchQuery('foo-bar')).toBe('foo\\-bar'); + expect(escapeForElasticsearchQuery('foo=bar')).toBe('foo\\=bar'); + expect(escapeForElasticsearchQuery('foo&&bar')).toBe('foo\\&\\&bar'); + expect(escapeForElasticsearchQuery('foo||bar')).toBe('foo\\|\\|bar'); + expect(escapeForElasticsearchQuery('foo>bar')).toBe('foo\\>bar'); + expect(escapeForElasticsearchQuery('foo<bar')).toBe('foo\\<bar'); + expect(escapeForElasticsearchQuery('foo!bar')).toBe('foo\\!bar'); + expect(escapeForElasticsearchQuery('foo(bar')).toBe('foo\\(bar'); + expect(escapeForElasticsearchQuery('foo)bar')).toBe('foo\\)bar'); + expect(escapeForElasticsearchQuery('foo{bar')).toBe('foo\\{bar'); + expect(escapeForElasticsearchQuery('foo[bar')).toBe('foo\\[bar'); + expect(escapeForElasticsearchQuery('foo]bar')).toBe('foo\\]bar'); + expect(escapeForElasticsearchQuery('foo^bar')).toBe('foo\\^bar'); + expect(escapeForElasticsearchQuery('foo"bar')).toBe('foo\\"bar'); + expect(escapeForElasticsearchQuery('foo~bar')).toBe('foo\\~bar'); + expect(escapeForElasticsearchQuery('foo*bar')).toBe('foo\\*bar'); + expect(escapeForElasticsearchQuery('foo?bar')).toBe('foo\\?bar'); + expect(escapeForElasticsearchQuery('foo:bar')).toBe('foo\\:bar'); + expect(escapeForElasticsearchQuery('foo\\bar')).toBe('foo\\\\bar'); + expect(escapeForElasticsearchQuery('foo/bar')).toBe('foo\\/bar'); + }); + }); +}); From 7cb3ee44eaeae29edcfe39b17140040a16c8ad2e Mon Sep 17 00:00:00 2001 From: Phillip Burch <phillip.burch@live.com> Date: Tue, 14 Apr 2020 12:13:44 -0500 Subject: [PATCH 103/121] Add help text to form fields (#63165) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../public/components/alerting/metrics/expression.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx b/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx index 2e43ede2480ce..2430fe78e2053 100644 --- a/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx +++ b/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx @@ -264,10 +264,10 @@ export const Expressions: React.FC<Props> = props => { <EuiFormRow label={i18n.translate('xpack.infra.metrics.alertFlyout.filterLabel', { - defaultMessage: 'Filter', + defaultMessage: 'Filter (optional)', })} helpText={i18n.translate('xpack.infra.metrics.alertFlyout.filterHelpText', { - defaultMessage: 'Filter help text', + defaultMessage: 'Use a KQL expression to limit the scope of your alert trigger.', })} fullWidth compressed @@ -284,10 +284,11 @@ export const Expressions: React.FC<Props> = props => { {alertsContext.metadata && ( <EuiFormRow label={i18n.translate('xpack.infra.metrics.alertFlyout.createAlertPerText', { - defaultMessage: 'Create alert per', + defaultMessage: 'Create alert per (optional)', })} helpText={i18n.translate('xpack.infra.metrics.alertFlyout.createAlertPerHelpText', { - defaultMessage: 'Create alert help text', + defaultMessage: + 'Create an alert for every unique value. For example: "host.id" or "cloud.region".', })} fullWidth compressed From a4464c22ba90cdc7243e1116fc64adc1d5ade355 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Tue, 14 Apr 2020 13:36:54 -0400 Subject: [PATCH 104/121] [Ingest][Endpoint] Add Ingest rest api response types for use in Endpoint (#63373) * Added REST Response types to datasouces * Adjust Types in Endpoint to reference those from Ingest * Remove un-used endpoint type --- .../store/policy_details/middleware.ts | 4 +-- .../endpoint/store/policy_list/middleware.ts | 4 +-- .../store/policy_list/services/ingest.ts | 14 +++++----- .../store/policy_list/test_mock_utils.ts | 6 ++--- .../public/applications/endpoint/types.ts | 27 +++++++------------ .../common/types/rest_spec/datasource.ts | 17 ++++++++---- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts index a00ce255cbac4..2581ab37f5677 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_details/middleware.ts @@ -8,7 +8,7 @@ import { MiddlewareFactory, PolicyData, PolicyDetailsState, - UpdateDatasourceResponse, + UpdatePolicyResponse, } from '../../types'; import { policyIdFromParams, isOnPolicyDetailsPage, policyDetails } from './selectors'; import { generatePolicy } from '../../models/policy'; @@ -77,7 +77,7 @@ export const policyDetailsMiddlewareFactory: MiddlewareFactory<PolicyDetailsStat } else if (action.type === 'userClickedPolicyDetailsSaveButton') { const { id, revision, ...updatedPolicyItem } = policyDetails(state) as PolicyData; - let apiResponse: UpdateDatasourceResponse; + let apiResponse: UpdatePolicyResponse; try { apiResponse = await sendPutDatasource(http, id, updatedPolicyItem); } catch (error) { diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts index c073d26a676f0..cc771a4619e78 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/middleware.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { MiddlewareFactory, PolicyListState, GetDatasourcesResponse } from '../../types'; +import { GetPolicyListResponse, MiddlewareFactory, PolicyListState } from '../../types'; import { sendGetEndpointSpecificDatasources } from './services/ingest'; import { isOnPolicyListPage, urlSearchParams } from './selectors'; @@ -18,7 +18,7 @@ export const policyListMiddlewareFactory: MiddlewareFactory<PolicyListState> = c if (action.type === 'userChangedUrl' && isOnPolicyListPage(state)) { const { page_index: pageIndex, page_size: pageSize } = urlSearchParams(state); - let response: GetDatasourcesResponse; + let response: GetPolicyListResponse; try { response = await sendGetEndpointSpecificDatasources(http, { diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts index bfbb5f94e8950..5fccb01d1ad35 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/services/ingest.ts @@ -11,9 +11,9 @@ import { } from '../../../../../../../ingest_manager/common'; import { NewPolicyData, - GetDatasourcesResponse, - GetDatasourceResponse, - UpdateDatasourceResponse, + GetPolicyListResponse, + GetPolicyResponse, + UpdatePolicyResponse, } from '../../../types'; const INGEST_API_ROOT = `/api/ingest_manager`; @@ -30,8 +30,8 @@ const INGEST_API_FLEET_AGENT_STATUS = `${INGEST_API_FLEET}/agent-status`; export const sendGetEndpointSpecificDatasources = ( http: HttpStart, options: HttpFetchOptions & Partial<GetDatasourcesRequest> = {} -): Promise<GetDatasourcesResponse> => { - return http.get<GetDatasourcesResponse>(INGEST_API_DATASOURCES, { +): Promise<GetPolicyListResponse> => { + return http.get<GetPolicyListResponse>(INGEST_API_DATASOURCES, { ...options, query: { ...options.query, @@ -53,7 +53,7 @@ export const sendGetDatasource = ( datasourceId: string, options?: HttpFetchOptions ) => { - return http.get<GetDatasourceResponse>(`${INGEST_API_DATASOURCES}/${datasourceId}`, options); + return http.get<GetPolicyResponse>(`${INGEST_API_DATASOURCES}/${datasourceId}`, options); }; /** @@ -69,7 +69,7 @@ export const sendPutDatasource = ( datasourceId: string, datasource: NewPolicyData, options: Exclude<HttpFetchOptions, 'body'> = {} -): Promise<UpdateDatasourceResponse> => { +): Promise<UpdatePolicyResponse> => { return http.put(`${INGEST_API_DATASOURCES}/${datasourceId}`, { ...options, body: JSON.stringify(datasource), diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts index 0d41ae0d76da4..20d5a637182d2 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/policy_list/test_mock_utils.ts @@ -8,7 +8,7 @@ import { HttpStart } from 'kibana/public'; import { Dispatch } from 'redux'; import { INGEST_API_DATASOURCES } from './services/ingest'; import { EndpointDocGenerator } from '../../../../../common/generate_data'; -import { AppAction, GetDatasourcesResponse, GlobalState, MiddlewareFactory } from '../../types'; +import { AppAction, GetPolicyListResponse, GlobalState, MiddlewareFactory } from '../../types'; const generator = new EndpointDocGenerator('policy-list'); @@ -19,13 +19,13 @@ const generator = new EndpointDocGenerator('policy-list'); */ export const setPolicyListApiMockImplementation = ( mockedHttpService: jest.Mocked<HttpStart>, - responseItems: GetDatasourcesResponse['items'] = [generator.generatePolicyDatasource()] + responseItems: GetPolicyListResponse['items'] = [generator.generatePolicyDatasource()] ): void => { mockedHttpService.get.mockImplementation((...args) => { const [path] = args; if (typeof path === 'string') { if (path === INGEST_API_DATASOURCES) { - return Promise.resolve<GetDatasourcesResponse>({ + return Promise.resolve<GetPolicyListResponse>({ items: responseItems, total: 10, page: 1, diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts index 54afbf220944e..015468f84e740 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/types.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/types.ts @@ -17,11 +17,14 @@ import { import { EndpointPluginStartDependencies } from '../../plugin'; import { AppAction } from './store/action'; import { CoreStart } from '../../../../../../src/core/public'; -import { Datasource, NewDatasource } from '../../../../ingest_manager/common/types/models'; import { + Datasource, + NewDatasource, GetAgentStatusResponse, - CreateDatasourceResponse, -} from '../../../../ingest_manager/common/types/rest_spec'; + GetDatasourcesResponse, + GetOneDatasourceResponse, + UpdateDatasourceResponse, +} from '../../../../ingest_manager/common'; export { AppAction }; export type MiddlewareFactory<S = GlobalState> = ( @@ -335,24 +338,14 @@ export interface AlertingIndexUIQueryParams { filters?: string; } -export interface GetDatasourcesResponse { +export interface GetPolicyListResponse extends GetDatasourcesResponse { items: PolicyData[]; - total: number; - page: number; - perPage: number; - success: boolean; } -export interface GetDatasourceResponse { +export interface GetPolicyResponse extends GetOneDatasourceResponse { item: PolicyData; - success: boolean; } -export type UpdateDatasourceResponse = CreateDatasourceResponse & { +export interface UpdatePolicyResponse extends UpdateDatasourceResponse { item: PolicyData; -}; - -/** - * The PageId type is used for the payload when firing userNavigatedToPage actions - */ -export type PageId = 'alertsPage' | 'managementPage' | 'policyListPage'; +} diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts index 66f734b904cfc..61f1f15d49259 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/datasource.ts @@ -13,17 +13,22 @@ export interface GetDatasourcesRequest { }; } +export interface GetDatasourcesResponse { + items: Datasource[]; + total: number; + page: number; + perPage: number; + success: boolean; +} + export interface GetOneDatasourceRequest { params: { datasourceId: string; }; } -export interface GetDatasourcesResponse { - items: Datasource[]; - total: number; - page: number; - perPage: number; +export interface GetOneDatasourceResponse { + item: Datasource; success: boolean; } @@ -40,6 +45,8 @@ export type UpdateDatasourceRequest = GetOneDatasourceRequest & { body: NewDatasource; }; +export type UpdateDatasourceResponse = CreateDatasourceResponse; + export interface DeleteDatasourcesRequest { body: { datasourceIds: string[]; From 959a0e5d3de1a6d7b9790aa59fba31e19f115a19 Mon Sep 17 00:00:00 2001 From: James Gowdy <jgowdy@elastic.co> Date: Tue, 14 Apr 2020 18:57:26 +0100 Subject: [PATCH 105/121] [ML] Listing global calendars on the job management page (#63124) * [ML] Listing global calendars on the job management page * tiny refactor Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../plugins/ml/server/models/job_service/jobs.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ml/server/models/job_service/jobs.ts b/x-pack/plugins/ml/server/models/job_service/jobs.ts index edcabcac93c2a..6024ecf4925e6 100644 --- a/x-pack/plugins/ml/server/models/job_service/jobs.ts +++ b/x-pack/plugins/ml/server/models/job_service/jobs.ts @@ -16,6 +16,7 @@ import { DatafeedWithStats, CombinedJobWithStats, } from '../../../common/types/anomaly_detection_jobs'; +import { GLOBAL_CALENDAR } from '../../../common/constants/calendars'; import { datafeedsProvider, MlDatafeedsResponse, MlDatafeedsStatsResponse } from './datafeeds'; import { jobAuditMessagesProvider } from '../job_audit_messages'; import { resultsServiceProvider } from '../results_service'; @@ -227,6 +228,8 @@ export function jobsProvider(callAsCurrentUser: APICaller) { const groups: { [jobId: string]: string[] } = {}; const datafeeds: { [id: string]: DatafeedWithStats } = {}; const calendarsByJobId: { [jobId: string]: string[] } = {}; + const globalCalendars: string[] = []; + const requests: [ Promise<MlJobsResponse>, Promise<MlJobsStatsResponse>, @@ -298,7 +301,9 @@ export function jobsProvider(callAsCurrentUser: APICaller) { if (calendarResults) { calendarResults.forEach(cal => { cal.job_ids.forEach(id => { - if (groups[id]) { + if (id === GLOBAL_CALENDAR) { + globalCalendars.push(cal.calendar_id); + } else if (groups[id]) { groups[id].forEach(jId => { if (calendarsByJobId[jId] !== undefined) { calendarsByJobId[jId].push(cal.calendar_id); @@ -325,8 +330,12 @@ export function jobsProvider(callAsCurrentUser: APICaller) { jobResults.jobs.forEach(job => { const tempJob = job as CombinedJobWithStats; - if (calendarsByJobId[tempJob.job_id].length) { - tempJob.calendars = calendarsByJobId[tempJob.job_id]; + const calendars: string[] = [ + ...(calendarsByJobId[tempJob.job_id] || []), + ...(globalCalendars || []), + ]; + if (calendars.length) { + tempJob.calendars = calendars; } if (jobStatsResults && jobStatsResults.jobs) { From 2b4c3003aba51153ccf64f2c6e46239390d3dbdc Mon Sep 17 00:00:00 2001 From: James Gowdy <jgowdy@elastic.co> Date: Tue, 14 Apr 2020 18:58:22 +0100 Subject: [PATCH 106/121] [ML] Improving parsing of large uploaded files (#62970) * [ML] Improving parsing of large uploaded files * small clean up * increasing max to 1GB * adding comments Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../common/constants/file_datavisualizer.ts | 4 +- .../ml/common/types/file_datavisualizer.ts | 4 +- .../file_datavisualizer_view.js | 28 +++++------ .../components/import_view/import_view.js | 4 +- .../import_view/importer/importer.ts | 48 ++++++++++++++++--- .../import_view/importer/message_importer.ts | 34 ++++++------- .../import_view/importer/ndjson_importer.ts | 35 ++++++++++---- .../file_based/components/utils/index.ts | 1 - .../file_based/components/utils/utils.ts | 22 ++++----- 9 files changed, 113 insertions(+), 67 deletions(-) diff --git a/x-pack/plugins/ml/common/constants/file_datavisualizer.ts b/x-pack/plugins/ml/common/constants/file_datavisualizer.ts index 81d51bfa25816..675247af2db99 100644 --- a/x-pack/plugins/ml/common/constants/file_datavisualizer.ts +++ b/x-pack/plugins/ml/common/constants/file_datavisualizer.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export const MAX_BYTES = 104857600; -export const ABSOLUTE_MAX_BYTES = MAX_BYTES * 5; +export const MAX_BYTES = 104857600; // 100MB +export const ABSOLUTE_MAX_BYTES = 1073741274; // 1GB export const FILE_SIZE_DISPLAY_FORMAT = '0,0.[0] b'; // Value to use in the Elasticsearch index mapping meta data to identify the diff --git a/x-pack/plugins/ml/common/types/file_datavisualizer.ts b/x-pack/plugins/ml/common/types/file_datavisualizer.ts index f771547b97811..c997a4e24f868 100644 --- a/x-pack/plugins/ml/common/types/file_datavisualizer.ts +++ b/x-pack/plugins/ml/common/types/file_datavisualizer.ts @@ -67,13 +67,15 @@ export interface ImportResponse { export interface ImportFailure { item: number; reason: string; - doc: Doc; + doc: ImportDoc; } export interface Doc { message: string; } +export type ImportDoc = Doc | string; + export interface Settings { pipeline?: string; index: string; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js index d1b615a878b2b..c73ab4b9e11c7 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/file_datavisualizer_view/file_datavisualizer_view.js @@ -24,14 +24,11 @@ import { readFile, createUrlOverrides, processResults, - reduceData, hasImportPermission, } from '../utils'; import { MODE } from './constants'; -const UPLOAD_SIZE_MB = 5; - export class FileDataVisualizerView extends Component { constructor(props) { super(props); @@ -40,6 +37,7 @@ export class FileDataVisualizerView extends Component { files: {}, fileName: '', fileContents: '', + data: [], fileSize: 0, fileTooLarge: false, fileCouldNotBeRead: false, @@ -79,6 +77,7 @@ export class FileDataVisualizerView extends Component { loaded: false, fileName: '', fileContents: '', + data: [], fileSize: 0, fileTooLarge: false, fileCouldNotBeRead: false, @@ -97,15 +96,15 @@ export class FileDataVisualizerView extends Component { async loadFile(file) { if (file.size <= this.maxFileUploadBytes) { try { - const fileContents = await readFile(file); - const data = fileContents.data; + const { data, fileContents } = await readFile(file); this.setState({ - fileContents: data, + data, + fileContents, fileName: file.name, fileSize: file.size, }); - await this.loadSettings(data); + await this.analyzeFile(fileContents); } catch (error) { this.setState({ loaded: false, @@ -124,14 +123,9 @@ export class FileDataVisualizerView extends Component { } } - async loadSettings(data, overrides, isRetry = false) { + async analyzeFile(fileContents, overrides, isRetry = false) { try { - // reduce the amount of data being sent to the endpoint - // 5MB should be enough to contain 1000 lines - const lessData = reduceData(data, UPLOAD_SIZE_MB); - console.log('overrides', overrides); - const { analyzeFile } = ml.fileDatavisualizer; - const resp = await analyzeFile(lessData, overrides); + const resp = await ml.fileDatavisualizer.analyzeFile(fileContents, overrides); const serverSettings = processResults(resp); const serverOverrides = resp.overrides; @@ -198,7 +192,7 @@ export class FileDataVisualizerView extends Component { loading: true, loaded: false, }); - this.loadSettings(data, this.previousOverrides, true); + this.analyzeFile(fileContents, this.previousOverrides, true); } } } @@ -240,7 +234,7 @@ export class FileDataVisualizerView extends Component { }, () => { const formattedOverrides = createUrlOverrides(overrides, this.originalSettings); - this.loadSettings(this.state.fileContents, formattedOverrides); + this.analyzeFile(this.state.fileContents, formattedOverrides); } ); }; @@ -261,6 +255,7 @@ export class FileDataVisualizerView extends Component { results, explanation, fileContents, + data, fileName, fileSize, fileTooLarge, @@ -339,6 +334,7 @@ export class FileDataVisualizerView extends Component { results={results} fileName={fileName} fileContents={fileContents} + data={data} indexPatterns={this.props.indexPatterns} kibanaConfig={this.props.kibanaConfig} showBottomBar={this.showBottomBar} diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js index 4c9579bfd4b46..2bf7bbeb641d0 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js @@ -94,7 +94,7 @@ export class ImportView extends Component { // TODO - sort this function out. it's a mess async import() { - const { fileContents, results, indexPatterns, kibanaConfig, showBottomBar } = this.props; + const { data, results, indexPatterns, kibanaConfig, showBottomBar } = this.props; const { format } = results; let { timeFieldName } = this.state; @@ -217,7 +217,7 @@ export class ImportView extends Component { if (success) { const importer = importerFactory(format, results, indexCreationSettings); if (importer !== undefined) { - const readResp = importer.read(fileContents, this.setReadProgress); + const readResp = importer.read(data, this.setReadProgress); success = readResp.success; this.setState({ readStatus: success ? IMPORT_STATUS.COMPLETE : IMPORT_STATUS.FAILED, diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.ts index c97f1c147c454..718587ad15ad5 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/importer.ts @@ -9,7 +9,7 @@ import moment from 'moment'; import { i18n } from '@kbn/i18n'; import { ml } from '../../../../../services/ml_api_service'; import { - Doc, + ImportDoc, ImportFailure, ImportResponse, Mappings, @@ -20,6 +20,7 @@ import { const CHUNK_SIZE = 5000; const MAX_CHUNK_CHAR_COUNT = 1000000; const IMPORT_RETRIES = 5; +const STRING_CHUNKS_MB = 100; export interface ImportConfig { settings: Settings; @@ -34,12 +35,19 @@ export interface ImportResults { error?: any; } -export class Importer { +export interface CreateDocsResponse { + success: boolean; + remainder: number; + docs: ImportDoc[]; + error?: any; +} + +export abstract class Importer { private _settings: Settings; private _mappings: Mappings; private _pipeline: IngestPipeline; - protected _docArray: Doc[] = []; + protected _docArray: ImportDoc[] = []; constructor({ settings, mappings, pipeline }: ImportConfig) { this._settings = settings; @@ -47,7 +55,33 @@ export class Importer { this._pipeline = pipeline; } - async initializeImport(index: string) { + public read(data: ArrayBuffer) { + const decoder = new TextDecoder(); + const size = STRING_CHUNKS_MB * Math.pow(2, 20); + + // chop the data up into 100MB chunks for processing. + // if the chop produces a partial line at the end, a character "remainder" count + // is returned which is used to roll the next chunk back that many chars so + // it is included in the next chunk. + const parts = Math.ceil(data.byteLength / size); + let remainder = 0; + for (let i = 0; i < parts; i++) { + const byteArray = decoder.decode(data.slice(i * size - remainder, (i + 1) * size)); + const { success, docs, remainder: tempRemainder } = this._createDocs(byteArray); + if (success) { + this._docArray = this._docArray.concat(docs); + remainder = tempRemainder; + } else { + return { success: false }; + } + } + + return { success: true }; + } + + protected abstract _createDocs(t: string): CreateDocsResponse; + + public async initializeImport(index: string) { const settings = this._settings; const mappings = this._mappings; const pipeline = this._pipeline; @@ -75,7 +109,7 @@ export class Importer { return createIndexResp; } - async import( + public async import( id: string, index: string, pipelineId: string, @@ -201,8 +235,8 @@ function updatePipelineTimezone(ingestPipeline: IngestPipeline) { } } -function createDocumentChunks(docArray: Doc[]) { - const chunks: Doc[][] = []; +function createDocumentChunks(docArray: ImportDoc[]) { + const chunks: ImportDoc[][] = []; // chop docArray into 5000 doc chunks const tempChunks = chunk(docArray, CHUNK_SIZE); diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.ts index 7ccc5a8d673f4..65be24d9e7be4 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/message_importer.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Importer, ImportConfig } from './importer'; +import { Importer, ImportConfig, CreateDocsResponse } from './importer'; import { Doc, FindFileStructureResponse, @@ -33,54 +33,54 @@ export class MessageImporter extends Importer { // multiline_start_pattern regex // if it does, it is a legitimate end of line and can be pushed into the list, // if not, it must be a newline char inside a field value, so keep looking. - read(text: string) { + protected _createDocs(text: string): CreateDocsResponse { + let remainder = 0; try { - const data: Doc[] = []; + const docs: Doc[] = []; let message = ''; let line = ''; for (let i = 0; i < text.length; i++) { const char = text[i]; if (char === '\n') { - message = this.processLine(data, message, line); + message = this._processLine(docs, message, line); line = ''; } else { line += char; } } - // the last line may have been missing a newline ending - if (line !== '') { - message = this.processLine(data, message, line); - } + remainder = line.length; - // add the last message to the list if not already done + // // add the last message to the list if not already done if (message !== '') { - this.addMessage(data, message); + this._addMessage(docs, message); } // remove first line if it is blank - if (data[0] && data[0].message === '') { - data.shift(); + if (docs[0] && docs[0].message === '') { + docs.shift(); } - this._docArray = data; - return { success: true, + docs, + remainder, }; } catch (error) { return { success: false, + docs: [], + remainder, error, }; } } - processLine(data: Doc[], message: string, line: string) { + private _processLine(data: Doc[], message: string, line: string) { if (this._excludeLinesRegex === null || line.match(this._excludeLinesRegex) === null) { if (this._multilineStartRegex === null || line.match(this._multilineStartRegex) !== null) { - this.addMessage(data, message); + this._addMessage(data, message); message = ''; } else if (data.length === 0) { // discard everything before the first line that is considered the first line of a message @@ -95,7 +95,7 @@ export class MessageImporter extends Importer { return message; } - addMessage(data: Doc[], message: string) { + private _addMessage(data: Doc[], message: string) { // if the message ended \r\n (Windows line endings) // then omit the \r as well as the \n for consistency message = message.replace(/\r$/, ''); diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/ndjson_importer.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/ndjson_importer.ts index 7f5f37abc5246..17c9de8ef4558 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/ndjson_importer.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/import_view/importer/ndjson_importer.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Importer, ImportConfig } from './importer'; +import { Importer, ImportConfig, CreateDocsResponse } from './importer'; import { FindFileStructureResponse } from '../../../../../../../common/types/file_datavisualizer'; export class NdjsonImporter extends Importer { @@ -12,27 +12,42 @@ export class NdjsonImporter extends Importer { super(settings); } - read(json: string) { + protected _createDocs(json: string): CreateDocsResponse { + let remainder = 0; try { const splitJson = json.split(/}\s*\n/); + const incompleteLastLine = json.match(/}\s*\n?$/) === null; - const ndjson: any[] = []; - for (let i = 0; i < splitJson.length; i++) { - if (splitJson[i] !== '') { - // note the extra } at the end of the line, adding back - // the one that was eaten in the split - ndjson.push(`${splitJson[i]}}`); + const docs: string[] = []; + if (splitJson.length) { + for (let i = 0; i < splitJson.length - 1; i++) { + if (splitJson[i] !== '') { + // note the extra } at the end of the line, adding back + // the one that was eaten in the split + docs.push(`${splitJson[i]}}`); + } } - } - this._docArray = ndjson; + const lastDoc = splitJson[splitJson.length - 1]; + if (lastDoc) { + if (incompleteLastLine === true) { + remainder = lastDoc.length; + } else { + docs.push(`${lastDoc}}`); + } + } + } return { success: true, + docs, + remainder, }; } catch (error) { return { success: false, + docs: [], + remainder, error, }; } diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts index 0f0036a7c4616..492a797f7a2f2 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/index.ts @@ -9,7 +9,6 @@ export { hasImportPermission, processResults, readFile, - reduceData, getMaxBytes, getMaxBytesFormatted, } from './utils'; diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts index 0d2016b71ed83..ecef01aae0519 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/utils/utils.ts @@ -15,6 +15,7 @@ import { import { getMlConfig } from '../../../../util/dependency_cache'; const DEFAULT_LINES_TO_SAMPLE = 1000; +const UPLOAD_SIZE_MB = 5; const overrideDefaults = { timestampFormat: undefined, @@ -34,15 +35,22 @@ export function readFile(file: File) { return new Promise((resolve, reject) => { if (file && file.size) { const reader = new FileReader(); - reader.readAsText(file); + reader.readAsArrayBuffer(file); reader.onload = (() => { return () => { + const decoder = new TextDecoder(); const data = reader.result; - if (data === '') { + if (data === null || typeof data === 'string') { + return reject(); + } + const size = UPLOAD_SIZE_MB * Math.pow(2, 20); + const fileContents = decoder.decode(data.slice(0, size)); + + if (fileContents === '') { reject(); } else { - resolve({ data }); + resolve({ fileContents, data }); } }; })(); @@ -52,14 +60,6 @@ export function readFile(file: File) { }); } -export function reduceData(data: string, mb: number) { - // assuming ascii characters in the file where 1 char is 1 byte - // TODO - change this when other non UTF-8 formats are - // supported for the read data - const size = mb * Math.pow(2, 20); - return data.length >= size ? data.slice(0, size) : data; -} - export function getMaxBytes() { const maxBytes = getMlConfig().file_data_visualizer.max_file_size_bytes; return maxBytes < ABSOLUTE_MAX_BYTES ? maxBytes : ABSOLUTE_MAX_BYTES; From d275d7f4df60f2370671f4fef56ccc7b5436091b Mon Sep 17 00:00:00 2001 From: Steph Milovic <stephanie.milovic@elastic.co> Date: Tue, 14 Apr 2020 12:25:54 -0600 Subject: [PATCH 107/121] [SIEM] [Cases] Case container unit tests (#63376) --- .../public/containers/case/__mocks__/api.ts | 122 +++++ .../siem/public/containers/case/api.test.tsx | 463 ++++++++++++++++++ .../siem/public/containers/case/mock.ts | 307 ++++++++++++ .../siem/public/containers/case/types.ts | 2 +- .../case/use_bulk_update_case.test.tsx | 128 +++++ .../containers/case/use_bulk_update_case.tsx | 4 +- .../containers/case/use_delete_cases.test.tsx | 124 +++++ .../containers/case/use_delete_cases.tsx | 8 +- .../case/use_get_action_license.test.tsx | 89 ++++ .../case/use_get_action_license.tsx | 4 +- .../containers/case/use_get_case.test.tsx | 112 +++++ .../public/containers/case/use_get_case.tsx | 4 +- .../case/use_get_case_user_actions.test.tsx | 106 ++++ .../case/use_get_case_user_actions.tsx | 5 +- .../containers/case/use_get_cases.test.tsx | 202 ++++++++ .../public/containers/case/use_get_cases.tsx | 6 +- .../case/use_get_cases_status.test.tsx | 88 ++++ .../containers/case/use_get_cases_status.tsx | 2 +- .../case/use_get_reporters.test.tsx | 86 ++++ .../containers/case/use_get_reporters.tsx | 2 +- .../containers/case/use_get_tags.test.tsx | 74 +++ .../public/containers/case/use_get_tags.tsx | 4 +- .../containers/case/use_post_case.test.tsx | 96 ++++ .../public/containers/case/use_post_case.tsx | 2 +- .../containers/case/use_post_comment.test.tsx | 102 ++++ .../containers/case/use_post_comment.tsx | 2 +- .../case/use_post_push_to_service.test.tsx | 137 ++++++ .../case/use_post_push_to_service.tsx | 4 +- .../containers/case/use_update_case.test.tsx | 119 +++++ .../containers/case/use_update_case.tsx | 4 +- .../case/use_update_comment.test.tsx | 116 +++++ .../containers/case/use_update_comment.tsx | 2 +- .../case/components/__mock__/case_data.tsx | 226 --------- .../components/all_cases/columns.test.tsx | 2 +- .../case/components/all_cases/index.test.tsx | 2 +- .../pages/case/components/all_cases/index.tsx | 4 +- .../components/case_view/actions.test.tsx | 2 +- .../case/components/case_view/index.test.tsx | 22 +- .../case/components/case_view/translations.ts | 3 + .../user_action_tree/helpers.test.tsx | 2 +- .../user_action_tree/index.test.tsx | 2 +- .../components/user_action_tree/index.tsx | 2 +- .../user_action_title.test.tsx | 2 +- .../user_action_tree/user_action_title.tsx | 4 +- x-pack/plugins/case/common/api/cases/case.ts | 1 + 45 files changed, 2529 insertions(+), 271 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/__mocks__/api.ts create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/api.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/mock.ts create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_get_case.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_post_case.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_update_case.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.test.tsx delete mode 100644 x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx diff --git a/x-pack/legacy/plugins/siem/public/containers/case/__mocks__/api.ts b/x-pack/legacy/plugins/siem/public/containers/case/__mocks__/api.ts new file mode 100644 index 0000000000000..6d2cfb7147537 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/__mocks__/api.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 { + ActionLicense, + AllCases, + BulkUpdateStatus, + Case, + CasesStatus, + CaseUserActions, + FetchCasesProps, + SortFieldCase, +} from '../types'; +import { + actionLicenses, + allCases, + basicCase, + basicCaseCommentPatch, + basicCasePost, + casesStatus, + caseUserActions, + pushedCase, + respReporters, + serviceConnector, + tags, +} from '../mock'; +import { + CaseExternalServiceRequest, + CasePatchRequest, + CasePostRequest, + CommentRequest, + ServiceConnectorCaseParams, + ServiceConnectorCaseResponse, + User, +} from '../../../../../../../plugins/case/common/api'; + +export const getCase = async ( + caseId: string, + includeComments: boolean = true, + signal: AbortSignal +): Promise<Case> => { + return Promise.resolve(basicCase); +}; + +export const getCasesStatus = async (signal: AbortSignal): Promise<CasesStatus> => + Promise.resolve(casesStatus); + +export const getTags = async (signal: AbortSignal): Promise<string[]> => Promise.resolve(tags); + +export const getReporters = async (signal: AbortSignal): Promise<User[]> => + Promise.resolve(respReporters); + +export const getCaseUserActions = async ( + caseId: string, + signal: AbortSignal +): Promise<CaseUserActions[]> => Promise.resolve(caseUserActions); + +export const getCases = async ({ + filterOptions = { + search: '', + reporters: [], + status: 'open', + tags: [], + }, + queryParams = { + page: 1, + perPage: 5, + sortField: SortFieldCase.createdAt, + sortOrder: 'desc', + }, + signal, +}: FetchCasesProps): Promise<AllCases> => Promise.resolve(allCases); + +export const postCase = async (newCase: CasePostRequest, signal: AbortSignal): Promise<Case> => + Promise.resolve(basicCasePost); + +export const patchCase = async ( + caseId: string, + updatedCase: Pick<CasePatchRequest, 'description' | 'status' | 'tags' | 'title'>, + version: string, + signal: AbortSignal +): Promise<Case[]> => Promise.resolve([basicCase]); + +export const patchCasesStatus = async ( + cases: BulkUpdateStatus[], + signal: AbortSignal +): Promise<Case[]> => Promise.resolve(allCases.cases); + +export const postComment = async ( + newComment: CommentRequest, + caseId: string, + signal: AbortSignal +): Promise<Case> => Promise.resolve(basicCase); + +export const patchComment = async ( + caseId: string, + commentId: string, + commentUpdate: string, + version: string, + signal: AbortSignal +): Promise<Case> => Promise.resolve(basicCaseCommentPatch); + +export const deleteCases = async (caseIds: string[], signal: AbortSignal): Promise<boolean> => + Promise.resolve(true); + +export const pushCase = async ( + caseId: string, + push: CaseExternalServiceRequest, + signal: AbortSignal +): Promise<Case> => Promise.resolve(pushedCase); + +export const pushToService = async ( + connectorId: string, + casePushParams: ServiceConnectorCaseParams, + signal: AbortSignal +): Promise<ServiceConnectorCaseResponse> => Promise.resolve(serviceConnector); + +export const getActionLicense = async (signal: AbortSignal): Promise<ActionLicense[]> => + Promise.resolve(actionLicenses); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/api.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/api.test.tsx new file mode 100644 index 0000000000000..4f5655cc9f221 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/api.test.tsx @@ -0,0 +1,463 @@ +/* + * 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 { KibanaServices } from '../../lib/kibana'; +import { + deleteCases, + getActionLicense, + getCase, + getCases, + getCasesStatus, + getCaseUserActions, + getReporters, + getTags, + patchCase, + patchCasesStatus, + patchComment, + postCase, + postComment, + pushCase, + pushToService, +} from './api'; +import { + actionLicenses, + allCases, + basicCase, + allCasesSnake, + basicCaseSnake, + actionTypeExecutorResult, + pushedCaseSnake, + casesStatus, + casesSnake, + cases, + caseUserActions, + pushedCase, + pushSnake, + reporters, + respReporters, + serviceConnector, + casePushParams, + tags, + caseUserActionsSnake, + casesStatusSnake, +} from './mock'; +import { CASES_URL } from './constants'; +import { DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS } from './use_get_cases'; +import * as i18n from './translations'; + +const abortCtrl = new AbortController(); +const mockKibanaServices = KibanaServices.get as jest.Mock; +jest.mock('../../lib/kibana'); + +const fetchMock = jest.fn(); +mockKibanaServices.mockReturnValue({ http: { fetch: fetchMock } }); + +describe('Case Configuration API', () => { + describe('deleteCases', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(''); + }); + const data = ['1', '2']; + + test('check url, method, signal', async () => { + await deleteCases(data, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}`, { + method: 'DELETE', + query: { ids: JSON.stringify(data) }, + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await deleteCases(data, abortCtrl.signal); + expect(resp).toEqual(''); + }); + }); + describe('getActionLicense', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(actionLicenses); + }); + test('check url, method, signal', async () => { + await getActionLicense(abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`/api/action/types`, { + method: 'GET', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getActionLicense(abortCtrl.signal); + expect(resp).toEqual(actionLicenses); + }); + }); + describe('getCase', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(basicCaseSnake); + }); + const data = basicCase.id; + + test('check url, method, signal', async () => { + await getCase(data, true, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}`, { + method: 'GET', + query: { includeComments: true }, + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getCase(data, true, abortCtrl.signal); + expect(resp).toEqual(basicCase); + }); + }); + describe('getCases', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(allCasesSnake); + }); + test('check url, method, signal', async () => { + await getCases({ + filterOptions: DEFAULT_FILTER_OPTIONS, + queryParams: DEFAULT_QUERY_PARAMS, + signal: abortCtrl.signal, + }); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/_find`, { + method: 'GET', + query: { + ...DEFAULT_QUERY_PARAMS, + reporters: [], + tags: [], + status: 'open', + }, + signal: abortCtrl.signal, + }); + }); + test('correctly applies filters', async () => { + await getCases({ + filterOptions: { + ...DEFAULT_FILTER_OPTIONS, + reporters: [...respReporters, { username: null, full_name: null, email: null }], + tags, + status: '', + search: 'hello', + }, + queryParams: DEFAULT_QUERY_PARAMS, + signal: abortCtrl.signal, + }); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/_find`, { + method: 'GET', + query: { + ...DEFAULT_QUERY_PARAMS, + reporters, + tags, + search: 'hello', + }, + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getCases({ + filterOptions: DEFAULT_FILTER_OPTIONS, + queryParams: DEFAULT_QUERY_PARAMS, + signal: abortCtrl.signal, + }); + expect(resp).toEqual({ ...allCases }); + }); + }); + describe('getCasesStatus', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(casesStatusSnake); + }); + test('check url, method, signal', async () => { + await getCasesStatus(abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/status`, { + method: 'GET', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getCasesStatus(abortCtrl.signal); + expect(resp).toEqual(casesStatus); + }); + }); + describe('getCaseUserActions', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(caseUserActionsSnake); + }); + + test('check url, method, signal', async () => { + await getCaseUserActions(basicCase.id, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/user_actions`, { + method: 'GET', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getCaseUserActions(basicCase.id, abortCtrl.signal); + expect(resp).toEqual(caseUserActions); + }); + }); + describe('getReporters', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(respReporters); + }); + + test('check url, method, signal', async () => { + await getReporters(abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/reporters`, { + method: 'GET', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getReporters(abortCtrl.signal); + expect(resp).toEqual(respReporters); + }); + }); + describe('getTags', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(tags); + }); + + test('check url, method, signal', async () => { + await getTags(abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/tags`, { + method: 'GET', + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await getTags(abortCtrl.signal); + expect(resp).toEqual(tags); + }); + }); + describe('patchCase', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue([basicCaseSnake]); + }); + const data = { description: 'updated description' }; + test('check url, method, signal', async () => { + await patchCase(basicCase.id, data, basicCase.version, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}`, { + method: 'PATCH', + body: JSON.stringify({ + cases: [{ ...data, id: basicCase.id, version: basicCase.version }], + }), + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await patchCase( + basicCase.id, + { description: 'updated description' }, + basicCase.version, + abortCtrl.signal + ); + expect(resp).toEqual({ ...[basicCase] }); + }); + }); + describe('patchCasesStatus', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(casesSnake); + }); + const data = [ + { + status: 'closed', + id: basicCase.id, + version: basicCase.version, + }, + ]; + + test('check url, method, signal', async () => { + await patchCasesStatus(data, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}`, { + method: 'PATCH', + body: JSON.stringify({ cases: data }), + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await patchCasesStatus(data, abortCtrl.signal); + expect(resp).toEqual({ ...cases }); + }); + }); + describe('patchComment', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(basicCaseSnake); + }); + + test('check url, method, signal', async () => { + await patchComment( + basicCase.id, + basicCase.comments[0].id, + 'updated comment', + basicCase.comments[0].version, + abortCtrl.signal + ); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/comments`, { + method: 'PATCH', + body: JSON.stringify({ + comment: 'updated comment', + id: basicCase.comments[0].id, + version: basicCase.comments[0].version, + }), + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await patchComment( + basicCase.id, + basicCase.comments[0].id, + 'updated comment', + basicCase.comments[0].version, + abortCtrl.signal + ); + expect(resp).toEqual(basicCase); + }); + }); + describe('postCase', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(basicCaseSnake); + }); + const data = { + description: 'description', + tags: ['tag'], + title: 'title', + }; + + test('check url, method, signal', async () => { + await postCase(data, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}`, { + method: 'POST', + body: JSON.stringify(data), + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await postCase(data, abortCtrl.signal); + expect(resp).toEqual(basicCase); + }); + }); + describe('postComment', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(basicCaseSnake); + }); + const data = { + comment: 'comment', + }; + + test('check url, method, signal', async () => { + await postComment(data, basicCase.id, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/comments`, { + method: 'POST', + body: JSON.stringify(data), + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await postComment(data, basicCase.id, abortCtrl.signal); + expect(resp).toEqual(basicCase); + }); + }); + describe('pushCase', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(pushedCaseSnake); + }); + + test('check url, method, signal', async () => { + await pushCase(basicCase.id, pushSnake, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/_push`, { + method: 'POST', + body: JSON.stringify(pushSnake), + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await pushCase(basicCase.id, pushSnake, abortCtrl.signal); + expect(resp).toEqual(pushedCase); + }); + }); + describe('pushToService', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(actionTypeExecutorResult); + }); + const connectorId = 'connectorId'; + test('check url, method, signal', async () => { + await pushToService(connectorId, casePushParams, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`/api/action/${connectorId}/_execute`, { + method: 'POST', + body: JSON.stringify({ params: casePushParams }), + signal: abortCtrl.signal, + }); + }); + + test('happy path', async () => { + const resp = await pushToService(connectorId, casePushParams, abortCtrl.signal); + expect(resp).toEqual(serviceConnector); + }); + + test('unhappy path - serviceMessage', async () => { + const theError = 'the error'; + fetchMock.mockResolvedValue({ + ...actionTypeExecutorResult, + status: 'error', + serviceMessage: theError, + message: 'not it', + }); + await expect( + pushToService(connectorId, casePushParams, abortCtrl.signal) + ).rejects.toMatchObject({ message: theError }); + }); + + test('unhappy path - message', async () => { + const theError = 'the error'; + fetchMock.mockResolvedValue({ + ...actionTypeExecutorResult, + status: 'error', + message: theError, + }); + await expect( + pushToService(connectorId, casePushParams, abortCtrl.signal) + ).rejects.toMatchObject({ message: theError }); + }); + + test('unhappy path - no message', async () => { + const theError = i18n.ERROR_PUSH_TO_SERVICE; + fetchMock.mockResolvedValue({ + ...actionTypeExecutorResult, + status: 'error', + }); + await expect( + pushToService(connectorId, casePushParams, abortCtrl.signal) + ).rejects.toMatchObject({ message: theError }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/mock.ts b/x-pack/legacy/plugins/siem/public/containers/case/mock.ts new file mode 100644 index 0000000000000..0bda75e5bc9e0 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/mock.ts @@ -0,0 +1,307 @@ +/* + * 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 { ActionLicense, AllCases, Case, CasesStatus, CaseUserActions, Comment } from './types'; + +import { + CommentResponse, + ServiceConnectorCaseResponse, + Status, + UserAction, + UserActionField, + CaseResponse, + CasesStatusResponse, + CaseUserActionsResponse, + CasesResponse, + CasesFindResponse, +} from '../../../../../../plugins/case/common/api/cases'; +import { UseGetCasesState, DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS } from './use_get_cases'; + +export const basicCaseId = 'basic-case-id'; +const basicCommentId = 'basic-comment-id'; +const basicCreatedAt = '2020-02-19T23:06:33.798Z'; +const basicUpdatedAt = '2020-02-20T15:02:57.995Z'; +const laterTime = '2020-02-28T15:02:57.995Z'; +export const elasticUser = { + fullName: 'Leslie Knope', + username: 'lknope', + email: 'leslie.knope@elastic.co', +}; + +export const tags: string[] = ['coke', 'pepsi']; + +export const basicComment: Comment = { + comment: 'Solve this fast!', + id: basicCommentId, + createdAt: basicCreatedAt, + createdBy: elasticUser, + pushedAt: null, + pushedBy: null, + updatedAt: null, + updatedBy: null, + version: 'WzQ3LDFc', +}; + +export const basicCase: Case = { + closedAt: null, + closedBy: null, + id: basicCaseId, + comments: [basicComment], + createdAt: basicCreatedAt, + createdBy: elasticUser, + description: 'Security banana Issue', + externalService: null, + status: 'open', + tags, + title: 'Another horrible breach!!', + totalComment: 1, + updatedAt: basicUpdatedAt, + updatedBy: elasticUser, + version: 'WzQ3LDFd', +}; + +export const basicCasePost: Case = { + ...basicCase, + updatedAt: null, + updatedBy: null, +}; + +export const basicCommentPatch: Comment = { + ...basicComment, + updatedAt: basicUpdatedAt, + updatedBy: { + username: 'elastic', + }, +}; + +export const basicCaseCommentPatch = { + ...basicCase, + comments: [basicCommentPatch], +}; + +export const casesStatus: CasesStatus = { + countClosedCases: 130, + countOpenCases: 20, +}; + +const basicPush = { + connectorId: 'connector_id', + connectorName: 'connector name', + externalId: 'external_id', + externalTitle: 'external title', + externalUrl: 'basicPush.com', + pushedAt: basicUpdatedAt, + pushedBy: elasticUser, +}; + +export const pushedCase: Case = { + ...basicCase, + externalService: basicPush, +}; + +export const serviceConnector: ServiceConnectorCaseResponse = { + number: '123', + incidentId: '444', + pushedDate: basicUpdatedAt, + url: 'connector.com', + comments: [ + { + commentId: basicCommentId, + pushedDate: basicUpdatedAt, + }, + ], +}; + +const basicAction = { + actionAt: basicCreatedAt, + actionBy: elasticUser, + oldValue: null, + newValue: 'what a cool value', + caseId: basicCaseId, + commentId: null, +}; + +export const casePushParams = { + actionBy: elasticUser, + caseId: basicCaseId, + createdAt: basicCreatedAt, + createdBy: elasticUser, + incidentId: null, + title: 'what a cool value', + commentId: null, + updatedAt: basicCreatedAt, + updatedBy: elasticUser, + description: 'nice', +}; +export const actionTypeExecutorResult = { + actionId: 'string', + status: 'ok', + data: serviceConnector, +}; + +export const cases: Case[] = [ + basicCase, + { ...pushedCase, id: '1', totalComment: 0, comments: [] }, + { ...pushedCase, updatedAt: laterTime, id: '2', totalComment: 0, comments: [] }, + { ...basicCase, id: '3', totalComment: 0, comments: [] }, + { ...basicCase, id: '4', totalComment: 0, comments: [] }, +]; + +export const allCases: AllCases = { + cases, + page: 1, + perPage: 5, + total: 10, + ...casesStatus, +}; +export const actionLicenses: ActionLicense[] = [ + { + id: '.servicenow', + name: 'ServiceNow', + enabled: true, + enabledInConfig: true, + enabledInLicense: true, + }, +]; + +// Snake case for mock api responses +export const elasticUserSnake = { + full_name: 'Leslie Knope', + username: 'lknope', + email: 'leslie.knope@elastic.co', +}; +export const basicCommentSnake: CommentResponse = { + ...basicComment, + comment: 'Solve this fast!', + id: basicCommentId, + created_at: basicCreatedAt, + created_by: elasticUserSnake, + pushed_at: null, + pushed_by: null, + updated_at: null, + updated_by: null, +}; + +export const basicCaseSnake: CaseResponse = { + ...basicCase, + status: 'open' as Status, + closed_at: null, + closed_by: null, + comments: [basicCommentSnake], + created_at: basicCreatedAt, + created_by: elasticUserSnake, + external_service: null, + updated_at: basicUpdatedAt, + updated_by: elasticUserSnake, +}; + +export const casesStatusSnake: CasesStatusResponse = { + count_closed_cases: 130, + count_open_cases: 20, +}; + +export const pushSnake = { + connector_id: 'connector_id', + connector_name: 'connector name', + external_id: 'external_id', + external_title: 'external title', + external_url: 'basicPush.com', +}; +const basicPushSnake = { + ...pushSnake, + pushed_at: basicUpdatedAt, + pushed_by: elasticUserSnake, +}; +export const pushedCaseSnake = { + ...basicCaseSnake, + external_service: basicPushSnake, +}; + +export const reporters: string[] = ['alexis', 'kim', 'maria', 'steph']; +export const respReporters = [ + { username: 'alexis', full_name: null, email: null }, + { username: 'kim', full_name: null, email: null }, + { username: 'maria', full_name: null, email: null }, + { username: 'steph', full_name: null, email: null }, +]; +export const casesSnake: CasesResponse = [ + basicCaseSnake, + { ...pushedCaseSnake, id: '1', totalComment: 0, comments: [] }, + { ...pushedCaseSnake, updated_at: laterTime, id: '2', totalComment: 0, comments: [] }, + { ...basicCaseSnake, id: '3', totalComment: 0, comments: [] }, + { ...basicCaseSnake, id: '4', totalComment: 0, comments: [] }, +]; + +export const allCasesSnake: CasesFindResponse = { + cases: casesSnake, + page: 1, + per_page: 5, + total: 10, + ...casesStatusSnake, +}; + +const basicActionSnake = { + action_at: basicCreatedAt, + action_by: elasticUserSnake, + old_value: null, + new_value: 'what a cool value', + case_id: basicCaseId, + comment_id: null, +}; +export const getUserActionSnake = (af: UserActionField, a: UserAction) => ({ + ...basicActionSnake, + action_id: `${af[0]}-${a}`, + action_field: af, + action: a, + comment_id: af[0] === 'comment' ? basicCommentId : null, + new_value: + a === 'push-to-service' && af[0] === 'pushed' + ? JSON.stringify(basicPushSnake) + : basicAction.newValue, +}); + +export const caseUserActionsSnake: CaseUserActionsResponse = [ + getUserActionSnake(['description'], 'create'), + getUserActionSnake(['comment'], 'create'), + getUserActionSnake(['description'], 'update'), +]; + +// user actions + +export const getUserAction = (af: UserActionField, a: UserAction) => ({ + ...basicAction, + actionId: `${af[0]}-${a}`, + actionField: af, + action: a, + commentId: af[0] === 'comment' ? basicCommentId : null, + newValue: + a === 'push-to-service' && af[0] === 'pushed' + ? JSON.stringify(basicPushSnake) + : basicAction.newValue, +}); + +export const caseUserActions: CaseUserActions[] = [ + getUserAction(['description'], 'create'), + getUserAction(['comment'], 'create'), + getUserAction(['description'], 'update'), +]; + +// components tests +export const useGetCasesMockState: UseGetCasesState = { + data: allCases, + loading: [], + selectedCases: [], + isError: false, + queryParams: DEFAULT_QUERY_PARAMS, + filterOptions: DEFAULT_FILTER_OPTIONS, +}; + +export const basicCaseClosed: Case = { + ...basicCase, + closedAt: '2020-02-25T23:06:33.798Z', + closedBy: elasticUser, + status: 'closed', +}; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/types.ts b/x-pack/legacy/plugins/siem/public/containers/case/types.ts index d2a58e9eeeff4..e552f22b55fa4 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/types.ts +++ b/x-pack/legacy/plugins/siem/public/containers/case/types.ts @@ -31,7 +31,7 @@ export interface CaseUserActions { export interface CaseExternalService { pushedAt: string; - pushedBy: string; + pushedBy: ElasticUser; connectorId: string; connectorName: string; externalId: string; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.test.tsx new file mode 100644 index 0000000000000..329fda10424a8 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.test.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 { renderHook, act } from '@testing-library/react-hooks'; +import { useUpdateCases, UseUpdateCases } from './use_bulk_update_case'; +import { basicCase } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useUpdateCases', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCases>(() => + useUpdateCases() + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoading: false, + isError: false, + isUpdated: false, + updateBulkStatus: result.current.updateBulkStatus, + dispatchResetIsUpdated: result.current.dispatchResetIsUpdated, + }); + }); + }); + + it('calls patchCase with correct arguments', async () => { + const spyOnPatchCases = jest.spyOn(api, 'patchCasesStatus'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCases>(() => + useUpdateCases() + ); + await waitForNextUpdate(); + + result.current.updateBulkStatus([basicCase], 'closed'); + await waitForNextUpdate(); + expect(spyOnPatchCases).toBeCalledWith( + [ + { + status: 'closed', + id: basicCase.id, + version: basicCase.version, + }, + ], + abortCtrl.signal + ); + }); + }); + + it('patch cases', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCases>(() => + useUpdateCases() + ); + await waitForNextUpdate(); + result.current.updateBulkStatus([basicCase], 'closed'); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isUpdated: true, + isLoading: false, + isError: false, + updateBulkStatus: result.current.updateBulkStatus, + dispatchResetIsUpdated: result.current.dispatchResetIsUpdated, + }); + }); + }); + + it('set isLoading to true when posting case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCases>(() => + useUpdateCases() + ); + await waitForNextUpdate(); + result.current.updateBulkStatus([basicCase], 'closed'); + + expect(result.current.isLoading).toBe(true); + }); + }); + + it('dispatchResetIsUpdated resets is updated', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCases>(() => + useUpdateCases() + ); + + await waitForNextUpdate(); + result.current.updateBulkStatus([basicCase], 'closed'); + await waitForNextUpdate(); + expect(result.current.isUpdated).toBeTruthy(); + result.current.dispatchResetIsUpdated(); + expect(result.current.isUpdated).toBeFalsy(); + }); + }); + + it('unhappy path', async () => { + const spyOnPatchCases = jest.spyOn(api, 'patchCasesStatus'); + spyOnPatchCases.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCases>(() => + useUpdateCases() + ); + await waitForNextUpdate(); + result.current.updateBulkStatus([basicCase], 'closed'); + + expect(result.current).toEqual({ + isUpdated: false, + isLoading: false, + isError: true, + updateBulkStatus: result.current.updateBulkStatus, + dispatchResetIsUpdated: result.current.dispatchResetIsUpdated, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx index 7d040c49f1971..d0cc4d99f8f9f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_bulk_update_case.tsx @@ -51,12 +51,12 @@ const dataFetchReducer = (state: UpdateState, action: Action): UpdateState => { return state; } }; -interface UseUpdateCase extends UpdateState { +export interface UseUpdateCases extends UpdateState { updateBulkStatus: (cases: Case[], status: string) => void; dispatchResetIsUpdated: () => void; } -export const useUpdateCases = (): UseUpdateCase => { +export const useUpdateCases = (): UseUpdateCases => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.test.tsx new file mode 100644 index 0000000000000..45ba392f3b5b4 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.test.tsx @@ -0,0 +1,124 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import { useDeleteCases, UseDeleteCase } from './use_delete_cases'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useDeleteCases', () => { + const abortCtrl = new AbortController(); + const deleteObj = [{ id: '1' }, { id: '2' }, { id: '3' }]; + const deleteArr = ['1', '2', '3']; + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseDeleteCase>(() => + useDeleteCases() + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isDisplayConfirmDeleteModal: false, + isLoading: false, + isError: false, + isDeleted: false, + dispatchResetIsDeleted: result.current.dispatchResetIsDeleted, + handleOnDeleteConfirm: result.current.handleOnDeleteConfirm, + handleToggleModal: result.current.handleToggleModal, + }); + }); + }); + + it('calls deleteCases with correct arguments', async () => { + const spyOnDeleteCases = jest.spyOn(api, 'deleteCases'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseDeleteCase>(() => + useDeleteCases() + ); + await waitForNextUpdate(); + + result.current.handleOnDeleteConfirm(deleteObj); + await waitForNextUpdate(); + expect(spyOnDeleteCases).toBeCalledWith(deleteArr, abortCtrl.signal); + }); + }); + + it('deletes cases', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseDeleteCase>(() => + useDeleteCases() + ); + await waitForNextUpdate(); + result.current.handleToggleModal(); + result.current.handleOnDeleteConfirm(deleteObj); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isDisplayConfirmDeleteModal: false, + isLoading: false, + isError: false, + isDeleted: true, + dispatchResetIsDeleted: result.current.dispatchResetIsDeleted, + handleOnDeleteConfirm: result.current.handleOnDeleteConfirm, + handleToggleModal: result.current.handleToggleModal, + }); + }); + }); + + it('resets is deleting', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseDeleteCase>(() => + useDeleteCases() + ); + await waitForNextUpdate(); + result.current.handleToggleModal(); + result.current.handleOnDeleteConfirm(deleteObj); + await waitForNextUpdate(); + expect(result.current.isDeleted).toBeTruthy(); + result.current.handleToggleModal(); + result.current.dispatchResetIsDeleted(); + expect(result.current.isDeleted).toBeFalsy(); + }); + }); + + it('set isLoading to true when deleting cases', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseDeleteCase>(() => + useDeleteCases() + ); + await waitForNextUpdate(); + result.current.handleToggleModal(); + result.current.handleOnDeleteConfirm(deleteObj); + expect(result.current.isLoading).toBe(true); + }); + }); + + it('unhappy path', async () => { + const spyOnDeleteCases = jest.spyOn(api, 'deleteCases'); + spyOnDeleteCases.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseDeleteCase>(() => + useDeleteCases() + ); + await waitForNextUpdate(); + result.current.handleToggleModal(); + result.current.handleOnDeleteConfirm(deleteObj); + + expect(result.current).toEqual({ + isDisplayConfirmDeleteModal: false, + isLoading: false, + isError: true, + isDeleted: false, + dispatchResetIsDeleted: result.current.dispatchResetIsDeleted, + handleOnDeleteConfirm: result.current.handleOnDeleteConfirm, + handleToggleModal: result.current.handleToggleModal, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx index 07e3786758aeb..3c49be551c064 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_delete_cases.tsx @@ -59,9 +59,9 @@ const dataFetchReducer = (state: DeleteState, action: Action): DeleteState => { } }; -interface UseDeleteCase extends DeleteState { +export interface UseDeleteCase extends DeleteState { dispatchResetIsDeleted: () => void; - handleOnDeleteConfirm: (caseIds: DeleteCase[]) => void; + handleOnDeleteConfirm: (cases: DeleteCase[]) => void; handleToggleModal: () => void; } @@ -117,8 +117,8 @@ export const useDeleteCases = (): UseDeleteCase => { }, [state.isDisplayConfirmDeleteModal]); const handleOnDeleteConfirm = useCallback( - caseIds => { - dispatchDeleteCases(caseIds); + (cases: DeleteCase[]) => { + dispatchDeleteCases(cases); dispatchToggleDeleteModal(); }, [state.isDisplayConfirmDeleteModal] diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.test.tsx new file mode 100644 index 0000000000000..23c9ff5e49586 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.test.tsx @@ -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. + */ + +import { renderHook, act } from '@testing-library/react-hooks'; +import { initialData, useGetActionLicense, ActionLicenseState } from './use_get_action_license'; +import { actionLicenses } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useGetActionLicense', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, ActionLicenseState>(() => + useGetActionLicense() + ); + await waitForNextUpdate(); + expect(result.current).toEqual(initialData); + }); + }); + + it('calls getActionLicense with correct arguments', async () => { + const spyOnGetActionLicense = jest.spyOn(api, 'getActionLicense'); + + await act(async () => { + const { waitForNextUpdate } = renderHook<string, ActionLicenseState>(() => + useGetActionLicense() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(spyOnGetActionLicense).toBeCalledWith(abortCtrl.signal); + }); + }); + + it('gets action license', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, ActionLicenseState>(() => + useGetActionLicense() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoading: false, + isError: false, + actionLicense: actionLicenses[0], + }); + }); + }); + + it('set isLoading to true when posting case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, ActionLicenseState>(() => + useGetActionLicense() + ); + await waitForNextUpdate(); + expect(result.current.isLoading).toBe(true); + }); + }); + + it('unhappy path', async () => { + const spyOnGetActionLicense = jest.spyOn(api, 'getActionLicense'); + spyOnGetActionLicense.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, ActionLicenseState>(() => + useGetActionLicense() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + actionLicense: null, + isLoading: false, + isError: true, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.tsx index 12f92b2db039b..0d28a1b20c61f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_action_license.tsx @@ -11,13 +11,13 @@ import { getActionLicense } from './api'; import * as i18n from './translations'; import { ActionLicense } from './types'; -interface ActionLicenseState { +export interface ActionLicenseState { actionLicense: ActionLicense | null; isLoading: boolean; isError: boolean; } -const initialData: ActionLicenseState = { +export const initialData: ActionLicenseState = { actionLicense: null, isLoading: true, isError: false, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.test.tsx new file mode 100644 index 0000000000000..10649da548d43 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.test.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 { renderHook, act } from '@testing-library/react-hooks'; +import { initialData, useGetCase, UseGetCase } from './use_get_case'; +import { basicCase } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useGetCase', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCase>(() => + useGetCase(basicCase.id) + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + data: initialData, + isLoading: true, + isError: false, + fetchCase: result.current.fetchCase, + updateCase: result.current.updateCase, + }); + }); + }); + + it('calls getCase with correct arguments', async () => { + const spyOnGetCase = jest.spyOn(api, 'getCase'); + await act(async () => { + const { waitForNextUpdate } = renderHook<string, UseGetCase>(() => useGetCase(basicCase.id)); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(spyOnGetCase).toBeCalledWith(basicCase.id, true, abortCtrl.signal); + }); + }); + + it('fetch case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCase>(() => + useGetCase(basicCase.id) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + data: basicCase, + isLoading: false, + isError: false, + fetchCase: result.current.fetchCase, + updateCase: result.current.updateCase, + }); + }); + }); + + it('refetch case', async () => { + const spyOnGetCase = jest.spyOn(api, 'getCase'); + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCase>(() => + useGetCase(basicCase.id) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.fetchCase(); + expect(spyOnGetCase).toHaveBeenCalledTimes(2); + }); + }); + + it('set isLoading to true when refetching case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCase>(() => + useGetCase(basicCase.id) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.fetchCase(); + + expect(result.current.isLoading).toBe(true); + }); + }); + + it('unhappy path', async () => { + const spyOnGetCase = jest.spyOn(api, 'getCase'); + spyOnGetCase.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCase>(() => + useGetCase(basicCase.id) + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + data: initialData, + isLoading: false, + isError: true, + fetchCase: result.current.fetchCase, + updateCase: result.current.updateCase, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx index 835fb7153dc95..b2e3b6d0cacf6 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case.tsx @@ -53,7 +53,7 @@ const dataFetchReducer = (state: CaseState, action: Action): CaseState => { return state; } }; -const initialData: Case = { +export const initialData: Case = { id: '', closedAt: null, closedBy: null, @@ -73,7 +73,7 @@ const initialData: Case = { version: '', }; -interface UseGetCase extends CaseState { +export interface UseGetCase extends CaseState { fetchCase: () => void; updateCase: (newCase: Case) => void; } diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.test.tsx new file mode 100644 index 0000000000000..cdd40b84f8724 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.test.tsx @@ -0,0 +1,106 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import { + initialData, + useGetCaseUserActions, + UseGetCaseUserActions, +} from './use_get_case_user_actions'; +import { basicCaseId, caseUserActions, elasticUser } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useGetCaseUserActions', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCaseUserActions>(() => + useGetCaseUserActions(basicCaseId) + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + ...initialData, + fetchCaseUserActions: result.current.fetchCaseUserActions, + }); + }); + }); + + it('calls getCaseUserActions with correct arguments', async () => { + const spyOnPostCase = jest.spyOn(api, 'getCaseUserActions'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCaseUserActions>(() => + useGetCaseUserActions(basicCaseId) + ); + await waitForNextUpdate(); + + result.current.fetchCaseUserActions(basicCaseId); + await waitForNextUpdate(); + expect(spyOnPostCase).toBeCalledWith(basicCaseId, abortCtrl.signal); + }); + }); + + it('retuns proper state on getCaseUserActions', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCaseUserActions>(() => + useGetCaseUserActions(basicCaseId) + ); + await waitForNextUpdate(); + result.current.fetchCaseUserActions(basicCaseId); + await waitForNextUpdate(); + expect(result.current).toEqual({ + ...initialData, + caseUserActions: caseUserActions.slice(1), + fetchCaseUserActions: result.current.fetchCaseUserActions, + hasDataToPush: true, + isError: false, + isLoading: false, + participants: [elasticUser], + }); + }); + }); + + it('set isLoading to true when posting case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCaseUserActions>(() => + useGetCaseUserActions(basicCaseId) + ); + await waitForNextUpdate(); + result.current.fetchCaseUserActions(basicCaseId); + + expect(result.current.isLoading).toBe(true); + }); + }); + + it('unhappy path', async () => { + const spyOnPostCase = jest.spyOn(api, 'getCaseUserActions'); + spyOnPostCase.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCaseUserActions>(() => + useGetCaseUserActions(basicCaseId) + ); + await waitForNextUpdate(); + result.current.fetchCaseUserActions(basicCaseId); + + expect(result.current).toEqual({ + ...initialData, + isLoading: false, + isError: true, + fetchCaseUserActions: result.current.fetchCaseUserActions, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.tsx index 4c278bc038134..6d9874a655e97 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_case_user_actions.tsx @@ -22,7 +22,7 @@ interface CaseUserActionsState { lastIndexPushToService: number; } -const initialData: CaseUserActionsState = { +export const initialData: CaseUserActionsState = { caseUserActions: [], firstIndexPushToService: -1, lastIndexPushToService: -1, @@ -32,7 +32,7 @@ const initialData: CaseUserActionsState = { participants: [], }; -interface UseGetCaseUserActions extends CaseUserActionsState { +export interface UseGetCaseUserActions extends CaseUserActionsState { fetchCaseUserActions: (caseId: string) => void; } @@ -80,6 +80,7 @@ export const useGetCaseUserActions = (caseId: string): UseGetCaseUserActions => const participants = !isEmpty(response) ? uniqBy('actionBy.username', response).map(cau => cau.actionBy) : []; + const caseUserActions = !isEmpty(response) ? response.slice(1) : []; setCaseUserActionsState({ caseUserActions, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.test.tsx new file mode 100644 index 0000000000000..4e274e074b036 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.test.tsx @@ -0,0 +1,202 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import { + DEFAULT_FILTER_OPTIONS, + DEFAULT_QUERY_PARAMS, + initialData, + useGetCases, + UseGetCases, +} from './use_get_cases'; +import { UpdateKey } from './use_update_case'; +import { allCases, basicCase } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useGetCases', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + expect(result.current).toEqual({ + data: initialData, + dispatchUpdateCaseProperty: result.current.dispatchUpdateCaseProperty, + filterOptions: DEFAULT_FILTER_OPTIONS, + isError: false, + loading: [], + queryParams: DEFAULT_QUERY_PARAMS, + refetchCases: result.current.refetchCases, + selectedCases: [], + setFilters: result.current.setFilters, + setQueryParams: result.current.setQueryParams, + setSelectedCases: result.current.setSelectedCases, + }); + }); + }); + + it('calls getCases with correct arguments', async () => { + const spyOnGetCases = jest.spyOn(api, 'getCases'); + await act(async () => { + const { waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(spyOnGetCases).toBeCalledWith({ + filterOptions: DEFAULT_FILTER_OPTIONS, + queryParams: DEFAULT_QUERY_PARAMS, + signal: abortCtrl.signal, + }); + }); + }); + + it('fetch cases', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + data: allCases, + dispatchUpdateCaseProperty: result.current.dispatchUpdateCaseProperty, + filterOptions: DEFAULT_FILTER_OPTIONS, + isError: false, + loading: [], + queryParams: DEFAULT_QUERY_PARAMS, + refetchCases: result.current.refetchCases, + selectedCases: [], + setFilters: result.current.setFilters, + setQueryParams: result.current.setQueryParams, + setSelectedCases: result.current.setSelectedCases, + }); + }); + }); + it('dispatch update case property', async () => { + const spyOnPatchCase = jest.spyOn(api, 'patchCase'); + await act(async () => { + const updateCase = { + updateKey: 'description' as UpdateKey, + updateValue: 'description update', + caseId: basicCase.id, + refetchCasesStatus: jest.fn(), + version: '99999', + }; + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.dispatchUpdateCaseProperty(updateCase); + expect(result.current.loading).toEqual(['caseUpdate']); + expect(spyOnPatchCase).toBeCalledWith( + basicCase.id, + { [updateCase.updateKey]: updateCase.updateValue }, + updateCase.version, + abortCtrl.signal + ); + }); + }); + + it('refetch cases', async () => { + const spyOnGetCases = jest.spyOn(api, 'getCases'); + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.refetchCases(); + expect(spyOnGetCases).toHaveBeenCalledTimes(2); + }); + }); + + it('set isLoading to true when refetching case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.refetchCases(); + + expect(result.current.loading).toEqual(['cases']); + }); + }); + + it('unhappy path', async () => { + const spyOnGetCases = jest.spyOn(api, 'getCases'); + spyOnGetCases.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + data: initialData, + dispatchUpdateCaseProperty: result.current.dispatchUpdateCaseProperty, + filterOptions: DEFAULT_FILTER_OPTIONS, + isError: true, + loading: [], + queryParams: DEFAULT_QUERY_PARAMS, + refetchCases: result.current.refetchCases, + selectedCases: [], + setFilters: result.current.setFilters, + setQueryParams: result.current.setQueryParams, + setSelectedCases: result.current.setSelectedCases, + }); + }); + }); + it('set filters', async () => { + await act(async () => { + const spyOnGetCases = jest.spyOn(api, 'getCases'); + const newFilters = { + search: 'new', + tags: ['new'], + status: 'closed', + }; + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.setFilters(newFilters); + await waitForNextUpdate(); + expect(spyOnGetCases.mock.calls[1][0]).toEqual({ + filterOptions: { ...DEFAULT_FILTER_OPTIONS, ...newFilters }, + queryParams: DEFAULT_QUERY_PARAMS, + signal: abortCtrl.signal, + }); + }); + }); + it('set query params', async () => { + await act(async () => { + const spyOnGetCases = jest.spyOn(api, 'getCases'); + const newQueryParams = { + page: 2, + }; + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.setQueryParams(newQueryParams); + await waitForNextUpdate(); + expect(spyOnGetCases.mock.calls[1][0]).toEqual({ + filterOptions: DEFAULT_FILTER_OPTIONS, + queryParams: { ...DEFAULT_QUERY_PARAMS, ...newQueryParams }, + signal: abortCtrl.signal, + }); + }); + }); + it('set selected cases', async () => { + await act(async () => { + const selectedCases = [basicCase]; + const { result, waitForNextUpdate } = renderHook<string, UseGetCases>(() => useGetCases()); + await waitForNextUpdate(); + await waitForNextUpdate(); + result.current.setSelectedCases(selectedCases); + expect(result.current.selectedCases).toEqual(selectedCases); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx index 1cbce5af6304b..465b50dbdc1bc 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases.tsx @@ -105,7 +105,7 @@ export const DEFAULT_QUERY_PARAMS: QueryParams = { sortOrder: 'desc', }; -const initialData: AllCases = { +export const initialData: AllCases = { cases: [], countClosedCases: null, countOpenCases: null, @@ -113,7 +113,7 @@ const initialData: AllCases = { perPage: 0, total: 0, }; -interface UseGetCases extends UseGetCasesState { +export interface UseGetCases extends UseGetCasesState { dispatchUpdateCaseProperty: ({ updateKey, updateValue, @@ -121,7 +121,7 @@ interface UseGetCases extends UseGetCasesState { version, refetchCasesStatus, }: UpdateCase) => void; - refetchCases: (filters: FilterOptions, queryParams: QueryParams) => void; + refetchCases: () => void; setFilters: (filters: Partial<FilterOptions>) => void; setQueryParams: (queryParams: Partial<QueryParams>) => void; setSelectedCases: (mySelectedCases: Case[]) => void; diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.test.tsx new file mode 100644 index 0000000000000..bfbcbd2525e3b --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.test.tsx @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { renderHook, act } from '@testing-library/react-hooks'; +import { useGetCasesStatus, UseGetCasesStatus } from './use_get_cases_status'; +import { casesStatus } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useGetCasesStatus', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCasesStatus>(() => + useGetCasesStatus() + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + countClosedCases: null, + countOpenCases: null, + isLoading: true, + isError: false, + fetchCasesStatus: result.current.fetchCasesStatus, + }); + }); + }); + + it('calls getCasesStatus api', async () => { + const spyOnGetCasesStatus = jest.spyOn(api, 'getCasesStatus'); + await act(async () => { + const { waitForNextUpdate } = renderHook<string, UseGetCasesStatus>(() => + useGetCasesStatus() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(spyOnGetCasesStatus).toBeCalledWith(abortCtrl.signal); + }); + }); + + it('fetch reporters', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCasesStatus>(() => + useGetCasesStatus() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + countClosedCases: casesStatus.countClosedCases, + countOpenCases: casesStatus.countOpenCases, + isLoading: false, + isError: false, + fetchCasesStatus: result.current.fetchCasesStatus, + }); + }); + }); + + it('unhappy path', async () => { + const spyOnGetCasesStatus = jest.spyOn(api, 'getCasesStatus'); + spyOnGetCasesStatus.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetCasesStatus>(() => + useGetCasesStatus() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + countClosedCases: 0, + countOpenCases: 0, + isLoading: false, + isError: true, + fetchCasesStatus: result.current.fetchCasesStatus, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.tsx index 7f56d27ef160e..0788464602357 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_cases_status.tsx @@ -23,7 +23,7 @@ const initialData: CasesStatusState = { isError: false, }; -interface UseGetCasesStatus extends CasesStatusState { +export interface UseGetCasesStatus extends CasesStatusState { fetchCasesStatus: () => void; } diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.test.tsx new file mode 100644 index 0000000000000..3629fbc60e4d3 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.test.tsx @@ -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 { renderHook, act } from '@testing-library/react-hooks'; +import { useGetReporters, UseGetReporters } from './use_get_reporters'; +import { reporters, respReporters } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useGetReporters', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetReporters>(() => + useGetReporters() + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + reporters: [], + respReporters: [], + isLoading: true, + isError: false, + fetchReporters: result.current.fetchReporters, + }); + }); + }); + + it('calls getReporters api', async () => { + const spyOnGetReporters = jest.spyOn(api, 'getReporters'); + await act(async () => { + const { waitForNextUpdate } = renderHook<string, UseGetReporters>(() => useGetReporters()); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(spyOnGetReporters).toBeCalledWith(abortCtrl.signal); + }); + }); + + it('fetch reporters', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetReporters>(() => + useGetReporters() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + reporters, + respReporters, + isLoading: false, + isError: false, + fetchReporters: result.current.fetchReporters, + }); + }); + }); + + it('unhappy path', async () => { + const spyOnGetReporters = jest.spyOn(api, 'getReporters'); + spyOnGetReporters.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseGetReporters>(() => + useGetReporters() + ); + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + reporters: [], + respReporters: [], + isLoading: false, + isError: true, + fetchReporters: result.current.fetchReporters, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.tsx index 2478172a3394b..2fc9b8294c8e0 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_reporters.tsx @@ -26,7 +26,7 @@ const initialData: ReportersState = { isError: false, }; -interface UseGetReporters extends ReportersState { +export interface UseGetReporters extends ReportersState { fetchReporters: () => void; } diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.test.tsx new file mode 100644 index 0000000000000..3df83d1c8a596 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.test.tsx @@ -0,0 +1,74 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import { useGetTags, TagsState } from './use_get_tags'; +import { tags } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useGetTags', () => { + const abortCtrl = new AbortController(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, TagsState>(() => useGetTags()); + await waitForNextUpdate(); + expect(result.current).toEqual({ + tags: [], + isLoading: true, + isError: false, + }); + }); + }); + + it('calls getTags api', async () => { + const spyOnGetTags = jest.spyOn(api, 'getTags'); + await act(async () => { + const { waitForNextUpdate } = renderHook<string, TagsState>(() => useGetTags()); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(spyOnGetTags).toBeCalledWith(abortCtrl.signal); + }); + }); + + it('fetch tags', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, TagsState>(() => useGetTags()); + await waitForNextUpdate(); + await waitForNextUpdate(); + expect(result.current).toEqual({ + tags, + isLoading: false, + isError: false, + }); + }); + }); + + it('unhappy path', async () => { + const spyOnGetTags = jest.spyOn(api, 'getTags'); + spyOnGetTags.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, TagsState>(() => useGetTags()); + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + tags: [], + isLoading: false, + isError: true, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx index b41d5aab5c07a..7c58316ac3fe9 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_get_tags.tsx @@ -10,7 +10,7 @@ import { errorToToaster, useStateToaster } from '../../components/toasters'; import { getTags } from './api'; import * as i18n from './translations'; -interface TagsState { +export interface TagsState { tags: string[]; isLoading: boolean; isError: boolean; @@ -49,7 +49,7 @@ const initialData: string[] = []; export const useGetTags = (): TagsState => { const [state, dispatch] = useReducer(dataFetchReducer, { - isLoading: false, + isLoading: true, isError: false, tags: initialData, }); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.test.tsx new file mode 100644 index 0000000000000..8b105fe041d27 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.test.tsx @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { renderHook, act } from '@testing-library/react-hooks'; +import { usePostCase, UsePostCase } from './use_post_case'; +import { basicCasePost } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('usePostCase', () => { + const abortCtrl = new AbortController(); + const samplePost = { + description: 'description', + tags: ['tags'], + title: 'title', + }; + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostCase>(() => usePostCase()); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoading: false, + isError: false, + caseData: null, + postCase: result.current.postCase, + }); + }); + }); + + it('calls postCase with correct arguments', async () => { + const spyOnPostCase = jest.spyOn(api, 'postCase'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostCase>(() => usePostCase()); + await waitForNextUpdate(); + + result.current.postCase(samplePost); + await waitForNextUpdate(); + expect(spyOnPostCase).toBeCalledWith(samplePost, abortCtrl.signal); + }); + }); + + it('post case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostCase>(() => usePostCase()); + await waitForNextUpdate(); + result.current.postCase(samplePost); + await waitForNextUpdate(); + expect(result.current).toEqual({ + caseData: basicCasePost, + isLoading: false, + isError: false, + postCase: result.current.postCase, + }); + }); + }); + + it('set isLoading to true when posting case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostCase>(() => usePostCase()); + await waitForNextUpdate(); + result.current.postCase(samplePost); + + expect(result.current.isLoading).toBe(true); + }); + }); + + it('unhappy path', async () => { + const spyOnPostCase = jest.spyOn(api, 'postCase'); + spyOnPostCase.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostCase>(() => usePostCase()); + await waitForNextUpdate(); + result.current.postCase(samplePost); + + expect(result.current).toEqual({ + caseData: null, + isLoading: false, + isError: true, + postCase: result.current.postCase, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx index 0e01364721dc5..aeb50fc098eee 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_case.tsx @@ -48,7 +48,7 @@ const dataFetchReducer = (state: NewCaseState, action: Action): NewCaseState => } }; -interface UsePostCase extends NewCaseState { +export interface UsePostCase extends NewCaseState { postCase: (data: CasePostRequest) => void; } export const usePostCase = (): UsePostCase => { diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.test.tsx new file mode 100644 index 0000000000000..d7d9cf9c557c9 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.test.tsx @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { renderHook, act } from '@testing-library/react-hooks'; +import { usePostComment, UsePostComment } from './use_post_comment'; +import { basicCaseId } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('usePostComment', () => { + const abortCtrl = new AbortController(); + const samplePost = { + comment: 'a comment', + }; + const updateCaseCallback = jest.fn(); + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostComment>(() => + usePostComment(basicCaseId) + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoading: false, + isError: false, + postComment: result.current.postComment, + }); + }); + }); + + it('calls postComment with correct arguments', async () => { + const spyOnPostCase = jest.spyOn(api, 'postComment'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostComment>(() => + usePostComment(basicCaseId) + ); + await waitForNextUpdate(); + + result.current.postComment(samplePost, updateCaseCallback); + await waitForNextUpdate(); + expect(spyOnPostCase).toBeCalledWith(samplePost, basicCaseId, abortCtrl.signal); + }); + }); + + it('post case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostComment>(() => + usePostComment(basicCaseId) + ); + await waitForNextUpdate(); + result.current.postComment(samplePost, updateCaseCallback); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoading: false, + isError: false, + postComment: result.current.postComment, + }); + }); + }); + + it('set isLoading to true when posting case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostComment>(() => + usePostComment(basicCaseId) + ); + await waitForNextUpdate(); + result.current.postComment(samplePost, updateCaseCallback); + + expect(result.current.isLoading).toBe(true); + }); + }); + + it('unhappy path', async () => { + const spyOnPostCase = jest.spyOn(api, 'postComment'); + spyOnPostCase.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostComment>(() => + usePostComment(basicCaseId) + ); + await waitForNextUpdate(); + result.current.postComment(samplePost, updateCaseCallback); + + expect(result.current).toEqual({ + isLoading: false, + isError: true, + postComment: result.current.postComment, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx index 207b05814717f..c6d34b5449977 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_comment.tsx @@ -41,7 +41,7 @@ const dataFetchReducer = (state: NewCommentState, action: Action): NewCommentSta } }; -interface UsePostComment extends NewCommentState { +export interface UsePostComment extends NewCommentState { postComment: (data: CommentRequest, updateCase: (newCase: Case) => void) => void; } diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.test.tsx new file mode 100644 index 0000000000000..b07a346a8da46 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.test.tsx @@ -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 { renderHook, act } from '@testing-library/react-hooks'; +import { + formatServiceRequestData, + usePostPushToService, + UsePostPushToService, +} from './use_post_push_to_service'; +import { basicCase, pushedCase, serviceConnector } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('usePostPushToService', () => { + const abortCtrl = new AbortController(); + const updateCase = jest.fn(); + const samplePush = { + caseId: pushedCase.id, + connectorName: 'sample', + connectorId: '22', + updateCase, + }; + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostPushToService>(() => + usePostPushToService() + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + serviceData: null, + pushedCaseData: null, + isLoading: false, + isError: false, + postPushToService: result.current.postPushToService, + }); + }); + }); + + it('calls pushCase with correct arguments', async () => { + const spyOnPushCase = jest.spyOn(api, 'pushCase'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostPushToService>(() => + usePostPushToService() + ); + await waitForNextUpdate(); + result.current.postPushToService(samplePush); + await waitForNextUpdate(); + expect(spyOnPushCase).toBeCalledWith( + samplePush.caseId, + { + connector_id: samplePush.connectorId, + connector_name: samplePush.connectorName, + external_id: serviceConnector.incidentId, + external_title: serviceConnector.number, + external_url: serviceConnector.url, + }, + abortCtrl.signal + ); + }); + }); + + it('calls pushToService with correct arguments', async () => { + const spyOnPushToService = jest.spyOn(api, 'pushToService'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostPushToService>(() => + usePostPushToService() + ); + await waitForNextUpdate(); + result.current.postPushToService(samplePush); + await waitForNextUpdate(); + expect(spyOnPushToService).toBeCalledWith( + samplePush.connectorId, + formatServiceRequestData(basicCase), + abortCtrl.signal + ); + }); + }); + + it('post push to service', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostPushToService>(() => + usePostPushToService() + ); + await waitForNextUpdate(); + result.current.postPushToService(samplePush); + await waitForNextUpdate(); + expect(result.current).toEqual({ + serviceData: serviceConnector, + pushedCaseData: pushedCase, + isLoading: false, + isError: false, + postPushToService: result.current.postPushToService, + }); + }); + }); + + it('set isLoading to true when deleting cases', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostPushToService>(() => + usePostPushToService() + ); + await waitForNextUpdate(); + result.current.postPushToService(samplePush); + expect(result.current.isLoading).toBe(true); + }); + }); + + it('unhappy path', async () => { + const spyOnPushToService = jest.spyOn(api, 'pushToService'); + spyOnPushToService.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UsePostPushToService>(() => + usePostPushToService() + ); + await waitForNextUpdate(); + result.current.postPushToService(samplePush); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + serviceData: null, + pushedCaseData: null, + isLoading: false, + isError: true, + postPushToService: result.current.postPushToService, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx index d9a32f26f7fe7..89e7e18cf0688 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_post_push_to_service.tsx @@ -68,7 +68,7 @@ interface PushToServiceRequest { updateCase: (newCase: Case) => void; } -interface UsePostPushToService extends PushToServiceState { +export interface UsePostPushToService extends PushToServiceState { postPushToService: ({ caseId, connectorId, updateCase }: PushToServiceRequest) => void; } @@ -131,7 +131,7 @@ export const usePostPushToService = (): UsePostPushToService => { return { ...state, postPushToService }; }; -const formatServiceRequestData = (myCase: Case): ServiceConnectorCaseParams => { +export const formatServiceRequestData = (myCase: Case): ServiceConnectorCaseParams => { const { id: caseId, createdAt, diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.test.tsx new file mode 100644 index 0000000000000..86cfc3459c595 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.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 { renderHook, act } from '@testing-library/react-hooks'; +import { useUpdateCase, UseUpdateCase, UpdateKey } from './use_update_case'; +import { basicCase } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useUpdateCase', () => { + const abortCtrl = new AbortController(); + const fetchCaseUserActions = jest.fn(); + const updateCase = jest.fn(); + const updateKey: UpdateKey = 'description'; + const sampleUpdate = { + fetchCaseUserActions, + updateKey, + updateValue: 'updated description', + updateCase, + version: basicCase.version, + }; + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCase>(() => + useUpdateCase({ caseId: basicCase.id }) + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoading: false, + isError: false, + updateKey: null, + updateCaseProperty: result.current.updateCaseProperty, + }); + }); + }); + + it('calls patchCase with correct arguments', async () => { + const spyOnPatchCase = jest.spyOn(api, 'patchCase'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCase>(() => + useUpdateCase({ caseId: basicCase.id }) + ); + await waitForNextUpdate(); + + result.current.updateCaseProperty(sampleUpdate); + await waitForNextUpdate(); + expect(spyOnPatchCase).toBeCalledWith( + basicCase.id, + { description: 'updated description' }, + basicCase.version, + abortCtrl.signal + ); + }); + }); + + it('patch case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCase>(() => + useUpdateCase({ caseId: basicCase.id }) + ); + await waitForNextUpdate(); + result.current.updateCaseProperty(sampleUpdate); + await waitForNextUpdate(); + expect(result.current).toEqual({ + updateKey: null, + isLoading: false, + isError: false, + updateCaseProperty: result.current.updateCaseProperty, + }); + expect(fetchCaseUserActions).toBeCalledWith(basicCase.id); + expect(updateCase).toBeCalledWith(basicCase); + }); + }); + + it('set isLoading to true when posting case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCase>(() => + useUpdateCase({ caseId: basicCase.id }) + ); + await waitForNextUpdate(); + result.current.updateCaseProperty(sampleUpdate); + + expect(result.current.isLoading).toBe(true); + expect(result.current.updateKey).toBe(updateKey); + }); + }); + + it('unhappy path', async () => { + const spyOnPatchCase = jest.spyOn(api, 'patchCase'); + spyOnPatchCase.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateCase>(() => + useUpdateCase({ caseId: basicCase.id }) + ); + await waitForNextUpdate(); + result.current.updateCaseProperty(sampleUpdate); + + expect(result.current).toEqual({ + updateKey: null, + isLoading: false, + isError: true, + updateCaseProperty: result.current.updateCaseProperty, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx index 4973deef4d91a..7ebbbba076c12 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_case.tsx @@ -12,7 +12,7 @@ import { patchCase } from './api'; import * as i18n from './translations'; import { Case } from './types'; -type UpdateKey = keyof Pick<CasePatchRequest, 'description' | 'status' | 'tags' | 'title'>; +export type UpdateKey = keyof Pick<CasePatchRequest, 'description' | 'status' | 'tags' | 'title'>; interface NewCaseState { isLoading: boolean; @@ -62,7 +62,7 @@ const dataFetchReducer = (state: NewCaseState, action: Action): NewCaseState => } }; -interface UseUpdateCase extends NewCaseState { +export interface UseUpdateCase extends NewCaseState { updateCaseProperty: (updates: UpdateByKey) => void; } export const useUpdateCase = ({ caseId }: { caseId: string }): UseUpdateCase => { diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.test.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.test.tsx new file mode 100644 index 0000000000000..5772ff4246866 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.test.tsx @@ -0,0 +1,116 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import { useUpdateComment, UseUpdateComment } from './use_update_comment'; +import { basicCase, basicCaseCommentPatch } from './mock'; +import * as api from './api'; + +jest.mock('./api'); + +describe('useUpdateComment', () => { + const abortCtrl = new AbortController(); + const fetchUserActions = jest.fn(); + const updateCase = jest.fn(); + const sampleUpdate = { + caseId: basicCase.id, + commentId: basicCase.comments[0].id, + commentUpdate: 'updated comment', + fetchUserActions, + updateCase, + version: basicCase.comments[0].version, + }; + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + }); + + it('init', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateComment>(() => + useUpdateComment() + ); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoadingIds: [], + isError: false, + patchComment: result.current.patchComment, + }); + }); + }); + + it('calls patchComment with correct arguments', async () => { + const spyOnPatchComment = jest.spyOn(api, 'patchComment'); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateComment>(() => + useUpdateComment() + ); + await waitForNextUpdate(); + + result.current.patchComment(sampleUpdate); + await waitForNextUpdate(); + expect(spyOnPatchComment).toBeCalledWith( + basicCase.id, + basicCase.comments[0].id, + 'updated comment', + basicCase.comments[0].version, + abortCtrl.signal + ); + }); + }); + + it('patch comment', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateComment>(() => + useUpdateComment() + ); + await waitForNextUpdate(); + result.current.patchComment(sampleUpdate); + await waitForNextUpdate(); + expect(result.current).toEqual({ + isLoadingIds: [], + isError: false, + patchComment: result.current.patchComment, + }); + expect(fetchUserActions).toBeCalled(); + expect(updateCase).toBeCalledWith(basicCaseCommentPatch); + }); + }); + + it('set isLoading to true when posting case', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateComment>(() => + useUpdateComment() + ); + await waitForNextUpdate(); + result.current.patchComment(sampleUpdate); + + expect(result.current.isLoadingIds).toEqual([basicCase.comments[0].id]); + }); + }); + + it('unhappy path', async () => { + const spyOnPatchComment = jest.spyOn(api, 'patchComment'); + spyOnPatchComment.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + await act(async () => { + const { result, waitForNextUpdate } = renderHook<string, UseUpdateComment>(() => + useUpdateComment() + ); + await waitForNextUpdate(); + result.current.patchComment(sampleUpdate); + + expect(result.current).toEqual({ + isLoadingIds: [], + isError: true, + patchComment: result.current.patchComment, + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx index faf9649a705c5..ffc5cffee7a55 100644 --- a/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/case/use_update_comment.tsx @@ -60,7 +60,7 @@ interface UpdateComment { version: string; } -interface UseUpdateComment extends CommentUpdateState { +export interface UseUpdateComment extends CommentUpdateState { patchComment: ({ caseId, commentId, commentUpdate, fetchUserActions }: UpdateComment) => void; } diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx deleted file mode 100644 index 64c6276fc1be2..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/__mock__/case_data.tsx +++ /dev/null @@ -1,226 +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 { CaseProps } from '../case_view'; -import { Case, Comment, SortFieldCase } from '../../../../containers/case/types'; -import { UseGetCasesState } from '../../../../containers/case/use_get_cases'; -import { UserAction, UserActionField } from '../../../../../../../../plugins/case/common/api/cases'; - -const updateCase = jest.fn(); -const fetchCase = jest.fn(); - -const basicCaseId = 'basic-case-id'; -const basicCommentId = 'basic-comment-id'; -const basicCreatedAt = '2020-02-20T23:06:33.798Z'; -const elasticUser = { - fullName: 'Leslie Knope', - username: 'lknope', - email: 'leslie.knope@elastic.co', -}; - -export const basicComment: Comment = { - comment: 'Solve this fast!', - id: basicCommentId, - createdAt: basicCreatedAt, - createdBy: elasticUser, - pushedAt: null, - pushedBy: null, - updatedAt: '2020-02-20T23:06:33.798Z', - updatedBy: { - username: 'elastic', - }, - version: 'WzQ3LDFc', -}; - -export const basicCase: Case = { - closedAt: null, - closedBy: null, - id: basicCaseId, - comments: [basicComment], - createdAt: '2020-02-13T19:44:23.627Z', - createdBy: elasticUser, - description: 'Security banana Issue', - externalService: null, - status: 'open', - tags: ['defacement'], - title: 'Another horrible breach!!', - totalComment: 1, - updatedAt: '2020-02-19T15:02:57.995Z', - updatedBy: { - username: 'elastic', - }, - version: 'WzQ3LDFd', -}; - -export const caseProps: CaseProps = { - caseId: basicCaseId, - userCanCrud: true, - caseData: basicCase, - fetchCase, - updateCase, -}; - -export const caseClosedProps: CaseProps = { - ...caseProps, - caseData: { - ...caseProps.caseData, - closedAt: '2020-02-20T23:06:33.798Z', - closedBy: { - username: 'elastic', - }, - status: 'closed', - }, -}; - -export const basicCaseClosed: Case = { - ...caseClosedProps.caseData, -}; - -const basicAction = { - actionAt: basicCreatedAt, - actionBy: elasticUser, - oldValue: null, - newValue: 'what a cool value', - caseId: basicCaseId, - commentId: null, -}; -export const caseUserActions = [ - { - ...basicAction, - actionBy: elasticUser, - actionField: ['comment'], - action: 'create', - actionId: 'tt', - }, -]; - -export const useGetCasesMockState: UseGetCasesState = { - data: { - countClosedCases: 0, - countOpenCases: 5, - cases: [ - basicCase, - { - closedAt: null, - closedBy: null, - id: '362a5c10-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:13.328Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: { - pushedAt: '2020-02-13T19:45:01.901Z', - pushedBy: 'elastic', - connectorId: 'string', - connectorName: 'string', - externalId: 'string', - externalTitle: 'string', - externalUrl: 'string', - }, - status: 'open', - tags: ['phishing'], - title: 'Bad email', - totalComment: 0, - updatedAt: '2020-02-13T15:45:01.901Z', - updatedBy: { username: 'elastic' }, - version: 'WzQ3LDFd', - }, - { - closedAt: null, - closedBy: null, - id: '34f8b9e0-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:11.328Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: { - pushedAt: '2020-02-13T19:45:01.901Z', - pushedBy: 'elastic', - connectorId: 'string', - connectorName: 'string', - externalId: 'string', - externalTitle: 'string', - externalUrl: 'string', - }, - status: 'open', - tags: ['phishing'], - title: 'Bad email', - totalComment: 0, - updatedAt: '2020-02-14T19:45:01.901Z', - updatedBy: { username: 'elastic' }, - version: 'WzQ3LDFd', - }, - { - closedAt: '2020-02-13T19:44:13.328Z', - closedBy: { username: 'elastic' }, - id: '31890e90-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:05.563Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: null, - status: 'closed', - tags: ['phishing'], - title: 'Uh oh', - totalComment: 0, - updatedAt: null, - updatedBy: null, - version: 'WzQ3LDFd', - }, - { - closedAt: null, - closedBy: null, - id: '2f5b3210-4e99-11ea-9290-35d05cb55c15', - createdAt: '2020-02-13T19:44:01.901Z', - createdBy: { username: 'elastic' }, - comments: [], - description: 'Security banana Issue', - externalService: null, - status: 'open', - tags: ['phishing'], - title: 'Uh oh', - totalComment: 0, - updatedAt: null, - updatedBy: null, - version: 'WzQ3LDFd', - }, - ], - page: 1, - perPage: 5, - total: 10, - }, - loading: [], - selectedCases: [], - isError: false, - queryParams: { - page: 1, - perPage: 5, - sortField: SortFieldCase.createdAt, - sortOrder: 'desc', - }, - filterOptions: { search: '', reporters: [], tags: [], status: 'open' }, -}; - -const basicPush = { - connector_id: 'connector_id', - connector_name: 'connector name', - external_id: 'external_id', - external_title: 'external title', - external_url: 'basicPush.com', - pushed_at: basicCreatedAt, - pushed_by: elasticUser, -}; -export const getUserAction = (af: UserActionField, a: UserAction) => ({ - ...basicAction, - actionId: `${af[0]}-${a}`, - actionField: af, - action: a, - commentId: af[0] === 'comment' ? basicCommentId : null, - newValue: - a === 'push-to-service' && af[0] === 'pushed' - ? JSON.stringify(basicPush) - : basicAction.newValue, -}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx index e008b94ab9e16..31c795c05edd5 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/columns.test.tsx @@ -9,7 +9,7 @@ import { mount } from 'enzyme'; import { ServiceNowColumn } from './columns'; -import { useGetCasesMockState } from '../__mock__/case_data'; +import { useGetCasesMockState } from '../../../../containers/case/mock'; describe('ServiceNowColumn ', () => { it('Not pushed render', () => { diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx index f65736e7cd109..58d0c1b0faaf3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.test.tsx @@ -9,7 +9,7 @@ import { mount } from 'enzyme'; import moment from 'moment-timezone'; import { AllCases } from './'; import { TestProviders } from '../../../../mock'; -import { useGetCasesMockState } from '../__mock__/case_data'; +import { useGetCasesMockState } from '../../../../containers/case/mock'; import * as i18n from './translations'; import { getEmptyTagValue } from '../../../../components/empty_value'; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx index b0ff3dbada6c9..c50b7d8c17abc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/all_cases/index.tsx @@ -131,11 +131,11 @@ export const AllCases = React.memo<AllCasesProps>(({ userCanCrud }) => { const [deleteBulk, setDeleteBulk] = useState<DeleteCase[]>([]); const refreshCases = useCallback(() => { - refetchCases(filterOptions, queryParams); + refetchCases(); fetchCasesStatus(); setSelectedCases([]); setDeleteBulk([]); - }, [filterOptions, queryParams]); + }, []); useEffect(() => { if (isDeleted) { diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx index 8a25a2121104d..8b6ee76dd783d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/actions.test.tsx @@ -9,7 +9,7 @@ import { mount } from 'enzyme'; import { useDeleteCases } from '../../../../containers/case/use_delete_cases'; import { TestProviders } from '../../../../mock'; -import { basicCase } from '../__mock__/case_data'; +import { basicCase } from '../../../../containers/case/mock'; import { CaseViewActions } from './actions'; jest.mock('../../../../containers/case/use_delete_cases'); const useDeleteCasesMock = useDeleteCases as jest.Mock; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx index 3721a5a727ca5..7ce9d7b8533e4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/index.test.tsx @@ -8,13 +8,8 @@ import React from 'react'; import { mount } from 'enzyme'; import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router'; -import { CaseComponent, CaseView } from './'; -import { - basicCaseClosed, - caseClosedProps, - caseProps, - caseUserActions, -} from '../__mock__/case_data'; +import { CaseComponent, CaseProps, CaseView } from './'; +import { basicCase, basicCaseClosed, caseUserActions } from '../../../../containers/case/mock'; import { TestProviders } from '../../../../mock'; import { useUpdateCase } from '../../../../containers/case/use_update_case'; import { useGetCase } from '../../../../containers/case/use_get_case'; @@ -29,6 +24,19 @@ const useUpdateCaseMock = useUpdateCase as jest.Mock; const useGetCaseUserActionsMock = useGetCaseUserActions as jest.Mock; const usePushToServiceMock = usePushToService as jest.Mock; +export const caseProps: CaseProps = { + caseId: basicCase.id, + userCanCrud: true, + caseData: basicCase, + fetchCase: jest.fn(), + updateCase: jest.fn(), +}; + +export const caseClosedProps: CaseProps = { + ...caseProps, + caseData: basicCaseClosed, +}; + describe('CaseView ', () => { const updateCaseProperty = jest.fn(); const fetchCaseUserActions = jest.fn(); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts index 17132b9610754..70b8035db5c16 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/case_view/translations.ts @@ -118,3 +118,6 @@ export const EMAIL_BODY = (caseUrl: string) => values: { caseUrl }, defaultMessage: 'Case reference: {caseUrl}', }); +export const UNKNOWN = i18n.translate('xpack.siem.case.caseView.unknown', { + defaultMessage: 'Unknown', +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx index 5c342538f0feb..e34981286bc81 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/helpers.test.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { getUserAction } from '../__mock__/case_data'; +import { getUserAction } from '../../../../containers/case/mock'; import { getLabelTitle } from './helpers'; import * as i18n from '../case_view/translations'; import { mount } from 'enzyme'; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx index 0d8cd729b4a1d..1c71260422d4b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.test.tsx @@ -10,7 +10,7 @@ import { mount } from 'enzyme'; import { Router, routeData, mockHistory, mockLocation } from '../__mock__/router'; import { getFormMock } from '../__mock__/form'; import { useUpdateComment } from '../../../../containers/case/use_update_comment'; -import { basicCase, getUserAction } from '../__mock__/case_data'; +import { basicCase, getUserAction } from '../../../../containers/case/mock'; import { UserActionTree } from './'; import { TestProviders } from '../../../../mock'; import { useFormMock } from '../create/index.test'; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx index f8f3f0651fa3c..d1e8eb3f6306b 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/index.tsx @@ -179,7 +179,7 @@ export const UserActionTree = React.memo( markdown={MarkdownDescription} onEdit={handleManageMarkdownEditId.bind(null, DESCRIPTION_ID)} onQuote={handleManageQuote.bind(null, caseData.description)} - username={caseData.createdBy.username ?? 'Unknown'} + username={caseData.createdBy.username ?? i18n.UNKNOWN} /> {caseUserActions.map((action, index) => { diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx index e2189367068ca..8a1e8a80f664d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { mount } from 'enzyme'; import copy from 'copy-to-clipboard'; import { Router, routeData, mockHistory } from '../__mock__/router'; -import { caseUserActions as basicUserActions } from '../__mock__/case_data'; +import { caseUserActions as basicUserActions } from '../../../../containers/case/mock'; import { UserActionTitle } from './user_action_title'; import { TestProviders } from '../../../../mock'; diff --git a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx index a1edbab7e1fa2..fc2a74466dedc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/components/user_action_tree/user_action_title.tsx @@ -43,7 +43,7 @@ interface UserActionTitleProps { linkId?: string | null; fullName?: string | null; updatedAt?: string | null; - username: string; + username?: string | null; onEdit?: (id: string) => void; onQuote?: (id: string) => void; outlineComment?: (id: string) => void; @@ -63,7 +63,7 @@ export const UserActionTitle = ({ onQuote, outlineComment, updatedAt, - username, + username = i18n.UNKNOWN, }: UserActionTitleProps) => { const { detailName: caseId } = useParams(); const urlSearch = useGetUrlSearch(navTabs.case); diff --git a/x-pack/plugins/case/common/api/cases/case.ts b/x-pack/plugins/case/common/api/cases/case.ts index 3c5d3405f395e..1f08a41024905 100644 --- a/x-pack/plugins/case/common/api/cases/case.ts +++ b/x-pack/plugins/case/common/api/cases/case.ts @@ -167,6 +167,7 @@ export type CasesResponse = rt.TypeOf<typeof CasesResponseRt>; export type CasesFindResponse = rt.TypeOf<typeof CasesFindResponseRt>; export type CasePatchRequest = rt.TypeOf<typeof CasePatchRequestRt>; export type CasesPatchRequest = rt.TypeOf<typeof CasesPatchRequestRt>; +export type Status = rt.TypeOf<typeof StatusRt>; export type CaseExternalServiceRequest = rt.TypeOf<typeof CaseExternalServiceRequestRt>; export type ServiceConnectorCaseParams = rt.TypeOf<typeof ServiceConnectorCaseParamsRt>; export type ServiceConnectorCaseResponse = rt.TypeOf<typeof ServiceConnectorCaseResponseRt>; From 287d477f211e2ed7b92f78812c8f065c6e779de6 Mon Sep 17 00:00:00 2001 From: Christos Nasikas <christos.nasikas@elastic.co> Date: Tue, 14 Apr 2020 22:09:03 +0300 Subject: [PATCH 108/121] [SIEM][CASE] Tests for server's configuration API (#63099) * Test utils * Test get_configure * Test post_configure * Test get_connectors * Test patch_configure * Improve test * Fixes Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../__fixtures__/create_mock_so_repository.ts | 70 ++- .../api/__fixtures__/mock_saved_objects.ts | 32 +- .../routes/api/__fixtures__/route_contexts.ts | 6 + .../routes/api/__mocks__/request_responses.ts | 64 +++ .../api/cases/configure/get_configure.test.ts | 112 +++++ .../cases/configure/get_connectors.test.ts | 63 +++ .../cases/configure/patch_configure.test.ts | 156 +++++++ .../cases/configure/post_configure.test.ts | 294 ++++++++++++ .../case/server/routes/api/utils.test.ts | 418 ++++++++++++++++++ 9 files changed, 1213 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/case/server/routes/api/__mocks__/request_responses.ts create mode 100644 x-pack/plugins/case/server/routes/api/cases/configure/get_configure.test.ts create mode 100644 x-pack/plugins/case/server/routes/api/cases/configure/get_connectors.test.ts create mode 100644 x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.test.ts create mode 100644 x-pack/plugins/case/server/routes/api/cases/configure/post_configure.test.ts create mode 100644 x-pack/plugins/case/server/routes/api/utils.test.ts diff --git a/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts b/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts index 95cd66a9c51a2..e83dafc68ee69 100644 --- a/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts +++ b/x-pack/plugins/case/server/routes/api/__fixtures__/create_mock_so_repository.ts @@ -11,14 +11,20 @@ import { SavedObjectsBulkUpdateObject, } from 'src/core/server'; -import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT } from '../../../saved_object_types'; +import { + CASE_COMMENT_SAVED_OBJECT, + CASE_SAVED_OBJECT, + CASE_CONFIGURE_SAVED_OBJECT, +} from '../../../saved_object_types'; export const createMockSavedObjectsRepository = ({ caseSavedObject = [], caseCommentSavedObject = [], + caseConfigureSavedObject = [], }: { caseSavedObject?: any[]; caseCommentSavedObject?: any[]; + caseConfigureSavedObject?: any[]; }) => { const mockSavedObjectsClientContract = ({ bulkGet: jest.fn((objects: SavedObjectsBulkGetObject[]) => { @@ -70,6 +76,7 @@ export const createMockSavedObjectsRepository = ({ } return result[0]; } + const result = caseSavedObject.filter(s => s.id === id); if (!result.length) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); @@ -81,6 +88,23 @@ export const createMockSavedObjectsRepository = ({ throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing'); } + if ( + findArgs.type === CASE_CONFIGURE_SAVED_OBJECT && + caseConfigureSavedObject[0] && + caseConfigureSavedObject[0].id === 'throw-error-find' + ) { + throw SavedObjectsErrorHelpers.createGenericNotFoundError('Error thrown for testing'); + } + + if (findArgs.type === CASE_CONFIGURE_SAVED_OBJECT) { + return { + page: 1, + per_page: 5, + total: caseConfigureSavedObject.length, + saved_objects: caseConfigureSavedObject, + }; + } + if (findArgs.type === CASE_COMMENT_SAVED_OBJECT) { return { page: 1, @@ -101,6 +125,13 @@ export const createMockSavedObjectsRepository = ({ throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing'); } + if ( + type === CASE_CONFIGURE_SAVED_OBJECT && + attributes.connector_id === 'throw-error-create' + ) { + throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing'); + } + if (type === CASE_COMMENT_SAVED_OBJECT) { const newCommentObj = { type, @@ -113,6 +144,20 @@ export const createMockSavedObjectsRepository = ({ caseCommentSavedObject = [...caseCommentSavedObject, newCommentObj]; return newCommentObj; } + + if (type === CASE_CONFIGURE_SAVED_OBJECT) { + const newConfiguration = { + type, + id: 'mock-configuration', + attributes, + updated_at: '2020-04-09T09:43:51.778Z', + version: attributes.connector_id === 'no-version' ? undefined : 'WzksMV0=', + }; + + caseConfigureSavedObject = [newConfiguration]; + return newConfiguration; + } + return { type, id: 'mock-it', @@ -143,6 +188,16 @@ export const createMockSavedObjectsRepository = ({ } } + if (type === CASE_CONFIGURE_SAVED_OBJECT) { + return { + id, + type, + updated_at: '2019-11-22T22:50:55.191Z', + attributes, + version: attributes.connector_id === 'no-version' ? undefined : 'WzE3LDFd', + }; + } + return { id, type, @@ -153,16 +208,29 @@ export const createMockSavedObjectsRepository = ({ }), delete: jest.fn((type: string, id: string) => { let result = caseSavedObject.filter(s => s.id === id); + if (type === CASE_COMMENT_SAVED_OBJECT) { result = caseCommentSavedObject.filter(s => s.id === id); } + + if (type === CASE_CONFIGURE_SAVED_OBJECT) { + result = caseConfigureSavedObject.filter(s => s.id === id); + } + if (type === CASE_COMMENT_SAVED_OBJECT && id === 'bad-guy') { throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing'); } + if (!result.length) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } + if ( + type === CASE_CONFIGURE_SAVED_OBJECT && + caseConfigureSavedObject[0].id === 'throw-error-delete' + ) { + throw new Error('Error thrown for testing'); + } return {}; }), deleteByNamespace: jest.fn(), diff --git a/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts b/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts index 03da50f886fd5..75e793a80272f 100644 --- a/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts +++ b/x-pack/plugins/case/server/routes/api/__fixtures__/mock_saved_objects.ts @@ -5,7 +5,11 @@ */ import { SavedObject } from 'kibana/server'; -import { CaseAttributes, CommentAttributes } from '../../../../common/api'; +import { + CaseAttributes, + CommentAttributes, + CasesConfigureAttributes, +} from '../../../../common/api'; export const mockCases: Array<SavedObject<CaseAttributes>> = [ { @@ -225,7 +229,33 @@ export const mockCaseComments: Array<SavedObject<CommentAttributes>> = [ }, ], updated_at: '2019-11-25T22:32:30.608Z', + version: 'WzYsMV0=', + }, +]; +export const mockCaseConfigure: Array<SavedObject<CasesConfigureAttributes>> = [ + { + type: 'cases-configure', + id: 'mock-configuration-1', + attributes: { + connector_id: '123', + connector_name: 'My connector', + closure_type: 'close-by-user', + created_at: '2020-04-09T09:43:51.778Z', + created_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + updated_at: '2020-04-09T09:43:51.778Z', + updated_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + }, + references: [], + updated_at: '2020-04-09T09:43:51.778Z', version: 'WzYsMV0=', }, ]; diff --git a/x-pack/plugins/case/server/routes/api/__fixtures__/route_contexts.ts b/x-pack/plugins/case/server/routes/api/__fixtures__/route_contexts.ts index b1881e394e796..d947ffbaf181d 100644 --- a/x-pack/plugins/case/server/routes/api/__fixtures__/route_contexts.ts +++ b/x-pack/plugins/case/server/routes/api/__fixtures__/route_contexts.ts @@ -5,13 +5,19 @@ */ import { RequestHandlerContext } from 'src/core/server'; +import { actionsClientMock } from '../../../../../actions/server/mocks'; +import { getActions } from '../__mocks__/request_responses'; export const createRouteContext = (client: any) => { + const actionsMock = actionsClientMock.create(); + actionsMock.getAll.mockImplementation(() => Promise.resolve(getActions())); + return ({ core: { savedObjects: { client, }, }, + actions: { getActionsClient: () => actionsMock }, } as unknown) as RequestHandlerContext; }; diff --git a/x-pack/plugins/case/server/routes/api/__mocks__/request_responses.ts b/x-pack/plugins/case/server/routes/api/__mocks__/request_responses.ts new file mode 100644 index 0000000000000..846013674986e --- /dev/null +++ b/x-pack/plugins/case/server/routes/api/__mocks__/request_responses.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { CasePostRequest, CasesConfigureRequest } from '../../../../common/api'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { FindActionResult } from '../../../../../actions/server/types'; + +export const newCase: CasePostRequest = { + title: 'My new case', + description: 'A description', + tags: ['new', 'case'], +}; + +export const getActions = (): FindActionResult[] => [ + { + id: 'e90075a5-c386-41e3-ae21-ba4e61510695', + actionTypeId: '.webhook', + name: 'Test', + config: { + method: 'post', + url: 'https://example.com', + headers: null, + }, + isPreconfigured: false, + referencedByCount: 0, + }, + { + id: 'd611af27-3532-4da9-8034-271fee81d634', + actionTypeId: '.servicenow', + name: 'ServiceNow', + config: { + casesConfiguration: { + mapping: [ + { + source: 'title', + target: 'short_description', + actionType: 'overwrite', + }, + { + source: 'description', + target: 'description', + actionType: 'overwrite', + }, + { + source: 'comments', + target: 'comments', + actionType: 'append', + }, + ], + }, + apiUrl: 'https://dev102283.service-now.com', + }, + isPreconfigured: false, + referencedByCount: 0, + }, +]; + +export const newConfiguration: CasesConfigureRequest = { + connector_id: '456', + connector_name: 'My connector 2', + closure_type: 'close-by-pushing', +}; diff --git a/x-pack/plugins/case/server/routes/api/cases/configure/get_configure.test.ts b/x-pack/plugins/case/server/routes/api/cases/configure/get_configure.test.ts new file mode 100644 index 0000000000000..66d39c3f11d28 --- /dev/null +++ b/x-pack/plugins/case/server/routes/api/cases/configure/get_configure.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 { kibanaResponseFactory, RequestHandler } from 'src/core/server'; +import { httpServerMock } from 'src/core/server/mocks'; + +import { + createMockSavedObjectsRepository, + createRoute, + createRouteContext, +} from '../../__fixtures__'; + +import { mockCaseConfigure } from '../../__fixtures__/mock_saved_objects'; +import { initGetCaseConfigure } from './get_configure'; + +describe('GET configuration', () => { + let routeHandler: RequestHandler<any, any, any>; + beforeAll(async () => { + routeHandler = await createRoute(initGetCaseConfigure, 'get'); + }); + + it('returns the configuration', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'get', + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(200); + expect(res.payload).toEqual({ + ...mockCaseConfigure[0].attributes, + version: mockCaseConfigure[0].version, + }); + }); + + it('handles undefined version correctly', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'get', + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: [{ ...mockCaseConfigure[0], version: undefined }], + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(200); + expect(res.payload).toEqual({ + connector_id: '123', + connector_name: 'My connector', + closure_type: 'close-by-user', + created_at: '2020-04-09T09:43:51.778Z', + created_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + updated_at: '2020-04-09T09:43:51.778Z', + updated_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + version: '', + }); + }); + + it('returns an empty object when there is no configuration', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'get', + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: [], + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(200); + expect(res.payload).toEqual({}); + }); + + it('returns an error if find throws an error', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'get', + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: [{ ...mockCaseConfigure[0], id: 'throw-error-find' }], + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(404); + expect(res.payload.isBoom).toEqual(true); + }); +}); diff --git a/x-pack/plugins/case/server/routes/api/cases/configure/get_connectors.test.ts b/x-pack/plugins/case/server/routes/api/cases/configure/get_connectors.test.ts new file mode 100644 index 0000000000000..62edaa0a4792a --- /dev/null +++ b/x-pack/plugins/case/server/routes/api/cases/configure/get_connectors.test.ts @@ -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 { kibanaResponseFactory, RequestHandler } from 'src/core/server'; +import { httpServerMock } from 'src/core/server/mocks'; + +import { + createMockSavedObjectsRepository, + createRoute, + createRouteContext, +} from '../../__fixtures__'; + +import { mockCaseConfigure } from '../../__fixtures__/mock_saved_objects'; +import { initCaseConfigureGetActionConnector } from './get_connectors'; +import { getActions } from '../../__mocks__/request_responses'; + +describe('GET connectors', () => { + let routeHandler: RequestHandler<any, any, any>; + beforeAll(async () => { + routeHandler = await createRoute(initCaseConfigureGetActionConnector, 'get'); + }); + + it('returns the connectors', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure/connectors/_find', + method: 'get', + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(200); + expect(res.payload).toEqual( + getActions().filter(action => action.actionTypeId === '.servicenow') + ); + }); + + it('it throws an error when actions client is null', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure/connectors/_find', + method: 'get', + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + context.actions = undefined; + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(404); + expect(res.payload.isBoom).toEqual(true); + }); +}); diff --git a/x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.test.ts b/x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.test.ts new file mode 100644 index 0000000000000..5b3d68a258664 --- /dev/null +++ b/x-pack/plugins/case/server/routes/api/cases/configure/patch_configure.test.ts @@ -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 { kibanaResponseFactory, RequestHandler } from 'src/core/server'; +import { httpServerMock } from 'src/core/server/mocks'; + +import { + createMockSavedObjectsRepository, + createRoute, + createRouteContext, +} from '../../__fixtures__'; + +import { mockCaseConfigure } from '../../__fixtures__/mock_saved_objects'; +import { initPatchCaseConfigure } from './patch_configure'; + +describe('PATCH configuration', () => { + let routeHandler: RequestHandler<any, any, any>; + + beforeAll(async () => { + routeHandler = await createRoute(initPatchCaseConfigure, 'patch'); + const spyOnDate = jest.spyOn(global, 'Date') as jest.SpyInstance<{}, []>; + spyOnDate.mockImplementation(() => ({ + toISOString: jest.fn().mockReturnValue('2020-04-09T09:43:51.778Z'), + })); + }); + + it('patch configuration', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'patch', + body: { + closure_type: 'close-by-pushing', + version: mockCaseConfigure[0].version, + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(200); + expect(res.payload).toEqual( + expect.objectContaining({ + ...mockCaseConfigure[0].attributes, + closure_type: 'close-by-pushing', + updated_at: '2020-04-09T09:43:51.778Z', + updated_by: { email: 'd00d@awesome.com', full_name: 'Awesome D00d', username: 'awesome' }, + version: 'WzE3LDFd', + }) + ); + }); + + it('patch configuration without authentication', async () => { + routeHandler = await createRoute(initPatchCaseConfigure, 'patch', true); + + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'patch', + body: { + closure_type: 'close-by-pushing', + version: mockCaseConfigure[0].version, + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(200); + expect(res.payload).toEqual( + expect.objectContaining({ + ...mockCaseConfigure[0].attributes, + closure_type: 'close-by-pushing', + updated_at: '2020-04-09T09:43:51.778Z', + updated_by: { email: null, full_name: null, username: null }, + version: 'WzE3LDFd', + }) + ); + }); + + it('throw error when configuration have not being created', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'patch', + body: { + closure_type: 'close-by-pushing', + version: mockCaseConfigure[0].version, + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: [], + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(409); + expect(res.payload.isBoom).toEqual(true); + }); + + it('throw error when the versions are different', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'patch', + body: { + closure_type: 'close-by-pushing', + version: 'different-version', + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(409); + expect(res.payload.isBoom).toEqual(true); + }); + + it('handles undefined version correctly', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'patch', + body: { connector_id: 'no-version', version: mockCaseConfigure[0].version }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.payload).toEqual( + expect.objectContaining({ + version: '', + }) + ); + }); +}); diff --git a/x-pack/plugins/case/server/routes/api/cases/configure/post_configure.test.ts b/x-pack/plugins/case/server/routes/api/cases/configure/post_configure.test.ts new file mode 100644 index 0000000000000..7e40cad5b1298 --- /dev/null +++ b/x-pack/plugins/case/server/routes/api/cases/configure/post_configure.test.ts @@ -0,0 +1,294 @@ +/* + * 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 { kibanaResponseFactory, RequestHandler } from 'src/core/server'; +import { httpServerMock } from 'src/core/server/mocks'; + +import { + createMockSavedObjectsRepository, + createRoute, + createRouteContext, +} from '../../__fixtures__'; + +import { mockCaseConfigure } from '../../__fixtures__/mock_saved_objects'; +import { initPostCaseConfigure } from './post_configure'; +import { newConfiguration } from '../../__mocks__/request_responses'; + +describe('POST configuration', () => { + let routeHandler: RequestHandler<any, any, any>; + + beforeAll(async () => { + routeHandler = await createRoute(initPostCaseConfigure, 'post'); + const spyOnDate = jest.spyOn(global, 'Date') as jest.SpyInstance<{}, []>; + spyOnDate.mockImplementation(() => ({ + toISOString: jest.fn().mockReturnValue('2020-04-09T09:43:51.778Z'), + })); + }); + + it('create configuration', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: newConfiguration, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(200); + expect(res.payload).toEqual( + expect.objectContaining({ + connector_id: '456', + connector_name: 'My connector 2', + closure_type: 'close-by-pushing', + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: 'd00d@awesome.com', full_name: 'Awesome D00d', username: 'awesome' }, + updated_at: null, + updated_by: null, + }) + ); + }); + + it('create configuration without authentication', async () => { + routeHandler = await createRoute(initPostCaseConfigure, 'post', true); + + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: newConfiguration, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(200); + expect(res.payload).toEqual( + expect.objectContaining({ + connector_id: '456', + connector_name: 'My connector 2', + closure_type: 'close-by-pushing', + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: null, full_name: null, username: null }, + updated_at: null, + updated_by: null, + }) + ); + }); + + it('throws when missing connector_id', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: { + connector_name: 'My connector 2', + closure_type: 'close-by-pushing', + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(400); + expect(res.payload.isBoom).toEqual(true); + }); + + it('throws when missing connector_name', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: { + connector_id: '456', + closure_type: 'close-by-pushing', + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(400); + expect(res.payload.isBoom).toEqual(true); + }); + + it('throws when missing closure_type', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: { + connector_id: '456', + connector_name: 'My connector 2', + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(400); + expect(res.payload.isBoom).toEqual(true); + }); + + it('it deletes the previous configuration', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: newConfiguration, + }); + + const savedObjectRepository = createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }); + + const context = createRouteContext(savedObjectRepository); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(200); + expect(savedObjectRepository.delete.mock.calls[0][1]).toBe(mockCaseConfigure[0].id); + }); + + it('it does NOT delete when not found', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: newConfiguration, + }); + + const savedObjectRepository = createMockSavedObjectsRepository({ + caseConfigureSavedObject: [], + }); + + const context = createRouteContext(savedObjectRepository); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(200); + expect(savedObjectRepository.delete).not.toHaveBeenCalled(); + }); + + it('it deletes all configuration', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: newConfiguration, + }); + + const savedObjectRepository = createMockSavedObjectsRepository({ + caseConfigureSavedObject: [ + mockCaseConfigure[0], + { ...mockCaseConfigure[0], id: 'mock-configuration-2' }, + ], + }); + + const context = createRouteContext(savedObjectRepository); + + const res = await routeHandler(context, req, kibanaResponseFactory); + + expect(res.status).toEqual(200); + expect(savedObjectRepository.delete.mock.calls[0][1]).toBe(mockCaseConfigure[0].id); + expect(savedObjectRepository.delete.mock.calls[1][1]).toBe('mock-configuration-2'); + }); + + it('returns an error if find throws an error', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: newConfiguration, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: [{ ...mockCaseConfigure[0], id: 'throw-error-find' }], + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(404); + expect(res.payload.isBoom).toEqual(true); + }); + + it('returns an error if delete throws an error', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: newConfiguration, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: [{ ...mockCaseConfigure[0], id: 'throw-error-delete' }], + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(500); + expect(res.payload.isBoom).toEqual(true); + }); + + it('returns an error if post throws an error', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: { + connector_id: 'throw-error-create', + connector_name: 'My connector 2', + closure_type: 'close-by-pushing', + }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(400); + expect(res.payload.isBoom).toEqual(true); + }); + + it('handles undefined version correctly', async () => { + const req = httpServerMock.createKibanaRequest({ + path: '/api/cases/configure', + method: 'post', + body: { ...newConfiguration, connector_id: 'no-version' }, + }); + + const context = createRouteContext( + createMockSavedObjectsRepository({ + caseConfigureSavedObject: mockCaseConfigure, + }) + ); + + const res = await routeHandler(context, req, kibanaResponseFactory); + expect(res.status).toEqual(200); + expect(res.payload).toEqual( + expect.objectContaining({ + version: '', + }) + ); + }); +}); diff --git a/x-pack/plugins/case/server/routes/api/utils.test.ts b/x-pack/plugins/case/server/routes/api/utils.test.ts new file mode 100644 index 0000000000000..a22f4db30bf8d --- /dev/null +++ b/x-pack/plugins/case/server/routes/api/utils.test.ts @@ -0,0 +1,418 @@ +/* + * 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 { + transformNewCase, + transformNewComment, + wrapError, + transformCases, + flattenCaseSavedObjects, + flattenCaseSavedObject, + flattenCommentSavedObjects, + transformComments, + flattenCommentSavedObject, + sortToSnake, +} from './utils'; +import { newCase } from './__mocks__/request_responses'; +import { isBoom, boomify } from 'boom'; +import { mockCases, mockCaseComments } from './__fixtures__/mock_saved_objects'; + +describe('Utils', () => { + describe('transformNewCase', () => { + it('transform correctly', () => { + const myCase = { + newCase, + createdDate: '2020-04-09T09:43:51.778Z', + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }; + + const res = transformNewCase(myCase); + + expect(res).toEqual({ + ...myCase.newCase, + closed_at: null, + closed_by: null, + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: 'elastic@elastic.co', full_name: 'Elastic', username: 'elastic' }, + external_service: null, + status: 'open', + updated_at: null, + updated_by: null, + }); + }); + + it('transform correctly without optional fields', () => { + const myCase = { + newCase, + createdDate: '2020-04-09T09:43:51.778Z', + }; + + const res = transformNewCase(myCase); + + expect(res).toEqual({ + ...myCase.newCase, + closed_at: null, + closed_by: null, + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: undefined, full_name: undefined, username: undefined }, + external_service: null, + status: 'open', + updated_at: null, + updated_by: null, + }); + }); + + it('transform correctly with optional fields as null', () => { + const myCase = { + newCase, + createdDate: '2020-04-09T09:43:51.778Z', + email: null, + full_name: null, + username: null, + }; + + const res = transformNewCase(myCase); + + expect(res).toEqual({ + ...myCase.newCase, + closed_at: null, + closed_by: null, + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: null, full_name: null, username: null }, + external_service: null, + status: 'open', + updated_at: null, + updated_by: null, + }); + }); + }); + + describe('transformNewComment', () => { + it('transforms correctly', () => { + const comment = { + comment: 'A comment', + createdDate: '2020-04-09T09:43:51.778Z', + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }; + + const res = transformNewComment(comment); + expect(res).toEqual({ + comment: 'A comment', + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: 'elastic@elastic.co', full_name: 'Elastic', username: 'elastic' }, + pushed_at: null, + pushed_by: null, + updated_at: null, + updated_by: null, + }); + }); + + it('transform correctly without optional fields', () => { + const comment = { + comment: 'A comment', + createdDate: '2020-04-09T09:43:51.778Z', + }; + + const res = transformNewComment(comment); + + expect(res).toEqual({ + comment: 'A comment', + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: undefined, full_name: undefined, username: undefined }, + pushed_at: null, + pushed_by: null, + updated_at: null, + updated_by: null, + }); + }); + + it('transform correctly with optional fields as null', () => { + const comment = { + comment: 'A comment', + createdDate: '2020-04-09T09:43:51.778Z', + email: null, + full_name: null, + username: null, + }; + + const res = transformNewComment(comment); + + expect(res).toEqual({ + comment: 'A comment', + created_at: '2020-04-09T09:43:51.778Z', + created_by: { email: null, full_name: null, username: null }, + pushed_at: null, + pushed_by: null, + updated_at: null, + updated_by: null, + }); + }); + }); + + describe('wrapError', () => { + it('wraps an error', () => { + const error = new Error('Something happened'); + const res = wrapError(error); + + expect(isBoom(res.body as Error)).toBe(true); + }); + + it('it set statusCode to 500', () => { + const error = new Error('Something happened'); + const res = wrapError(error); + + expect(res.statusCode).toBe(500); + }); + + it('it set statusCode to errors status code', () => { + const error = new Error('Something happened') as any; + error.statusCode = 404; + const res = wrapError(error); + + expect(res.statusCode).toBe(404); + }); + + it('it accepts a boom error', () => { + const error = boomify(new Error('Something happened')); + const res = wrapError(error); + + // Utils returns the same boom error as body + expect(res.body).toBe(error); + }); + + it('it accepts a boom error with status code', () => { + const error = boomify(new Error('Something happened'), { statusCode: 404 }); + const res = wrapError(error); + + expect(res.statusCode).toBe(404); + }); + + it('it returns empty headers', () => { + const error = new Error('Something happened'); + const res = wrapError(error); + + expect(res.headers).toEqual({}); + }); + }); + + describe('transformCases', () => { + it('transforms correctly', () => { + const totalCommentsByCase = [ + { caseId: mockCases[0].id, totalComments: 2 }, + { caseId: mockCases[1].id, totalComments: 2 }, + { caseId: mockCases[2].id, totalComments: 2 }, + { caseId: mockCases[3].id, totalComments: 2 }, + ]; + + const res = transformCases( + { saved_objects: mockCases, total: mockCases.length, per_page: 10, page: 1 }, + 2, + 2, + totalCommentsByCase + ); + expect(res).toEqual({ + page: 1, + per_page: 10, + total: mockCases.length, + cases: flattenCaseSavedObjects(mockCases, totalCommentsByCase), + count_open_cases: 2, + count_closed_cases: 2, + }); + }); + }); + + describe('flattenCaseSavedObjects', () => { + it('flattens correctly', () => { + const totalCommentsByCase = [{ caseId: mockCases[0].id, totalComments: 2 }]; + + const res = flattenCaseSavedObjects([mockCases[0]], totalCommentsByCase); + expect(res).toEqual([ + { + id: 'mock-id-1', + closed_at: null, + closed_by: null, + created_at: '2019-11-25T21:54:48.952Z', + created_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + description: 'This is a brand new case of a bad meanie defacing data', + external_service: null, + title: 'Super Bad Security Issue', + status: 'open', + tags: ['defacement'], + updated_at: '2019-11-25T21:54:48.952Z', + updated_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + comments: [], + totalComment: 2, + version: 'WzAsMV0=', + }, + ]); + }); + + it('it handles total comments correctly', () => { + const totalCommentsByCase = [{ caseId: 'not-exist', totalComments: 2 }]; + + const res = flattenCaseSavedObjects([mockCases[0]], totalCommentsByCase); + + expect(res).toEqual([ + { + id: 'mock-id-1', + closed_at: null, + closed_by: null, + created_at: '2019-11-25T21:54:48.952Z', + created_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + description: 'This is a brand new case of a bad meanie defacing data', + external_service: null, + title: 'Super Bad Security Issue', + status: 'open', + tags: ['defacement'], + updated_at: '2019-11-25T21:54:48.952Z', + updated_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + comments: [], + totalComment: 0, + version: 'WzAsMV0=', + }, + ]); + }); + }); + + describe('flattenCaseSavedObject', () => { + it('flattens correctly', () => { + const myCase = { ...mockCases[0] }; + const res = flattenCaseSavedObject(myCase, [], 2); + expect(res).toEqual({ + id: myCase.id, + version: myCase.version, + comments: [], + totalComment: 2, + ...myCase.attributes, + }); + }); + + it('flattens correctly without version', () => { + const myCase = { ...mockCases[0] }; + myCase.version = undefined; + const res = flattenCaseSavedObject(myCase, [], 2); + expect(res).toEqual({ + id: myCase.id, + version: '0', + comments: [], + totalComment: 2, + ...myCase.attributes, + }); + }); + + it('flattens correctly with comments', () => { + const myCase = { ...mockCases[0] }; + const comments = [{ ...mockCaseComments[0] }]; + const res = flattenCaseSavedObject(myCase, comments, 2); + expect(res).toEqual({ + id: myCase.id, + version: myCase.version, + comments: flattenCommentSavedObjects(comments), + totalComment: 2, + ...myCase.attributes, + }); + }); + }); + + describe('transformComments', () => { + it('transforms correctly', () => { + const comments = { + saved_objects: mockCaseComments, + total: mockCaseComments.length, + per_page: 10, + page: 1, + }; + + const res = transformComments(comments); + expect(res).toEqual({ + page: 1, + per_page: 10, + total: mockCaseComments.length, + comments: flattenCommentSavedObjects(comments.saved_objects), + }); + }); + }); + + describe('flattenCommentSavedObjects', () => { + it('flattens correctly', () => { + const comments = [{ ...mockCaseComments[0] }, { ...mockCaseComments[1] }]; + const res = flattenCommentSavedObjects(comments); + expect(res).toEqual([ + flattenCommentSavedObject(comments[0]), + flattenCommentSavedObject(comments[1]), + ]); + }); + }); + + describe('flattenCommentSavedObject', () => { + it('flattens correctly', () => { + const comment = { ...mockCaseComments[0] }; + const res = flattenCommentSavedObject(comment); + expect(res).toEqual({ + id: comment.id, + version: comment.version, + ...comment.attributes, + }); + }); + + it('flattens correctly without version', () => { + const comment = { ...mockCaseComments[0] }; + comment.version = undefined; + const res = flattenCommentSavedObject(comment); + expect(res).toEqual({ + id: comment.id, + version: '0', + ...comment.attributes, + }); + }); + }); + + describe('sortToSnake', () => { + it('it transforms status correctly', () => { + expect(sortToSnake('status')).toBe('status'); + }); + + it('it transforms createdAt correctly', () => { + expect(sortToSnake('createdAt')).toBe('created_at'); + }); + + it('it transforms created_at correctly', () => { + expect(sortToSnake('created_at')).toBe('created_at'); + }); + + it('it transforms closedAt correctly', () => { + expect(sortToSnake('closedAt')).toBe('closed_at'); + }); + + it('it transforms closed_at correctly', () => { + expect(sortToSnake('closed_at')).toBe('closed_at'); + }); + + it('it transforms default correctly', () => { + expect(sortToSnake('not-exist')).toBe('created_at'); + }); + }); +}); From 29aba88a0017abaf926140156fff4ffb42a6bd3c Mon Sep 17 00:00:00 2001 From: Tim Sullivan <tsullivan@users.noreply.github.com> Date: Tue, 14 Apr 2020 12:55:49 -0700 Subject: [PATCH 109/121] [Reporting] Improve functional test steps (#63259) * Start of refactoring * remove unused fixtuers * fix the refactoring bugs * update archive with better dashboard * important comment Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../reporting/ecommerce_kibana/data.json.gz | Bin 2039 -> 4138 bytes .../reporting/ecommerce_kibana/mappings.json | 1704 ++++++++++++++++- .../reporting/historic/data.json.gz | Bin 2269 -> 0 bytes .../reporting/historic/mappings.json | 386 ---- .../functional/page_objects/reporting_page.js | 30 +- x-pack/test/reporting/.gitignore | 1 + .../reporting/configs/chromium_functional.js | 1 + x-pack/test/reporting/functional/reporting.js | 139 +- .../baseline/dashboard_preserve_layout.pdf | Bin 301135 -> 0 bytes .../baseline/dashboard_preserve_layout.png | Bin 349976 -> 631719 bytes .../reports/baseline/dashboard_print.pdf | Bin 359189 -> 0 bytes .../reports/baseline/visualize_print.pdf | Bin 124146 -> 0 bytes 12 files changed, 1733 insertions(+), 528 deletions(-) delete mode 100644 x-pack/test/functional/es_archives/reporting/historic/data.json.gz delete mode 100644 x-pack/test/functional/es_archives/reporting/historic/mappings.json create mode 100644 x-pack/test/reporting/.gitignore delete mode 100644 x-pack/test/reporting/functional/reports/baseline/dashboard_preserve_layout.pdf delete mode 100644 x-pack/test/reporting/functional/reports/baseline/dashboard_print.pdf delete mode 100644 x-pack/test/reporting/functional/reports/baseline/visualize_print.pdf diff --git a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json.gz b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/data.json.gz index 2b204d0bde2716e4813714d2a923ec611a0c2c2e..454d260a518cd39001004d026afd8dc00c5e01d6 100644 GIT binary patch literal 4138 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 literal 2039 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 VA6q&kGjr6C!@pTmj>*J7003?*^&bEL diff --git a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/mappings.json b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/mappings.json index cf647f5c53212..fbcfa4cbe49b3 100644 --- a/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/mappings.json +++ b/x-pack/test/functional/es_archives/reporting/ecommerce_kibana/mappings.json @@ -9,45 +9,62 @@ "mappings": { "_meta": { "migrationMappingPropertyHashes": { - "action": "c0c235fba02ebd2a2412bcda79009b58", + "action": "6e96ac5e648f57523879661ea72525b7", "action_task_params": "a9d49f184ee89641044be0ca2950fa3a", - "alert": "d49f9b8d1277c6004506eec20dc0b108", + "agent_actions": "ed270b46812f0fa1439366c428a2cf17", + "agent_configs": "38abaf89513877745c359e7700c0c66a", + "agent_events": "3231653fafe4ef3196fe3b32ab774bf2", + "agents": "c3eeb7b9d97176f15f6d126370ab23c7", + "alert": "7b44fba6773e37c806ce290ea9b7024e", "apm-indices": "9bb9b2bf1fa636ed8619cbab5ce6a1dd", - "apm-services-telemetry": "07ee1939fa4302c62ddc052ec03fed90", + "apm-telemetry": "3525d7c22c42bc80f5e6e9cb3f2b26a2", + "application_usage_totals": "c897e4310c5f24b07caaff3db53ae2c1", + "application_usage_transactional": "965839e75f809fefe04f92dc4d99722a", "canvas-element": "7390014e1091044523666d97247392fc", "canvas-workpad": "b0a1706d356228dbdcb4a17e6b9eb231", - "config": "87aca8fdb053154f11383fce3dbf3edf", + "cases": "08b8b110dbca273d37e8aef131ecab61", + "cases-comments": "c2061fb929f585df57425102fa928b4b", + "cases-configure": "42711cbb311976c0687853f4c1354572", + "cases-user-actions": "32277330ec6b721abe3b846cfd939a71", + "config": "ae24d22d5986d04124cc6568f771066f", "dashboard": "d00f614b29a80360e1190193fd333bab", + "datasources": "d4bc0c252b2b5683ff21ea32d00acffc", + "enrollment_api_keys": "28b91e20b105b6f928e2012600085d8f", + "epm-package": "0be91c6758421dd5d0f1a58e9e5bc7c3", "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", "index-pattern": "66eccb05066c5a89924f48a9e9736499", "infrastructure-ui-source": "ddc0ecb18383f6b26101a2fadb2dab0c", - "inventory-view": "84b320fd67209906333ffce261128462", + "inventory-view": "9ecce5b58867403613d82fe496470b34", "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", "lens": "21c3ea0763beb1ecb0162529706b88c5", "lens-ui-telemetry": "509bfa5978586998e05f9e303c07a327", "map": "23d7aa4a720d4938ccde3983f87bd58d", - "maps-telemetry": "a4229f8b16a6820c6d724b7e0c1f729d", + "maps-telemetry": "268da3a48066123fc5baf35abaa55014", "metrics-explorer-view": "53c5365793677328df0ccb6138bf3cdd", "migrationVersion": "4a1746014a75ade3a714e1db5763276f", "ml-telemetry": "257fd1d4b4fdbb9cb4b8a3b27da201e9", "namespace": "2f4316de49999235636386fe51dc06c1", + "outputs": "aee9782e0d500b867859650a36280165", "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", "references": "7997cf5a56cc02bdc9c93361bde732b0", "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", "search": "181661168bbadd1eff5902361e2a0d5c", "server": "ec97f1c5da1a19609a60874e5af1100c", - "siem-ui-timeline": "6485ab095be8d15246667b98a1a34295", + "siem-detection-engine-rule-actions": "90eee2e4635260f4be0a1da8f5bc0aa0", + "siem-detection-engine-rule-status": "ae783f41c6937db6b7a2ef5c93a9e9b0", + "siem-ui-timeline": "ac8020190f5950dd3250b6499144e7fb", "siem-ui-timeline-note": "8874706eedc49059d4cf0f5094559084", "siem-ui-timeline-pinned-event": "20638091112f0e14f0e443d512301c29", - "space": "c5ca8acafa0beaa4d08d014a97b6bc6b", - "telemetry": "358ffaa88ba34a97d55af0933a117de4", + "telemetry": "36a616f7026dfa617d6655df850fe16d", "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf", + "tsvb-validation-telemetry": "3a37ef6c8700ae6fc97d5c7da00e9215", "type": "2f4316de49999235636386fe51dc06c1", "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", "updated_at": "00da57df13e94e9d98437d13ace4bfe0", "upgrade-assistant-reindex-operation": "a53a20fe086b72c9a86da3cc12dad8a6", "upgrade-assistant-telemetry": "56702cec857e0a9dacfb696655b4ff7b", + "uptime-dynamic-settings": "b6289473c8985c79b6c47eebc19a0ca5", "url": "c7f66a0df8b1b52f17c28c4adb111105", "visualization": "52d7a13ad68a150c4525b292d23e12cc" } @@ -64,6 +81,11 @@ "type": "object" }, "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, "type": "text" }, "secrets": { @@ -85,6 +107,145 @@ } } }, + "agent_actions": { + "properties": { + "agent_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "data": { + "type": "flattened" + }, + "sent_at": { + "type": "date" + }, + "type": { + "type": "keyword" + } + } + }, + "agent_configs": { + "properties": { + "datasources": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "id": { + "type": "keyword" + }, + "is_default": { + "type": "boolean" + }, + "name": { + "type": "text" + }, + "namespace": { + "type": "keyword" + }, + "revision": { + "type": "integer" + }, + "status": { + "type": "keyword" + }, + "updated_by": { + "type": "keyword" + }, + "updated_on": { + "type": "keyword" + } + } + }, + "agent_events": { + "properties": { + "action_id": { + "type": "keyword" + }, + "agent_id": { + "type": "keyword" + }, + "config_id": { + "type": "keyword" + }, + "data": { + "type": "text" + }, + "message": { + "type": "text" + }, + "payload": { + "type": "text" + }, + "stream_id": { + "type": "keyword" + }, + "subtype": { + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "type": { + "type": "keyword" + } + } + }, + "agents": { + "properties": { + "access_api_key_id": { + "type": "keyword" + }, + "active": { + "type": "boolean" + }, + "config_id": { + "type": "keyword" + }, + "config_newest_revision": { + "type": "integer" + }, + "config_revision": { + "type": "integer" + }, + "current_error_events": { + "type": "text" + }, + "default_api_key": { + "type": "keyword" + }, + "enrolled_at": { + "type": "date" + }, + "last_checkin": { + "type": "date" + }, + "last_updated": { + "type": "date" + }, + "local_metadata": { + "type": "text" + }, + "shared_id": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "user_provided_metadata": { + "type": "text" + }, + "version": { + "type": "keyword" + } + } + }, "alert": { "properties": { "actions": { @@ -114,15 +275,18 @@ "apiKeyOwner": { "type": "keyword" }, + "consumer": { + "type": "keyword" + }, + "createdAt": { + "type": "date" + }, "createdBy": { "type": "keyword" }, "enabled": { "type": "boolean" }, - "interval": { - "type": "keyword" - }, "muteAll": { "type": "boolean" }, @@ -130,12 +294,24 @@ "type": "keyword" }, "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, "type": "text" }, "params": { "enabled": false, "type": "object" }, + "schedule": { + "properties": { + "interval": { + "type": "keyword" + } + } + }, "scheduledTaskId": { "type": "keyword" }, @@ -221,52 +397,947 @@ }, "apm-telemetry": { "properties": { - "has_any_services": { - "type": "boolean" - }, - "services_per_agent": { + "agents": { "properties": { "dotnet": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } }, "go": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } }, "java": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } }, "js-base": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } }, "nodejs": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } }, "python": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } }, "ruby": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } }, "rum-js": { - "null_value": 0, - "type": "long" + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } } } - } - } - }, - "canvas-element": { - "dynamic": "false", - "properties": { - "@created": { - "type": "date" + }, + "cardinality": { + "properties": { + "transaction": { + "properties": { + "name": { + "properties": { + "all_agents": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "rum": { + "properties": { + "1d": { + "type": "long" + } + } + } + } + } + } + }, + "user_agent": { + "properties": { + "original": { + "properties": { + "all_agents": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "rum": { + "properties": { + "1d": { + "type": "long" + } + } + } + } + } + } + } + } + }, + "counts": { + "properties": { + "agent_configuration": { + "properties": { + "all": { + "type": "long" + } + } + }, + "error": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "max_error_groups_per_service": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "max_transaction_groups_per_service": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "onboarding": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "services": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "sourcemap": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "span": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "traces": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "transaction": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + } + } + }, + "has_any_services": { + "type": "boolean" + }, + "indices": { + "properties": { + "all": { + "properties": { + "total": { + "properties": { + "docs": { + "properties": { + "count": { + "type": "long" + } + } + }, + "store": { + "properties": { + "size_in_bytes": { + "type": "long" + } + } + } + } + } + } + }, + "shards": { + "properties": { + "total": { + "type": "long" + } + } + } + } + }, + "integrations": { + "properties": { + "ml": { + "properties": { + "all_jobs_count": { + "type": "long" + } + } + } + } + }, + "retainment": { + "properties": { + "error": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "onboarding": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "span": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "transaction": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "services_per_agent": { + "properties": { + "dotnet": { + "null_value": 0, + "type": "long" + }, + "go": { + "null_value": 0, + "type": "long" + }, + "java": { + "null_value": 0, + "type": "long" + }, + "js-base": { + "null_value": 0, + "type": "long" + }, + "nodejs": { + "null_value": 0, + "type": "long" + }, + "python": { + "null_value": 0, + "type": "long" + }, + "ruby": { + "null_value": 0, + "type": "long" + }, + "rum-js": { + "null_value": 0, + "type": "long" + } + } + }, + "tasks": { + "properties": { + "agent_configuration": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "agents": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "cardinality": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "groupings": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "indices_stats": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "integrations": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "processor_events": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "services": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "versions": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + } + } + }, + "version": { + "properties": { + "apm_server": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + }, + "patch": { + "type": "long" + } + } + } + } + } + } + }, + "application_usage_totals": { + "properties": { + "appId": { + "type": "keyword" + }, + "minutesOnScreen": { + "type": "float" + }, + "numberOfClicks": { + "type": "long" + } + } + }, + "application_usage_transactional": { + "properties": { + "appId": { + "type": "keyword" + }, + "minutesOnScreen": { + "type": "float" + }, + "numberOfClicks": { + "type": "long" + }, + "timestamp": { + "type": "date" + } + } + }, + "canvas-element": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" }, "@timestamp": { "type": "date" @@ -285,26 +1356,257 @@ "keyword": { "type": "keyword" } - }, - "type": "text" + }, + "type": "text" + } + } + }, + "canvas-workpad": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "cases": { + "properties": { + "closed_at": { + "type": "date" + }, + "closed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "description": { + "type": "text" + }, + "external_service": { + "properties": { + "connector_id": { + "type": "keyword" + }, + "connector_name": { + "type": "keyword" + }, + "external_id": { + "type": "keyword" + }, + "external_title": { + "type": "text" + }, + "external_url": { + "type": "text" + }, + "pushed_at": { + "type": "date" + }, + "pushed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "status": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "title": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-comments": { + "properties": { + "comment": { + "type": "text" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "pushed_at": { + "type": "date" + }, + "pushed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-configure": { + "properties": { + "closure_type": { + "type": "keyword" + }, + "connector_id": { + "type": "keyword" + }, + "connector_name": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } } } }, - "canvas-workpad": { - "dynamic": "false", + "cases-user-actions": { "properties": { - "@created": { - "type": "date" + "action": { + "type": "keyword" }, - "@timestamp": { + "action_at": { "type": "date" }, - "name": { - "fields": { - "keyword": { + "action_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { "type": "keyword" } - }, + } + }, + "action_field": { + "type": "keyword" + }, + "new_value": { + "type": "text" + }, + "old_value": { "type": "text" } } @@ -389,6 +1691,136 @@ } } }, + "datasources": { + "properties": { + "config_id": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "enabled": { + "type": "boolean" + }, + "inputs": { + "properties": { + "config": { + "type": "flattened" + }, + "enabled": { + "type": "boolean" + }, + "processors": { + "type": "keyword" + }, + "streams": { + "properties": { + "config": { + "type": "flattened" + }, + "dataset": { + "type": "keyword" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "type": "keyword" + }, + "processors": { + "type": "keyword" + } + }, + "type": "nested" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "name": { + "type": "keyword" + }, + "namespace": { + "type": "keyword" + }, + "output_id": { + "type": "keyword" + }, + "package": { + "properties": { + "name": { + "type": "keyword" + }, + "title": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "revision": { + "type": "integer" + } + } + }, + "enrollment_api_keys": { + "properties": { + "active": { + "type": "boolean" + }, + "api_key": { + "type": "binary" + }, + "api_key_id": { + "type": "keyword" + }, + "config_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "expire_at": { + "type": "date" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + } + } + }, + "epm-package": { + "properties": { + "installed": { + "properties": { + "id": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "internal": { + "type": "boolean" + }, + "name": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, "file-upload-telemetry": { "properties": { "filesUploadedTotalCount": { @@ -538,6 +1970,26 @@ } } }, + "customMetrics": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "label": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, "customOptions": { "properties": { "field": { @@ -572,6 +2024,18 @@ }, "metric": { "properties": { + "aggregation": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "label": { + "type": "keyword" + }, "type": { "type": "keyword" } @@ -699,9 +2163,19 @@ } } }, + "indexPatternsWithGeoFieldCount": { + "type": "long" + }, "mapsTotalCount": { "type": "long" }, + "settings": { + "properties": { + "showMapVisualizationTypes": { + "type": "boolean" + } + } + }, "timeCaptured": { "type": "date" } @@ -803,7 +2277,7 @@ }, "type": "text" }, - "space": { + "visualization": { "fields": { "keyword": { "ignore_above": 256, @@ -828,6 +2302,37 @@ "namespace": { "type": "keyword" }, + "outputs": { + "properties": { + "api_key": { + "type": "keyword" + }, + "ca_sha256": { + "type": "keyword" + }, + "config": { + "type": "flattened" + }, + "fleet_enroll_password": { + "type": "binary" + }, + "fleet_enroll_username": { + "type": "binary" + }, + "hosts": { + "type": "keyword" + }, + "is_default": { + "type": "boolean" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, "query": { "properties": { "description": { @@ -917,6 +2422,73 @@ } } }, + "siem-detection-engine-rule-actions": { + "properties": { + "actions": { + "properties": { + "action_type_id": { + "type": "keyword" + }, + "group": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "params": { + "dynamic": "true", + "type": "object" + } + } + }, + "alertThrottle": { + "type": "keyword" + }, + "ruleAlertId": { + "type": "keyword" + }, + "ruleThrottle": { + "type": "keyword" + } + } + }, + "siem-detection-engine-rule-status": { + "properties": { + "alertId": { + "type": "keyword" + }, + "bulkCreateTimeDurations": { + "type": "float" + }, + "gap": { + "type": "text" + }, + "lastFailureAt": { + "type": "date" + }, + "lastFailureMessage": { + "type": "text" + }, + "lastLookBackDate": { + "type": "date" + }, + "lastSuccessAt": { + "type": "date" + }, + "lastSuccessMessage": { + "type": "text" + }, + "searchAfterTimeDurations": { + "type": "float" + }, + "status": { + "type": "keyword" + }, + "statusDate": { + "type": "date" + } + } + }, "siem-ui-timeline": { "properties": { "columns": { @@ -1051,6 +2623,9 @@ "description": { "type": "text" }, + "eventType": { + "type": "keyword" + }, "favorite": { "properties": { "favoriteDate": { @@ -1255,6 +2830,9 @@ }, "telemetry": { "properties": { + "allowChangingOptInStatus": { + "type": "boolean" + }, "enabled": { "type": "boolean" }, @@ -1262,11 +2840,15 @@ "type": "date" }, "lastVersionChecked": { - "ignore_above": 256, + "type": "keyword" + }, + "reportFailureCount": { + "type": "integer" + }, + "reportFailureVersion": { "type": "keyword" }, "sendUsageFrom": { - "ignore_above": 256, "type": "keyword" }, "userHasSeenNotice": { @@ -1315,6 +2897,13 @@ } } }, + "tsvb-validation-telemetry": { + "properties": { + "failedRequests": { + "type": "long" + } + } + }, "type": { "type": "keyword" }, @@ -1391,6 +2980,13 @@ } } }, + "uptime-dynamic-settings": { + "properties": { + "heartbeatIndices": { + "type": "keyword" + } + } + }, "url": { "properties": { "accessCount": { diff --git a/x-pack/test/functional/es_archives/reporting/historic/data.json.gz b/x-pack/test/functional/es_archives/reporting/historic/data.json.gz deleted file mode 100644 index ecb85ec6faca43ba103d37e3173f383a6fa73b37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2269 zcmV<32qO0%iwFP!000026YX5xZsWKWzRy#*?%g7BWIN7}uQorMVv9*87^hS0t^<RX zXo(FaYDp@NH}G?`*S+rx6n&Zk?Q`_-N48|k#$=MQnV>)rSciWfzr%BQMCs^hr&g=W zNs8;;T0LNXeOCz{5Y3e22`=E01gi9bhzwEk8<K=2-Ot6VfB)^D|NYnB|MQQ(?p+{> zZqblp-H~dW1o%-kZ`_k1N>DBrEaU!si~@?%IJSCiQ9N%4MFAE*C#fx{FJjPj%;-Jz zfP;_2zhGZpVTnrJC{P%2Kk8{{f9!p{R=qv-%^dpmZof`hC?pcm-go`_ZomF(hWP{v zp6t(okeno8L84ok$}l{g{Duc(LIWT10E#5f@N^1gBSIzSAo=BPTAv}B7Vt|Vsivoz z_*&(pGt!et&Zjah7CvAu3}elrlnC9%PF)YHCvlC(wbIynQc7vMSgNtLC`BB_!f=pc zeuF|)qv=7Bh}ifBaY+#U#Kx-52vLD;3221);#8he`T;*+IxANUp)gd}zbJJCdc<ZK zfX}i-YLW0G93w4^F(|}efCY@tduf$>iHMLagqn*z4Kx29%cTj92&Sf^;Y4Dg%Si&d z1QP;r%k$K{@uS4BhJwKmKn51X^bSfWjE57@gpuXCpYG)Ur#sV~ou}8b(!I|Z*!K}V zL;O4fO>EIjS3r5+)>>OP>kXP~d7T$mv;b82r_)Cw?35K5L2%0$l_V|6KHw0R^;{%i zUZ#6W5>SrrJ7$5Afhxd+0)vCZSex^m?H#VK5Wm-~<~||7Ba~73(+|peWXW6LD(S?6 zewuF3VFW<_V5Qd(IE-<!&TV|JsgNj67kvjzA(Ko?{S5k#e=L@@BEv382H+3|b~4?j zGu~$JmQc`Xx<wCDM(~auORZw2o80?h^g)c$rDYDX+q_awIftNjPPk8T%^17gFU18G zNM;;{4%R!J2qSrg9)D&mR*U^G7m?&+ihLp!(O#oz#h*|>G6kj8v63^IDSDgv^)=(M zniN*y(|nk5J^`GluqG%tnT#9zi=<3NcYl9~1Q>hTNHi~qs^1}d*oPGq60tA9Vu_E% z{-1h(=-slE?Sq<nAjEwC&sRP3OS8cAvbEz{{TR2^Xg54vg`$bE-G1E&Mhd>v0un=< zwV$e0r&PmHB0v+`_sj^Duq=m}%sU1oqLy;@K)_klhLf7YXgrvlP;3V3*Qc9wry*t$ z7}g-<BzV3vh1Lz9F&+?5hmFRR6TRWsCzeo4Mp_WHHt!wn?a~L>C$}AkEn;}be$w76 zRnB;W{!&FpuNrs3&6Dw~g|;GQOh#&|#TZG)7b&BFdNEL|jNSr{#=4I)EXNopH;kB| z%Z|dei~Xb~3Br?i71{w)u~>3KDJAP%kPg1oT4?}trZH?UP^7jT@JyP9zP3T*_Lb;t zQkVs2<Jpbx=A*VN&C<4g(lUzo9KEfW?FKzkrENfvgOY&aYxW5Xu-1avk60pmW?dh8 zUu2Rg26ZGlQiRy#UVM>t77Z)LF;l953VKoN;Z9EOwzhYla*VcZCyN-~|K43W;|*F0 zY|`je_wLGVx^gdGvv>dhkmVg8vS^#!OX2nn^Q1es%jf%@Qcq>aqRA4f7p2Su#fJIs zfj6N~@QeD$ZGU&B;I2O2*RH8_yKLNyc{VV!f-vMbMD~fntST5*aLHMG!Tis;gSW^3 zRfuNs)we;F$F~)rv@0uPk|-1oQKaCw#ZSrpN_M>sJOg{UuyJZClr^wht}Aea&-jA5 zCs{nSr&P~@lM7$Am<Ps<l@S$%TYzM6IHED|g?96E!ue=8E;*n1gV~oZ=vM&aQ=;yI z7W|;S-Y}NgQH48;XZiHRfdy1`s$4v<9;E6}Y+K0Sj!?S9l;FN&a9m<2f?6=NL&0K> z$R&%5m~d!EQ)pabXEAu)-fs4-L)T|2O2ctVQ%>yjl;r2FPH0KPaY;)t@*|Sq26Kp{ zIVKmG$`9cja6yH~0#2Zjr~w^vXEde&aZJstHO{PVg(?%6H%5dDY2@yKqo@ko_EuLK zrEV>Ejz^edXBN9%=jSX@Pc0hiMRT9xZp;EQA~+bRQ%E-sAXgwwvmqrSdJ9km_N7xt z2kUXVw2Q7lDpBY>n}E?_CRx}mJRf(K%rZ>3`P8qKy3C{o_y#!aMwo<=be>9!^DQts zCV`CHCsf09n@>R`9=H{SuL0>cm-bB}cX`wR9p~`dK3{z~g#gQK26dW>y95F}hxwCZ zqTZ0|npYPcWw8kI4RHAu0`m&2Z-801L-Z2LH^8QfGMpz<fqVm8x*ZCYP&&+}%Uii~ z`}nUJ7Eaw{Yd~&sBvO_Lr|i-oa)~98A|E^SJlNoIiJ|Si1G|jHDHrLOPt2t6(9@(x z;gC@Qm@RASu3pM}i}9sO!?^~4Didd(Hc_uik1J#X?JQ)`%`%J189%e)EL9627$B)C zwY=uhUbDI9wQrl9ZmZR8b{a=s=jZxYr!4s_8IiDi)bJYK9-?W4n$OQxGM$vul!h4r zezF*(#|MW;yT!~%oyhiM-u+UZl&<x7gZ%p|mJrF5n!74>{tP7v=Fmnfb|sY-&KGld z+-M%PUclkHEbSZejXoQ(c2bAk)=A^A1C#oSRMiE@8_86qC<!z3{W-YEd~CnFur`@> zMe^$Ia+<4Ma)WuI;dlAxQocGDyo#p9^wz$j-GKEOW!(PuG=$%`FAtB~Z4L0i+x0vv zJ~=#UdnT{)xFBv_c8)qfXmPVutbTHE;GG)zVL{$GZXS5&THf*sa<9`m>zL%vR&m%) zvw3uIV&uhf+m}%POv~HFanH|B+v+#a_<|(fYEBn2(#flSgoB6+mSnQ9KP-(zb(0$g zx9|Bkc({2exGtA={tY5K((5GGuI}~)iMEB;lL|?;2j1GxAihG1tPYR6)*hel6m|3U rpArL7YVao`T(iT}bgSPLS7~B5?h6ZK<z8Y2EKc`-Ri>-NiB$jqH?(I3 diff --git a/x-pack/test/functional/es_archives/reporting/historic/mappings.json b/x-pack/test/functional/es_archives/reporting/historic/mappings.json deleted file mode 100644 index 3a5af0158ce00..0000000000000 --- a/x-pack/test/functional/es_archives/reporting/historic/mappings.json +++ /dev/null @@ -1,386 +0,0 @@ -{ - "type": "index", - "value": { - "index": ".kibana", - "mappings": { - "properties": { - "config": { - "dynamic": "true", - "properties": { - "buildNum": { - "type": "keyword" - }, - "defaultIndex": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "xPackMonitoring:showBanner": { - "type": "boolean" - } - } - }, - "dashboard": { - "dynamic": "strict", - "properties": { - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "optionsJSON": { - "type": "text" - }, - "panelsJSON": { - "type": "text" - }, - "refreshInterval": { - "properties": { - "display": { - "type": "keyword" - }, - "pause": { - "type": "boolean" - }, - "section": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "timeFrom": { - "type": "keyword" - }, - "timeRestore": { - "type": "boolean" - }, - "timeTo": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "graph-workspace": { - "dynamic": "strict", - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "numLinks": { - "type": "integer" - }, - "numVertices": { - "type": "integer" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "wsState": { - "type": "text" - } - } - }, - "index-pattern": { - "dynamic": "strict", - "properties": { - "fieldFormatMap": { - "type": "text" - }, - "fields": { - "type": "text" - }, - "intervalName": { - "type": "keyword" - }, - "notExpandable": { - "type": "boolean" - }, - "sourceFilters": { - "type": "text" - }, - "timeFieldName": { - "type": "keyword" - }, - "title": { - "type": "text" - } - } - }, - "search": { - "dynamic": "strict", - "properties": { - "columns": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "sort": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "server": { - "dynamic": "strict", - "properties": { - "uuid": { - "type": "keyword" - } - } - }, - "space": { - "properties": { - "_reserved": { - "type": "boolean" - }, - "color": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "initials": { - "type": "keyword" - }, - "name": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "spaceId": { - "type": "keyword" - }, - "timelion-sheet": { - "dynamic": "strict", - "properties": { - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "timelion_chart_height": { - "type": "integer" - }, - "timelion_columns": { - "type": "integer" - }, - "timelion_interval": { - "type": "keyword" - }, - "timelion_other_interval": { - "type": "keyword" - }, - "timelion_rows": { - "type": "integer" - }, - "timelion_sheet": { - "type": "text" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "type": { - "type": "keyword" - }, - "updated_at": { - "type": "date" - }, - "url": { - "dynamic": "strict", - "properties": { - "accessCount": { - "type": "long" - }, - "accessDate": { - "type": "date" - }, - "createDate": { - "type": "date" - }, - "url": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "visualization": { - "dynamic": "strict", - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "savedSearchId": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "type": "text" - } - } - } - } - }, - "settings": { - "index": { - "number_of_replicas": "1", - "number_of_shards": "1" - } - } - } -} - -{ - "type": "index", - "value": { - "index": ".reporting-2018.03.11", - "mappings": { - "properties": { - "attempts": { - "type": "short" - }, - "completed_at": { - "type": "date" - }, - "created_at": { - "type": "date" - }, - "created_by": { - "type": "keyword" - }, - "jobtype": { - "type": "keyword" - }, - "max_attempts": { - "type": "short" - }, - "output": { - "properties": { - "content": { - "enabled": false, - "type": "object" - }, - "content_type": { - "type": "keyword" - }, - "max_size_reached": { - "type": "boolean" - } - } - }, - "payload": { - "enabled": false, - "type": "object" - }, - "priority": { - "type": "byte" - }, - "process_expiration": { - "type": "date" - }, - "started_at": { - "type": "date" - }, - "status": { - "type": "keyword" - }, - "timeout": { - "type": "long" - } - } - }, - "settings": { - "index": { - "auto_expand_replicas": "0-1", - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} \ No newline at end of file diff --git a/x-pack/test/functional/page_objects/reporting_page.js b/x-pack/test/functional/page_objects/reporting_page.js index 7cdd1c083239b..cdfafeec1bf46 100644 --- a/x-pack/test/functional/page_objects/reporting_page.js +++ b/x-pack/test/functional/page_objects/reporting_page.js @@ -19,24 +19,10 @@ export function ReportingPageProvider({ getService, getPageObjects }) { const log = getService('log'); const config = getService('config'); const testSubjects = getService('testSubjects'); - const esArchiver = getService('esArchiver'); const browser = getService('browser'); - const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['common', 'security', 'settings', 'share', 'timePicker']); + const PageObjects = getPageObjects(['common', 'security', 'share', 'timePicker']); class ReportingPage { - async initTests() { - log.debug('ReportingPage:initTests'); - await PageObjects.settings.navigateTo(); - await esArchiver.loadIfNeeded('../../functional/es_archives/logstash_functional'); - await esArchiver.load('reporting/historic'); - await kibanaServer.uiSettings.replace({ - defaultIndex: 'logstash-*', - }); - - await browser.setWindowSize(1600, 850); - } - async forceSharedItemsContainerSize({ width }) { await browser.execute(` var el = document.querySelector('[data-shared-items-container]'); @@ -130,6 +116,20 @@ export function ReportingPageProvider({ getService, getPageObjects }) { return await retry.try(async () => await testSubjects.find('generateReportButton')); } + async isGenerateReportButtonDisabled() { + const generateReportButton = await this.getGenerateReportButton(); + return await retry.try(async () => { + const isDisabled = await generateReportButton.getAttribute('disabled'); + return isDisabled; + }); + } + + async canReportBeCreated() { + await this.clickGenerateReportButton(); + const success = await this.checkForReportingToasts(); + return success; + } + async checkUsePrintLayout() { // The print layout checkbox slides in as part of an animation, and tests can // attempt to click it too quickly, leading to flaky tests. The 500ms wait allows diff --git a/x-pack/test/reporting/.gitignore b/x-pack/test/reporting/.gitignore new file mode 100644 index 0000000000000..99ee4c44686a0 --- /dev/null +++ b/x-pack/test/reporting/.gitignore @@ -0,0 +1 @@ +functional/reports/session/ diff --git a/x-pack/test/reporting/configs/chromium_functional.js b/x-pack/test/reporting/configs/chromium_functional.js index 05c3b6c142946..753d2b2a20ab9 100644 --- a/x-pack/test/reporting/configs/chromium_functional.js +++ b/x-pack/test/reporting/configs/chromium_functional.js @@ -5,6 +5,7 @@ */ export default async function({ readConfigFile }) { + // TODO move reporting tests to x-pack/test/functional/apps/<integration_app>/reporting const functionalConfig = await readConfigFile(require.resolve('../../functional/config.js')); return { diff --git a/x-pack/test/reporting/functional/reporting.js b/x-pack/test/reporting/functional/reporting.js index 012f0922c28cf..6107363986a40 100644 --- a/x-pack/test/reporting/functional/reporting.js +++ b/x-pack/test/reporting/functional/reporting.js @@ -15,8 +15,14 @@ const mkdirAsync = promisify(fs.mkdir); const REPORTS_FOLDER = path.resolve(__dirname, 'reports'); +/* + * TODO Remove this file and spread the tests to various apps + */ + export default function({ getService, getPageObjects }) { - const retry = getService('retry'); + const esArchiver = getService('esArchiver'); + const browser = getService('browser'); + const log = getService('log'); const config = getService('config'); const PageObjects = getPageObjects([ 'reporting', @@ -27,65 +33,32 @@ export default function({ getService, getPageObjects }) { 'visualize', 'visEditor', ]); - const log = getService('log'); describe('Reporting', () => { - before('initialize tests', async () => { - await PageObjects.reporting.initTests(); - }); - - const expectDisabledGenerateReportButton = async () => { - const generateReportButton = await PageObjects.reporting.getGenerateReportButton(); - await retry.try(async () => { - const isDisabled = await generateReportButton.getAttribute('disabled'); - expect(isDisabled).to.be('true'); + describe('Dashboard', () => { + before('initialize tests', async () => { + log.debug('ReportingPage:initTests'); + await esArchiver.loadIfNeeded('reporting/ecommerce'); + await esArchiver.loadIfNeeded('reporting/ecommerce_kibana'); + await browser.setWindowSize(1600, 850); }); - }; - - const expectEnabledGenerateReportButton = async () => { - const generateReportButton = await PageObjects.reporting.getGenerateReportButton(); - await retry.try(async () => { - const isDisabled = await generateReportButton.getAttribute('disabled'); - expect(isDisabled).to.be(null); + after('clean up archives', async () => { + await esArchiver.unload('reporting/ecommerce'); + await esArchiver.unload('reporting/ecommerce_kibana'); }); - }; - - const expectReportCanBeCreated = async () => { - await PageObjects.reporting.clickGenerateReportButton(); - const success = await PageObjects.reporting.checkForReportingToasts(); - expect(success).to.be(true); - }; - - const writeSessionReport = async (name, rawPdf, reportExt = 'pdf') => { - const sessionDirectory = path.resolve(REPORTS_FOLDER, 'session'); - await mkdirAsync(sessionDirectory, { recursive: true }); - const sessionReportPath = path.resolve(sessionDirectory, `${name}.${reportExt}`); - await writeFileAsync(sessionReportPath, rawPdf); - return sessionReportPath; - }; - - const getBaselineReportPath = (fileName, reportExt = 'pdf') => { - const baselineFolder = path.resolve(REPORTS_FOLDER, 'baseline'); - const fullPath = path.resolve(baselineFolder, `${fileName}.${reportExt}`); - log.debug(`getBaselineReportPath (${fullPath})`); - return fullPath; - }; - - describe('Dashboard', () => { - beforeEach(() => PageObjects.reporting.clearToastNotifications()); describe('Print PDF button', () => { it('is not available if new', async () => { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); await PageObjects.reporting.openPdfReportingPanel(); - await expectDisabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); }); it('becomes available when saved', async () => { await PageObjects.dashboard.saveDashboard('My PDF Dashboard'); await PageObjects.reporting.openPdfReportingPanel(); - await expectEnabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); }); }); @@ -95,15 +68,7 @@ export default function({ getService, getPageObjects }) { // function is taking about 15 seconds per comparison in jenkins. this.timeout(300000); await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.gotoDashboardEditMode('My PDF Dashboard'); - await PageObjects.reporting.setTimepickerInDataRange(); - const visualizations = PageObjects.dashboard.getTestVisualizationNames(); - - const tileMapIndex = visualizations.indexOf('Visualization TileMap'); - visualizations.splice(tileMapIndex, 1); - - await PageObjects.dashboard.addVisualizations(visualizations); - await PageObjects.dashboard.saveDashboard('report test'); + await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); await PageObjects.reporting.openPdfReportingPanel(); await PageObjects.reporting.checkUsePrintLayout(); await PageObjects.reporting.clickGenerateReportButton(); @@ -121,30 +86,36 @@ export default function({ getService, getPageObjects }) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); await PageObjects.reporting.openPngReportingPanel(); - await expectDisabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); }); it('becomes available when saved', async () => { await PageObjects.dashboard.saveDashboard('My PNG Dash'); await PageObjects.reporting.openPngReportingPanel(); - await expectEnabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); }); }); describe('Preserve Layout', () => { it('matches baseline report', async function() { + const writeSessionReport = async (name, rawPdf, reportExt) => { + const sessionDirectory = path.resolve(REPORTS_FOLDER, 'session'); + await mkdirAsync(sessionDirectory, { recursive: true }); + const sessionReportPath = path.resolve(sessionDirectory, `${name}.${reportExt}`); + await writeFileAsync(sessionReportPath, rawPdf); + return sessionReportPath; + }; + const getBaselineReportPath = (fileName, reportExt) => { + const baselineFolder = path.resolve(REPORTS_FOLDER, 'baseline'); + const fullPath = path.resolve(baselineFolder, `${fileName}.${reportExt}`); + log.debug(`getBaselineReportPath (${fullPath})`); + return fullPath; + }; + this.timeout(300000); await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.gotoDashboardEditMode('My PNG Dash'); - await PageObjects.reporting.setTimepickerInDataRange(); - - const visualizations = PageObjects.dashboard.getTestVisualizationNames(); - const tileMapIndex = visualizations.indexOf('Visualization TileMap'); - visualizations.splice(tileMapIndex, 1); - - await PageObjects.dashboard.addVisualizations(visualizations); - await PageObjects.dashboard.saveDashboard('PNG report test'); + await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); await PageObjects.reporting.openPngReportingPanel(); await PageObjects.reporting.forceSharedItemsContainerSize({ width: 1405 }); await PageObjects.reporting.clickGenerateReportButton(); @@ -167,44 +138,64 @@ export default function({ getService, getPageObjects }) { }); describe('Discover', () => { + before('initialize tests', async () => { + log.debug('ReportingPage:initTests'); + await esArchiver.loadIfNeeded('reporting/ecommerce'); + await browser.setWindowSize(1600, 850); + }); + after('clean up archives', async () => { + await esArchiver.unload('reporting/ecommerce'); + }); + describe('Generate CSV button', () => { beforeEach(() => PageObjects.common.navigateToApp('discover')); it('is not available if new', async () => { await PageObjects.reporting.openCsvReportingPanel(); - await expectDisabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); }); it('becomes available when saved', async () => { await PageObjects.discover.saveSearch('my search - expectEnabledGenerateReportButton'); await PageObjects.reporting.openCsvReportingPanel(); - await expectEnabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); }); it('generates a report with data', async () => { await PageObjects.reporting.setTimepickerInDataRange(); await PageObjects.discover.saveSearch('my search - with data - expectReportCanBeCreated'); await PageObjects.reporting.openCsvReportingPanel(); - await expectReportCanBeCreated(); + expect(await PageObjects.reporting.canReportBeCreated()).to.be(true); }); it('generates a report with no data', async () => { await PageObjects.reporting.setTimepickerInNoDataRange(); await PageObjects.discover.saveSearch('my search - no data - expectReportCanBeCreated'); await PageObjects.reporting.openCsvReportingPanel(); - await expectReportCanBeCreated(); + expect(await PageObjects.reporting.canReportBeCreated()).to.be(true); }); }); }); describe('Visualize', () => { + before('initialize tests', async () => { + log.debug('ReportingPage:initTests'); + await esArchiver.loadIfNeeded('reporting/ecommerce'); + await esArchiver.loadIfNeeded('reporting/ecommerce_kibana'); + await browser.setWindowSize(1600, 850); + }); + after('clean up archives', async () => { + await esArchiver.unload('reporting/ecommerce'); + await esArchiver.unload('reporting/ecommerce_kibana'); + }); + describe('Print PDF button', () => { it('is not available if new', async () => { await PageObjects.common.navigateToUrl('visualize', 'new'); await PageObjects.visualize.clickAreaChart(); - await PageObjects.visualize.clickNewSearch(); + await PageObjects.visualize.clickNewSearch('ecommerce'); await PageObjects.reporting.openPdfReportingPanel(); - await expectDisabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); }); it('becomes available when saved', async () => { @@ -214,14 +205,16 @@ export default function({ getService, getPageObjects }) { await PageObjects.visEditor.clickGo(); await PageObjects.visualize.saveVisualization('my viz'); await PageObjects.reporting.openPdfReportingPanel(); - await expectEnabledGenerateReportButton(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); }); - it('matches baseline report', async function() { + it('downloaded PDF has OK status', async function() { // Generating and then comparing reports can take longer than the default 60s timeout because the comparePngs // function is taking about 15 seconds per comparison in jenkins. this.timeout(180000); + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); await PageObjects.reporting.openPdfReportingPanel(); await PageObjects.reporting.clickGenerateReportButton(); diff --git a/x-pack/test/reporting/functional/reports/baseline/dashboard_preserve_layout.pdf b/x-pack/test/reporting/functional/reports/baseline/dashboard_preserve_layout.pdf deleted file mode 100644 index b7370109c687c8488b8e4964f3d7f1f5e8f3fec9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 301135 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%0D5&n!cH9#og^ob-Y5)k9a(rN;xz|c1H5&;RQCV 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®9`o0N!(ZQO5jo{bv(yyUU2>cy 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 diff --git a/x-pack/test/reporting/functional/reports/baseline/dashboard_preserve_layout.png b/x-pack/test/reporting/functional/reports/baseline/dashboard_preserve_layout.png index a0dfea9ef4fa799e8dbd6e512fe74031f5e6f79f..1eb5f29d212c230c984be34e4aec189dbd2aa751 100644 GIT binary patch literal 631719 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 H4o>~~{=zoe1dOR-CgddY z;mh6A32d`~-uD;u7=aj&Lx=Qa&*wF$7=o;=cipN@9U4Jh5%lfl@iCcn>u~wn!rCDE z422Rygv6Qz>5XPK?m<rM8~ptZpgQSy$!Vs(C0si<ue31LVFi3^9k5AfSmQfiI3)%O zkU?OjUMP13VzMG^l@54eTffM{-eAglIHW796lOuU0yT1*@r}`ip&i@3D%h0OkABXJ zyD6yVhv<p$!r`P8C+4z^s-S3_H1f-OC>`AMHr%Gjvr))y0H;u7Lr@GMxS}EL6PjPB ze&%ulovvE;1?0Wf<-QmY#9cCvHZ1ljLIivJ<OBUh-U)`;WM{D~#`ib>6_p~B3u=IX zU&L=HznyelkHYe|K9Y~{kZPY|frQAW?fnOA(_Km3-QC6~puV}HGqCcNcz0~1#4S$r ztSc0kYox;CGO4*JjcnEWU(|*6WHx{ZFTead@?2$EPm~PI&`clyvo%uY^8IgR)?r2h zTmYi7<G{6g{H5wVSK$oF&&bGWnfHs|_K4|F5Hoaw^I;+s8rHvmpGFvMFH8@C?Uyeg z3Nl|ipqyEQ6;)e^Xt)}4#b@AQMoWze$M`3Q4f3L`w3wk$R^Om}jqjOvbmd9}Jx~bA zK9xb`;|P@OJDCNXO3oW;l}<R2tk*F{87eS*L%Pwem?)UN{=MeJq)C<{UBbDw<W#q~ zb7!1y+x4^JTN}fn7%!;H3zH)M$&pWEHtkvPogLWsHmGnjxch4Fk!fCwoT^urM4FdC z73<m;HHbS)a~bV=r_>W=1Wk0YWKwR_*#}7efGBw3oww&VJl$A0l6pMHZ6%9MrVJA$ z_r^-nYu)81i(C1P41>0vDurwZv;2H<MOHid>4%t8$tcN>J5l;&&TM5$ESQTHyF<Au z?lC(rksP__Kr?>#o}I36NmPkb;wzy<femI6#g(ZRkF;$Z-*BeGlJ+y-vC*dLEvCQG z9u5r<cVs~|V1qeWorEY50M3{n7At7l06}8nAP{DPzO{?GMP5~VJB#{nyT^cxu4Q1} z-@tForAY7VI}s{-Zq4<T5Y2TVQ!yC^zo-6FE6C9eYbhA=A+F1pZ`>!HCl32kqR?xk zD)SY`A3r)i?SOF3R6T6T^T{eVw|1dAcC}`TxldgiyY;M5)tDE))81YZXa)00G|Y%^ zt=o6`n?Fk3{O*bb-ld4gB|P)<9mP|>KHMemL>E|n<Q-jSb4X+bW}Tjf9g1olxMW02 zm?rn(ju1zs%S2Q9+w%?SKpoPZUx5^PO=&8=+?Awx=UqvGPYwN;0}zz9I2Pb%mr4EK zjdjqvc@4Xt8od&9z40^RoD*YqQcTpWiykl$i~zsRiaw&cDKi1Xtx#xY%<5C6-_P!+ zQX3&MF1Tb;+vjRD53g2EER=@nNQL#<_|O?fzF)}V;i_|jgKJD;eraB~w)tfZRQ?RK zK@kCJRz-|6BjM4LCBwx--gkR+O-+-WuIuJ2EWD+Sy%wdms~22tP0jOle`hf^B3C=n zs?)*-90`{<q|-paA3!<_8bDA-cf$q)O12Y(8Hli!+c5vmRLhZpuv0W4ZSXMHNQy3G zzmXp`_eunLc$5zuc&b}!8HJSj-P!w%_EFsfg~ns%cAx=5&9pGC#Do@L5;7qjWZ$_| zbOFk9ev20Cp=~_EY9cQU!u*)giQPYA9%G9zqe--Bd3!umCBrCTfpfydkAEe^yZSb3 zPn`J8{$k(A$=$MB_?BIR%pTh|U`*y345%uQrN>Y$u3zCdWEsOf|CI&Q^^of)iDG!# zDvu}>x)TpXDX!POm~ekh?ABvu$8H^U1L4lL>*QkpY7Y@@e(dXY6Sxi0e0CAt*~Fww ztz1$4;sU<@vh(}f*RIdyBk3%0s;Os$Wxv6ckIsy{ZpQ)N+6iU#e7?`mNUX~VIz8kN z@ey5laD9I_^pEIC32N0H1V-Xo9rk^zMHR60WIak%SMqtDM6WxPMc#|U%rz_+KNS!k z$t()mfdEk1c~h}r^kHd0ZS_166M{r_sok&XO7C-P1{|uc)bH*Ju(qB!aJi~2B!X`> zQ8J!v84`W<K9yB}m{Z0BTo%d-NJd1Wp}h{+Ba#b2S@}r^Pfmx7f{oNyw&sH;OQ}GY zirgRZGuS~BBj>$%j$~>kfdmt%iG*(BE_C0PTS{2d-lojdTr1*WN2^G#C3$W7veaLC zVB>3>GVaHbJzEV!(bKA-ganBIB6f)-rle`L=5Xqzgeg%x0CC9p%IFE}<rcl@{i%}( z<N}4@Y@f|1C<3D97G0A64vbrmTspFz9XWyWX5v^Qp@iLq&vUD4gSM};WJru|t(+xi zuI>fo@TpqTKDwUix@OH$k~J5ze~I1Tk+LAQ!$+`$2Z)HCV8C|{C_0|(tk0X~n#c#A z2Yf4$PRG_Z>nP1l_T-g6zp`86`ui1Cl=r=gZTo;2mX_43{0L&80eF?(Fm%X@oHLF| z+y^BGi6jB|`-;V|Bw_kN2O1jY;vhZ8WNM$-_0H#&3Ftul{%u6&fL&Fp6XG<iOuK0Z zof9l3$k|9JpP;3Vd<eMi_Nox&wl1ZY^mV=`GDh!YMGF?8Q4d+`gfv6K!n`4xib^aa zzUrtvwpq_KVv8QPRNfLRnhD){z0IU+Vv<*2_0~Sfx=$sp{F#xKmL2UTTpq#D1z2(X zqYKytzqqcUT($ge)|&uQt9`z6<m@h)n{*8g8h^pP;*(2P(QC8)7MBWrq@X5&l+OlK z&n%34O-Af=W;uf=-aDhFi6*tgiNzt0TCLKrk;|Y?hoq58<lM)sk|HQLR}CCiZvFve z5(EX8D@HCM07;gPoyruFiUeAnU7MN8cHM5m!1jqXWu~!NIHl87`tWW*^?49T-wk3A z?8-l%S!6yW6C><%fk&SWy=_#GLLEu|dA84XJ^dy0ju^AZ*Z{mzWHWHb)iBdcvBJ8D zm;i#7EW7tjx1E3h{eY_4QDzA+dwZVii)-dQZyJmmPx?*_QH40awz<xb_}Lr!m4u@9 zM`;usn*S9Lmm;_)Z?!;Ot6r?g5wL<Ie2quctvN$5{G7@7$<gF>x1<1=!f!phs#AW> zO$T(d<7TeyCcdAS?4WH3S)p*0!<x9}zMx+#KpJ_~pjC<qhK?G@!UsnN8bBM}-J9^L z?^Noa&W~s$zQjwGPp3MC29{)UU#Ghgaor&O%3aJ?J^NkZAJ=~XitkclNPXx6QZ5>m z*yn(Zy<u|>8g-EOLQp>t9u!#;+85?mbc?Lhj20KD#VN-soLKZh1n73LNheeDRM17S z%Q|!ypWVF^^r;_4-y&eCT;Z-(v$O_)Ac#=hW$Ia|;JKer)z7xu_*XL!kXlY5bIxFI zk1{CWCpIuZ3R^bs@<f@uK@{~}pXhPhDNwXxKE>Ffb%bgVpO?Q&jkVKr5LNbCo6CUl zc9wl_2||s4+^FHDB<F@H!kQRq<0||t+^a`GXz`(%(yF7i^BnNhRd~{5#{+-5`N4dg zl-QH$uYUA41H)mUct}xVN-eNx6>TbR1JM|DK#Iyt*~`FO;4}_WACW4KWAz{JFXE&4 z>3*fFqYs-;*@Qr2?<{W6@*46nwSn%}C6Qkd3!3Yw@nUTWs*N^}Ql&Tvq4pW~#|v_N z?o{TDlOAbm6u;!AWfkbQ+nHMZ3S}R5XXy|C2}GK1u!VLz${^&xDMkH^U)ce*%f_(p zfN{dT$17`d!=inOOsI|C$XL9Ee7aA(=R{9-;_{#Z?!!kt%>$lD>PT$Squx$HrQ7zY z)^3%VHM+4x-H~62?8uP1v`UtPByA}6`*IJuA-qwDKLL7FK+_Z^x<W3$0%tY-y07#p zMk!s8MECqTZ6dHWm0;U|`Wf!0rM3PY&LRPe79T`oqFZy~QGQ^s-dBI$M@ElTE0hr_ z@QJBbz6QH(8=Ggu`G$WX>{Z(%ovJt=Pr_(stAN`eFKp8^fW0gH1R)GcPx5qyB(nGV zE&zbb5<nxcZu3~xIZKWvhpG7&5*U5=CL_zYH}dB3D(L-fH5JKpz@^(O7BN@R+uj4v zENI&DCE9T6!?=%R_h*C5d;GtK%UtR<2UtSvcBX9^H%sSJDLth_-~URx#$uib@F)lu zi}8K^Ym=vQAa1BZq5r0M3fb~c4+RuHp3vns%9DW_NltSo;k3lLr#P%=Z;8#68zRQv zE#GKgEJ*q5!4;Q3?X!Xm<M5dgF*ihNus%xxKul?WO&F1B!J#2uKjGmusUW~_1#&Z% zzu5QM1Q8{!sUO!b(1n1Sm{G)04y?)_&ZtUdK#`(!u8Ipwj~(K>R|?f)OjrNkt$Q>f zh7jPYJx|cCt3p)+@(96()O))nu8eO$Z`M>r$!^gStJLk>^Dhu*0v0&zG06SwUj!ia zUXgi_XF0r{M)oLTCvfe?4LK#EuU?U1`e&vg{6oM21p#7#wv9FQEbR{{JU<Ghj#aPn z3P0Sao@;o&Q8P=ZL4LBN>e(W>BH!T%1Y-o&LD-ZWBm8IJ<}y@kmH~&%9a>&zKGud! z=3+%x%j}x2`2XNL`5Xm3m<TfbDU@A>l+K=j5Ju`aeY$|Pr^!!|bM0}>+i92_-H-YG z9?|N}^(8zYG=!^vz9SmbBK{8PLp-&@jNuU&o|Zdqv0-vYUo@E8p_GuJ!T<eehWx~i z&L9LS2HIDEfX#eXoY@i9prqL|IU8tsyqgEGh~~T1z*fx^X)RJd(B-?bsmYnkJ~R~6 z8W3{H<nUE!a+?W{w7GU|I;|yMJQqPc$Al#Xd}lo>0;sS8cG04@Ish@IqFwHQE*lhD zAtFZ|o~7Mj;eBXanE^0p8cMC&wtn)_lNwOh+YbMD7mPDI`+6F>exSl~-Q7eVVWRGU zJp&k4MuOiZ>k=kNC9HeCtH2*f!<g6hOlqM;2p*#2+6Ga4wQ=0Y?iq7qI7c!xpcWke z3wRxkl?(GhO<Cs~A~iUe9p?K=jF8fqh*@l#BTkC>oaMn8XhzZdaB0Zp`($fbTQ24( zp(6@lSazV8`%X)#KM$ZQTgwv!0IN{w(A1^}Ir^eOZh24-Sg-q?jgxTg7csovdB*GV z5VXV~_zFnue^poCJrHovb@V3(asklgYB_juC-~)yrjMespwdBL4<zd|j^rf)Jbw+i zE*PWP39Lu&r4vBd5Z9P2LzPO*gRH4eRb7Tk+q&m-%m?Eh4Z5|#e0^p_c=z^vqfM(J z2B{Yj)XXRZM|D!-3v3}Iv|PPvPw%kNtoQXEESQoqH|L4LJGHJX68aru<XguaCv@p3 zMhhfPT+{yKk2HIN@)xXO6q6Npew94-l-$sF3TTy&^-T%8(E7+We@n<N_TJ13NhAtC z0aNPf*0M?e^&Ugt8lGcR6ioM56Z^g}&$rLXdaFaXm^?1Lp%H`e-y61OnD(A*(utYc z<<-c{+KrD#*n7BmdQt1Fg+W}Rij=*1fg))O&O!B}x1x<H$(Tog=#@K9WB`{dp;1!P z=baLUluUuoreC{`KA(!`w%=uRbNFaeUyN`2XZ!24yJC7_8Vz8s_NXp8kTbViJmQNg z1R#l9H-GS=ZWS<ARk{@^h^E)sOd)eCG9hig$H=O={}d8UftQ~K!5jOg!G)aF3b6_r z7#A+!9JZB=11a+i{0+nHnC`?e=(kk^O0pd^*5?=*xry@U$4PqMjrp=yb3*k2a4vQJ zSF*bE8^n7MsIf_L73=g-WY#HCyDLeU?lumVeY*3+TWEdNfZ7dtcHFwIU8Of!5Jh5o zIX6uPQ*&BN0!{m$4<<+>W|or!>iD~`^;|u?e$m9@yv!#DuQ=J3Zj<_@sVdr?6Q1V_ z|GSp&-HCdk7%QR?xiG&WRkb^3c;{>2AJt@e){4ODV0DOJp!%QfFCvNg?Ir<Ml(HwE z`ZR#8O$$40Z_1=;3(yEKFELAtb$yTvdQD8s(hGczJblRpl6;))uqFcEKtK##^S{b* z787qi_~$3ayIb`sbao=Gu6D${fse&N`uz>y3q0<<CAoA@D6)t3%0GHhC2fya2%qx? zo%mS;nZMQIXRO0ijx%QpKc;4q01k1sH(b<dIc!M?X8J9^!sxgyHotC_+DZUTHcS1k zkVl>JP|zpo`dC$;`6}VptaPWmliyDICkMq8TlOqep`|{RLRs&0GqNq_Vs|HCiLRt> zZX_jz91x=?$k~5M<f82wMYVGtagvmaV0(5E7FCAOuhOenVM%cG-A$j@`}{W*hY<Rp z<Fw(QZy;o1o1&QALEE5g;MK3V@7v;o?f^h;?iHusLfOu#o)y-34f(Qv@t!^-!!PgR zyzAbxbU($wY%9V_t8@(8zz3#ykE=0;o@M2T&b?}9eZaJOD6cWLJ_m3@M0pEvYzCwF zh9wbqNa*|P2+B`_8AQBg{7Rh<QXgZ<dO^@Dq2Acd=nCD6u4|-h5SZpwl$Amn%P3yh zoyv^4h6W9JSENx<&kX;*)mRF*%=$wG|K^eE+uNg=ZrCL7-07FlUXXT7gDltHbgIbj z<G)E-Md*F)h7Q_G-6{+A_S>$r9%G-s%@33i3VLoKMI^x5dG*@5Uw*o{Rf`@bdpDJ) zUAk%O-;C3%G<}I<UQdKZmy8mID&sD*<9WC?ZuM)f0Y=AZLLSs96FDKaA!&2#Sq!3{ zMo+G|4Q|#)mppnS6HK28Vh&QWb+|@KVF+-H?a=Kq4x}oy2Z=RpTXO@ufaF83()gkt zuZ>MFA;0A|Kb#5@?taNXDsq2=@oUMr-BFXV15cqe^Bu~0hq4+OH4}1ZQrY#4Ui$I_ zAi$ZRqpm?F4z0sv2%~!WuLjY<fj;&+79WJ76zPRV*`dK*6-X8ZEcEl*9nLhu``tAX zaL5EUAzP=SeX_rv0L6VPC|QCiH;xba911z4l@os8G7j=?)~JB20;X5agxNK0Q(QC5 zo$d%#>8CcDnd49H@;iE#-s>UUybq`%>!p{2gRvE<zUm902DuTX2$={0Zt)rsGbLcs z&0MPx7%W3|&|mg6*>a;jWPKW-&Ib7~55v8kLxIK_tS*np!UkT*&4hzd&~HvIaeov_ zeDY@JVWg?lq?Vl3Ut~?+`n0;5r7P#IFdRf614x1v!`@@B-n@OQ30fTl<pl~*joBA~ zrpHuTqTa1x(MV}$T#dn+Dpwj0?SqAt#@OP|GcUEb>3BuxreiLwjQ~}L=5s(g?rNu` z_XOH64i7v=3Q7j^V%y1ysfKVh==11!{m`V)YK2%&wdz_-)NuA=F0Cj_2W14p6+(o! zJ=mJH<C7(u7S>dsjhZ2E47Wp>-@lrg<Q_Nv??e}*B+M^h@W92oAlLoOg0*SDS~9c} zzW=MCH^f1l;eabG@5}Tpt$Cz50putwghRgkcR*kA*u+F|a|f{Hx(;E+f!=VZ6ik(V z86Uz9-MPbaF(LVHSacFuF$;rbiO`Cni+db&nxelj-LBS8YxY~6l{9(=BVAyz=r`79 zH|5aZZ;&f1BSYUaC4~;WV7GLqe#dtY-ds}PDXubq|Jd}Jfp82%5Y(Doqr>mVfKTi{ zSv?jAVczQdk7R68@P6yCuPltPb)wiiz<K8SC;x+w??1er*4sU7;N4S{TjieTv;O1p z_gB~6_Ig+6aOD`}WnH^=A*|@i<@>k0{2yT#LyUQjN4<D|IB`>I%7a=NZO+E;Zoc5V z=v^12{wtO}v|ju6l#mIN{o&zPa;C4kv!g$&EG}ICHY4-ft|`7k+xX&T-!tz*Z;oM3 z9B|x`zO0seRf@${^Sjxu&(_KOXg)!~``kVB6cnu*!`JU#SgZ~>+!R~%o-8e@<2227 z1!m!DPk66P(pCMwz+)I(r}E=L$LGU7-MK%LG0HIE9N$)mzWcp(gkds4a-X+xF)*aH z^h!NVc6`*XgkPLTSqvTKY++vUosfmN_RqcyZqHZxN{@gqjryhpgALcE72@*=1==6g zzVSaKwqoMp^B3bweuD4BIm7PBCKrn;K~E>A!Bf2Bx38VhcXZ|qIY9PGbQ;@s9uPaV z@tpZu)&Lk1*siVA9$gIQ>|D)EY;;n;AGz`ougpzQ7n`UL4LB0EOmjjskNMTIUX>Wd zr$22=BX<vyYV?H3Vpi`B%h>VyPoA6<e^oSb&_Fp}iqc=)$ZKu-OPfvFoh|2&k~W+a z3zwSo*(m6ySXu`MFTtEJv;D>4qQpBFs$lxs=L>D$_y3~>*mD^4t5m{79q<of4()Yh z%hcLSK6k4hXJGThl6dr1?Q>0YHMS6qi#au2UFXK?%uWuy*GS>OWgYbQay?&g@yW~} z6GLTLK4<0%?JtiTITN~f7w@8A0F<d@)t)Y2<Pq?SYg~A-#PTrZ2?xc4wAJRE8T+$+ zl7CTv>g%R?(~b50*T*JSZl7mQU8cH?qxe0m8|P~8u{B%tV;Pfb@qHf5Jp1>CRY$Ji zl;@-S=w%enN{<#Dp*S(wVoHko`0-lU1b7ZS{3T~+{P1H{VWl7A_Y~4t|8{tDbk(sU zlAzYsV*6OC=r)<pu{DD)>Lg4*b8=cLbtAKZbw`8Y`iob)sBx{&jRkyHUi=EJH_hr~ z{wA2UIy1zG%o11HURfVwH~uIvfuX9_CaI<-EsA{vqoaerXD<mbrfA98dj+tS-L<uq zDBrmB8b=N=>7KiP?1XnPU$TPnMz9k7sbu+MSIUkQB|a3_wRezhY`)aNKU8l~P{F)Q z@!?_nUvHXz7nw)>NK1eey(SE8V(d_NMAV=hd-GhS&(1g1jV&s=#d}xzn;c_~P01@e zKDnORHu;&$ju^Gt>=G_)qw-PAEcVX80V2<}Gf`Jmm<VN~n{Ktg{vW#DI<D$%dly~^ zNJ)u+G>8I{(hVYtfrQf1AfbRXNF$91s0c`d2-4l%9nxLWjr1blvGzIl-1EElz5ncw z8(8ZbbIuXZc%CuX$3OWjC_A;42DUN#>`FR+#Y9$c#e3tSwdN1?Qb8kbhGPm>@xKGi zy?iI~78Ba`!dGQvWJYW3(Zwd0>o0fSeUFYVaN>?C$P!G`B}d0P`vCKv3oL|O7lf)t zELGKeej9x)X?;Pe-D4<S)ab#L(rKk3u!v4l%<&k#$M(a)p+m{{z1lap8oWVc>V_cr zfg2A}NRXWGjO22j@TW_m=Kt1s!94mTBZ%xw!K%p2VtfSY`2;D1kk)=Y9%1-E=2L8d zj>ol@rgmP9oi(0NOk8UU&v!<%xpuMF&L#GsRUo@o(G7&)SF7##j=!3860b4ttEJ7R z^(}Xp&_{65dDuy+$jpTOx@h@vr}IVCd+u;9gIdbRtpzNsJ9YF4Z@5<nn0@CQ3mAnK z7}mcGlv%sMKGxB9f0;U6Brm@>H(w3I%2J=x2HCH><=c+9Yt`7$m|RHozN}dfg2s%o zPO_tTpy^$@YxLl$>^$yud(5meS9jzFrGy>**43%U4<6j|yGG}~r7fBSLx!<kXhQ~m z_1?WP9gR`>7cD0uf{cBK{q8CW+iP((cH;pm7zyrdZ<h2pSLzv;no);Ur;j*Z@2==T zO-g?45Dgd7$yMrnPFf~3(#Pka-DW>pq49HLu8()`-n}Vlebq~v)&Qs|rjung59nj7 z<2YROzKzsqQz<*-`1mwE9JI-Xw)s5H`qge!z6_163=9m!FvO<5xYJ~GJE8oZj*v&h zgOab%fBYH^H!TiM;CF5_w4ONOA3HBKi$C%frGRZhMv26>LR=x2U~;RBpcf2*fi+Km zf7xbl;Q768uZqhUSg&8d{+H<w$1{;{dQxn+zEH5HO12GWG^_B*z|3SOCbH&_V=U}y zNn%HO^kmG1_gkPXC$_r@bmy8Y@1TOKV!Iq_G2{^;);cgV_gFg)?sdc>(GVX==bate zBWur!EetJuqxpTjhoc3}KEeIZwJXg%!%ezc^Ob-?JgH!<S^3AqmYQ;xtfpBhHw{Z= zAp8x=OXft+_G()cnx^j^-;JzKdeJz8anuU84-*1VJLB(cJ!5w5<CXW(K@YP=%%5j1 zk<R7tXX4d-R)Nlc%U3vA_6yFAxdT;{9aj5w-q0XcCevxE1Ye(9<)+j99k;Pz&E5aX zHX~Z0p|rT%_GfiO^-pW4d9*|h$B*coU{j4ZGx?F@NEp>{!*z=utjzj9R%W8oh4+ua z{0pE#D@XJ$@EY<ApC0R<hE!t{I0XQ3YS=b=fw0R}>Q|$A4wIM9LgO(|?I6{E9etkM zCy=wrjm*_C3?7l`is7XxDQUh|E$l<|bv}(Ic)ZWu*P&?glfqJ6sV!RFz<$MOM0X4; z#_-<mVrLM{QZgKgM}L3L%9xKnBk?=c9<M&BAUo@$L8|~=^*c$07)K_z@p2c*kmCdd z;yJbCv%Bf2;aCV3j8NRU35rDzLb=6<PRE-Qg2PM=j<*qr%Y9;W@~)Wn0)MsaKc6yG zV*fHQp#AC(3*MpbpC~h!|MPcsz@(mD#A&>wa?SY~OtAC>JHqOw01Zg;4Pyum4CfV- zycjpkg9@EsGk+Je7l6al+B0?9m!~fd%s70{xz5`bp~<Wjv8{fl{+BwtOLGNg?x#%p z14SH<>BO)x>xyUEnOEnA(&s<ARi5uxoQp|ECi`6{CJrQx*FktfE8euOZ&`Au&N?5u zGW{w-ia1&^j@WW{-JP;0e4yt&>m-}qU38C>`PVB)6kL|N4!H?}jv~*Wf178jdCC*= zC6)14d#mn(c~G(YIfPF7y$$)M?Ka<IVj69cf7t1A+(`v&qOcdE+T+T2(j9&+cwAOD zfzd*<B47K1Ss4CqxJ8D7x#r31tJ}q$;qEckhJN#JMr|j{NqiC$^{RD#gGcHVuZF=# zatN(ZF>><7S=I}ocJjdo$H<HjGu5}lcJ&p-o!st!>~7z_-C(&c?~9a+;q!^Ju-=&R z_>Q@r-gvZA%n|=$wMWvfeArGuoTN(3X}7M}*gggK<DcfT1I7hs;q;e9Ph^_gTSK3E zekA@V;r`sfW3Q30UGS_DzW!S2Q`~{w<=)UCw#x?qI>Yf~6gp07==5au#UsCdrj3^P z5Jxmiv+&wERxk!a4BsVWjZ>w3le_15Yfc)A760kVtX`-QE#5tY!P}hoH@hd;{a^Qg z<NTL<5Ea$*@vpsa(C}C#Q;IdbK>5-Y^OgLDf6_NjmFr*!pFDYjYO9Wl&bF>%q9Z8z zvwAy9!F%Q}dTse8YEP(Qzf=!lJBs%=+27z&d3oS8uhottc*SzQJ<Q}8*UW?J^Tk|> zBrNG9L=5w4V<<?$l4VQXpY5U1GkiI<AOWlNh+UP^=Gn@fo~EXoV3?ZzyoMfl^}UNj zHrWIt(VW;7<X*OD<W`)sS316N`l9Tx`*}s$;w$k^e-&Df3ttK6AAP%HfA8&cBcMx+ z4Qu4x7@hP}uyrt#G70wY*afXh6!mckZUKA9uc{x9d~@%9p%`IPxOHT}sY}d3mlo$V zaXh0!=iX!{oAy^mN0m!k%uP$Pwg6}T@eg<B788bO0-B$e@G{iP4Fct9oUz;SuOYLZ zW4CKVTS&#}{MeV$+?E?F`tJ|c@L_s;hzGR73g)O7zPp-9VBFf{W=;idZ$DSZ_1+e& zmJXY&A1=9hQEg8QP3uu}yN1>U^Q{L|C-EynrKDx%SH4W`6G&sXAN*r478Zy9F&K9G z%;eA8M)nef?8&5#yf8=RJ?3{Vby%{OSt4)zaru21_f)s%;+$~U>GTSs!hSR0;`|%Q zZFLP&%(@|4*_4;zWAsP|8Bq=|QQIG4XY_(T!ZRhe!On-^Kak1?R*oXb|021#%(JqI zsK`Uhj*r<5Uldt5cBi{|rKjJGWfQJ1{~Fd`b%xwCT>N-vrN5ePB!uMbGp0L5#q<6{ zp^P7$PUZm)$J>hsG1w{FL#fnqva*I2r65h|$=@V3Sg{#YynX#H8HWaer|2@%C#rNC z4OB?cB&+%;sNl`N&b<$W?dUMi?PyzaR)2*ACS_7s-kLVpA5BLEKCGf@7>Sw`$80pr z(lxzsK%1`fmC4cM?$RnZ@g%$Ri=AP1s%Fa<O}6d&76)K)-#8EPkCSeQ_eBkZg#q2I zObJ6){r9?g=1jvlP*V$KLg)SXONxr>-YPiy&dodBD*re;vo`dCqG-5m&Jy7nQ+hFE zc32`8Q(740yx+!<^;pMPby$mmD&bLug}X#;mB89iwy*bTseZ%pmo%kTQh{OBmESe^ zpdkrN@#r?Grpd}KxCm)_xaeQKL(YYUFzUdT6w^>=y}atGFn48X>DeAn7@?``XIaaC zvKkuX^Gb-6NjILpNc0r$TuWO^;;xL1?I<ilGQe!tit@<|0kh#JR#R_P*a~e$7o^f= zdB%S){`2m;)NHEN_VRXC2bMo=Ka-TSHITg4+}0Lg<b8Rx<%X#1j&VdFYKJnj^Rx<6 zgZm>Zu@Ger^QrwdXGA!+zC`IE+veFAiz!;3DD5WDP>^yQD@dg66;4`abG5Xzs8>2u z$Xugp%4tRUwV4l$5Y&h`A5r|c_w%EOs;X90<mb-;@5KpqNungEW6$t{c8^TDI^~z9 zV!y_11O^69c6vQ|oqA78-Z*-aknhomYLAYlB=5wZW<a_r!Y`E%(!RZBB+`kKqf(up zy|CEOg<3b7l~E8=ufETMgP*G^lh2v+F)=ABZhOlbSuR6o|EyxTz6!#n<khHnnPBQ4 z)-6~nHUpx3?b-n3;kmeoqVj`j9X5njZ*!|cEcZ?XF${zFFy5C&!%<qAeBPx~?T+qA zbv^#*Pcz$LX@;|AylWl*jD+G7`oDomIMuwX(t42QYVMFD5-%+6@41a*)GsbfJd#LH zUtR)F>%Gn&PO_-)rB%tSdv#AL7~*NK&D&(Yz9hvzQzFr$Z{zlrObsa>VSH)37EEcC z;B@JZ9rJF5=jp_J+DFdie1`G4TCBi_9bUqV+nM9vl6R#7B@GN(Vp$*KuLfLNWB7|< zAi5GnrRSo%pT`^?w65ZWnlEhS!#OGVkwLB0JUV)Fcv#hRI*YjE-CyJS0?m>wgU*$g zS1+Emwksax^d{8m0Z4`L1V_+Ut!Wb8*%A3vfuGt}@XSfZByW2PO`2TNRYq5$O^vBh zfo6eis6fza>Bi`cG{nU%3bW4rA0HZzR#|gosqA<0b8{P4PYmLB>P69tC%{q<4)PV( zKaLiGe%5SSFl#BbM2$fArmugkVpJSA1kEmOeI?91xzAT$vM5#D0A+plJ#D72{G{0+ zvz;qV<ezbDs)>;nO7^x(-c<{M%?5~%!N|4IiLqNSyE-W}J`wV8uTC-N-ESP7VUh}i z_~#}T%^a;*wyV<R1x8kaD-zS~ZpPN-)6*r*L3r6$Nk~Z4U#Z_`mzU9Uu5fhg`<FH9 z!fL|Al2k+@cN=>&+o#(0tLgldOGDUTkgl)U2s$wZMYGP!V}D-cB7|>E!F3bw&qchn zy^FOn3yqGGs=x`|W^z}Ksz0!IzVj{Fu;+ki*(E_#B%&FtMR6x31r?iez-n0f8;NUl z0@%`53Gcr@_ISUu!;R|DUMY2i3bn6ZqYNzkMUaU<jo}$>Bi<R0${BnG!BABRnqNh9 z#Y#N2K&~w;1hl1@!e&mliE3;66giT>q4~gf|9LY+@HMW;Tk2b~x33FS`PTd{4lf)T z&h_$mvA}yblQ99QF?8=C0l^_|FVlQ$NF6)^qD&?SX=}1lQ0{ZKf9)JR6tZ}<1E2Be z@BCwRP0iJ8`KOU0-z`KBe|q?1Rv1$nYigFS(nK%Ft7Hll5<49~H}N6bWlVJ7d;1t2 zybnht`lhL5a$6fqL~upUq~c;v4=J(Bq6h#PUTEhonXhO(|Lk-_cM)j_f+1A2G4{5n z-|zXE>7NwJZQa3+xF6mTK07C&dv{$(p+<YBeZYj(-_PUoG_h9Lr->*CRas`-A)1lC z&0~1_gZ1f?A6h%5Vl~v<1BvKqC7U^ZRm?k#8;>5oE(%3?nUwQa0dRDZ#^-FueS;#$ zW_B&C;po6QFmL*OTz15g`9nH5Y2l&p+b1Zu(cEE=C^O%%Un|SdmZ;oZhu0~Zus)dH zo=UYQ((j`voEq5Ri<<;Jlt))8<rwDkIscWt+HddfPB$4)E_Fw7-VEsG6%ddCdt}YH zBk+J$qJITa+r^Lai}vHg+pGRPE2q4eNOu_ANY1HKFG<dcS3@u19BWOy&>3mXv#hX9 zOh!YKTtt8nb3In?)y$YC&%YU#+SL#fP>KQ;)(e?B=QOkj=&-laSMiCW<4<N%UXfOd z1ze4-ZF~22bE3Ef5Qjld-4vTUhezR=f*6rs5;$wCQXz8ZHi;JnBukBjXaUn->@@`k z<fxI0CJ`+9goyWld6FNitiHU1W<^o#<9rJzj@Od0oHiqxpt!S^olex6^5ust=a=c< zjH<qP<d>8d8bygA=V*N<D_i5(_%kX^i^MArsp|}mNQG<#?pxJBLOnT9k)-lQw5 z)BOV?%x%frdF0}5gmc-O{{UlU&{7Qs-)m&NTY;nuG3)*qNy~OJO(<=X-5#z6uO5oW zxSn_mUDUCyTqt+Jc)`pQ5$1vjquX5{+q<N{&A|~Ij@3gN?yvBh{MSBKC=?oD%c7<( zv0l1`-hT+4V}yjmA4C6zxkC3ls_dE=o}yc8Tclzp%O5vB*q8r`d=Tow0G<5nQD+$f zv8?Q&ZCxXit%~>i$LSqL@e=ctB5`cOZw75oAOE2z|L(f@HgT2*G)zOMNBzYIZaLYL zJq+jN%YVb})i1ws5`1TcRtX-xE$ne&O%Q0yq<)1=DslrKK*`CScsKLjKBS7bkHBhN z37S&V%Rj}veFq0?e5dyvd<ZvuWgMcvWCEsJx2`kG$73R{(M;+to7YsK@<VqCef{3C zgS2<pPcB^5_=|4C049vLkCRd7uCpA%y|)8Pn;YB4tH~W`6!w(xuG6v$IdrPNKcHu+ zou1nNvg+gd{254VZ^4MF{Svy0D&9Bi&7EpD1?%w<YRfea2QQ1Cs>6_(1~118iKEb2 z9%AAzSp<QWj$NE?k^Z}_tURnA<>rqLB+Ii>#FCzSxV9p|Px-36J`4XPTWKagNs^;o z8`!+XmN(t1aA1;p>5yYnAMeK*W+xo-z)m<6e~2I<tj1lg`BiT4h6`H<zEQ56@LO~9 zPpqr<O|B7RT@dO4-0<b|XY9a-KT6%WQD^dc;0++GVAXB*`dBj-Xfca!uEP*{4-W0- zi<zo7hKHp|IgA#a`3nm-9Nx8sUc^Ny#?=1nNG?dOyHxj1R=7oq%T~(8Ah57b*+=Fc zbK(Gu=j|Vwu6+nu?9N053F3E-1zYtHo(G|%x!iQ`jRia_@#iKNmJG(-I=A05=#*Ju zBFOLE(*5u@(tWPh^&tAu{2nx|wpM-g;WNogrGa~HORf>|ZkuZ<>~)XgI9DkY9?*%` zr*w{dTdIAJ#BEiuX{>7}zYY4TQ%>Vv?JEe=@t+J!Jr11(FQGH7foZ%1^(Ks|3V(Nz zAmP>m|3X7_$ME;3MOqm{g{nTz!yA>v04Fx{+efiGcQC13OAv?(ht<Ts-=FSmY$B{a zD7h}Wwtv;SgYv@;+u~_?u60ORz*_kcv$dBx1*>Plj|W<iv{Rz_+eDNN+fD6-S!#^6 z?75D;IS9{ltdP8po6QzgZ6$rpDIXiEK>f<VdJ@+!f*Q>d7-o|1?o9_S<p*B^*DSAx zar#Sww8ai1&^Ht)t)^%(h1FYj${${KsN7&nm2f-B`i&=62`i3JTZM6{YKI=$J@YV) zBtP<1ZMJAQYka);B_SLKbj1GVgwkAezrCdUZ89?7IjulE+)2k-Y(x%qdzRJQgN+Y? zx;gqMis=6&zA2QBHQ73qXu7qjtZqHVwQ)p2VQ2_>8!m+t)oE_Vpmk_Xj2ZcNs)`1M zfdwj=*uJJBpq22;Cz;IC*oywc|5emsyYQyhm03TBoBTF#mDYozRa?wZE<~)b3oY6* z7usx(w!L^cBJt(PHr+1$4fqjjcW6*hE7Obx!ZSmK4bNQ$L`XWi@(1lrP2Uf0LSF$I z?kFA-I8+T4`x~t%4<SU=)~x;763kPO@IGf(wG696)ZvWpLBC7g#dNAsNsVDsp47&+ z{d7#x=(7hlgxU$=I1D~&S>O5PW5t3<n0x<h@B6Vi(MdARwGropsZ~1{lP<l{{Pi<b z<U3SJ(Ps;g4qJor^XJ{qQ24ZD!k?1n(S!F(8&35`w{G1UdqNI^zw`K*$Jof`7owCX zaGH{tdA!di298J8&VIvKZTWiTHl6s59^o3!lZIwCFRA(T^f%u{+z7}jbMGrEw%nU= z{jAyMtq6(I&!XwZ->s%&6?m^oH~n0WR7{q-IJKvvivDhCUy})rx{@zM0Rimj>}J&B z!D~3iHEu3f5b_B)iqF2%hd<M}{|V|Ru<~z;ElxNIf$^dte0FGYBSwc&yl^ptf1R`= zT9DXMW1`8n+-<>|EK?;r)<~2jQL{2Lr*(F7f+b~}O*xMq^=39j4{<}r{~kZR*%{K! z{CbX};CcU|(3K7gBnm%z>)(49>O%Ldcdtd@+x9p0;qC!mjTER6KPA9%m>e(Mrbj)% zutnuu;e9Rtk{U<hx29MG$U=ua%srDge1GmcjE}gTJLJvo31n-s*xB(6+W)i=Ha3o+ zo15dZ`m><1F<PvUhdw-#t2^d202Llzr}2mnwd2+&@!PzpBU^>(k+SWL=WI8Sby4J0 zC}Uo<1Sl11l+LUTH+TN`drnNJ9!tbB?sk%|6SsTG7Vr?zu*L|DBXc;b6()!5T%2S5 z{P|N4P&{_Lm-El-*>_I`EKamAu1?Fq;8B<zgYQ8=k*xGt-{HyamtDFm^*V0>#Kwa% z_1{B_Z~e7hjaq|Qa}9@XCtXOPKOR@O^R1seJMn=jr-kG=2-B&8s0L^<S#)EM+<8`) zUz~Xnzz?s#B)`ySc@QC#+&BCBxV<KjU=DrlT@Ge(S72TKnab{T^2rDzmd8SXtq8eT z&<Q|`cBP%(M0wK`2?K+c<=o@Y1cUx>8XI?#OhS7o-Hd_qJ0?9hu>U|rx2DQUR}2d= zTWF1U6`wX3UqbWVo(CSc%a%b&&ShWNC^RWL+>-2aX5%yeZoh5fiD#a%)o{RqG+Sk* z{ww*RsVVfy^E2$rWahc8{ObtCsT5W`uRjNy10)d<lRGt_>#T>sW(T=PUgbjW?d=~@ z(2;^dm+o^Sj&~RF#_czJd$dm*%;F4Y@n^hQ1UP98TjUzcJ@JnBS9yU(lW%+E&aRnH zhEQuWktdaW)4+n5lsz3>wY8Q!Mnn0iy`9TE^X6A%Wkc!Gn%{pBQuJ`mRH-l*y_>*? zX1XIQWvhEaTcTDNus0v9mrUKz`CKF(3Q=Cr#j0Q$uSu^V1d;&(0S})&!+keZ)9HM0 z<^IHTDW!^y)=(B(MpbRnMlC+m&u_}d`NJdT&|4ZBby2~9kFU7@b0%pmEinS>eUrwz zLl{Z)C`f(Ha1S%^q47<T*9Zis&^y>C8};XgFR#NNwJvdpS|7Zn&&(Sv1(xbuPaOU6 zyXlZjHFS+s9{~Ts4jFg8Ik6dna_6BY#C%O@++o&>Yxqsg&5WF!v>ybw^?Jk{VN;=b zu6K`a9jR)#zq5~IH8&-33=PK?@*sw(o%COxSZ(WIgFkHYb6guL3~Hz#?J$Xjxdqg% z{)9NJF2R)jMR(^JpjHLR82Z&<pPAt}q0=MD(Q-4%lS8W1LHb)jHK+Ps`x{+0GPnH@ zLZ@)vk>Or;@H4Z#l$Tt#n2DKY_5y=*utYccjd4+tL|NH;SK=UI>RlrEjQ$Y~RA|ro zDm6<=($%@CU>GbGBBxI_?Loq4-N2IG4j-ahTpkx^rl+DuwB-#0c;F@J**AnC)<NBR zi@cTLcE*{Fn8o@xyKHYK$lCY|@Tqw2=W0;dOo;L!%WrTh2Z$@>YL^mcj-1TSR3803 zFk}51rep=v-9J(CMseu=Dmh7##9?@t@DIcW{|O_3L?`q6cOeG}3BpT42<AV)bFU0o zvYg6M({vi_r!nBJtK{kg+v~&&IWfUA;RO2NsRw>^#|kydw1QOw>z1jArO{a|BKwWo z!HX(Ks~Rov;g!ILUZ1g&)bp(FB66l*sGOGw*g2VumlzT*aqYM9@X~N`|7C=!V}?fa zm&Wo^&pOoVdFX8o$dHHibBxUNJ4-ZRP3R$pWK(l040(NidLRQl-C_~4@d*F59gQla z{7r<K40>IhsMN~ubV1eJgL++AHT}B8FXmB@RA#-ZrZwq_Z?#e2Lfp?(jduIRxtUWz z?VUcboM;w$0V6Dn9(+~}XYFBUTReWso3~v@j5>s&PoI`q{l$gy>lM%Sm1yLo!0V`= zP-Gg4$o&W9dryBlQeFk$?;z(7=7-k=J+Eg12;7H{6rC$oU_#2buY0DNA%`o&fpJ{W zZ?|>NinHtmyL^jpkQ(YQ5s?gqR!I-Wrs-6mNKot)!BaGn%a{l9O2mDj4CF!IISb7g zSB;z;xAXbd+gm!Nrguxsr!YO)NK)k}eih;Sm4(>dZ5=OOG{8VDMQPL?YHe@dach8Z zeg|-1Ci(bwFM}AP3bG;&bdTcseeoHS;rGbA<?oVM2hz&lP7aMFIPbtF`wq2))7W;U zOMkFyM6?%PL0mzfye{*VZt|E@pPq3i`#1FEXUR+)B;R``7uHsw^QrO3;p;P_&+V_D zgt<1xu)JH&{8p+``nDui>_AX8N9S??1G!5piPN}}Pr+<yjB=~BjzKTy>v0vh!UZ?$ zy-)J>B0MaOUeivlRN@0{^Wc1DO%Ec@XX^l<+)ub@L?F;i&c}Rno&f;$JeEgxGn&P> z_<wN$cy<>`F%h>IlTldyFyoVe?H2y5BkDT*4}B%*BaQX8NCUn%lk}b2o06tK^>Q&7 z-VHD%su4ERXQM1@(npMuC=uFf=Zu`h_m>Q4wWaF>2%$VnwvLFq+4m$lIPjBO<&CP% ze6n<qkur_=f5A@pcyMa@B^zpNOy}b;F)<;^8Z3IJrExpQC&n7!YEY8YSrwy}bilwf z?|TU54z-)Bm3Y_y`5DgDWDwe@KcFhT=d^aI>|O$;&okF*JtLKGa(GovSR?~3asdyG z%WVD@HHcia%GXQ3JNE3-%225v=a<DqClWZ_^vs<h2wxYl=qIAx+PmR*p|d^T>fB!R zX6lM8SvQ&12$a~tbfRVm&DOln>36jVolmS!9>ZIWy_8dG<NUel6dMuY2WUazv_=#d z-kn#~&(j4{IZyvGRzQKDQAW<-vep6lNiTT|LZq8K?DO@99nAw?jg)Z`B%YW-JRSO9 z+Mdsym_eW)aZ!9f32SFI$&mPD1&8SqUHYK(3S^7dD7y|aZm`yhM`ZhfLo}Vq;V0|r zTzPXltUa%3N{JyeEx0)RLAkl5Nst`XNaFWkengI!q4`Ot(UMKv$WJGifaZ4feDg1Q zeyTbTAKpG8q)f`&hGGLQ>1MUF-G_-H99Buj!f)ShuxnLOUuu<QIh2doYt7Y|hBOdq zd9KX^CQp8ij{k*4-MXrzWy%IVq*YVS*A&yzwg;0qmU`wwl9*b<YD<_EsDojccZRmY zl+zWf`WB#$KZ@#4v9h`p@O28Mm26Is_VJ&m;&o;LIkP`R4&fc-7f}yacnfzKwKO%v z>4tJz@y8hKB(P#@1IBD4>-zhzpth==MNYQv80zF{HV#vAu-Vl{KDn)4Y>ZAoE0W=$ z4Xg<D#nl|XrlD#VhMQ5eWmZcIQuU|(tv_$ut@UFWSlgWJh3Cp>P-3@d7dZje`?>4S z{ET771huc<P*;Q#`+XQ~7@lgT^b2D}6^qv+39BbooKRL4FIK2RaN<MFlnX%<;3=q? zT@@)<nQfhN+rJl<0Tj&qZ1FN6B?VK}r6Re2tTBh=K>+9fF!(_mgLEb5)pv}$zhB|y zU0k+La=z%YxDKIra|fyHs4$w9#veZdy4;;gqZ}6<c!ql~lb8xbj*8t({>+G<T=b!b zG2@INJ2gwE$weJEM@(a41l|OYc9PwFj)#NO?9<Mx95DbBmFv#R2fhgAuHB!>nvN`T z!%|)hxWtL5T4?HX%PU^wp#!uB!;w%S#qBS2;S{k1v?mQP=RD(ZEGRGWo#<$fYZnV& z)va-r8X%(?yCkF=P5SJ+r@vzODP}fxx3sXR$TPQ>@*Ai2%Qrgm5l_jvv>QKZ?5S`j z12!}AZ<~F*p|iZZNv{#br_TptL>b=em}!PcxLnXd@9msC%iY%TmT_Dv!7M*-?`oNe zw$3%JzEtX=C5?{Xs<~sH)u)7JRjx|~S_6j%UkUC2Bj)bLz~jelT|^^aN)|^Up3a{f zz+;xrpmXE5trSv-;rV>TM)Pa?uS6JNJ;N4-kqd8nbGmVHCN8R7=mt`IUpTqGH+)Rk z2#hSgn(cMgePMFLm;F6goaA=vV9aVu%cP@;36*;r*=7ihd+Q<|vquKKt|y+*Xr&qN zIu1*&l7Go)e)r?NIXy@dZgQU~_|ivSJy<u`WF;Kz=Si`5pwh23GQ_q?(xZlA0JTUS zI;x50cdqMENpkCCqg8LR`y1cySKd5y^xcg<A7&c6*+L&W*?2V<RE9fN39Wv&W`)&k zy!=naio;2wB$ZZfE_cU}ua9Kct-O#9UxI2j?o6;*fr>C1V!p+SR1TG2EUY{gaO?N! zD<iU^23Bc9z?_Fc^$709OeJPWh>`W~sC$`QjOW&rh(44GM}cB+b-!1q!rIJ??HK8t z1clURwQnj*vS*jqQwpRqU~HbyQZ3ejM`rT9sp%dvFa`B3_?h3{d4Zrs8qO^O;eB=g z#YxvYZ4o`VOxdvAi|<=2>SRC$O5$lFNB9v^`2?@4<@YYbll*ft?LUN{)tYoJ$<ber zlDf?!?SE*2AxZApAe~KQ5o&m}zrP32)w9+Y6MI6I(^cw19%O!mG-=<EW%4v?aEmxK zS}O%~l0Q0nD1y~d_f;S@QvQ`>V&qj0KSrkn0%iCBG$n}HKaT{W{Zu9u8P}O^$(6PO z*5zYc{=IUO*ROpvc$p1%65Y);7wHO6WlD~ik-HeTjO{Os{k^@#9n25(qr4G$<Wer8 zn!uhA*95}Z$a;s{UuyO}^~6DGg4u%i3O6OM>tsf<Vj?q?piow&%Js<XL;M)9g7V$t ze$5hDK*?(K&vLev+%5$ZVl(tt$$EO_h?+xAfM?-_`pJl^-TF8&z`_RiYp2z>i?4WN z9VnGgPds^N%BEuUK}7PTIGpt2{ZhA`R&jYrfHBOu3{M3fTb;$)`>wdn7U!@|TObU6 zIKQleisCb=nrK$7G$KEI8f;IOn(LID-yn(=Kt-`%qrz2QnD1%?Pghsmt+IrQ3aVZ+ zoTI~fa{<p(?H7irE*1&td5F>AO#!<^)iKw-s3j#)NmPkAK_TBjV6>_o4|Q)9wG--^ zsQoco-tF(@io<YKYSVNuL}t@8HrDiUCq6p|hav#P*H%WTTpTT1eqdgbT-(LuSwk-J z3hr85hl)B(6UXgc3<_VH!6Rcw<nqh*6+BWB2+nnJNLR(IbTsd9_{{bBpggx*H0<Fm zBZ_nA)0)`l@S0iip{c00Rz_X#NKo*nw!+fF=A9(;e5(ugVyT+@!`rgsHRu`r<w~Ls z7Fn+f<K--;GAJ&D9j~nqbGD-Xa6cD`EwoM;`Bo**x{<XE_-!>F`*n3_9(wa9Dmz*= zLYl1#kq&AWAs@=ig+=Vm@epZhrDV?{*pu$nz9lu;nA-FQO3Yo?)Zk)L_;pY>)d=oY z<P~8}CY&j=g*PtLL&b~hHnbkw4(}~;Z0$ET&F5YXU;;(DAu0^3FV|8be7U$}(G*6+ z&sJLFi^{lCu)_I&w8u1BXl7gD?fN0Bm(-%;g++YIHMv`n*_tF#ox54%BNkcN_ni7~ zZcJ_^!#TRw^$&*d_U*^=!l`?fJ$5N>WPx43)8;Hk%iP2Dc32a&DcVlMLk5oCCvf+) zR9@q<rBJC<#iyPu#s7!Lr!)L-DrtiEiF+x%uG<L%@5$0tfJ0#jdPCbNHpGaOn14ZY z1_dXdC=K^&0*d46rztNVKCYF1H7*DOmBif!A#y7;+of_gqn=Y8$YqE~&j}n#npJ9U zuRUN2V}Pvq>C>lBZTlu4JdeV_uO@Infg$g8A9c3QJ$nY=@}ilWXo_jBr>3OL$vwOc zgUow*u%E$4g@qp({U%qq^#z60sH@+QnQIuM+MNqh|5Qr+C9kmXQN0)DAZJW;^wo6b zAEoQum95->TmtH$MAeqs>2wCHSHKECUB9zYKx&%SiToV%^!Cf9rj}d4Vly^I>YHdz z>KQq`eM<?$>c4#ZhGA=KdxPuUo_6USs1zC)80up%j*gR#OeoF(!6+aw(EA~)RQgu} zXB_1VNbskdo9^$*dBL!B)5+2JuV1~6j|o{`6+H==l(zY*%=&2RWKy;gth6s~H^8m% z9(0Tp#HAC>)<>AWJlWY@G=seJMN-wgf@3xDZee>5ir$qL_P6FuLUxZv^zdDy)LxOB zZpn_O2BvrKYE6BC0lX|PoBDspNMkcx`v-O_PPVrBL9?m0_lUiv(lP(Z)2APNAL-xV zGEROG)lf=^xc?Lj>$@>=VunI=6>l|UPa)c6h>or?&04G)@e-J{Bz#DnzA36_T+cwr z?Yi&~q2*Tt#j|z(v0x??!D5RW1#@(DcMowghP9*Cm8qqL1;GB6i7Pj2o_F+E5B}uP zjodqSDQcuT5m|nt8Pd{P+j@FL_gT`zT}WuujP&O(4!MpO(vq_0*vE$lgGI_W3iG7^ z!6`ha_*bTM`#R2#AJg@tO*diB6xv(1%TuuISJ!q}pJ+^*z$|SE*C+Q~&s=V>D-$)F zXW^?_X61gWxv?U9&5uq#NvXBuyXZvs@0dMlSvfiB%MXmB_jrJ(P!Ao_hpzstzWj^` zYVfT&mAwXo>KmT{S~X-Qn5Ytznx<O|5jhe!7iysSv;n$J27DGh_{sKN9-%Ko4gYKM zZrhRcrfD>kKfY37PFHyYP~8B*$S(z2zWt@M9We;2J)Bi7fg1|<A$M2yhZx|M5aVLv zrV&QpxeZef;|o_bJ`y$lFuUhnbH&XgcAsn^a&JRJ2$3jtzJXuA#|HXGE{AtV^}`k} zc^0j-(5VR%mE+46v$ANG@I4E+^Mp11nUccr$Kp2V6+(fIK3nLXGMhKzL-fEV7b+oE z$PW8hKvxG+KS^gsbSwT0xHJ8*su{rCxl$u$M9vRc_wQdKxyqmIKzzi~7WrTE$kE}+ zx&gp#5592udmZtceL!*l;b_-t*zC(}o``Jqpq(A^n|$y2fa;M9twLE;`q733RND*< zyjE6j0u!JKF2ZeaoN!aZE-^_k?yO-&q*r5~{ZW8^AAgz$YMD?b0C=*9M4hQuSEr*B zq%Y2p+{XKgkS9^IsX8;P=wLsf^|=L%kq&#P)7H+DU4MX$BnEHhH##aL=6?Muko0%7 z7PE^!LA*Sf8lv{SMbh;0!liS&AP(NZf9BZg4~9gzf$On}X$^%$wL6-RZztl68p2el zyqFDMW^)c_A2q`Q!U$w)C~~Rfgnj>fOjG)q$jB~knc6wxR#V;zWfz4^`kU)fsd$~Q zCx5(5zXlY$H(xE^lQfH;Dc@Cynh98fJxMF!`soZQH@BcX4O>s?<b<E}MPDBPaZNFT zmc-<jw3v9&jpH5A1~k&!u)LrR6s}2vVMGrC&|ELhFtG^f8iDgNiq3}sV!;n+!+R4_ zR49r4$dd<NK8n{^@%$+uMJq0rU=sfGh_`8qlUGB=``UW9oQ^$+Jf6yczEKZM*Ge~X z6(CzMY=0~s-iD=rq&z4JB<zNQ0L+f?yTQ1m)GzY%(4;Mykj=0mZU4O?6<@6EnSzZF z#arNSM+eI5O)4t1SrN83AFsGU#Q-)}K8$vyXP9IBcq8BE$!p`4?*F=*|J)by&I;Ra zL4^==nty(aWI*v7CnqO=$4LEWZT|NvJt)#MU%{vU&!_*dZ)8cnulrwr{(pRh`+e9` z|Hse%_y4vL2K@Wh|M$=S>t9H;7l~Z|*9HIcekJK~_wW2aZ)^eU;fI?4=Wl(^JXwDK z_rdy~kMNm}2=fH?_5b7IyXYN;|9UCz${#+IS_4%BM#tbZ`d#bl+jidFr^uNp^L-o| zKkL4Ou1?DFF+(M8ZbOTB)7{ed3T78+#3gJ%UgK^o1Tg(EG$#y%E8PD3PJgfkKEy4h zuw@8;HpD4tzH(nVUF#`~?E2k$yqwTkW_v^nz;Gf^V$xm>QNTq9E8_XUL&}PYF(8@h z!5Ao3mF+B}C`|yTS#7&x$BVi7JtJjHG{z?{GMk{h^K8`U)TQ~)Yie-^TyQ1U%QN(& zV`D!`%<%clhOzlG)H?I+531>WOy^-}c$w3>F2)p|%)=(l!Sv0K(frywF6(4@MMa9` z@tn&N2x<{mYM^K)Ib=t#jFkTBShV?(_2Lm&kvofQyUT*UFyci=@)X{LR)rn@CD5*v zmHE~N9Uj?(qIx_99rO;x>owr(!hZEKu&hV`5ws30HYuA*U7fo}U31E_k`igU#Y-SW z%rA9&Sg#+}1_THB+umX3Ggl-$KRN8M(N!)7`~})@NW;kcJP0YnJ6|9bu#wY6)jG9q zr+$SVm)^6p{=ohGR8+(_n5juMl&SUz(jz#GKWwzY128MZH8=idF7uGYKq&qqaGW`= zmXrM+y`)tBP8|rm*j2%zmse4y4;b(F;S~R_)#du;$o?yDV||2Jz1qRMrPW~gQ#*@l zmyCXN$&sLTh{EgFH+tevv67Oso@41=4CiQ*1XEt5I?xr^x&p1o59)fRR<Av;VB+ev z{}`j>kac(e|2Jge*od^3(*h<XpJC&36I~kqn$5Q(r4-Bw4eyLx7(GJ0{!a0cj96V@ z)vB`V`amPy!Z#5Am<|@vAoM084p`a5|9c}ZJSGNKCPX+!<*}!KgiWV1%KP_&B6IR# z0<@}Ag~?c3{Mavr1XQW#AL<zOXsJpPX9PJ|VMZARFZI|gK84#n-hdJShhpT|MbiCw zgU?gmo#Ut9XU{PAjDNUQ4m<0r&74XF2tZ5kpaThauRVBgbyqDFQaowzm)g?JUU_8F zt%CtIs0@lp@?KIcPUa3urvyn4RDFD>*S8bJgaE+|qRcE06cuUe`B$Kwrax0KRo&#I zSdfC!=6)1{9lB*%#lt>$pRM87;ERXT;{i+!nNRUPpqr>iN?$!{UHKx-H%+G9;Su%R z55^gf7B73wiU1lmT4E%=u~|S~xVt-Kb|(D#8Zfl}4Ia+gC|{5~s1dZt1t6mKkB2S! z{Myj{`d$kZXvZGScr%X*=;rC~Y<J+J_4ezRs#u+3Wb^?4KHIy3ZfW@E#!%dymSBny zkUZpFO1fY7lk$F?sU=ZJGvPX`)gE}RJ8>Gr*~$!Xd{=a};*KDiCvoFd{o_0-ue|~n z*TXGQ2zlI;ITOZeOF7?Gv2%a=y*yc{^WR3_Hm<T@pgrhcmXoyRapE>`=<`unI0ON> z&=$qZpxJz9ZHNk34&;FGbw!BV?$T#vXCoB<hdEtX-UE2s?-~^r;`^KcF>)8j1T*tR zH6=Cm25G8xr8|jIs`XgLvAH%h!7OvwWD1EB>ZY7JC)|AbO08|+S1%DDm#*gyEEoki zm?xkpN|HUgK$LkF=u2O%OMl?xBkn>_n_W42(i*biSM4@TL44;r4givY5TYPFlccXE zg1rGBI9Dg-K~`7XWyk<xkDsOgHaze{C{kTTpy1g!(PHoNa%`aU>7Dy^Lycb_<RQtA z59y(vXfAHid;asM0!mH6ruJ^ODZS9VBICZUTO|K3gsLT*quz2g6Qrp@4~_F!U)=yQ z7whxV{1UIzujOf5FZnfR&{?jsiK^K=*w&d+>}sI|1JxRlU5P*d%#!co&jq?Q(&6Bb z?*0<zeg!iIzY}X%w$;giLkm3@EKA}5N&XG_Z*a-u$X$;qXWfm-VmiccC=T+y>4#Yk zXqQ?IP`fhM1u)`;kckf}ECiY07M7&X_R^;rDV0R7@JpZ1+j5cX_G|mX>;d+`1xQoN z6@Z{6M+fiqqG`-9$2Xq3)So{S<tn!}Xayk>D^t$A0+1wh4<iAahmI(M8TBYcd$`(> z3xl!s`PI6qQeaa0f!Fy9SqrtKwO_d0dbMgIKre_%Q_7K?8D$r0;FkA92)pWGJqx!% zBu<>mP0TZT5EkZ_px~W`d@TxBV&?hZbB1NEiy{clJ*(0j8hZ(e-p0$uFy`Jt+63s) z#mK|@%HlEU?)-1HM9X;UF%gu*G+j8he%IzpusNYO9lN^0v;})o#PO{^><YcM9cx%U z>(vhX{k6X4&oTcaGI$jf7>HSiseG_9Ev&iz?ipd*+sQJCi&tWyM&lWauh1>Vi}W<= zVG{=bHGKRU=>$)z8uf*Z_cHm{sDq{YG7bdw2n2Z~YnnzQru5@a{_3&U;CJ`jwT5Th z_J(WO70u?(G)zZINMlCIUbq3uO$<m|p8e^&6g>{@;h`gUq94KFgwPNbcJD&R3R4SK zd%|O9Ulod6tcYUdTmQwzcl!k1Z`2ib9IE!%t{YEjnNZV7sblcxF&t)WM{igSkl_b$ z#!Vzc_{=W)<KZnSfZ<WGI_OCst|T+xl(4yVm2l1f3*%KbO!o9bxI98DZ{Wl}o<-5K z^V-JRE1Ekr8{E)C8I%-t-I|WS^Q6Rm?L&_fJmGl&$pR3lyMS#3<T8LlK8oBr{|u-o zh!o#YuVh*vfl}M%mD>_R>j%XtqdjmFgeE4;SvrMiC{z*re2QB;JL?+o)#EZ8D4hOd z>)-^z=IisiOxoP$7!w1SMX^HpDKz4v1`3{D&t)p>>m~duB$o^4bm>H>8w^!0R(Syj zv<2KUNd8uF*H6sHft2^`aH=T6NG%u4$at}ZuQf?3BkXro7o;BOBkyr@e}J3-;FrwZ zn;^^BfJ!+c^67WNUCg4|+Ep9Z9!x6=TUl@wB^>K7(iEixazO=Z6~j#k#r4N^$e?E* zYR0J(c0(3XI*E>X67XY?P9YGDegw+p)a`D39@lR}Am#q@@89je;6}=94z42T`NP+< zE6sY*j_Je$p@2Ge@f>skYPr+&vuAhAfye@l^Ba;|6$%e1a&;f)>GXPEZZMB3{Q^by zN?$fFAYwZp91Bml6V{G0s<A>&WTKAStwUxXAlVKY-;Qj5jSUDr@g>P<fjv3YZaZ1A z`Lr#e{10_<9AL|7<dBn4`L7GUL#e)mfarY1a{9x=TkSUD{}o_9*&;gUyo%6^?4BEv zrW2Qfume%I5v3IFH(;N$;6poA?mYOJsC&&tHj*_EK+=2WZTHP*Dx?-|+S~66ZFo>4 zc9s)sa6b?t$Y0lC#nT*0hAb?6W3N30LyEW`Cz6Bv;T70_PhsN<xhr+}6S3tNuO{q) z+K=6y1GI{bS6h3J9aE5t9T6yoDjLFZYg+01ug!8@(5<1kl28@Pb6tH<jH3eK9a@<{ z3KCCT{c|qBC0QDaAAr!qig6u)%|yG^ucm!fI8d6qXVa8`@C1VJ?C4)5N)KJ&50%hC z>udul#VQ92&BCk?XV!};KYz~d5a(ol=W$}k+g*gJ+IJ`_z&j_RqVhkYyUsVxWYKx4 zWKvdVh2(jr6Z$T04xH$z9G~enFG*C=PiY)z<4r#BORmYwiC2YFc2SaH!DV348K1x% z+mr3rqPM!!?xM_6nKzJ9P&Fo~peUZmBOttMSr&KxMojVraG+VDEtg+%6s=zBPRPAw zlSOuN*VEh#Z8gZ#@ySZ>8H~~kXh)*F_A-!RAn?7vJw0{9%hicy;*tP?QWSmr_G#w! zuMol+G#P-xk8<MpUimK&eCvY*<4F!m6@ao1fSsb=ig^=8%5(f+s*%<+VO|WnE}qk4 zZXDYsj(W(<!<YEqY0-6xlQlFo-R|r~o*{WpPp2x?zuB=cluaI6GY%fclY&hC^{9{! z2$k+l!4uKSF4YeeSM-a3&>1*Isd{=`BeHIsfHY%{#E4l4xOhg4WIiVUL@A7ciASdR zo%73+JpFmH!@9e@Pzi_;%=RrV4(~W;{I3LLfnfUw@_z20u~*v*>9uGG3lGb{TaVZ= zBcmWp;GJY*m6LpbeDiQi+y~ZCziCHuY#*YV(V4X?Lm;a#IcU#*#Ydu*suE;8I$MYd zgk6-_BH6Dt{j3V?OxC+{x77O_Izt&fc_6ws*AmOoDn|p0W2f`4ps~Nde^$Wa3ZgE_ zr+StL5_-gqD@Jz0&?xy$0Bp1ZlvXTlQbN0f(w^Wavm_cqQkSd5LM&YwH|lxn?~>OB z243K78j^g(fz#|CdBnsACErIuWbM1BIa+hqXGQ@52S~Wy2s*a;iaL5(tsiPbz29Kd zP%Rhp0lT~(*eJY;o-9-q<wGih=*Ep}y+hM1+8MW(y5g_eehKIvC^?g~S-?QdhU!dV zEH8IPg48vVS@{C6^|`jBIP)k7r_;~gv0maZ%*1exWQN<nK$UB5MUZK@D|C$H;$G58 zI{1vUAEc+JZ&-HTqDZ)0Smiw|4U$!<x0n5vXK19<=KY(UH&^!dOY`TwUK7yeQ8`B| zuzO(fBDM1`l=fa$y1u1!bcKWRS<q63IVo010yt&t0Zzxir2woQ<W#UB??7eV3y}<D z%!V891)(r(I`-o(FhuK|<+Q6Q1LQWIa_jvsE<nx1jfh;;W>hx$FvwVLln+cKLt{&R z<SI(_aTH3MWim08`C+v9)Kg{x`o+FEEbVRK2$0WRXv-1ai=f}{BY~okR4%QyI#)5o z-_NaMf?=(3J3WYlxSht$$rj9@WDQKZI-c{SLx`v$dIxpBvVJv?5Pj)&p&tM$8O-=8 zsYNH|dd+sZ5@hcm!`Ib6TR!!_zA{wEHqink5tKuEnXdfie_GD#6r}hFV0uuGSWY%L z(@6qt3C0G6&Y@VYh}tfls`r@xR0AL$r1g_%0SZ{YUf)Yp;*_gXO{}#I_%tx{0zQ3g z0ooLZIl?zBLV|<Q>xPnn0nc3aJn*_hR!)?zPB?In4jp0c4`w7cF!|?O@DZ<H*ALoj zyKQ4JjOUe<Jb>r_4To)^J4Wrz1td`#OQJ}IOnc#@Lg|SDnK;Nk$@2JISMK}L&uErz z8*E?*4rb3>KcFmna4E%TecWdKJemiO_p+1-@w-CB7R20Wkep6a37GB2om~jNn?$s< zG%zsiw!XMHu5oV+emIs^ZwX$tzEdrC&ST>SbieR}xNIKEx#7wD;E_K<tUbvRqn5+g zHIRCyASY+IjuJw`m!cS6)uD8g;;Of1&mJ|k){;+>v0kR1F)x_>>^xWl*(DSSr8>#L ziiGv<YpZg~OOc!opv!J<nv)KP)8(t1?i+Zn*M%K!QXx$3=&J3ItU5K$_=uaFk=^9K zH!mWTTA6_Za!P2``b%R#<{o$ZXbx;r+%eb67XmZ7_(mw`W>=OtDoQ^lL2zTU9BUr( zEdyw%fa=x&B;C}{UxtA$)BpR1LcBy{40g^}Lu9|N>2MKojN|_3-LqmlQV>!n8T!u@ zZm4ivkJA5h{6f9*9V4);rGDkO{f55qe3s+bDj7m-_&6!RaKELRdnTLYs0MMwcX3A? zNcqlatfcf=GRpTRHS%&?d#wW>egtjkJzxb~lv`1xJQLO%45&A+#taf8B0G#Vl8MND zE$YUEz$4>m23-J(1(&VKk5#AA5PN<qhDd~tCMY+ixeRFE%7ljyF#Lk3K9r_A-uo{Y zsay-<LBu;2ZRDI?Z|ve45y%Miy-S(9x=H=#7O7Sr-6Bq{=tk)d%%@j*(GX>ybUPzC zAHcNOdhc7j?*a~iO970!`i>0Kl2Tz#@qn!N)>Orvq+IX3;e3=-v2M?J=y_;nw6hq8 z>(rjfbE?Zm{*zKI_~28OU-Jcl-h&u_&SiH8Q_bNt+f#X>&K{w}OFHutAXKT}<KhB# z9N@^A_qw5U4y{0>W-c17AvFPfH<hO>uywmOJlcU3Ie!f7)NgERR}t#7S;fJm&=C=5 zrh9^PcyFu-rCl6dTMjm8zR^kY3pa#aG2?kE{auTWOCO(4=Iei6b4C%;9pfROMbuTq zCtCg+(ia=QcHERNl#mK-y)3_SMu2OszgobLK!9R5ue4O9(iKEOFO`&tX=nf@x<Cb; z=pam8Ps`Iv`A9lCQ(sT0{>ifnG_3T1gCRh<$ee<N^zW{#K!?$ueNNgvUGU!`W5N>9 z5Cm|A<C6n6o!XGP!?;uRjYmu7M<)^zz;+b^uZGZT%9GSLj*#qhV=Tw}2Lwc>JdYBK zfYv6Spk8eWrTSntVtEAt{ki~8)>%9`lcq!frlhH_6WO!*;)jnot4bE&I$gZEtZ9}B zwD<V=n{5<w{w&QVC8L5r1WJ+y<XehYe3o8fPRcU{rx$(FZ?OHLDb76bfv}y3J_@c@ z=c3UAoo`}fb%2R=pIVTcTL$ndB4D6jJXUD9TzN{ia{AZsI#rD+w6}p+1T7Izmoh3l zIv~+E!oJyH;D_=<X5HKGcR!a_848=v6ws;;tFjmyX7~NQ^<TdJEEf7h%l<%ENojKq zWz3qrWrbFcfum*b0m=7!s&wIRZx+b_=!UttL|&&wix@&r$`hqOKnY_={*nRkXLvZ- zjG{TLDFuJ}l;^g7b+X2mod0cE9Z35oCTK`V@DLhI4ztU9otX_-D46B#x*JE3`W4Ry ziZPt)Yc7)5eWjjz<S6Thr~^3%s#Ai1LZq!OR3Q1+v?{uavjGI~!dw6vtcg?&^jCPe zEWi0VI@%AcUL&XshI1O&w$%y#rS^VU8>AmatulAyElK-eccHyeLP<jLQ|)1?`BZZ% zs&N45t%$E*{|Jcyz=*AFePQ`d1Ft|Gl)uQNK<Pc>o{6qG@rOlCfbqB5#IB?cXPG@X zPm~-VK*?Y#!TTucF2=MB*b`TQcTzP~PJMs{mWYA$^nzrUw<CRh2zX?jUq$UZgu=&+ zoET-~A7*I@Xd%>>^6xX?P}ViSLiOkXRUfJqMo%~^>+4$=I}B*NCPsE|pUTU>IIV_i zlJQXxapR?ObZ+OlT-*kA!szIGyKP}b{a3)%$a_C``R&j1eK*&V?MXb(N^+neyx1(b z?fBy#AinknvQAY83W<k~&&^}U@6SLrb!=vfmW}(pqV6zW7aVJlXtxa?LiHdS2-*-7 z;9L-tc@CIdQNQ;We0-TRKam7gsloK*DrC}+c6i?o--zE@P^M)dd_a7@MH6!f)v(h_ z7r{CI+6y<Adf1HcdTs%0cz9S9TUNKXW&GKq1E1yaP1Ih5gnE<@<hi3WI@2-t^f#~v zGgQ0}1ah^?zs{Nv|5pNJlTckL$jB)`3w;P)W>Lj*Q>?q4<+-)$psH5WZvNb_tss$k zncAiL@0KmWT>?hC>RFoGLBJNB-wj_E+B<TxTl*csp$o;6aOwTGw>W~So(X1pN}vSR ztPpD<J{$ekh!+Fm;fvM%{G6I2Zz4Bb0FHowhM4^dxeIiKso`9%NwwoJQx5#}=?Y>n zd%hzT6F5}}P-6!_pdavbuhxH2b`QkoIs3w}e1G2kcB^tlige!Bb-zT;Cw&AP0j>pr zp8Pl5Ao0Nq-g$rUiXLpb6xcA(YPK{W3rA7v6_z`xb8nO`JdQtq=@SIA1tj{qEQ&A< zgeq*Y7KPXkv!DG@4h;qMLLG2aMEOEmzcLLxbZaEZ$U0zt)=iff2tDw7&v2@J7P>QI zi>J+|m~OBt6BTQb&NBevCII#sD5nCT6HJoJh<uuI{*{J!|M~q@TU;8#LCkxg1~uPZ zENByadrSqo{JR{<u;EB8LKKX-bgNq^bA!JNnuwTN1l{c#82KCc=_87hi0}mLLJ55M zjelFmwj;!H)c2c(I@%DLZJvPYwXrxA4}$brtvbwDyfROq;3okb0ySLDx8<rMX;_ZN z0K%>eREnPLZ-szDA4N_EXN=~!g@K}qGd@;mIpkQ!L^ljdTghj-9)*T@-G5o=I5YR+ zh6i=4q$f6pFUEBdFYK2;u|9`*dMcBW;<0}8>~{%clKaWhAEQi+aTk~6(S2t^BJ3vY z{s-5w?-0@ZeqK0gU5pUj>fgE&dp4cBJm(ZL6;)l`y|uB`<!JmT*ogTY{r1xoUDl|T zL3t!QYrvHYVGb@X1tjwVUbT&iWs$jspzbLCz_;uA`hs@Mw;pIrO)e}&Jfa!*_%UWn z#zH^)O~i4XjgZiBDD9#kL-|lOJ9_A)*a`Q)#)x`e=Gd+Fr>pmoU$+q3p3INyiK|Ss zm~dR3O=6TuR6DUdTIZgcEHGXBX)QAwrx7W?dEi)gmquuokuD+mE^du%x)x5d%B!of zV}?2jod$NYE?ony{=QR+T3T8^4vGXD-aRYG$+c&)e051cpM7?^tzo|{eE;j+GKU2< z?{5s=_J~m4W%p;|Sp`e|cLq#@A{b{*X!pWy^IIN9%bmcOi18_TXmV-Swj9un9drny zQ#Di-AjDtX+S<BBc`o9^qli}bv(YaCMh=^=hKBy`l|*x!#RFiSc6@yN`mvu~(OKza zj$^aU+DxhcPyvisH2YJkoB1Y4^<zN5U|(`;_7%6dM@Yii7qaW?_5kEY^VpZ%PG5}a z&X$o-=*Z1<e+fekbF?dS=G`x%1>8b7F?5t$d#a1|rtPYgGkm_37&O~N^Sp_zaM=Ep zmq&G?KYc6HqWa~p)ZNAI<U5kNiqI_Y`gu>c=2qy^1hhn|d=pz<J2v0;w>?I%lwfNj z<NNoUzJ5A=A=)ndw!>mHyTU&NEJWWPbToIYEgAn*$eb^<>U;SVCmC7O$3Ax66xMz* zMTbC)hD*3P%S8*R(u@~>@%OL%|JZx4u&B1JTNDEZ6j&}rBpW~k1SCsV5wM7oGpOXO z<Wyi-iXuUZoKa!{1(GwU2na>a8I>H0l2Bx*)92p*f6u?qeY`LC;na(Mgrer0WAxE` zYpwUju0@N>!0YDNZ~6Od9hB+z(u!ZT?qIf?SQb%DkTMm@LR<TF*1VP-R!uRc49fVR z9K*rY68QZrLl0B!SGjvC3%tG<O3J{Y18ec9K7vtsNGCydPro6Mx@-OQ8I+*Ty}Uhi z+8ck%9KYdW>wusw_z1}BOGNGpj|c}U&@Xg;#iaL?vC~EBnf@Hz@M>R=1iyuz3@t)@ zKYPn5DP^8y)6AdTc&=%JK!I46x|?tE*5G7Owj#Q#^dAZuyg_ebYeG}~u?J_qUWw@| zRCboXf4{Y%!Q?z=u;>Ya!s)ik6iwRPJc058eVY5`G#k7&0`JoeHkZpLd0H+--EtMY zR;9ERKrUrJ+ITZ8ZDtj{$)NSLIKk+mx86->G3Ss)er3VZE#r!x#tE@;V1nzC8VhD1 z8gI^){o?JEiqMJr+iG+}+)r3_voUy$?Mqs8^x#sm^q$B@ZUG0XKUYViUS?dglz*W& zD<&o;3&vt(c)MmX-feW9JFtl;Tf|3|?9c5i4v<`Ru)lG}rpa~#CE=h?Om(hfwF-_W z&e#S7n8ScY^I0iWX83_}v{$#2g!PIut;^=NMO&-}AUwT$#JUV@M6<HsIDLT8dZ4PI zby#QP`>%!vOA@Fa`jm2=*|y->J#x@FFcg0P*<Z5mo`+-KW^b6=?nb?Y$9{U*VW}MQ zAnyH?NB7OT;>^mwIazAkdHco;2I7otTl<D#!2DZK1}y7Zr1zcSm*PiBxXv1Xvi+1s zWTaE)zrb}9#U1~lz^40Z{O!kXn8|QHw9ib(jAdyaYU+($PsPWh$6mRO5z{x>Zl}u* zkg?FS<4zQLDBBjF=Q5)txeo-zzh3)WVBp@o?YBOw>h0~#E%#=lb!G<J#iJLIm_O0b zAiQp%KSVuV%ajHep%#G_JSmbWgI4(Ut2~l-v{=;kTZ8igD5G>2&QIA26vdJ!$=Ps& zmop`!|2kzOZu3gWyLZ=<qJ!#8^~d~im9){yO3UuVxQIN3+S31CCoL)b1utL9xvg7O zv==Q6HaPefix17+^<26CKr<+FQIvd`rWnQ%-$W(`1b0R^i<#9)VZyXOKYDS0G)?NJ zReX)dK@}ApckHqZN3-dUv$q3lBGou1CW~u)2LDlw7|78YKoMqWXj0I8pqAqc=A9}+ z2ch8SX;re{_am7%!LV-F7&@zBCQk=c+a~iHKj@_AOAj-ww=b2Fkuhx!P5Qt-gG#^F z0Ykk*w*T35lvQ(+g}7j#v^1p!Lki7x=bt~<^60(o>Nm@I_SD?3U-@EY&WnHif7gd0 zkN+unMK9>UOu5?i&82t&f>8*Y<UP!VbLX%PihdF8vaXwcrR19GH(|^P7FE`N`=~44 zzt1fyI)FusZuv{XIMM!7HPIc3wQR@tf4`UKh|9!d(qSGx^03sC$KD<K-uf}9`Ss;a zfBLgy)NG;;?REJ@qKQM5&DhER@*DqBnk37X9iG-~KRv%nMO)7H!^$bPlXT~KOnJGj zc1!xA$-%yw5~ekZH_7U59R|BP>97|%?$N8ySFYl$4o)4xm%mXniH)kBzjVpsxQ6x( zv+JsBnIs}b;xjnJq<yISUVnM-;)?$?EL5j1sNWaoDl5XOV4%hR_)gT9FPF^?-u+V+ zf1Z<EhDy<Y{=u6f#_!^h!gm7X!-&Hpx|8<E>|Tt@-R5Ymgc#m+Od*@+%2;8-)<5ze z^xpm6R5U4>w%JLMH8V9Iz)ziS9#3uvR1GKqr42_lKlbjwPJ{PLq_$yKu#qib*Lu2; z{%(?8{EmTzMWlwp-tI0(JYPi8xf!_v<9;ZhM7-v0aw&|I713c#LRSa#H2SR$YJIna zeLIe#GQ0hh*#+YZrpFH2Z<aQ5!g>76FP~EY^VvIcd}Dza_$0G&_4L`ZJ@KVW9H<nK zPNwY~rd;a+GE!T=?zf)%%7C8hEMJj<9?#>d>!_;eHaA90B!{aN3rRZPz23QR@}1O> zyrQDL<F{8vaI|l1^fIuFxkfyZe}5^3Q#H=ESO$pFNq;dN%!cvTqfI3b8iVRCw_I?j zc{1bdQ7#Rik+dSFZ$E$&izbW)JUCXzoX=W&0v1aLH+rI`GK95RFW=Ptx89L|Z|$e< zm9D-p^qU0!l(nMl!e5N4yoHQ;^zy^OZ_IGmZk*}#HNBmrKZ9nY9wXDzuA7PeM)vX7 z2br_27k)QBYHVyAzN!9B%G)IuaxY9e<(ZhF<Jj>kccU{G`NG-zbB*v;?D^oy&2w}4 z%_@0gp?B#O?L;{H!C~|D1J^~f+zmMQcONHX4~N@%-<x8!cvROU_9UN|xNJEEgU~+{ z9zP}>b-rHU1QRM4QVYA=Mgv3Ze!uQv(!cz3nRUVc(Lg$vkh{?S;e&cu69V~is48Y3 zc?{RXAI!%sk}Czc3i_~?$9WHKIftw6Y;|G-N>{c*FzK{1Ud`M$uq!-U>mA9(T~?!> zSFZ-6Zyso(5`JbwWTRtYaV%|%TO*HqPDHXF)Hq~3JA2b{*EJW$`tzeatV7fHv-VFO zDks*O@|#rU@k@|2@83^fo5SZWXmJj)&<$xu-;4v7L<X3bY<ecZ*si=SI5bqWl?Vg9 zFX3Hhe|$W45{=johA_#ZR##Vbcc9b<Z#!dDPlB^>aW(&vn1iUoI^mB&0{d2f++M=; z&}vJBSot&BJ@bPUkKW@aPS|cGA7IiM`^`k7vl>_9${!W7_uAAIl-ppY>wdQ=rt(uz zV4u#mi9>dm2C1V>bEtHcub2X6;g{pRd(ZPMjLtpo<Z-uSOpzt_X(0=S+YK26+z^N+ zwOA*GOq9FZ4L<cDgDq7a4M8@X9cNgpyH0<Y{^0{2qoVaZm_-&<ce;1iZKbc{#~h@n zDWwMwFv7p8vAe5TmO-I)Jg6!L)_gEru<aO=A1O2s>vlC1RAni$T!Mks#b)cXWSg2` z<9gQ2sN4aY$wN6zdc4TWNz}1_FHEmBi;hHt5HnvLjIjSV3)K_>y(34mF3{0szz6KF zG%~yP7N6LW_vE#U0@|+rNJEKBKcfjv?WaF~j1WVt?nnG6YBQXDRJmvUSD$qPEon82 zg@tC*j#S3gwG1aJX;J9GVE{P|(zPA(L6{GT!D6{wJSmPSAlq->b&r~<yswN<9Xu1l zG)_hnWQm#5zO-OUp!DL!-QCS<tioSk196k34EtZ>YC;bo7yjPVWIOanK;r2aMGV+Q zT6@p7Vc*lgay*QC<=>VlzNOU~S9D!~^2}@udm2F=GvU4GPRDC_ADBD4)uuf#0I0dH z7XNX8&HdKVRE~uufl0gGlmOfL&)t}GP^8RbvyzoIB~$z*(qvR(8TZ3T0e1W4T8MXg zcJ>X}=szyCJS>vQ#~>%};uyA;-L|EZXJh=ktprG&As<-$bIy!3FWxoO>^b2-&Q0vG z<moT*<`Hoi(}V;qc%~zg%vM7NQ@JrZICVmkd~6}SSE2Vp`CxU=)aMPPUP)t*JDP)! zDy7-T*!Mj2r108ct~GTYtH1)(&B$`Lj=4)2EGRsPg|sw=18~rw5HrSp&o2)h59|Yx z9AKi>S7OCe6WX6{DI^xypPTw{Mb4*oM?nacsV11Fp#GttAZ2ADr2Ab&K(1oJ3yDQv zV+=uB4g+FFVMwJ>nM3cUB@S=92Dol)TXaUNmfGvZSS+RrJ?lBkBIS0!yW5kFfguAI zK<J`R@?l)a)!tMqo^n0(OFdUHmQPR&o;{OM&2*kA#ZU0OtA)3*an0|kDZ2B%>hv#F z>F+E&@n-8_JxcKt%;^34#D9HU`B{ha=<UM}YQr;P1SUm?V&xSiOdF3AXcXi_Ef%FM zhp(0Qk2(YX=EOBpj@ZNgOg*QI9~&#ucQnIDl#uTeM*P#E9zzL|R&q!|*yaJ~t6EmW z3ph5>8h(EI&aOW%lXyK?G`hLD*}iZ7wC**c%yyEruUpSaVy$DTwC|1!oZuU+2i;!l z5Lpa_>h)HPO)=^7^VPebwA8QZ51S_U@JIFaaZN?_xAPV@9RK&;`FZ*&X;Fl<B00qU zfpFKn*)Ib|5RTrYrJ~Xe<oD6<=asS9Y$NJ?^fQ<uL(uHzAtf-8%?cepLW*P)K^!67 zsvVf-MfDVAtZPs2d=s^eCKnk_)hA)*J+}zsI=G2Knu=S4-AbBiZ%86`-!Gdd!IP^Z zEjw$`I}Bt$MpHBOs51zSoVY0wF&I91Bt1&ncQY5VDlRqhql8eQxw_$hh?#c7YdUsA zsrd?F%uk9Z!i%nRK_%F|#}<D=cV~9#anpmh)}2XuG5Ki6x-9hqKC0?xT1awUItEol z{Y|6P<>8`?d0%r_8!$rHoNE0fk~U7iGbe<;WIBI7jkUI3_-GMfVS;o9JyaFdUnH91 zA>6w4)oinn(Yq^dEdX(s9Nxp<U!UoW(UWaUzNy}s*i;l5O*SHrVE^T=%lp2}`Cxoy zlZ$*r$}ZHnKr6F-;1gSbTKA?IR!eKDc_K{XZD{B~#p#GrE5a_j%WyOSvyj|f=<1wH z!%G{#O&H8ENXuzo6R{sevMNk^;~8rXrg{5A8O0Un4(1dXLxr=t_PP1rWzm2#?RQ5= z5Z_R<r9m>z1tmVtp!T0TljK|VTA4Hsoina_O=s1)Osd?JQYJ3!nTH-xdUsat4b2{R zshJZiN`g;DP0U#yg>jit@ws77LBSfM9CNR9g;q;Fi-xeQzV-RhufH3=k7+fWaM!8$ z<ND5t$9K~q$0#eBFYwLc{>~j#W~xz(c6e8@FDH5zwRC}K1RmTv)m9=<&T2e*^nso0 z`fPIHMD-JK_ocPU3GXHMT&8^_FADgo4hI5iM(I>usoS5f$4Dx3uaiz2R!7JTQZque z#skI$S!!hHSodx6^zo|5wU43kDbP_)AjGXVHa0D!Xl2ozcU4DDVG{48L;g84>PRTe z3YW22g7f{m1vdl*l{nQ7c~J_iaARuM2bLID`|q$S{X30$PCn-3<Yc!$l8c}KA)jG- z<&wv@wVOFQ#qmCF#PpHUoYD3K2#r4LAy&wbfX`%zgsNEi%^bb*P?-1j_`KKFMz8wP z+RQ`BeOE&rv;1^$$HF_w*|m*d;x%-z+lDEu<&o0Wj+e)k`J=SM=gx4kPh+5G-s&d5 zPEiHu;qsvKXLPzHnPA{JR3gtHWTib9O3+TdBV%roELEvpte`__dRF&g*Fm^4vYEFG zOSKD<P5x%7?1d9#A5M@&Y0tX}hb6L?@vk6+%=d~85O_Nh_pJ74x92M+QMG@*t?TxN zC5USduyZKV(3;e<UJoEs>@aWk8}S<5FmDQ8d+IrOl30&3EY0CjUop1p`<x6W@#%~G zX1W|isvPaYni?r-of4aKr90bb@ciN$UTEaC{PE!~9Q4{%ZkZGuuHHN-ogA;FB@H?4 z9PM}a*F~K+a$IKrbfL%;X)G$39KGC6>aw<up3`5?G6>o<cSs|JAWX!)VLz~Utmd}X zq3o9N5fR6phhXZg{j>41x%VNsbX9ccf^kZ@s-%Guo($POl1B+zwb{7V#c3QK^Xg-+ zG^J&gxM?=|{S}HAITZ^A>H}!~7O`2{Ssv6g?GZ-6O7=me)+B*EvRxNT^l*L5;sDOF z7zdvtTcg3JHB!8ohDG8@X}%JjGsGV=e!bPQ7EaW`N&gH;KbN8;L`a9nUVY$b>fTEb zYMzU;F3PcuPzVZpKiHn|tLoWQW+5K}1oUA)7AVqagkLR7qGXYlfwK`@Z@5lX!EzN% z8<?u+*r-~NYCm+avV4$Y3Ts;^Sy}V^JpOGR1;y<fQv1kW;!f(}a;}q73wyu>*$O_U z;KoL)&P)d(<LJ&h7kYQYwxoPhUU9NN130t2O~=Y=Ydu&XQCH;NSga#OG=v2@R@VGH zgJLM&j9X4D#Rr&aYez~+yK(~pWJ?nIcaW#pKM6}96D}_I&Wrul4_9W~KSDB1b-FSg zHW{~e_M@VZG>Gnq2VBy)i5%2AFXi~S%qFB-F&qm%-PNAv7wG8|EDmhJYmCqI>_Bm+ zOd7Me6rds<)2i)63gZw2%F8IrL$$U4d0Of<g$4{K$G=vB@ph_pkm9T=&lY~vkIU|4 zksHA$7J<~hy-x1!Rp*p3EV8gW(;B<FV1aj2#FHV#GC6g&N2oLT!e!KdYXK}otYTEC zX6n(A<SzluQx&EFr_eF`p%#SF^?>it^dr9y3)7pA%B7;E9R$pZV|3>_FLL(7typmW zoh<E}(>mGw%<m^-kKKJUa76yEyMp|~ib33O{&aO?RMM`|Fb)|}GxaG8qv1N8#wuD; zx!^}&V&(49|M4sPCz-b-vEgY=OUsq(nDqUfwH*CIdTof4tr3zj$==s<^G$2{>dzmJ z6noa2-qh80wNmwI^QDHjuucborTLxz%3J^So>KQMm124@jjkorb9C{NL`8t&Zrr$i zf5b`lfFS94fr)AFN9NU&6co>wp4>P4A0Okn;yl<9Re1^M(;wyM24}TrtIu3IlTBVz z(P_W?-8elnvs2-D4t_!H|M)#}YNEL74Ok!Cdifhu6Ljz+6%`v{zVJ8x^EGr8YSI6E zJ-z#%_X7DY-`hL?^K&6z`a*eb{tWV;|M9B0{GWFo`4;_sr1bcY*Uy)yHvS7}_<z1` z{MQTEH2?8>e&+vvxc|5z6cqoT?woo?|C@ca*XjM4|Hr#NC;JBfzn^8QFjIHATVaiD zDY8TU=j*2|o~ZpG-XRbHtN!!#f1mdMkN3$Bj$`O@aI>o_5Y_u4o5i-3|DO+!f+DO@ z3xdQlkQZUUr!oM>=xbXzue0CyDa<z}an`p@eVu-v9mObVRUv5UvnxQ<_`OMxO$SGT z*110#lqXEJqgp2*QYM<(>zlE%uApY6p~8cHx84_Wfe8E|ZC3H2HIggC!%<cj;HO>( zwgNNS-X_`d#XpbDSZ>d!`9Y*r$_UEQ#RcWm8FRJN(DR>I3L_=BZNDwpCm$+uDA!~o z_Tqq8b3eRnhVgFr=48_sdpf9=J{K%-Zm6^F)pG#~=Rq7U07zxpbx5z1?q+IFhVo*= z08Tq^{tOLy<@*?%t8NSF!3;u~3m#KbQ>Fe5R!}qQpQPD-fXUHb)tynI>)$Tbi-K~O zecgGYNY!_XwXg2rB%RMpj#AXk{CJU^9MVY~P;nfpo6mlyGe`s+zGTN*Z>hman_9R6 z`Lk-Guyo@n<4}E;%Unm)r;@vOzZ%v*E8gGVcb}dYfUZBis9K(E@VbMn)DYusZaxKI z2^Vr+(@yvrLE4q&#l|t$@#~sm*g`?Q$6{*dIm(lP*-Dnqh%cfu&_ylv?~3QXO(ACC zVEL|$DYEX&EO<lnU{$8z&^-y-V0clBU5DqRxDEC{60BWLP%~g9J+JmvThr6sj3s|W ztGjKO;3ofMsqLObGD_s#-4-;tA%D%$0n-M$*5T=$gD}-y*L5>)u)377UH>XKDn^mt zUR0ynp`4+Vjjk4LB4?>2-~!0fxqxJ4dlwI4+I)ZiQ$O2gg4|s@m^$vWYuhW-h3zHV zjcl+j&$h$~1;P~kj2Khyk5@bCb>Ez2(A>^_&Z+0%khr_a_Nk(xg1xtNZ`nM`ADiCp zVm*PUkTOW*RcCKricG}50;8^;MZh~-1yJxo|A`lIOm8Zv&DmHWgoXbF<vv1ge&{?$ z7%SE5?(Rl@BuB5{)7B(fSzS8HD=JsW`$gZ=%oT8DJUP;BqnO4*_*Ift8K1sLTMTy( zfXk)EC;Zu9E6Ha<BXy(FRhD-mPIC&N3d8!x#o!9Zm(rj}2lZqQzn<>Snq^=5vsdg( z3fHb)E!`b-2Z&<qhAg+Q-ox>#Qtgj^!|e59B95tHIa0y|y*$7zBE?;2g~#)!y+(64 zY+!1@ff@!BIeAcy8{vrK&YzzU8#8T;a1;J={kiptpGp8~Fsyc}4c*&W`f<(-mAO{v zS1IU&>&|U4ovhE>R;}Jz)<Tx*?ki8tjil&F!o2wY?U7$v*9t{H0JzEn2|#PosPY6I zJ{NwGZ_?j+;YYVQ_|RjKweqXs#7JI1pXL0Nu=C*)7D@lBjSEaQhI(NCP-5Uu7;(oP zIwoxrx4L)Eya);n)%|s^6MO$1JxLdT(Wg*<t<$K(Sh=GQwLDyG2E3FV@$eObF2VM2 z`hJ;xD-XT>xxiz2<eHh8Y?8RI8sxW{J1&-efBLI*3-52<HoPwBnwZGNljNQ3F?$=z zSOfcj$s24b*Ve?BbAe*x)>xBAkL^l>tDHnj4VS=A{I8&(Af;!!{1SdSe{-0Y7$jdD ze9oifDRx~{Cga`IlqzcK_is8jwu0Cp->Sd-<S^P*`V+$Ah0g=jmexb1qxh1N-#(gz z1%h=Ze+1{r(L=8rwBfdozkcJ07j5u=`rVcCjLmM}>31jYIUU$%?b0$w&zIFF+>%h` z4wt*fmuo&}N<~FeSX~Fn|L%6f)^h%tQ@1l{SbT3>z1m}y1Y~4;@@j1mJ-?M05oc81 zpWAsEN?$&dVVPTUkd)cb^>JVv`)gwe4S@*L-ak9Fb>1Z9Zv=IuW)j8Ey)8I;jGwW7 zuJR?Nc9F$1I(}2_8GMumsBf4LLx+a+LlSO*+jT){bsf;x{RQftmOmbi&LbDhrDeU; zoDx0Uz64Ctj%yZIfXrNLNPQVWyZ*>lXQg=Ybu2voCbIhO$?Wzl7Ok4v*X!2lH{QB- zP8?&rZBsG6{s8bPdvm%93ocPnHL!5)!=&gvz?`6&&xm#wR$i5naHSywMvoTx%~ZXF z1i+TbFrCfi;pOGxskxWA6`sW8oc<c}b4l}&@|<atEAl(>!p<3=Z}rwXwatI@DLv$& zb(D?J$}-i0qG7R_Qivdvm;M?`n||jnw~{t!9|)`Nb;=A_JIa>rCUhoBn*p|yz1W{) z({q1sj^Q~cxS=^}0^5XRvr-p5B+F+dBdbK$x&C7vx{4#t^WW%=GOA}lc5r^!Iwjn~ zN8q4FtJ9*s8VW$Pq*FRxCgNC_5)=@2BQ-ij3jj0ay`f$-;B}p?J^Ll1Id1K~OO0Af zoJ6do=SsHc<X3oqdrveJ%JIUhOlflA25xR8J|q^0<1SL!Fe;Z($S!-lBd%kbQnMkh ziig6>7zrlr!5$?g_KL3ZTsT=bV7EGwMsfiXlzLg~qNdb=ww{dBye1)GXhy?;Ws%$* zG9fD^#WRXL`8@vfV}e*iKTeT+fAnn~qr?}dJ8_X!qFsR|tZ)7?9>|m}x0}nat@_KW z+h%V4&r`jH7^NJGck~EF*q?3MkKI&N95u~QbX7lfx-##g^8~-Tr2lH%h=0!rx9Us| zm+T}I{@Jt>>N4}9P(;9SJphOYA-}*B7t|EG!`<zBFv~kC{Iu&7N)zB95ufP~7l>&> zbAP660@ZPmWiO@y6O%hZ0`%NFtA714LNUtNj-ntuAsimTD4-m*egogtjDwv8aJybm zZ~bUa#_q=AlTwHNf+gYE1R|zwFwgcH_3|V>a{}KMXAigf9YgV~?Zkeg#~^~$#dbGn z*Ba7QFU9;9x@a@u+#IGPtnj^Ca5!#iTE$?YZM{UOd10*b%wktz;4?Gy!%=lv?dHzW z>s4l4;qiMIi$!+B0w>;FOWSAE=^_A=c^1#DRq~j>$%5HZ5*g~wiyy+{LmBua@84gg ze{VMs{BF0#ypz+;!c4EsVTU`-<&#Fku1~G}dCT_2>rmYNw;*KH!=%J#MqQM17a;7A zd!1uETzY)!gt1D!`urUexC@K@)*o~a*3z^>=wOVPMnV}2-9-;MNPreWa}!jruMOn) z2EKI?JlFYD<0OoRlhL})H4}Z@&JQ1cmT_3GWbc*pt1e^1ZohB5@TZgO;1*Hw_3QDj zKu4Lu0v>vvfWy7o!o$NoHiUXxX1jRZP(O}EX4(EiW@U{O$tgFQTPriNBU!p&a$x@> zaAffk=uo9-SR82;N<H<~9S9Xcb?UZdsZ>B+P0-t5gnfn8q`@TS7;aI8^<3!d_()aw zF2d?k6m$#^4BCe*Dq}<)#y%m1bN^y#Ypg(8yWA^w)g+nb>_nUHyh1=mt~4qqh>{U! z*&D#-?QSrAdcAIS+t_9T=sxo%H5EbC38_jEi-(i!y$+*w$}nIoirv!PRe94lY%fWB zEBP3E++h<UWctJ}RUmmTeAlwE0O4w^$e$m=Ir$I|_K`b)QM3#WszclpG2PI@cf0Bf zO2@{U@gXtD)2LJ%0C0(U*ZWAgfa~7<<jT)$dV6&C^+25KR~?*jsi^#mI{3?~n^ggr zu{yLOZi3wBHGh~#P|S(#!Y_a5)F6!2BBG=2#LD*<SkQW)i1SLUKJ%rq)UUYGlw0R& zH>rhG<*vJxZw8|_tU2NsP4CGSEM^m*AzB`U97r3ygC>t(igCPsoD~UaA)N<%9)rE= zqeK?dqJP}2Z~rTYiDUlXISg2CXYrwfm9~LM(||Mag3AKtaN9h>k7jQXk{8u@sfL_m zJqVTxTk_h&a#)oBOh&`Jgc4`+-Gh>8ddlO8J>Y;WVm-i~t7K@sb`<-|W}J@VvUf>Z zcc@iM|7iE&nF+tNIDxe%&`io_T#+51c91J4qlkzIR?lC@Ps-kb4Xx@{7ShZmGFK-= zRKZ#@OpksvVFI4l0Dz;BLf5d12iwJn`!%8i=zDutcLz*FN%C{1$T82Z#iU_Lq(azL zd~`t%AcDx@VA+Cc<W9X_>X=GfEOnN)K10Bq({4T5Q5P>QH8vB?@g7tgC9Z>}X^s^b zPfD~%NkEXbU+J{U=u%o0XD|yH4OTidE7oVXtvexK5V2mliqZtYDq`Fea2^?l-mf<H z%YCatQ9MS541yM2upLW5K1CSzz0;r=+8f&~7vcw7&8=^%qRe>`C$coaxhK7O+lNLu ztbk>LA=>eBIdQCexOk4#DVycqBYWrW*DJ`Hp=KN!<yf)?_Fx)n9K}%9!DaC?7*#S7 z(+ElBrs|?U0(OGTLadV(b$E<$31R_-R&DXt`}GLl137bR<bo{_HKurf101Nt47c_a zOsX#AfZS&|cx|N(E->l)H+kid%ae$=Hnb)nRYK@4>tIic9ye^B6EuwZle)Z!tSYxA z;c(3Ec!BO(erlLuxh7~S+z#)h!XV4kGcV}-fla{amvvcvH&n!1ScgWWS!PU+Az_j0 z_B3XsgpduQotd>Y?F3P_Z2j)5Ya~+dh&z+pl|P?m+s*PoHgH?SYXa`mdFsE#n8bZ* z*tH(HEc6Vdd1W<<{A@KA?b5qCw54IRx2J&WVJZ;oPkm7vGLxZnF~+lT&4>7^j0#kV z{{Eagg&_YU6#wm12dvxR;I%+TX$l^1y@zQEq!10A0F(9VDi05-Tg$LbrsNj_ha*Uc zI-!bNr$)qYS|0~uGl(t@>tBlOND`>bGw9vO)7*w7Z`rZNl|4E79}{Jkx^$4_x6~&| z=g-JolFxOcx3O_&&H&ioo-EQbZ)*f>m5A-w9g`|j1aP#fiBfX!={uBk9v4C>M}4qp zZ@%YT?(ngxK;$6^41=3e5`O&xHB=(a4s$;|+Y$)(gmK?HlfewpIoQyAC_;;7a@pfD z|6JO)WSf$-(+)6*6O_gwTn$1@?V;>ve*AhoO%0+XdD+98C?v2$LG+?9--EEot&>x6 z-Cx!O2_r9F$pFn`7qo@%X){<44$Ap%nha~d|C9IB{ql44^jRR|QxYV-K{=iBL5)<{ z=CW%Q5Fuw{pzXwHXSm3x1@^;nZzvtxmMEeQtiM{fvvP3S+-LT7qeniMk(-pM8kcIF zEKvIvQGU5nuG<g&aR!YT17Y0r%cAq|w#uKa&>4|AAuWmT6|%-G=;j%&zuo*HvMl@b z#|>ii&17>OCvA|i@yn34Ax`%d)F0&2<@#%7g{B;2vHDO*8AkEwc;%&~irML_o0=wz z;s^6g3LpmH=ROx8<-XoxpWj*ElNBdiDY20C)*cKjadphK`9hu+kv8*g+A9eo<bKO{ zi$(aQUlx2=?kFC{B|~BRJX7=uTgYP!5#h`HpLa#pLLpVIuvfb;@7pE}EW*aVX4W6W zgEb!RSrmH|>le1OP~a$u%e?P?o&N)4=zz%)3XGy8Bf-Xs3@(J^m+;0TIN7rxuK}5k z8*Jw#|H<qarKkra-=?$=@vf6`o|%28XzMMH?}TnIDvS6Nbj(e_8BnL9%au{UE>YBJ z<P$J}WmGPc)x^|udBT1}cVJO{(bucibuT4<s#Z&pN%KB)(TMV9Mj7?S<ETK;9P~k6 z|Jt;YyG2{K+-5=__J&w123Yqb;A`O9!suCJ<Ydq#2IO3MwVPSRH`-k`80Zah5r7e( zV2iPkApR|>mmucL+d}XYdlp|9a-v{Bb<=liS=z>Lu%}V>($?QCZZtmLvwa9J3el5M zG(F`R&0(oymI7M($_`ufamCKZ3#%m!k~~o8q4#KQ=k?4GNsU6-&cLOwBT>gsnrVWH zH9|f1r$*Gr{L7W0Y7prZKA3}dmUitfzDWYI8{JOBGjr_^0fr%3=kuWVyM2)~26@16 zPLynC&4^yBmvH43H{?7A#0898ejph2dNN?ERM4`Oy=5a&zuuGu5h6lHZwHc&#nI~A z{w<_(Vs8ObP&G+v;#3Yl%mG7G$+=syIv@%pjMR2s=lk*RgwDo*OMFX;(Dux*(k=u{ z1EN5%)gCX<J<qNMo4eF!PPKMb*B(iOUdk&c*|Dkd5eMo$E~V^|7V?cR&O9<SIhNl> zs;ZOz!o1AH<{aN4_A{jyaH<|{U?-6s(C|*>yw}ozBi#7*%)vPE$!GNu3ROTp+fTeq z*=XLCbwBibl(RY26q2A27Pd9%i?=#BBTtp9@QwQSmyZp)OZ#fuOx`D{=N*OG6|tB` z(xy=X9@yEsI)Cg)!AV49fUylafp0x6w5~c1n`7nv{Y&_3*V0O!^gCnH)kpju={!)% z4CGsXzY(NU&m}0>s;>u24+^BaAO*;yT+igJa@Nq$P~dNrsjV7P$%+tnwL**Z^|>}~ zT=u+WDQk!UCS5~ZgEXVGYdL(>-G=;*>SCL-$T#IphhYF13`)t%=2KQrA-wx+FlWQ- zyQs4{p^Ca`uCBJ)5Up6{wvgu(A8pHFJI<CF#D_PxTOdRi<Z8G4&RqW$Yd-f1VkfWJ zYA*W%{zxtJ$QyRY(Yn!!RgVY1++GKO4h94uq?Kx39IH}WyqHMsS)dn7C1xvKypcWX zlWTc~H&M1>Whdc+b;sjLbN?n0iBvP%shMwxqO|E)TIG}0Hb}(!aR<^12hssDx4IX! z36;REi5^tyfFum;?CTf5d~E=9p)6rwD>emrY`_SjGGiiC1DyKzU(4DqnMpD;%HIYu zjfQQrAA~BTDRq1a7`2brp*eL%hYEYOcX~lzQXLf!@?AX;%}zrVtP&>(Br^GW6%OjT z`7cM<c=appgQ`hg5Er*|iO;x1Tb6f6e$;bWO=H*{#AO~UBe@{w?)uayn`Og33z7<n z1-4X3r^BBT$I^d(P;T+3e@?Eu*v^y-SB^=aYF3w-tv$k8fJm)TJDTEj*=a;eie%%^ zXwJ|9E^(ui>&o|%?k&+y6jH5;EP?F6+p7XuJRlCe6`fEo1c|uriz+L3Gi-*HDiaDb z%e&oTm-H`qss!LEV>*HjRt|}E>MvhHj9*FQLNGXX+vRN(6+|>K+%>{6+F7IhUKd!0 z?A^o%DoUN`mQ@IN5<Y!yAy82vf4KPUy&}KC@Rjm&y4c^2QEC{3x;n8zxYBarp}n_L zX6C=58qlfQgRBP#xQR&CINs0MbbXoNhF&P0=UTIEaXLlc-}_9FGIwX@D09pTLSeIt zKxUdGk>n>C9Vg^i5cWIyFIIo$sp~4y7F0Ie2EXM4%Us1bf&^@I_c}*@wDT$#d8;LE z#DJ0=>^GfV`NPu(8OLS$)f2Zzw-cp(MFH$k0amWR!ubtSFsJ(jut*28=}GQ4Xu{ez zT$^H^B3iQ6_OdGCAL2b$b#ez6zn_L;xslNFJ6aw=ctQB43nK22y?`gIIt+`8V2dMc zSHg7}1j#1S)t*I$WP+zwNM{76zd6g#*vr6=GYa{{BHCSyZS)H!F(<=}XB&nX=7NaZ z-hyAY_xrmJ6+RRU116Mhma>9LM?_CR4L4O)RNQtPt}?;&m7uOAgcpyG7v};Aib)5L z4}F|#rV4;r;)c2s>quk+z^W%GD$}J%ud_q++OO(LON}rmmKj)|U0pm?9@1^IVi~VN zzYLlceUv8XJK;^`a!I!C)D?m;tlfjlDAwVvEmDH8=R{Zz6zi%)Q`FiPZP%B(*Vqjd zaS7|lk(MOsdH0$^NO8;PW-l$$BEdBh1{|w7_qUgn%j)Du$wj}u(wnTGv6~t+Rdo~Y zJVaOL228GSjl`sD=RMQ~ZMy0P(ODe#9SV-%&RH%~cI;jBo^(4570F!?n&rNFRTJR7 zOAWvHVXr@k(0)8k-jZ#ab2-hQObZx%%D+WPIy<cE${Jxf5Zvv$d|qJA2CYR?7>lje z&xvYJb#-Y=v^YIb`DbR;1{I;I1^huI;1}jX3N6#$nK$jAq8wic5(I7G#db#f_A1iI zXWREW#5Ykqs@GEM26HmT9c2&P6mre&0PW6lZc^?0)ldh*Hj_`+2ETv*ZnH5ssU)bQ zEk3fu3jmhTc^{WP=!Y@&SvY*UA|s<H^7ywl9p6SG3_(fDb8>2`0vJin1t{+oB|&L@ z%Ql!LpQ@a-Nkhnr1Jq-aP|XqdhQJT&f4oMONv!L|F`1Ea@&^#DG0>WHB%aC7ff%qR zJ)4ywThQ0cRu?n>mco7@KJ#@8$RA>Tw=jNKgDQuN?zDbQ&^w5v2B_<xD>40RM9%gP zAQ?xhjZ^=WB7Hp2`u=%gI4V{(;4lNcQ%7!k0-ge+W=0$<$~YxP+zwArzGjcV4pIbB zocgZ38-9Sm_-E#60yxr(=#u@Vm(@g~hXfF)sry<WyAO^{W;yrBt2d(udmDsaRp;8_ zv03MRP`UOOkRMV~jvjX8CrQpvg-s}LlppaDjN~>ju4~>ubY@bfC|15QOVuNVZJnD( z61f;i<kH-gI{LmE*D>cv`>ICuJJ(ILIZc40@d%o@x+*|<sdoR1WO7Dp6t~?tk%{iF zr%Hf*2r%v>wwy_Sljg2R@iWIpQJDpS*?l#oNPSvJ|3s<dpgg9;e#=zE)`6w%*Mq$~ zE;}bSiE%?Ms?-0i1^8`1tLd|%99l1w5uK%{239Mo;!<M~s!W#WBIzN_>}|4PEbN3z zvQ*+Un@E-DJty;9ulq_~$mFd(ogSPDiF-ufk@68>X#-psl-h6xM#>x<6kP#*(=JHK z7==7O>EcXt3#YEzg6<91!`>8Ere_`c6%Hf27K|BS`p4j;MSa>617RN0hJZADkcXQW z!*4bE+VL8eXk)Orj<u=^KXL7}y5v;w7o?saY~X%?v!A0uh2HbqS}~a_Rt(*nTL3|= zVSC+N#DkM5-*3Cp$mV-&2e$MIWsRUW3$Lrkaln~L1u{GscbV67+wjfxflLI#g#~b_ zS%eF)ozk@!`6hCETJZH*B$0ChEJkA5e6f$z|KU(~PV?c@w~(VKV@^;n<Nih+-<Dlh z(M5|rE}8J#lSB1{n)vp8inGmhu+HabS(P}Ar&*&t5gs4KA3)w&{oYcq18^HE^J{A| zkNzD*U%<!L;bgk*>YQvmFzQjF;<5R^0~vw_K-7oG<>cn%_b{S~+Tmz&?+9q!Kp)Bl zDjbC8>aQxPI$=B>aJ5TMkaBNxW!M11k`_pLH+nyb`)m$dvu-&_gF%TRLbpvl33~s& z7c{j9BH_JGkMJ&+&TXMq*Va^u^!flm4|z%Ys=?ZsD9+i^Cv*d3?$9geHvK~YArttc zxUsPCvY-B%OWcmy>c^T~Ya#8Or_zK1(cDlTMMYhEwZ%>A285^a8cM2ZE!c;27nq-< ztB0KQT^c!$umu0STm>kRYh>k3NCI;7fyxRw_7rBmgT94#ch%Z)=#e229tU?+txm<$ zyE{8Oxq!UGY-D%p`ANAH&t>Fu=eF2WJG{{==e&Jo8>CjP?=rEvxT1kPBj@xe73sRR z7p_q?cpiwM&_1vP<O`xL;?~Pa1$qrx2<@9RY^(iHg7Kktt;V+A={~$^T4W4T#~7%r zNQ>R#!;_d;K=QjFU~-@cY?s<SoASI700yZ|3`KHBw3*q#)<Qv+Ur6Nm06HUDRURXh zC?41@J!UtUA3l$_ol)94b{BeI?W8V9`0!N}l^d3QfV2-utbsNp=w48eA17AsK$=(T zVDS3|F5z$=Z#NRZ*snq>>btq32a62peuEknTOxm}a`@$I<qH>>Kfy@jYzTu@E~Fff z<y+G1B(~cs&`46cXt~ii=Sb(j9_=#Q_Ly`qd)W*gN`H=qYPToR4jMNQ!5!3VC4LKj zAa+vU9J=6L_o3`Z-<}&l#T&Crs^@t-|3=Ef&1LD!@T)qxh6d`EUP_Xl2|fY&2IZ!p zeknPfZUTf{|Cz^dXu=A*lG0EI@2lN8VP^Mr%vSfv4hG9i7@kv}nyH57qDVYmStc-y z8#FgloGJt3AejB^&T~y2&{x9%xB4C|6!B|o8^Q{j$%2k$t<mU~OI*<WwqR9(%_5S0 zGyZzy@6nmS83syqPGrkc*M0*2l8Z<+qn-ZXadqd>(7Ko-UM}K>$+r!&rd3$lps@?1 zVyO)?jNL(c%Oc~V0-zF%Fj3D1a+}+%&LK#FyNL7p^`>p+3l|b|76g(YXnt?Vt3FDh zCodT<GSZ#A?@_{u0`h0tq%aYHLAz$Pr8{PdBPUtg5Ouu{cY?ym7@(!>wrxZ2syql) zs-qu^nbFotI8BcCNP_<^znpnH^~d__kWRgPV-XpnG6qAX6q#CB6(8w%0)$3bwU!=7 zA{A|kd7y1mt46~~hP!ozg@p*{qI*y^5c{hXFgoaUe1r5`7Fn8VB5->azf3P|m>Iyy z0G%jfVCiDD9x-K+J^@-yVVTE~6XLG)Slfs<qAwCK*d!!iVbZU>+8ZVWfA~9w&qUN} zh|sliKG$;^pcSSgPRaqMSon6PSG6o>@bfq*0drlu3_21U!g5&-AN$VX21UGEZ=!l& zrG{u6a5Uq)pe_&@adY+d&e6<(*hwWYGBN5tpUD-`G<^2uOrE07o2nvE+KYIAP$4sp zCs+0_hsw?;)4If<nTYXZ%UkoCEY%^Gn*+UN9~7xwr3|R|6#%K1NzEmT(tM|JLxddl zH`qyFtRMJd_p?wrhR?n?#fSq{YNu1&I%gBN|CyNZE-I=+MqSb;vBRvw#?Uk^UeMx4 zYVlkL?C&WF|NVccF8(NJjpE5co&rr#%tfebtb!km)jQKd3zi{HJ=gwA|AF;UGzZpO zsQ0f4h>}Pk3?`Fhk*42LJKf$N=UxSCC?X9=S&ouiAQ*&rG<QMgA-nZ%TV>Ok&R2Jz z%^roB+o}kcvm(70;$BZKL}6^d_dS~o{wx_}Zg`rCYM^a+odZRbdN}MdvnYbnOqSa8 z^^cutiBLwsfZe{&iEF>-yUjs$ova$)OHLN>xj$YNRkUC>z`k*L2N=%apLGCixGznZ zaUKw9&Dem`U^?&fm$IPKG96E()`5?E3DUhW8gOfvDhPgZ>IGjRD^K(ioD_5b89+BK zfD-=B{cnFfa9<f2wEM2&N_oGTUq)+G-O$Lf)1`iy^1f0Ja1rq`=K1Vcy|9i}PzT6e z`==4QCz@2=LvvNsXG1fPpESK+Sx418g02c=4+FC=5g_vrW}=9^A*nAVbHjRx`J0td ziua`)+w|k^;w@0k`TTl4mn1=NYyg`OIq49Pm`C@}O03HhO3IMQi9A%={bOk0L@(Vf zb1rrG2o*B}ZTeuoi5~fdSql`S3c<`-DgKGLU<MriOX|<R(A~eZKniU?HPhKVmt8kM zri>|ZAu;AAcM<FDB{{~}mQ-gPx<AR6c>TIL^~?6>^JKe&$G)KTv*`|#%{3bAjF1*3 z){ScN=;Aa03<=qpl|0xSB_f0q#JI+lk`tTvK~m{c%8hV>-B;!YaHB|v8t5}@R`%IQ z-GM|#+GJ=+WYo$*u+M|N&0E}O0K3$Ju(y~V@La;3kOuB8jI<8rPUE^^rpJ)x4G0JJ zi_@!3TZovHSeNpz{+gc1xE!tOH&hpeLy8J{KU(A1aeD;oG{r~cx^WSQ?Mt}H&j#n~ z5^_MIo-x05bemWS5k})#$`D@c5Bch?E^P*cFw4bG9qN;_*tMp*Hn8U-MeJJ@BUKg= zJ{8}+_Ptwz!+P-%_*?O{2+vF+-1otY@DP8)wfF3{Bax>?i_^68weLb{0fV~bg2KYe zjXu^{6Avbz&Z*sxpQdCc-B`+}_@dJt>cIw8u)pL;M7B*gJ)-ELfAuoNGPI2LpTJ4Y zxqLK|LHurfzc9L*7AYAM!`?fI@Lm5+C9(Pa3GEL~>F~MaehcePoRCHfZTg}x&@<ke zLOyhxga<Ar<I66<__-3dih1>-jy6qdtYn8Dl{u-M5ma8dUro%i-{H^2^{}pqKM8(g z>r@Oz*a=l`i>c4fU$<Q<W8tFOa4#X~xa?o5uxxn}{C$2ly3r}{Ig}T|E`46mBgmC> zy3BZcs`K<-T%%Rw(pCAD@|60A8$0af=iwl&_9Sw%PZtg3kETM?2nu6ZrZW6vm}{o( zUs?{f*RYM4=7KFhd`z>Phh7-_t`8cRbifR3@6;!^Mz#oFU7G3QvD-7S22?WV_50{d z@6-aG$d6%K(AlnlcC0Ex;O8_W#RTE#0CW7BG?yhldI0#|3(S5k`q9x_ulo8>+7B+_ z#9(K|$Q4}LvR2-s-My63z~-gqFpwTT0O&8YtJ;m$y_Y%sW8&@QHUI7Po%Z<RJAlxG z;M>;ikAQ25irUhil@eabIwgxmT21eKt8{^Ja=egdxK*dYqf&oJS`clxx2%e)+kGo* z<7(E-@HExIJA{#b!hmf?zsS$U`6BZ1OB<GKx%44O!o4-z3@x5E(Y=3eKY<8b`Xs~F z0`FuZQy#x~RYqpQ>j=c1Y>;{JL-vU@j!Xn>@k;A`e$I|G!Z8Y4Ov@#di9p_Ua6a>0 zC;aI!)_DWB9hYo&gOHcDVcxakXgiD6NK{k}&jZYLKe7HxSDKc0Nw=skc?EFq{dlm1 zO;|onQ)w|azt~?rDdY*0Vh}`Vj_P7pu<hhxLA$-k>SzHjv-q=xQ|#_sUww=JTz~GC z^8-`}g<WMw;#^K+dz-O%I3BO%Tu-V3p_0YePph`X+(ud6@)1)$e)WT@Mb3~ts|qkT zv0Fz&(;wq{`+XFmkx8W5m@INn;5#1glQ@(xkZv8OhP03DdbddBGR?d~_(z<l%)m*u zvOz!sE<ojl^dBR8)kZ0(@98YFs972-O8d4n6kQ5WVZh>d1cZz8y}1I7cA!HOU25k) zrOGJwpy*S_SQ-`-61kVnS~kir3I6DNMFPe1uH-MnGHp;7z}Hc0n|uWd)Jse|7*`Ok zp)|)OL~uS2fXVHRL`{{rt<o-zaID(0-L!-rto49cyI?C{fZ~B!(0(sAImpCoWWO6+ z3Gw>YFySmi-=JOJfprR6AxW|<!h*Y?z)0mtvG;rIpbp#-(o%1Gj^fi$W>!Y=Cm+H) z$0UdLt6#m8Ln`HndNz9!T3t3t17?Kj9{OdTtf()WOj&7^GLZvFAIB=#o1vTqF?=D= zAVP#3h;2DkplD&bZSxPe9xi6S9-4{$vnSd3d)MXs{Az&6bf0O}L1bbql3SvT=F6%( zr}yjMhJ}eGzvIxdoJYF#qn$<d^8X1Hfw}`o-Wbu|j_cPew*)EFuPfruTQ4GVv`Ux8 zjgBSXw$4*)h`+Ur-9bL&S5E0mW2IrMb(Xpx?-`&nx0V4sA7Xw#!{c8X@6_YMZ488M zs81x6$bV!Zx2nrrr~SFjDTm7Yhh6Y{Xk^Z1J7-><oE+S4w`O&=i9A84crzHMz?Gvw z(D6NfMd59nd~mGT70mu&MJ4CfZ0Oh+)A7lzrJ4Rw-&tw#Iq^BE&aEApxVVxul;lWt zSLkNhnp#IbHtB9}&*lr5q5O9ebC;0E#>1q`R}~dc?ve<1TmG)Qz@vL#yg=|9KKoVS z_wOj7NRKR;+JK$~zieA3H#fI06BAzfw^fbOJf2ron(BI2xG$+uWH?gyHH_N7^ivFD z{+>@D!x;3lhUmeupAy2P@AUk}g14nblt)c*;wMB!MQ@tkeh+qppPkwTi>%sn%G-em z<9_kw&Cw(6bPVpwl?CpLe~!`6RH2d=2e2*Qc7$R@raWOfvz?0xizF%4U|n=$zTfP$ zF_W0prOERBf!_y0-{W1k-AfwkxnEP|3WeL9<S;aR<23n^CTDAH<55?EEDxA3?Ti^S zNK~*j2GRXmjo_3*?+Q2g%UN;BnPrJAiT>p!cnU^g`}gl8*xDR6%^ctv+xe2>uU}N~ z-FOjP!<L?<c2AP&pzCq{!U1pRi4?t}_+wJOo5t2YkW}aw+ns)WhK`+mTJYG(uuph( z^d(7uDggmnn0O<l9MjhSPX2SIO2_<OW~F6DX=iUVGv@=Yt&2DJ<xa2R9)3;HofOkM zjPCYa>A|}4Cpk1TSnmJBrIgirq<%y2wz`7JvAA)jsBX`xOkD6K5mwJFKLxYz6C!XS zR|;MPzIoCZbR&gL+TUUIDK_g>2Y0QDU0?RS2!6&z74>oDZ-aw@!$SUgPB&|P-7R<9 zD54KnIf0S;If;`Llp1%xckk${H^G|V49p~QpFhpU&xOiUi!yI>W7`YQtqEGN#&=(| zzJHfWbqq||Uc@&=dez^)5+gTU<DH=PD{0`>)%1<Uryd@ko_>7!ys8|V`6%V~<McIj zX-*V!@n&N7IM0Y1#`@CgKQg+6%NfX5En^>OH7onZ&%W^>`zxtW$Ht!Y8%{rWY?q{I zdI5BM^8;yYa2bN`yUcJMpT?N)9z4wUwoxHW@=8XsMjt!5AyEBDjrYox7nMgAnbb*k zQPebM=FZN}xA3{*kYjv}v~|5CI8R?Jlp5av%fi5ADz&zDL3qcY*h)SlNaqbz>8$aO z<s9w&=f%b6;UR5XH(Z37%UR%bSDCl5<~;J<&AI32Blj+wh7&25m{*D(-E|J4<GE)u zuk-EOx1G=0sHBC%nbu2EG4JX5TOnO<TNIzx%DZvb`lUhL8b9<>VU4ohXr8e1(a#Kw ziQ#m$R-fHiD0UdDi5mAkl*<U>xGESVuN+-$)8bNRHxfG`UCp?xYEtp=?yK6jrM_7c z@9NUVsyo=NJDrA$;=Y<jQ`W5aLi41k<3v;A`<Tef<oERbQM_z}*bJ>_`KuGY2H9HG zCjxGoHHIv4eQkLi5jb#4;(Xi7*8yGWsB4yHP<+2gNfCCVTFucPeG49vDG4;Umb>z! zy60%FOwjQ}w@;~Un1D37@#M(x^Ig)D+2tL89$xm|wKgbpp>`bgvvx6=t%*5(Wx_N% zl5=2y%fRqt+IR)!Ex&n+q?>;|etfQEX($Aq;|9~MU`KMk&Z3A?!1fUsreZ~Y(Qxx% zO5JJVY?cCv8(bcq&HoWdI{Pd&p}Qg8^7W4g{JASir>+R{*eXVNlz3*a5F9g5PuEm( zuO(&>j?MAsjQTGQ<|-dfQ#^6x<MTEsvhjGcQm>#e@KyiGLXoUNwbL;Q>8gXb>V=;q zdQ)WePO30avG!-$+WT4EZT=pk!CL3Fdhhhaz;T%)c}Df8pFft{<r$`ty{UttRgRkW zS2>#?>fCD(=IQV5Yq*hAE#<%e{n1}ZqDZKcJ^|9BpHo$(XPuUINeN0!+nu%5aVi#( z(HzQpM;9r|_(MvfGM(0iuaj)DD8LAiLoYv3B0$LAz?G&x)MHzZ<9+S!cD+}4s-Lwj zLym2)<M?8LL`#-1xAq_FnW7zrDl%h1^;vY%w{KS?DF*oygazYy4O~q#Y1+g%-oGe2 zj6uuZ(&Y>nvDXE6xgQ&GM~)|-{e;e9_1j!%_VTJY?<M#a6j$?kobI*5gn7yR9_P2+ z_w5uzlOK(2h@aghS!Wm*AyH>4GP$THe$G}oG{Q=p8shxyNtIsj=xt~6mE8@NboSeq zWVAhxi`Y9%78;>K|Jai!PMB+4p2~mGwi0rBgSzrU>syVfmSky3up?7h|FvlHap5B- z{?))4AI(pecP{{>kfvC0_`K>4lek0b1oh~^b&fmj-Q6!3w3?R=9Q_x2UcA2&BkpnY z!<R3;42E~XIqUoOyWXLIpSMz1!mV#SP<Bl$F-xWHRuS_s?$yjsWb4fe%`yrzd;8A& z%l>O+_e|)PrB<i))ZMRa%5$5EXRTvh;S#&u{wgLwTsFhyUc<x$E7`?zgZswVIyQ#3 zcX7c&WkQOJ@}MCw?8}c+^0aI+nlkpL7fO8ncVpJm%qEj1CL!?+X{jeGG&Hq8#6A&6 z@8+pdz82UbHsA99t$ioyMfpRQ)MO5i6{VKh(T`~R_k+iN{t6G9QuF}45XAB<hmucY z0p4)A`sV^nJe?($;sqV_+3Y(WtE<yOQnq$^_G9<V-{;RqZ5+fW)QZgAv$D3fZYIYE zH0BMT(I*W`jFj7F9LF6dNeP3Pno{)y8W!ry)M@&7m|6b!E$4S%cZ3J0N|(e)nKSM7 z+g{=l*}e}rY--&YdJEC^0K&ajqQieaXU-t|j2jvVGJY!__GOz=dTwoqjSP>BAa`-5 zbw^-+Fy*w2=L_^6P0_-nBSi5>zzD-4j}31)xk$;)WY6A~NxBmi%REL8IH<)CuV%%E zuQL=u7d1|vKA9w)<>x87Ek(g3>UibPwCyXrZ73RKv#p+HB93iqQ2`${8wEKZopU{U zQKN|{2g^FkDkSH^7MI;qlY4JBmL_oLb+~nINsNy@))I_|SX-}t$<jkU{V!)8CMG7o zAi940q3-#SO6kFZNeg1#F>nfKwV=dS5-sn&Esw~Uc~|PL6g}{DXehH!%gts`$vIoh z*_j{AEfkvBeE&Yb{v3p|QI9c%<>gCY^jg2c_U&UsGkCaD!0Fay;Qy`S+y)`5<8!98 zTb2l(>M>T&z!QeP#zi5?P<&Z=Da4vg)Z5=!x}OfVd(W*ZpBTPFnZ6FrgRCbSCmAPm zjpBKxnSY1p357>J$J^oNT^11Nw)w^ZsZSQ=kvaY}sXo@bn!R;c%|>n(rn8id{@QhU zrl~|<qUG22{@3%8o|Ud!PVt2|qRVRQ@_g?-d2%(ad7ma59}PKlR%NgN6is=1zSk&{ zB+5{FUm~w84f1jd2!#7?t+<MA9~H80pR&@w4buf5uYNP|d$@+q9VmF*F1{}@^2;oW zNvvU`%pS#%)0=7Z-78@Q|ECJyHOO`4O8B|7relli`FrX~!5z6fO!kLrv!|$a$Y_(b z%;RcS(+8Jp-T%hbId>G#b)JqbkA<NfKEtE{*rjkdP3^z_D{1MLj7;+3u{T^TV<7vM zgOmJ6f*9?uU*UO^pW`wD_FL+WJbp$>ih%*ZkvyIVq20PT2rxYmV8YI)u7?Ue9(z!` zR0!c727p8l!zO`(34_77B|qbZq8mMPsGDmglC*q)wd@o5Fl-S0_d4Af2r^+NKH<{7 z9<v?E!Op8s3VdTGZbVxszYngGpG)a$V3d@U6!89SQ`<L25o-9_33?sQ(r7?ys9cC$ z)RD+D5@~Ho<@(-T%VStv&ozD#dOec7x0udAbf0jq$hy%d&BnF7L)UZT)$X6}Q3i|| zo7nVymT3swv|e_Wi!!~Eui(RA<NN2%|KjegAF5opcHxOAh$3KtfPkoUw=|-H(%mWD z-Kms8NOvd_3X|?e5TqNVySp2{G50z9JL}!=d;WprFS_<xvY$Dh`yO#!*SN;zJEpxA z4#W*&tWS2fgO|j{t~VB$zc8>BYn0p4ChKhoGV>%Kuy?R>+kVfkwM<mQU`tr|6Pma) zKfo^)$p0*z6RH-4pDH(;7rA)8f8xG#=S~d25qZjnYVMl`OC-H&!PNYG%Vo{^C&E5T z#8abB=UguaaR(C{;%?-)QEEw%3VMbWAm{A*;_Rj+w_IL07^+0lDw$|_?9Bb>O)Wnz zO%I4G&*CWhL^+H6>O~Yn%0H+sD#ACWkU7<L=4~Rj$sb7@b$P+t=sTIQ>k@vMZ{5QR zQHVjSHZhUJGfljwTAgYzS5s=XYXCPFBoEVJgu}NadOUSG@%ON&7ScUshH~_)UH2<? zxRH9fnqT9%tVjp5)xOEM*zhdTqwV7N?VRG+Z;ULaVN;PeR{m+=Cj)15&XX>c^scLP zt@IXlMv{j6$)6*<6tfhr_8%JCB{lfs$y7$UK25y)F2ng^%((>1ZnDi6Z<F!G{2P&e z8dW*WRQ|Bn(EQ)puv*3ylv$}~C*k8LF!Tu7)(c>>Y`2CI=>d~8ZtIc9>t-CmJkxpM zwA9B-PX5J)s^r<*v@1Ejcr%ie>&Cso2kE7$)g3vLGE}lHiwi#??Vbv~+}Ro|$JWnt zA8$wcyvcnL5X`Fo*UH<qs7>2*!_rz{ea(5q!vBZK2oXR1Yt~)X)`ka2M@mV;Y%KG= zoxMk9gNJ)jHm%57P4A;Q+egT?KpmIS)wT*M^O33`D3H(|bmx{Tu7}(tV3M9t#*E`M z(cgA0f(SgbvLc)~GN4+f<9{cmRA-uuu)s5K<Dn<X`c|&6u<*A#jp-iJ#ow_9Ec-eF z-w<jm5uQ{aH4j5<EpSQ3q!+m#a}W^h7s^PqqbEMYkY`6rwp2U(8*L-_S~~G%fFm-7 z&F&5?6KI6u{+Hj4-fzc4?FpRk29Xz{3OmL)BVC>WxMa%jd5xsvg`g3bnF%9+kXuz< zy);<-1oqin)A^lj7BQ<Q8GFVWEbrPXCZ3eRz%Pa1w#&?Qg9_oSEs~||a%4S^%PM`` zrSqX)v-I<{Pro6lU)1igb6cTW63z6kr7Wx+NwJwAoE^!cJTB`Mh3Q;jc;X5NWzh>> z9v)aRs-O|H*Iry$sOVZ6OGMi=JglmExVyNGLH4uHY+u`p?i$#m#Ko<}rqUo@K-vTh z+Nb^l9BU;~d;0Z{*|Ja+-yop<bI4FTa4bMW^O4P{pOB`brQk<-XruAINdH=V{`=*6 z^z(_gw2?QuE!tUsxApma_(T1^OEX0zh!$g!+iCh6Yp(x+%UjbWL1lt{_fjj-jB+Nh zx>|&O0<r())j0<CKy1>NFJasEFuhkc*YUzHq_t<pYjO!`HhM7L>SGd6g6thDp%9=~ zymM*m2~}9{s;>SmNcNIUiO@tp(7g1UBi%@e=lIhL*LG?qEZQ}>-|#e;|E$=Me_!AS zl1;(%+%+9tK|@pC^5BX8x!5o(SzLnPqB!>Z13Jx5%ks^3m!8=5i;UJMd#ZyM)o5^w zA#lDmGi$>|s;g9!z$@`QF2^M1{29=Ms_jpeuC`ZJR7@=`d5hf_*PmlZ<!9kgEi3lf z6_0XHUh=>+K5)2ObGe}oIr}>frM-iL?$VU!-s-5&?&6E<JjCtklA~pW_?^(&VLy2G z9vlu0Uq33r`{f=-uyV77Nikgm43peBqh#wwN5vP1zpD=gKjgE&C&OiXi)5@TZv6gC z;uO%K?w&_mU+WKl?ft7c(DZK&5Bw=FW<?TMsYH1b*U1Sxzp$`jxCJYcc2GyO4txvb zG8`RN9$ddSQS3&R;>pCt9+3vAIrO%c(s(4Eu!{Id&v%kr-$^86nMl@+tqMO_muEcq zw-(^TYYJkASIDoe3>IWt+caV?_3!nlHAoxbFZ9=c9~z$8-CIJE@>KR?Qb0M7*>i}! zUQ!R&l8}VxLc&(`wH>Qv#sO>Vi}e(G$wyxnO22oGA-9F-j@0ARAKEa7r3lBTS>!UU zCT*S05w<S2$Qvz7;_?w*ts5!6v|f;4mXazb<osSc;SSx781Ym{;s}xCpl;Auxoyv0 zTUYGeJZeo<g1)zqo+}_dmuOZV(k8c^W?WrRmGd_(1&1TMuDRF9+=e#l7uu!qy3-Oz z9y}?XO<G^y*R~wDMbaSMYwT&*J5p>R-g9TrDNtv)Ulwd)F7&@SI*qQMti{&kDeXJH z0M}MARU}D_%f(yUy!5QkJ+pf*snW6h%8B>3&W`b*VScL^dsYw<&TU}en*6Ujos_hJ zcYR{w_?Dvry7i!#n)T*|hk-A<IOzMt-~8pW7D{Gk`(}hn#Re;ZHCA$8HleNk3oi(U zB{+`WJ8!tR`W;TV(cr!v4s-K;^=h26Yyu`Ejkc2F4iwV98EvACVc%?q(BM5R-&=Kb z7EX3UD(MC*kF>SziC1lJ8tZr4w_q97Dv6vn+FwFOvW|U`Ba4s`*gV}#sdp)=9ZH(i z0O*6&_>VEnr6PCp(%0>~RVj3kY6D^>Ic#2@Oo$vU@nuEDOdT{K5*?#VuCT9mlzhVD zF9ycmE9@3jfrP*(RtQ#79lM=VCb~S=RGnU1`#uq(GrPFaG8g@^z~HQREE>k<=Ix-x zgLAB~I2oEs6|qbXZ3$SSLjyCU-UT1}dQ9m98Kd3er_Wdb$pIT+ow+3}%7Be-zAYm0 zE-Nh5jYq5;-z4|-d-Xs=>F(6Z{PI^jpQ1etXL<L113e)R3x9ttgMpP=G`N4^>~wo; zYvz%dDOA!)GaE@=bG6DW_Y9NxI-yecgWc)*27N?lVp#z?qp@Qu=3*);S4nvGQ(k0{ zCa`X^np#=q?tOwi5QU~*78VvX=hK)7N@9YpWMx77C|X6iV<|Si-_@rqCZujJsyBr^ zkWqAtqOh$?^?dQ|Jo&RF3FcDE>e2g|!c{mEEnWPJOui4?lLj5PQh0QRItH$}x$T}X z;xnkJw20N1>~b<{)`T_P5w04y9J?-`WN|Bq4?z>zZJEP}K_}XGszvGR%&RJ&q@tFg zFG&)3Amh|T+qyX(B1_~a*zby~dOkFXO~e`(TewI(KFMJ=klM&@y7!~=aFCwPw_M8z zb+y00LS1diksd86-jPvrOWR6Pq4l_dh_0v-T;nKSo0*6n3jz1N4*()G{#G5j_{#8P zMW=UlrFiwMznUop=V}~}OLl$sED>yLmVKX4VmWGJos^e%eV&9CImgwcZ|{=nk^T7b zlgLf>+Wl6=bI#e%7_G?>Yr!~koMGF_@f>isXOmLo(uy)NEX9YO)_O;j9J~k!A=K#l z^}7uL0M<+!6H$8kct5zNM%eLFQ~zCZU(lD7VlwNT9vZ;8WCgKs!jHZM>d}GVpuF$c z#l^*nBPJY#hVtUCUq7W>Km#DjKCD=E)gj_*t~%JWKM@JW?63WCDoxU-k*?oz82M;# z`)<avevvc-)cBK4QgRoyQb?j!BeNU|vz4d8B!VsAq(;c&jxC)mz)>~^hM{Qt9GN6B zr_YY7m?I+<ch9b^xK;b785D3dx5WLcqc;l<ca#XoukGSSx(*(CAc-~4AwaZptCdPg z7K((nXPP}KY%Ah$flJMl`DEtwk|zNTUGzcK@#aVxP614W^w4DUg)^POMgi*386xn6 zG58#MW!k{`f-gz?1Xoc`UOJHvUt2qwJ=!en><fYW#ubo(48?oyk2qWmXG)cCY+60@ zb8>yi?fU+mk0_c96!sXnYw?C@MU`#>6!NVz6m)x}2&ig*!JiNSQ&oU*m3&(~6>f7d zW&w=AHA%<(<O&qg(0EvA$b^_`qYT16xGK(28%>qs`D|$H`ptVX%B-lqb@<Z&&#u*E zegHfx!g{`yW8O{D&)ab}f=1hGKxNqftNk%Cr=_fGtMS6X(Lp>D+L7IW+Wf-T%8<%P zkG);GG`98Mp9x-yjQ1XQHZ&yGqn{F;bESA$8BE}J)EaKp)v%w-c|8baP<NsYvL_iW z=JY_wOg>8HcT3+*tP~Z18I@oDLFy6o4L|(+UQshi#P#n*y{`6v(*epGI;Nss0>*(X z`wIKx8-OUGr@Z=XWuHT3*6GLf9NfrgrV`1#b)PiTEE<MWE>u@VF{XK@fG;DKbhz7@ z8LGvB00|9e-BMd32VB9~(){qFNvHMw0ts#&9vOa@2OpWyhu)f6TIM9+@U$(b6uKIG zE<wk{rMr(oczX=#LY+{m^P^tR9>BG<X3v&8G`Dsr#E-751S<QJzD*Vk$>?J8dBE*@ z<=wlL=?*yIF#>GfgBCoiif;julPfe-M9wFxA46HbteEO5b`TEpe@o*59D|pIs)WL) zeJ5lYX2c|;8GPsx$t*+ftMARMhcYE+?U+|8nkk?ML9Ln3$vu@Vmlm>@uD<hM!-Yis z`-zA{Wn4c#uX?#^jI;0GpDr+|{5-qFOp_zpS}WAo9X-$lxKTJ`HoplD(X-o`I7G(1 zDu>m*01z?{Wo1|10W=}ZksSpQvKI$hin<YlDu6|IhP}jGQG1dh&I@VRsoE=mpnhiw z7%U)7GFIh<^^3=4T6b4Cj9Xjeo9=%59$oCfyzBro0G?~T#F4c4&{7z7#KbJ@>zkR0 zf5u<wk>k3o)MR>tYSVWKeolrzBq7OEl=t$zV+Ya2*vu>|q5*o~)<c8v!V}3jR{4zV za;TtM70uAfviFHO-hECJJgYNK7q%EIs#bHu{?+hgzl6*A%XY~g95&i|W9W$V;hbSV z>=w1E=4$vA>0vpvP|03+EZ}+ek}94jQ*`p?t?E`dWhy((Vm>6~;AE7pf$6Z?&t4w1 zXFiEyIEou;=|g2pmwK|udRi=+!4PmT))K%)ENd-5o_!KaqH;APt1%>h45iRW2VT9R zHlrB*HMag|?I6v%4y>tTHfuzKM!<8eA793Z{qi`vp3lv&teRKn;tmC(+OxWXha@q( zA}TvG+}ft40if+8r#74@M)kB(4QJ=4;uk7dLc3P+D-u~M&q)gLARKU6`Vx-iP_ogd zgm(<~vJS`1>PxDcbnF&!H2-i!MiemWOx&rSPx`4K#;v;IbBB_bAXaY;xQ+CS8bK#6 zv)I523|8LCdN8XK-xQA9eab=;8W1uNIc@2}X8C%Di{TGJ|BDmN8h1a~UxxzQq{{7P z7gpXQk+<lSkp_#54r*txlWSSy?BL)4)(nz*KM@U<uj3VTJU9S2>67PqfGt1{23qTN zzR-ViJFH+&OlYwmDG1h0Uz|S}%#ojLN0rH`FNn-wiv+4Q6k}H0)Y7DxR!<NOAzeLp zJDbBQw@p8*2I@R=vIZvqcNT0YttR-MQa(ii8(>A-1QP%V*gcHt64vKH1wZ9&|FeU& zap~ZP+!E=+L)QU-lS*_$lYz$qlH)NL?oN4*{QbMMXWcft)}HQFy1mu&<o)~i+uJms z<To@lD%|~apETXErD1m=bNksBObpBDnhWMv#NJueTnJ}y`M{@#r9|`n%WN+v%iGpR zovd3E<M~_?${*Oq-i9cn${K*ZB0j-qayZx;$3fSooJ}ckag8jJDWJ5Jz|qn19_>=c z2LGkaOd|~rDW9-HzXkLhvgNYg6+?2tYr!bHIl{Of(wjLvr{;j9x;*ndds=EKT6kHf z3m?9zuOYFl%;>DrAfUJKYv5$SS$BnBX92~;p#iw+1Gwl5>hW;FS}I1DU0Y~tE-i=a z|Mc8NbJ*-5<1MBT$9KR7-^S$Lqc(hcwW@@&zt1SVyL;-<w6)1nF98*l_0&GJOw0s> zL@nHiqa$a}3j=0pMOv`LYy$k$V&^bdqd3ZP+-tgPU^P=aml05UM1L&0Fr(%|QxJ17 zDQ|sW2JPDVx=l-bH2ih2FmD8EJkq;M`}B}=<cSTmoxAXbgJYe<M}=X(AdAUfyT6^C z!30cquJgIXwS84~*_tB1cGEeWW7RF;I-lgE=Zgsc4iLqyXmAZC+>CvLTHBlioK<LV zcvn*shPt{s4k^#ih*A{5lI|d$IIo<2_Bn(0KG_iRP3U8q7ol^9J36Z+nvln)8b8Xr zZ`Gg9b%Y1No-(irZ1sNk1Xj-Yrm)q!?>gK~8=4g)zMz2da#|(&T>bF@#|z=>n7Aar zhg&{c)mXmWbAm!7ki5Zj7S6Awzn?rHueNi4q#%Pf2VZ0LFhsz_F8jq<A$uX&-_cQ< zQ%834XyJ03CxKAl%4Qqi2A=1d(94(ivWCt&V)Db$9ISGZ#=SsJh4K2d<{qHHd}Ah; zw{{i}-?j}VHvax?b0WcfT+L@=XGgIy%!c#u*{{q=$~y!EqQDf}ALk>(%KHWeBEbvz zHlf33(4fg=%AoDIx#*giz0mJxNQWIP!HI5I<@dzOZ9R|hnf$A(NkDk{WUrM2Ue)t7 zv3VOu+s9B5L952%F!IoHGPns^csMC6E>*sG{wC3-6yhggT+*aIT_ykwEVT4xwDRNh zH`Ew!6hh@b`*%Bht|J~(6caP=-R>e&f%CE$MR-7b)=eLb3yFg@8p6KRZ<chCh79WN zscg3%i3YC$Z5s&Rwy)?*IdEXF3M2OQbsmE6>MkkibKv;EEU@+S5y4z*WcWkw0z2?Y z#=t!d%4$)Sc0E|iX3z0)_!mGO!ZH6b%|UE%u>R;C-LH!M_%aXPIJ-rrndNCIQX?ZE zB0H<DiAVAjHw6)G*^H~T+Cn)E98~Dh5y4fAq+j(tXov2Wz(Pj=fxrUI4?-YEUEGBF z&j-kQ$|8fBSmZB7AmRO=tk-8eMCPgT^QlWhqRZYAOKEB<@D}uyhiA?39wRz!fDhK~ z|L~3{)fJTtr#3d4%IyfQhkTd=pks?c3w!fS>nR0=4IugrqJgv1siI}&72T!MrS{k6 zVtEdcE=Foa`rNCR!|jQchxQ^=EDQBM0ro3npGQjvQt^XH`0rt2V)_^efo4MLkrdkI znHb){pat(X!-h|mnbx;&mTXoRcLu32i%XBEd1>AC-9MPgTckuq1*9kNIrxKd_%ujw z)|6YqHVaR3Yd?PYAU84xVX_OL%G+d@S7b1)1YFL1V=!@#J$58uX2-ZMoucM<-$tFT z<Y*R0a|)`25!9tU#eJCGLU1dRlV@_KX|&hF!vh8R%gUCT^l!<>d5tQxxaU~x^usuV z`!(1->yNu`W&5-mb-M<#?*mEt$|m{SJ=%zZn#HbUJE)g{nq2Iimnrx=8V+FR+S=MP zrwb_FgOpk0oYu!CjL*-2Re0vKaRq?R!JF4POHei6P!A67a&1%bsF3Nv&!*1=SbVN~ zG0@dRxcEJ2QTc$`x{USCFJ(#MUClN_p4Ge}YzBqyc(2lpsqI;+wNa-putgyp&NM*9 z7o%PuCYv%hJ(4+&o{qm!gM-ro!|W|#6rZ(ttJ4fJDY|51>w}1O_byx>AwZX~qv|6a zSW=kA*!KDKo??OcWCck_{_MMFyu6{~J)s0lT6nh0tl%WCAi@o?{_W0Y?eet)byo&e zc`E3O8>btZKh)So%V%`y7@0wmaQU;Ng)j9`@J((q=FZXf-Gs!%qhc>I2%r(`6=id} z+j9FC8{<w0kYA6D?}k!*=Eo)DpGo%OWV7A7DnzoB;~}XcPpK}yprWRvw##SHVS~y! zusdY2`)g{#ErG7^W@&2&2XeQAwFGYB_ROBU@&~2jZtm`%Xxq|D6HZYD#?wusO3q37 zJnzyLGojN&%G8{9(c~vJCw#4mY{ZTwC4c|^r9QOj@aoXr<r5&MSs(6a51sn>@eLg3 z+sRw+<3m@pSkv5Db7aQKOz3K*la8CN9-AiA;t9iuv4g)z_rm;geKH;XQsSe#lv47v zG;(Hr6%?PN=rN~`LdRPVfxyZKgjV5)#ygnPUtu61a*e$77$WsvS079}mUCU|mUZ1D z)v+bD7&*Oycl-7m;Gbx#-(zFNu)SL5$6O(2CSsR6w2pb^`IN&<fukgIrgAV*0%tP^ zx!E;t5=ARyiGn&`+$YpXm*$G2IQ-5rH*x+z;Czh^p@h_U9s0}9J{^pn`^wG8(wu_G z!@Vv$vZwvoF|Z%j!%3h~%D&zf)&9Fv%A+BU)q=B4`7DhsH#!3o=-BU?&6ci<y09GE zWZ%QCu+(j_Q?tTxHEWMZ3JHRY_5^|YscuY69MZ4K$=X3VqYzn-(fXja%W`*uv+ugM zf}819v^H8joPF-TJ##HGYXDtmV(dr6b{`q7VM7x`>n)SvuyT`wJgf2a!rmudAf?%T zHQN<o0x;_8-e0c9;o*-hcSU#Kef*kLbCP}^>RQ6?S}w`>CBsLY#UA2a(~yE;J4NoE z*c%ilY!cqQypMyq+UeIWe98xOeo3$V?WvyB=6>X%-_B*KC{C~V`Q+BFA*!+ga{_xJ z7c|BIt*;)<8?77}E?)*~Fe)7_bLC@)(lwP)Ag^1gl>6k4diA+x;Q?8bWQ-WFsepkz z4zGnEFr2LtD~AtZZYkn-XQxzq(l#%Ot|%v!IovXx{2>}QpAFw*UwW{70r`uO!!*d* z#VeUz`~6-%PzD%pYhs3vsu$^`PgJk9glE_v<p)Snq83^wl2$=AKX-_g8c|>e%;nxX z*UMPTrA>pShj_v<qLo#WpTC}ZfU+h$z5Ok``*@8KeJt2}@es+?KF|{W+<xVoW&4TK ztf|jodO!$iPg%<)u+ZVjxmVg-dmlB9E^Umv?Je{EnJZi`V`<2gS9kjR*bK#*Sdodh z-ObCE!phF|iRJRbLfhSElQHi9sTu@&swED~bj1LrG}~*yks9W`|BLFMltl(0lQgzH zLJ=gul9=WekT4X!kv`Y;krp%*s-3_<-)1l&LpWF)RpN}>UswhQ<M1pteE*mldHZfh z<Y2kgGH-Y~fBvi8+~t8n@wihKC^5t@kNUDbauf@R?luK=A2U)@$81!e5He(}4rR4< z*Vlf5Dlc`FV*ukuR4qDDq2oA4Q*iQ?I{#Ybndz^cB^4gcq#_})nTP72M9@14L{!^m zip}4Uh-GhD(;+q+(PH4n01zZiX}l})QoGRf<1pcMueILKb@0ty<dax<8UNrq2T6u| z-x+3IRYes5PjoFFpc84!yp0}d(v`%och+cP{<rM+9FJV-y9`e7frl|K(Q0W^HrF|w z!cwdM#iI7P1(}t;`<`ZW*jaQmIfT(=BHq>wtJS-AP9r$S`{y&DiU2p)rqR*1Y>)oG z)kcEA6>zwE6$1P-$4$!?!)Jg`ccGzoaQ35Z2ZljW=iL4qTe`QCXSyVz8T;RfUbB`s zo{!+fyKC{eM5J_iVddA@u>7B7ZLj3M5p5YK(zu;dtGTwt^xbNXLkjVba1Mhsj;_AJ zhZ%5fTn~;1rZTS+fxabksQgj&yhh=IMWBE-ao9;sr0kH8$jzE;(swo98Fy9J*22T@ zqziU)$(I;=O)SYDY>XU<TswZxGo|yJY&TOs1=C<w<dzCtxB5>fN&Gy0`3<-{{0l#o ze*EcwqepEujmMwvszSK)n7n??<yP9?gPol@@ZdH+=!oX&BY{R3>g?SGsR6pZZy+ZZ zAUI^%w6cf}P6|Iz!+l89QF9!II)7JV-kn%+8SdeQN8bH0WU}<Ys3puVwvVd&xY^OQ z5A*?4I-L>ric*NP{#Tkk_aMp^ds!*eYz|kmRhC>fY<)#v`a6wjC>37^!CEF;<u+%| zWjOSSi&^PG%b*iLDV0t)_k6G<ZGh15tYa52+xj>$xmSph%q*xA*HhPNsz{gbIc^Ku zu9V$sxY`{xmcJ5I!|iFQ5MUW539$jq`275`w>X!m=|(Lmq|sIa9@_c$oc#RZ`hbE< znV@>|3sW*NeAHCQ)u`4BQ-~c~kZ)Bgj2+`{QEbNkF*P(jjY?`zEzs9J>PAD!5^_t` z{BB&d<Hi_n&0oppC1AZN&(#EUaqph^{^$JERCLG*eeul-etsZQYLDT3j>W3{<835n zDiC+9hI?P^jd-P`2`36qL-tmNU;X$n=!rnW&7!-AF;e=%BvfKP93$vN3uHTs#-N*P z_t7o}y(*tN)t@0Xf#08gc0ETQ4l?V{{1s?&7h9=l5y)tWu`Bv>-BsQ^JUrcLcD$6q zWIuMVr~x*YE=80Yac#saH;lqvwMr-b>hX>3PY+rjf;dHVQegZ6UtTWj_YzL%#6Y{5 zP+my2dhIxl&M8Nu$ZF_@jG#6l5u?HfC%@0)TENn`19P{+2PS4bGQjGjOOcu}Q+JIV zvXVEBHuvsarO%STvbw6nQ)JZvE1UKv*2SZ?()0qz9&o(<Qtwnqt4Ld*-(y~V2*fF_ zTFH?=)~pE8t$q}#+a4+Fpe%fSoAots+`qIMBdeyOZEH}NQ13s-s<Ap|fP<jdn5P|N zI9l@E1MvvF4JG1Pm8gDvP7kWfwWo<<h>hQPr2YDItaL6BC5eE_3{jO#%a+5kjCGHt zDB069EryI)(x}W*COIDVs=b9*NjchHXHQJ6a)D#qP7ow0pA+;(-jH^3==3`$Zz<B~ zq<<S;_NV;XTL!054o8uUzu{ax;J3vC_(?KrGoH<8;VFF4u{pCwP_9xmKZ1IP{h|sD z0aRXw(7V0TzG0$ckGK?JNFPL8C+r>j?iv}C5Nw~pO9F9Uq6x?o4N&+H;oj$o%3L@% zDE(Y#`x{ChceHA=p|N#!(3Pz?I*aGn$b((`7Sp0=h^64pX462C`F2o`-AFHMQJJ*t zl?4ge;84fM*%c0^1!o~H%Q!oJMXO&JXkIY51h-<}xpTLV!)v90PrbxEkd*s_jh;WD zxto)n!&l`lMtV)YQGM^!w4pE#hdUb^$0%LvEy2EZyt$>Nx@HHneB)_)pXW7k=jV3E z!bI*TES5i#YEjb2&kNdx))Uy(Q;K;THTugo1?kyE3oavZvk{O9(xnMSYis!T-g3dc zto!o3cIn!&nq24ba7L~qjl*#$gfhcO8jz9P0=WbhZb)6zAO;+YaNNg4Z{ED&bKb(k z3^2E{PxAz14(j|5Azse`QxqX1EwNC>6<>my7Pd8NZEO7ukog!`;g=EM7WaZx^)ax; zAi;r7={87nC7jYiOF(nUW_EA|fIZY9e8m(q_*zU%j?|Zr9~-w>U&7s;kE`MFpU@|~ zpcL*KlL8ykda*oZ21dqUdesSWwgzpDgcH8r?+sp&qooTEYrF*gn?sVn2-aq(&WHPR zEdHu|1Uvu~M&Vz+c*n=nfnKpskwz!T*Y~QW=;ZWvYO{V<5{b0*q5UnoNHsaRJBJ(N zi%L72G-}_Oxo!2k>i9X=An~_ayMbLCw4ZE26#amljaA&2gzg>)NSm(3sD*OmuoA?C ztv!3`LR+!x+ba}LpIWbv+=BlSq*n)WNyEN)G;&F|tHC=J?-y-U6xG5YO`4$vNxOXH zr>(r}eEj@>V6<wu4K_60CMA6Xn|*r6(FUPbcpVb0h*C%m{{L7jS1}0#TRvQ|{$UTR zaiz=g8_sTY4Fa_{7OL1_l~a6Ie5OxDUwAb~Du8Er@Wa5ON^8XKd)lV=k3<|E@c=1) z#6ERAIK^00j0m#52ZnW-AC=lE+zz5AwW6aIyJp`=NW9+lO!)Fe2xx5cb@S~#>#jUU zdAkx+lBNYN^^hY+7a-2@&Xx6b1I0>v*I0S~nvKQGcG&qEJX*TB#dpDdJT}&D={988 zQLJy0*a%3+hro(!kcM;Zqe)Qh%EtKVa*aQ-oJrL#fu4a5>5){j_w1c3yANos<bhY5 zaO<*8cx6bv$T~yx=Q?3zkMb3d-)5<Va$mO>Z$VhxT%AaiSU=u%t}z>seIu;}{0dka znih~RK_Q=DyXZR4#PW}2ve#kb_Aj2^U_${D(Yscuz%%uvDx*Y4f2(ZvQ9sJ6y{si$ zymLhpk{l2wS<$hI@j&FieLF+<#`cLXxouFb#?C{E##O3$jZc9$_KK^_zT+uX*wfte z{;Al@b+xN<srs-W&wkq+pHZ#z8%5hN@U@kWn+*{CKHZ~vS$}2X8TULT=(zH>u1h66 z`wgUJd(v@by>6}_-hX+}mkSi@#tVQmY;(f=E)k+w{+1{c_Ufg$^qH7fT^W`<)~#x> zRnEli{r#`6r{CYBp9;!~zj@&3`0~~G0`RoK5BZ;iET{XcX4X*k>I@0R&`}$7tin~E za-9ZzSbO(#U%^QSJ@*x;aF2(oxUBrmhYNZjEkV83fa?80#tPl})kG}L3JLqYapkgr z|MGzFO{(<<M|t)ZEvCNzw-z9na)NWQD*z!=X;?f|MP-EnptgXSObFOOp&&3|g2;iv z1%5Y(are<eJ>A#~a{CsJi=97q5qPma5q5-K3oh=$VdZR86hDk4B_vS6;>ed^EKou4 zEMjNdncIzeLhR$mk6=iW1dltjy1HB8v>3FvHf;Ae_1pEEpQjc&tT)E0MLQFQZ5(Xs zn=`0?f5M-JcT%-6e(yh?e;I1;LDV;#Uir}V+CZO*SS0Pc#Kdtp2wYOY6atWgh5LC5 zw0@zXrGKD#?sQ3@Rx85;zUm32wp=%^-@Fnz+tH#)slI<6eoqj;?aqC}`%03Oetu!| zzwk$5p>fp~jXO(p|JbbkAFmmsHB(4?G`hg)KOXL%|CseUCHKGnwSWG+*e_R4Zv11F z{6GJl@byrvH~&xm<@41EwEz6jjg_mvev7x?Qn@OG0zucdd^-1BcB8E~&R!J`D&}O9 zfxOakunLmb+TZd3=vorE-GadyqBWXHyqwjuA4-ax97f7$L5CA;@u-}qP8%B7WIT1* z7N%Bi0J;Kk5vJFC1uYXMLqb}kQ|mLxK<B7uuL`9^?U2<B>ei9qHum-Tgq*d>RXRGf zM$uT<RsuN%m^?3)^fjC5849r~?F3tc^P}wN{D9?33|Zm*A_8gn)K=*1)g(Si6_scA z1$HttxCI4}$^=l8q_(NrU7(*8FOUJ2{Y!Mdt*78Om&hV7v3pV?@1gBl;~S7Q%YhtA z;4JUy`e+HzTgk6#hhu=wo0&-h-c%`ksD?r+QJ?|FJGn`nKf&jvb)S<ati?Spc=H5u zt^}hSuy34}6CyfOG*_fCrlA=+rTEnM)4=ZROw8cVMRm@OcG@Qc@C8V?Ra5sv{<(Jr zHskCedGg?8Ot$JITX_}7d@aXfUc{wv6)%0cAs87nfhwMI$jr#9d5at!GIwSDywm1* z7qr+3wbr3`HVK+1Yv~<K6*G)`eo+n)gJxJ(k1}lQF-pePI6l5r&HDIp7{jRJormu4 z01=~}|0_xsnd(~HN?EGg!t&<z>+e>z^<b(Hr{Q$!h(wj2)thXmEVnoD;}^HF-Yj$` zM0`);U}5=)`Wo(PS+nh+A=2FWv^q)u+fA7e!@|OHAF8<f^{X-(^`>^zFq_v<Y{p?1 z`monjp6Y6r7LqlbGFZy422hA6qLMmbWQ>tfSzdw1Y;;3Q%ijkBHQRz~QJEt5dj`s} zn(_FK5kZ;D1yB{_Z)^r(WN@AD*r8Nnj*cfjg#zwJA7C2X=0f;Gy+OdOW$A{l6~YAk zJGQX^$AcPnMbggR{*lhXJ$Da}_6rhW71Qmo`|Sz*lT$@kCXQn{^d2AYlrKvbE}UWh zEjMFA#|TEGOi&dQ^4sRsAH%GrbS>J8pd6###vY|>03z;0@Vgxrf}JO@*H0d^-jLA_ zpqOClJl!P7fSS~FFjMSc?c|-x!pPaCqkqr?Gix=tIZ(6*kCodICU~BoNb)#tyaDZ? zPv2<CaWJ?gt5sQTowQzp#sh{F8bJw<EtM-*er2`^`w5h;7#ZsF7f=w3A2T&pHuRb~ zg4z!IAs=hUzST(HCwI#no=Fm3{MYau1~Ia^Eo?>{GMQPA08zJezAGe!nRrcSpw;gl zjmB%M8pzHpI#bp@wKr4rP6zFcCr75(#Y5hJREYhoDz;}bjm35D(Tazh=wfBNr$l4? zlcRzY)!hHpb%RGj{h-o#IURpu)zj4f7CdK)L509W@uw}uaMJw^_)`Q*NxyzQ1?)Zo z+mMP)e<~#uC9Cs>*^h5ZK|h}@+AN$Mf0l@6iH6G6r0;@?^StoW;Y8aN0Nwde)V9M3 zN`xC<O!9(KIuUvGcraHvT6%Tp8j4*4XWh>ZURF=Vqv+4ZPN}LVkM)KoTDMJy4%`HG znA%`MBwMXIc$Yx<0q0wK92}hfADWs*!(b9xV>XV3fDkZJdQLhyBjBr1(SGLVg$I{q zQ_bn^`G|ptPrTos>tMVq|K1&i@IZU?#LZC@;5VIxY!^^}WmudhAGxjD&X1tCbzK5) zY6oiJ(*qLyhI9s#jY-&<7Wqh9azUMoi{M~Wu>Is#yzGy+%kU-!&-XEbkX=4mhs!~) zR*+DRRxuv{y$^~zWTQ`j*m*Tc!6?ST&OvuCvp!<`lv#5W%^|OV@=qxsYBd&v5%8`b z;`055X(wx7$^;$PI|?Y!ToZ3RPPOc*urLCI9VPZ2ueb)?GTyy=?Vzhc@%F!7wQbQT z`G%|xiXGONR0Zz{LNy7WSK-P}m<0>aUX}x8L_RQ{QS_QEzyLfDu;tSe!Ih0_`>-<^ z$EwllMLt0?s8LvIIf>DK7$QY7`e0lnCxP4HLhxwp8b!(gD06Yv)uxlWf}jKgrc(r{ zB_5~shEE2&@PDkJx-s)x{AzNgP~91Y2(P~}Am!2_TIZ4Hs{ny~y3f!quSoBORP6${ zi|aA9zEv)}-JmmMTZ<X1Awjxt0NcD-ZS+jf?c<@xWTxKZ3CaH<`#aA+ew-QukZ}r* zJzG@EPtd?q4iy@0dd}MwTGdF{!MOPZyi&}))wDiqt(o(g2>N3Iq~}p6sIaak^GcT& zcp_ekOnkE&5-`b`j5s~iQz>>OK?Dg})um{ADHS|ZM9PIiWYz<q7<INv1dE<ZlNuQe zg99(!bFGE|oGE~2sQXM6a)krP-0%SK@%tRTe9aYk>UK9pptCSt`nyX0W5m&M<Tnjf z!4Zcwf0$~isO9Qe&j?mJ7a^AzE^{G9NY)ttsY9a~l82CS6ixSH7vJI|Fc?!)yAgDY z84{&?XOo3af~lVI#s?Q2k~lNjvZ*&}gB}VGX0Lds>|7Z9(5_`fj@o1B06lHLYI;$; zGgbcr1+Iho)%(QNYUkApT1DVmgC$?Tene0Io=!P8-~8AVg)V~_ugGLP4E1)~cP!db zQZZ_P<JmH#72fNdpSQ`>jeds1aR)vbd}djsDMg~eP|hfbaz6w51cQG{1$5C2@^Pr^ zAD*j*8d~`+uB`TO>9nHt5&{q1s9L#sjU4_J02KVP#I<14CkpZ><T)akw+g=v>CT|+ zU+FHp+|X)L4zn1ffA5=;xtQJJ-3~I_dLdM+KC|-g?P-GJ_EV8|TQe&d?xWG97pB8| zHC~5hgQ7Dj3zUkP6Q3dGO^yalebapbT2Y|1QLGtE01VzVEnbOvig^M!&ep!Nb`?kS z%c}TxuRH%)#R`AGX7&7~fDrSLc^`Fo+Vsr<C75vQ6c!?RrVP>!6Gl6ze*mP}+SyA1 zrRRQnv~z9Q9ifz#Y^<rNB_SXT72vpl>b^dY{JgKa797VF1rEW{%P3O`%J-9lWkYK% zAuPNcnR;!iKR5eh=}!;Wu`&ZVad_@#OMDIr((9=3LL7Z{xS3eTDT8_CqPyZ6c&(kk zFgMqz@QTJ;a0c2QN`AB>?cLnHbOHvs5Acm#v4+wm(IhJAvfOSFH4BT9W}p3?W<Ra? z*mHhU!0GvL?Yr|+>gP2?pqSc$Z(wR|?IpMYeN}uA5fk&Lds;8z(IlXo%m%#=P-{7_ zhFyWkAPX!vYB(8&F6>v1&=Ei;8J!Epw@+ww$Lh>G?Omp2Xr+&K5%s6Sw8^9SGE-pE z^9_*|RZHVpS$F2Lrk9q4x;7GR933C?oZuX8G{;nHk7#Khd!a!fhR!HU8UKpA+U0D7 zOP8jCfYHlit7UHUjsm%ho7;x@2XVJTK3uJ9XyDfz<+q=EfM8JP>}yHKotpY0iN(rq zJLlV3Bz*0r%tS3cRBCTwdWf>rW_yMLMeQAort_d7iITa_?#T$cHUCaKV>AnS)6d`# zr6&!T%W1Tlp#bH~I0d1{e>94|c)9)Hm&0wZGVXn`>OHXr^4(Xf!<ANoLphU(loyps zt%q1xA7S}#Y&ezA(nuOVEDw}PAIO%CgcUh)8dm1ElsOQ_s3*(IEAkF<(^@Y#!Gpl6 zyvTgK=B78W<V#nNz}F!v2>zI-+lOCbIr(Z;=@K2q4n5@liSyJrhW3y6Yy+<N%)*K= zq-Wq!@jzdUcy`-atcCvI&G-mL^!ay73oyur3)lv?TOn78d%RZiLs28JYln*)2<OE^ z7^sGZ)LTmEGsmJAq-2ykA#1YZmZxdl)CoqiXLh)xx;nsBAm|C`ad=R$l3N?OV+mlh z!6ZA3(!3E9`vp|eaVIE74lLBC6DL1|TOXT6lLqQ=$Wsy)S|wNTLB5)9kfXTO*_T&O z^^h0;59p1Z_m=YS=<I<B8Vp7QTTAnN=!eJP)ZJ<wd2g7Elt|$7ftSW?Jk_P|WY1o9 zwn~3l>9B6hdUtnsu`99*n!<>#!Kll@ga*_p*vNxZfGdr&=g?(zz!@GEW;`-y7xtPp z?iD`^&28@t+Q`mBar_P?fsBD|J$U-?zU1btHf=av1^RE6jrG=9%I~LP?QsYmaTk)^ z-QEZj(*AF44joD-14hCm-keDF8TstYSMRjo6+`2Lomt53nG)HtJ@?}ghy)3}^Jg=b zuDYhp*VR9H`BH>twc~YY%PLai_(|%nLeAN3m>`s0xK?Jjn6q=7x-*Z>Xau6WAR<Lo zAnhpJ2!&vx5&@XzpXABDse<EOx0(6n=P&gmSZnbJI|c@R>x+y7(q;`sg?A_O-@$~- zWt;sK2LwcIX&~7^+ibnkPne@s*@;OZz9oBHaF15uk>+Y(NQhCVhQr`6<l*J3$D|-q z6^zQA`I|2!#Q)GayeZjcYU*}@L0i+`Nq@P`aGvbTMQy38NpHcR1e;`xsl&q5(+i$4 zznFvXPvL=06+Hc&CAV3_XNZ9;r6zd)AVsxa*;9pW3jt1^OadpF4<UrCT%|B;PpbUV z-JRv@ua)LnEapC#k~F~=TYYxP#%-4adEwO!0<l9+LcI=d`uSSCO&qhF;l{?7mi|B5 zwtzRtx9L+7X7sy5O#IoaoE6mn<jL__6DQ{8=0^*wOcEPI^**8q=gFbwZ<CQxKoebP zq%nG#4gCyG)NHM88?lwxmDrr#=maSxOo{-aLLzXKa`nRCoLcVtm(J_NUyegQIy?Oj z&H7AaET;z}e5YDTq(v5ey)*l3!>8I}oXrPFhxGgOOGtMqvuB3@nC;HB$Zw2Sc1@=? zt5)e>LnzWJGe5x7{Q(RZ#gkZA7Ch1iRTn5Y{zNel1IDSG4zqiN>i44O%#%xtd>S_< z(Cfy>JLWFRD=Tl`CQNH*YRuv^3+5qCMuFZxmE>wl7tW+{C56&bQ=fR8;LLzUTx(Is zr6p$n^R(IK;BMlk(U{ccE0L=gr<-wflba*eAs4kcL$O?d`GE24z;S0&lmA3@MfXf4 z4r)#dCHB2FG0=VHNpN@At2ks91Zp&DMa&4N@LVrtE`kLH6|uUi-#l#{NtJj&0^xTi zKd*7GF!%&>h=5CBq~wJ@8g5s*5Pd1KeRgaIQkOz_N8l5DQ>ZUJS-r~2U*+GONSqlb z<-)rimp^%v_6w7FHa8L4Ui;T-&&D*F@&+PcmXmgPi`YYHa&2A$y30pk1Yp#aWHT%B z;B#~i%09wdtI64{Eg!lbkOpWq|D5Z5hyVc{8VYD=k7Ef1E6e!m%iPnL4^Gkl1019E z5n^wIj*m9x9yxSL_(&?SNf@^4S7pso&T7Y`m>i1TfVTU@p{?AWCIZm17>%I>?^j|6 zqCwDd^+L;!zaG!xw3&X@jGKF&6J{NYphyHUU&fsx)UZ)?^){u};@qR@>qzrDK)TVt z48815KCtgN6Rr}2YQnH%#0#->Ax{M=vor~49=Vj|<iZLxP!hUzaJKqb<+5YF)h!Fc zH9PnX1BbK)NPdZp&rM0yr)Vga5eH{whY>uG?w~eM(A5~95q2dv7arE4w`=DqU||nJ z?R*cWq2Pc46A4POhB;1-+J@nm0ax7I+zb*&p3BCqde#3DjMxOeanVDY41|>fv3Q$f zY4VF&?eV<#m6Zt$YP9$(Wy)=@fu}W%+Do8K*`hANS>%x#ogQNyigDM>0!g-E;J?8J zRP~k7s;^!w_UaQpg9HH8I3xm}AjiZNUrsGe36&=E#1*6RAZlO);jU4Ne{o^Ze!-Cb zQgm`Y%Svt8T^W!Q5uD5WlL~~kNN!4ihQy-uWH9$nfJlNtTyE<rW|)Dog${<_?Xq?6 z$838AlYu|f^_u@vUB8Ty24fFT0B;0BE9dLBc55Tm(k5kAlR1&~E)Yn2u|J?=8#Zfz zkhs9eX>Qa|l3}8`e@45JE?M%LnTfO;Xgv^J$%2?L;Ft|qhm{p(W=L_t_z{7LrMz2( zp(nXkBuqCFK6Ac@;4oGA3W6(#balIn_|=}-W}eH<)zyYI!rE{)BOHY5;Yur@FesM? zFtDksRd?zxll5UABEEeaOX&BFi&iH%7ij(SI)D;WPkMn?1MqUg#>{QkRT|Y94+yw3 zBgMofQD$+Ix!j~p`W<oi0p~h8iYR!)E7J~=5fH4P8m8lo+Vg;=J}11}p|b5U93j&$ zFsb`MrR2cMk};9du5w}2@+~>mWn`}$rQCzEAN7f|xdYP92xi80J2=#fUXw@B$4Np! zgvDI`83C27C}sy15ukL%;?d{e>laC_o?g^qF;+>|AU%EpC<&_40AiH>T-C7L@f-v8 zeCz&6(caqnli_Y<!Cmrpm~Z3dBn9Ai?kS1$)!Iykok?9V>F|uiKI%T*P<Kg(6J=?r zYA^)cSkk`dC|cm3cq=(;U9aH9900$-1MV#yr2bxoprA9jcFmh7UJq`(()y6MXZ15r zeJ<Y8T%(II6ObsOW&=T<pJzLumNkfEuu6)M&<BSDR@7bPYat}k)Y!SQq8kh2P(h5R zj~2)gNor`8mMw%_o0B0d<z8{imTH7Ne$K-=8s#F;aH2U_um90S&oAt|B~uLdH5w@? zw&V+em@Pe6`Mo;_%D&-73tHv7cNraOu*__w{ryO+l~3nY^eq@X+h1T(9<-iPyf{lj zxDFfL>N)f5*k*pp!Xit!pvf!#?I1sy+48#-(AYsMic4cZ7!Uy=52<KqXgbc{wX0v` zYL_OY1~{TP%s^tc1n6cyeh5Uhn+d#LJwF}H3Kt$m?Pz~+3g8$rhutqUs=uOP+5&R< z6;z!#Nfr2Oco@qYfV()2%f1Zh<(@1-xJ5rVKlV{kcYP<UZ+Jr19J031ePNNUT^R@& z0R@~vU07r}8VeN?Yc5AKO8A=m_SFx$v~QMQtO{}xN9BPiM+7H7Gq636UH-qt*`LrP z-evZ}LY$u*G`7%`{$2%>xl&ek7s!@u`j-gX#a6#$Z5qnU3u3rGXgZx^emujB$WS_E zsd>Bhb4-!NzNB<jk-JORwm@^2+BPAMW4mQ7-EuNN^Hb|!qxzKcP?}AXtrm|-9aOYD zm;IP9vH-;!rS!v~)Ks4dcPN4uZ0+q81e9|W>U9VW{`VmKu8#(Xfg*5v5u5DqY9@}W z_ZGSmN3Dl5X#xt;LI>{4d0z70eJ(rFEPHyi(Eb(2(h&@uY7?fX|70osxSokFZ8d?- z^(>^MUF%|W<RZEHG}x5Zqycg9*RS~NTjl;&`6<*oxqsc5%v8s_Chp%4{jD|lzS`;c z#LWZ7PjAtm-+r0*I3>mV(N}+WuSSi#VM4EkQUz-5_%PW@B`m{Y-Haw;TX6JdzZvWH zUF9vwz5Biqc2kDaG-KM+H>h6RJ?AXg;W9He_NEN_?(jENbi%Y0rmGtJO$w(r$q)#Y zjUvST)_7z0q`*IsbOd72jDDUTZg0nls1Uss^AT;_y7AeJ&E|39=pJOQe8O+Pt+;u5 zR8sDpin(c-ffMCFev!cRqx#Wl@4Q)={c)VIt5DrdM6cAroA5O8`mQ6VpTgdEA0>9! zv<+&434|o^H?hdp*rXxIzIq^;Ds$PzdHL;`uWwbr$2Y?g+>Xm~6t^GVxsjaVDa>qR zDt(@WHQIVFGTx?d6LN2^5z=<DSsVR2(2|r@lsDCGV!MA_T6*B;trrWwUB#$T_?tvc z_ew-W_srMiLtx<huV2whEY*<At4Kc0n#;IWV5C1061-A567`$ZG8GXK5x%&4H~b5g z^agtf-DyW#S3iRr1Nhr5^NTh&X7WjyXWLT>qWe@W*ANV!9`3kiI}+C#b@|oK=UV-c zqd?%Mm=Cl534O6&Wg}wC_Q3Pghu5X<XR)o9@2}lR5k2huTVz1xo^)a`V&ia(Q+P&o z;-SB9Rbp>qa*luRUN);HJ-*(-*emBH^2Bk+ZLdOI3q{@+i``1Mc1`mNio63dO7UcF z>YsDa&~Tk@gUB{=#lWKqUcyXZ4R~7qpI;GaFKyd8CTi@Ymy^$I_X>u9{f`K?o1Pi4 zD&)o)u;gq;jymaG2ve0M2;@4(^Oe_L+cfA(a?$*`UxQ(sXwRKxi**nYaWCPSi-@i| z0?OMwJa^~mnfsB=I5%$KU+FU)`bl18$yln8zuGZMdl>08uJOCK>18a9($inxTX39- z_i+6EG5!|VD8|))t8l+$`_(GO<AXFJVk0>@I=X_OH;v06p1X+vha`d>swX#PJXTI6 zOxzsa@iA%FU?9@w|0;%7dua=L71wJJFlk<Ubc=`aF~MuKLJ<dYGC+oD4?SoJ5bD3_ z&vn#2XfDCpipA^e-32E5_obyFBkMcH%x1PC%R3~7$I^SJ-Sb>-Z5<@L1U$OuO%|ph zOmtNG`-yxXUtY<WH?!G~qeJMVr;@0Z7)RxErTEu+dCOdgd}kSTpQ!4sr{6i8sL%lU z@_XN15z#Et*H4I#<l4(J<-X+BXx%;W*j5L@|37}I{<KOajafF%IM5Dn>P_<%kEZ<? z8|)avp+^)L6m&m0G$A1nsU7WQHBv<0-cFn5(m6M$@9SHm?8;A0j>eeLr8n-6H03?- zN~pYwpjIxyZjE9{oIcFjI73;2q<CU!MfWY<h83)N43E~wHYaPj5L0XA;?5Ti7!tAY z#>_{_6FK_2yAd7n9JhPLBB+D$IeRZRZ6|W~lJwrz=tS>&B7|<nQ&N+cuJOtmic3iR zDq1d_UR}gRs8rk9RMZ;4wIJ+4nu#KMg)(6>h$gMpeV-^pO5CgT=lkypp$zLJ_x7Zm zCGmZWT-PbxgD*JytYF9cmikq1T#y2J=WT^JpE_I$US@yU;Ev}qyYk`%I-;(Gq%soY zJ|C|0J2oSxD~OZBO(Y(le%~2HiV_|=5?-aJcXo`ms(<DoCEzNiJ<^1idJB8!G4mFM zhE#IEZW1~zraFLPQ@@5D8Ed{TfBUxPx&e2}s8h_mV9(}@=t=W;XUEgFCwz|Fo66kA zjYC~zrDJ1g2&Jf2hrfdsozEP{t|6Fh&ZzB|#{}#q?s?y#_}nnR=K|+H1O^MT#we+& zAHdc!bOgJp%I0Vdk4E^+?;yY3)>cQCWI@r{zbwmcIoh?sauxr2>nz>TAO88PKmisy z0`cxveECz64gC@LXNoT#KvE__73<c4y97DLeDQkb=JY)F8$LPXr+OVD9XCvn>YSL5 zZk3R5H{nxBC%&?NO)V!U2S9q@D{-ZnrF{8b3-wXseb0f!+OXy1Oat;ni|yLqbk=KS zH@|%octX3v2B|a%ly>L{Q`LSUiax>n!NWBcbkm#DPpGDXPdxydc><pchLrBUzY2ac zS@!E7t-wK`u4i}#&o2m}AoH$=-z1V&sIT5`EqT&<Lx>(f>)%>{w>CEnyEJ`I5BU*@ zaEs<|#-Wd$4;f!BC$E(<rnVhw%SRP6bXTeBA?n}|*}!uN`1*lr4TDQ#oY}Np|HDfg z1mGL&bj14T*Q&_8;-8l|<>oMRAg_l~<G@a_hO=u@D&?+EFwXdeuX|&7U*a<~r?m~S zm>mcsgaQtbp)mSl-xbU2#0Zmp1PCC34W2P*e@;o!floHOQ62Drt6u7_(nZA;Ay_}g z;@EDDsJrkH&3`-Z3Zefc@c(>dE_z`|pD)c&pwO<lO?9)_uZ>|^j2y~bFBr(!seN%e zi1^N?JtCRx2Z+OCc=VQ*7U!AS&mT+r{1Dvnxs!f@JDzJk_{ho>$y3s@=@rVVoVNdc z>P9EC%Uw7g5Z=Fn2u#)wK@SL?K0n1hdPowKHKf7fx~7lt4wWVE&oWEP+ni3N%6F)= zuM^6O>ga)QEYe}O(uw@FghcC>8?8zTB97DIx)9GFgZY&p=dG>V5U*j2SqMDS+x`dY zx~CNm_jWVZIbdTr(@1G}RI*gtpiV>6`qm*XioW9GuV!(4pO}|xUYR@}*S$%j{x(eI z+j7&LkM?~L_pqMc!3t|^aVCCD;-|0mLw|7Y%RkTV2Tzkx$F-&fhDsd^MPlM1CS@^c zF)`s%Qgl50i`x)J{QJUOOh`B3JV_KK;t26Hd|fRrys-?7_pe@qtUf-Gkc~uLE`zF( zx(ayS`U%~V*4Ye)i><AY2fPzFxmvZdE@L<5CG$Ly;k`Tch^h5;AFPrC;XGYai_xOS zwb;HdbkVjcv#2v$<c?h7x>;x0>b$qyA;i?m17p(-jV(AtR+m#79DbLpJLl1=C2vWf zMGWRdT7VO#MB3ie6dqVNV(Ctk4Up=!r7J>*nJ%(P4x!`Z)<X=0%Gsp3Zq#4p+)14= zXWq13i9|k}P}$^s5K8+E1qI%i{_|CnS|!C>WKk0E$FXB^8`<C3{@z6zYK68~^z`kD z8@wj1wZcLrv@jI#s}9ZMo)+<0ZI3YCR-jkLH`r24G{5f_bqOS!N`?6?h*r|O50>Wz zkvm?HY<{hUp+4k$mtf&I#!20%%a^sd7G8zY?(Qs>?-NICfBnhCD>2vb+nH~}%KhEw z{`~Wxrh;W|YYo4;Y<X|8SgzNn4=*cm_|XsnIBU@I&EM}8biXbi)1$3<p~R^EVMW`h zCK?XLF;u$ge>-09Rsk^i{APUmuS>5eGhsp8WW=&gnr+$*a^>Iz6lMe)sWA}nhxn%E zH(q4~xBvO8$LR}yz{<5Zxtg^!R~v7UMID$2BXm?NDQP3P>a&Kdn2$C+#g@V9@>L{l zWS+&TrL&8m?DY>&nFxV9LU*d$B70XTn<x&l)5=`q-e^g7{Z8bnb;E$<vr_w({ic|= zyg0BVLfJ**=1n{E(E^ODL36q5zvwi7J_RLf(AO6j<N<MJe>0q%?lGGC^1I>ET)n4| zW$IsxdGIPLmyP7EL8N}Z%B;n$Tel*#`sPoW!k+|9G9X~-><v*IZaw(6pV=L}|Fu~N zTd|e~3O_T`l~PJb(tR@uVMK+0@dTyR=jRp7?Ce5*JCx66ZLfEop-*jilKI^vu5T@f zVn(;tG!q}IKEz|uu1N`Yu;|Y(c?l~+*afVhpJR3^K?j+05F`t__AeTxIrk|gAEdFH zm7Ud?DKpfggaQWfY>%I$`WC^$<8O*>3lRMidp%){_}!*3)jc-GPw>B+CMd^l%3dtC zgk!Ritjn~0!;mUZkdHALhJ>vYRm_~CZKa}0!(_(9gxslB{A~EleeNnEMZUS@hDn8c z0IG@?C_3*LWX|<JcPrKH7?CV<+x#jMa36m9$^NQNcU`T{TRA1&<iM+hS5{VG>8b3% zqjE6q)?HoT_*>$^Wm#51gY8UbsBv#_uo$>^ya;Mpjrr~3YD$>hs9y-8%eQRcEGsX+ zx&IXk<&~jAks(Hs$d&AWMU?=ylRN+AxG;%64t>PPsAW*6V@f9AOD-UQ_W!Z>mQhu< zUDxnNloSyVDFG4b6qF7H1*DM{DUt4$1}RZOq`SKtNdW=r?v^e=Qu<x{dhYuhPmJ%+ z`}chq!*Su|hJEhyJdSm&HRoJ&>34=pa^Gg>>|+a+xP5wwibz)Kz$f8rP-AX`aQ8Dw zm=cSKtFyns+WHR$rd!A>8Y!4VX6biCGl&jZ;**H4UqAHsAA@w%53>K8=$AiTgM-DQ zEH3Wjx2EWSHn57e$otb>7en*l0sf;$+U1OkLNA{G8p^^5=VtJq{x;GVc@qH^&rrcQ z)}V~3%M9&lGvB3txFlG*`ZE~b%;<t7D>6FTC;ZN%y%lBchK+w`h)3K^aKZSe6uhN| zV_i=N{=Q#7V^k`hcVuaA81c{Wc&`}|%R1(BpkdIn*7a2TKUF)(Z&R6V{tPO2M_1hT zw7dIE+@HZ{sK$44yY=lOIH%K~32Bb$GcrdEzd^hv^`DYO<hKU|$m8Y&JKiVb8!}mx zjJSM$vbQXs`u@>U*D<<~d!T2ZqVTkJqkm_Fbcy}`24(y|_154EgBzzS-Cw8w^CS7^ zdqlFI)03^aTEa72iq<1?m)rO7Kh1xU|E_#^r2STp>h9-IXyo3BQ$Sw%Ab<S8e@$gR zeq7@}Jz%)DGwVBV-p_yi#trHhUq1kQ()=TxIX7DQLy7eOWx|Vpei+a20G`Bu`8vfU zWOzmV;?o^JU*D6EUM%Dlt$*7R=0p8&pZh=lnjYx&Un`e?zsmXJ|Ng_j@5R6V`@gs3 zzul1M&;KuO3B92K`A@q0kIQbsM9u&CbuhK~-)iZ9zs8w<$l%~fkrK!M-%k$hVPf=z zFItKH_weu^8$|HO|A-s^`w#!m-jehvuLh`+bcS*{&y&zE*YctF^?!a{+~)PLLsMc< zFTMT{Uk54yv&mw7g9sT9yGXm0i*a<Y5ko~Vt3M`k+FQD8;(fIPHIY^08G<5F3j@p9 zzs5da$Jp4*!TdGknewq`LVy0WMlf+(U8T@nL)A_daUvMbR=|Pjcp@-RoRcL4OjE1h zpO8X1VSVL=4pQoXn$bw3{$y6j1Y~XJ9Ct*Z1fzK`wC6WhwwnDqgM-;rBU$u}i(WBP zDfSG&Gu@_C{o8b(AGu9F45v>y6+AgZpFc`)slNJ-N|88=gfqH(^4`vS3T3}L%^Ka& zNci#N;kzz0U=^4YL*N9qx@;yCc)u3#Pr+%w`8p-If(G1teL*Ll@$D)ik9+?2CBkt> z@F{=<$kebcXhZMml@R1~{fxp<MQ{B5v$!dQoj!f}BCn<~=BLksU2bfS3ZN*~RHGAt z5BvfnS66fwjXP{w%ro0x!@{iL4c|KndiiG&fsLv>%-S8!RYoPBtP%r<k-=$U&Y~{r zqV{U{i@Ox>1w<qy=r=}7L|8tPuFV!G#<mYGmk|d1vih||0+}$LyN7+gNlRNMCV*ox zDd!$+Z%c?3w+s*nth>yfyk(hLXBQE?)_XVKSk9s$0*NnibCsWTmAYoOTd%nOX#2$8 z>TnMU_UNwyQSsvhI|@LV5IUg-3`|U4C^L~C7wvHKdugTbppapoX7e)Bm;xk_mn74| zU3+5BPh}eFWWcdqnca0<XW<H2iG3z2>Mwo430ASJJ#I-thb^PqwSbbdGRF%Oe6y9> z@w#?R8-!ctjK>VG(%DU-RYeasl;ulAPV6>KQ|G+Y;;-?a#Yh03W?QQ(ir!S`tei1s z@1}J>RolOC88g`}?klS~JEU7Y)*Jc#4c8ICFF(r)HXmrvWO~<E=p5`*UHyLA%DzQ3 zM7(-=B^Y{jl=5ERz#$ub0U8jf?b~AC==UiippVX_yx2H4<sv`{^VY4Vlh3O2i;Mo^ zS|PqiaeVg71L@Y@lnH_l9?)!w>j{&d4cP67pOK`GxT_WGpg;n9FM{bJ0I6}Y=l$~9 zdG4b7y+J32<|&8$I{KZ@ip6HFuYLR)#IG8iQ!F%@DyH0v_T*#P9>L@O!fiP#Ey$Ye zrp@x@$=LU<Gfaya8~<ZH%Int~Zg=j&@Rz3U{I7#YKuvk_sOJxqoE>cV`QdCDmlre) zN7M`(3#U>FQL}2*d;)xjzCICd?HwkAKzy1{DaMO_?2j1Y7*@};po_zI%JFw9EM>HV zor3VoU#(2}nvFC)dP_fJP;Cu)?`t;*momnw8^A2-_vcGFZBtbi`rg6hll1kM>x$Q9 z<N2VKMqqcv{5GHh^0Vppa+Pud69sFMZ88pas_b%b?To`f{y{<E{J!a878QwnROA|n z+!S$M_Rq@Vwy2r$s;a`(YH-G}-8aeBS3os?JwbnQ7bMR&081RKzlHe1rY*!Ay_$Vc z!@B%j>}}H0`XKAcvJ|syQoSdLLz-KLu>H``ic52EFiBy9egTWuhQ89*K$)D1^J4BB zjPn?Kf2Kfv=?{&EO!XAE|6XgCi}xzp;jDAtzYCGc>*cr7Y>jsOnHmS_edkNFQX1L- znpg|wPzi3Cm!VIgh<F(vSVg6PK<rD>a6Zwy>_dHIQ_fPV-@=Bs<<c^O<8V}lKvY@8 zcYTff*<IY_Bs^-VM1D`9(2T@PtxDSb{!+zemCg>k#&(G+vqm&S(9e_<N_N0suKWAs zN>d73Tt~w>m(q`I^gxIOCSDJvmu2XIf=h#|@RgG{HUbI>cBfqGy1FC;;uiV17t9P~ zGIw0<6_k$OO6Ix(RdoCOvy0(OQzTyYrrPQTMMxbU5(5=p?u>jkl54=u$@v0eLbk4! z%%<(f*0;=>m1uAWRAOe+Tnwe-_!M%I(bM%?C+#(g4d<vL&PYiJn|rr66>7p)mc{ZV zd?5L^I*iThJb2so0*nh8!&xu3{iXrJ^uFSLy=cp`GaYSl+Yr<^mkGR-ux1rvW&uHB zj^-BCUlcXajw)Ma)$OfoWgLQl(h{pIB@g=|<FTgDR9{lsBi*lpt{3M3Vi=CvMR0!= zer;pJLHhVIvM6XXs%0{_QtZrrZ5ll^bg;%^pjq8$q|_;LnNzUmwVjW|9e=@EuADlr zj+;>3=}sO@m<a13h=uHK``sc*-zA>_E(0hgZ>VeE9!iePNj*3{%wV+~daE#W4~l=h zOJS2h76F0!fh<+-ahZfKD-9M^JIxNAjR;TED9taz9zuvg^uM8cW<!FGGc_t|4R#H) zvta~oY=Gnpl-MTORcY{epiP!rr0mAB9)~|a*c`|ZKq<FW9L&I><>I;vvGse)kcNIu zg|d0R);Bd``G?5vzzzpapWd2b0M~T~KB$x8_TI#~@MN87T(&;QP9fgwLj)bsyjle` zi-)IIc>)a!LG6d5LTo4gJRNsDq|N;?$x)i|SjbUXfB8i}tP;KUo8n1YGYz7Jc4-}s z+GB>9f&Ce5ic#)QOL%UWj#@MW;D~~_HAI&tUM0&|)w8k3{`deDOdtI;EPeyfD!aDI z$-#Jie?wWJLQ+3EMp-1y@6g_)cCfPO?$2}6`=Ju^b!VQFd{_vTBDM58KFV1QD|6ga z0cit`NjCHPCa14dH(q63e02XCI9aL34MXlCemjh+R6H_mE0@Mi?!!_oob~ix6hHt5 z!==XKkvYf}#j5SU*nP52u^HG!b%)I$e%-0t1ojXTidoz~J6cCtaWK?5oG+1pOVop& z3qE@@Z1l4Z$!#r;nql;s@|Q4A1C`(5w{naD5QZ<X4bybJYZ!-cDS1(VF&X(?J8kSG z68Q5HRlL~dP%L69Z|@&;&QwFzh~VsDnpEvOIG+J54F3K-it*Tdq?C81yHq?;z{zK< zG&T53ROlk=AW900SuDmCK#d=U_9}R+_oQRbCS($JTXq=SuBG=GfC;%s;XPjHe&Kr8 z$4dS;G!*5&GjAFjB3hZN6_5&u5Zi1|%8G>e?fzE7C##f^vfCa+@i^DT0IpE2QI}~J zt-j@p?xNMNaiNUn%gDG|s}>rv1n7NNn66n44r4W>!f(~xQxd-?Tq>TWPT%Mn&^k|* z2HeUG>NF8zerMut#yBJ*EFPTDjHAk(uUU2D#@?zp7=jQU;lMcsdOQ>f%U}LDCu9Z@ zOifo#h|2A8Z|Kc|W(j<{kZompcJMg71y?g(+N1s+L%w}zNW&<e9?%!JvxBEWq$9f< zBV_S5yy(Dl<xdq8g71Z_?e#Q1Hm!!Xt#6-!mrdSv2L6-k)903{WJe@w{|^^dFx(zQ zlBw)H-Z?_%OV(d${yJ52DiYy|O;q&jS4JL>`>)3~%bgi^LkPqsml+``U5%Ydh(Ql2 z3jX|H#AfyTbw<Fc*zG5!d3MILkJ_l7w3F;xpY;kNo`N}8f1NQkF(KCn2;ceYRV1(% z|1`o)Tp6ZXh^CRc(=IJu`#1y{l>gyZJcvm%<8V*V7x7xq(%dijAX{ka(Qqtw>3fDe z`Okf28O8VCt=NOYBhqR}z95$bw8&n+S_A)lU&MppfeIfzkd&XqC83I5klyHQ;#2Ee z_`7=cU;kStWROoSimLGd+ItIL*Bw(ujE07W6_F>z=Wt#w=G6d~Fmy3<CE4H_@FL0m ziol`<`BRbF;){X@yUhhtzcGLg2BwpmiVAPBJ?L-f1kD4%F$l^aUVUNi?3`v{{{%Rp zJM>>DJ<D%lW1nHL?a;kn`-5@3<DxV84n6;MiG(Hpt$+r9T*_vj#_es|2aXmaoXbiD zsRG2ZQL8r~;;p?(G@8mxmm&)Uj4Rq&(YN;#Udz=pI1ez~t|-7W<^wV(brxvectS>q zcAtihuBFL3u|Iki7A#~vK#z$6=7@l4%U*Ckt@LVtD2P)v9hRv5VXRy;bzA=j0j2go zxcli8@uPFf=u35!l2jgW1;vN*p%^en=t&KvnBl*gpT@_#c=JyPb2=RjIpW-yEeK<G zF$YENY=fKsDhk_f{~{i6>pUzPsKRhN?aCEvC)+~8Lw6cj`=m)S%(XKsFFdJIb`}7k zU!;@8Zt6Ae=-gw6E$}%q{|6+`ceJ=6l!>CE!om6rHdH^i8Bhkc1{0>`zf4VP4n_=G zpNv;seUukhSAU(X+E+-gSaU~2L|A9j!4T4tAAsbKH#+7ucdwTjNE6VWD=q_HGG5~b z9A=2{U=q2q_J*YS=HvPHgO<%^h`owtjpRFu&#!CMy~m-X)JDE*N;~!W6CDh$d`-WN z7<Rq)2A_k2y`qi@s%vKbx?=X%Ev_zG&=G@YA491xvm9!#o$MRFrfAH9IY60Y-R^(a zUM^^5>0a<*8AEt$ZR_FpxjJ4S!C6@u0m|Q^&iN3{KREvByLWeb<Lf^j@3g=itydZ9 zv-Sbl0~s>SPRA%zKgUutd65B=AgpwE&;0`orJ~~Cz`7M|YrXN;9n`V%x^v)jg88fg zg7lwbPaz=B*=Or;nt@>1<ys>b3rYBp<{$4H<F+|mBF&v>1X&-(EllOu1l1@Tk+^ZX zr&SIw1D=1tqo%_`MWG9%#O#{9D<Lb{Hey=HW3@&Mwsu}1_0~C(cF}F@E~I{?QEnAE z>1h>nf}Mbn=;E{8x73e@rMQ$64B#*o!dQK-R+al)y+i;q-rXPVxc;{&(Gjo)yt9AO zLlq+Dx1a5ZANB)Z=8EPatrR|f7>)Ixm-q^AQkV9LLYF%BZ+C>PQhm+e>lS`GnE!(A z<$h$sLqN_;w*=I;PlGh@H=VhVf4){%S5qdCN1)v#r79^jq*mXZ<H#ugPE_P`?(+V9 z&WvMeLfS(ip=VUvIXj%Xb1)WcGrS#+$mSBbIj<y>I4w(l)FcMITUvW5X$<FTq}o_n z=;Mm@`<NK-Q@-52y(=;}oay~I#FTKK-bL`Rk%Awh5aBj!JEKDu2aHG6~Uk`<(} z525)Z3i;EpP_iHL^74xATuh&IHGk8n+GL%m)6ZH0TgR`!mFvc3_a)IJhSbq$RPtg^ z9jzT!Ejc~a@#{TYSM({q0*g7q-q5dKAAp-|&KF3<eVQAfLKd0q)jSIiuHX5NM|A<4 zK<oq)_lkbYcB}gHtD2&utE!!>ti5AJ@)9-X6VvbV0rrAq9X>CQU}c`zmRltv351MV zkX;-(CQgjKIEp)i7eRL(k#9NVak+w#tVspuJ3GMXV;Mtc>SM~Q)Bn+K|EivbhKAw7 zucbvevvw}}k0RmGH`nD;$DakxrF%d7`h=x|J(f3c7V2{uxqrMZdDrC8<x{HEaBr&G z$-k|U=E13bM^qIF3n#F45C3^Q8|8d6=F6MuAd^|J$Hiq^I4mx<ia1NO;iWUPy=W`A zxg5HtYJ1XYpQ6==q4^sOAI8$nogRc5&HWSX&g*~FpHWCUl_u;JeW5r!Dce2u_D^iy zglWZ!lRJ}#aU!R%VAmTQC+x#C`H|~moBueomQvw$d}I;f<aJ?>U=_(EKJ(1UBgF@) zlmQn;$l@+Goa@3!m_TL{cdo&Wj^v<^Ubhy!!rfQjn9x$sxoIZGaEL@TNSmLb81`yq z@A2K^w|=cpQI;#<dbIT|T{LU9`4an5gVqVEC=qoqQl$HHxF3ZSu?*H|IxcVyWM0Wl zHM~A?<J>1bfT#V>f?L`0m0UK22e2>+ZGQZyJFgz7H@r=-N_eaHV%?&M%|4^jKGs#J z!BDu4tJ1>p?#3f!<PDy?Y-#4@x7%Pj!6(bxcjBA^TYKe5s;l1UESs|o**u!jL$il4 zx$3l+cLaCmgQ$<`W5e0EzU5HSV;zf7QSC$=$w^Cx2gd2pnN@W;H4bvs{O~oJq6ONQ zF5Y%Hy5lS8&wUTLExmo_wg>f1!-GwC*u{A)Y)aLrSU5N&>GzL+^XHcr@liH6`wDE& zy2w+>OxcJ;jnipP(x6_`!Z6OA6mi^|WJ-qt*qLs+OYh2qe`W(Q?duAo-4&?JcN$u9 z8aOc}&l<08)4CoZFIP)Tjzcgc_G{~y`{jeLAAjN3ba9ORTMK{;3nKR{#NIj{TCQm@ zmd3cz;IG>>K(PjB6o<0BJUfIY6uBo|*V}%$Ho<8TE|$=7<nn8g$qZRcZH-spuJ&rT z#c@9)=@eHQHq`wg-q`5Om~jQ6iPTNAZQ)W>&i657OU(_zLs|4J`wEaPI3I3dK{mE~ zbkrf=@X7_4am4!L3#hvkBzH#2m=I6^kd-_L-F1HRMj)6%_y*#yp_NB;tcucj-*EW@ zz(yz$RtJ9>phF1Tcv+^iX)>3~4~N7@lb<WQM+4jz*(I$vmaHYa*1_kJ$kyPccp;oq zK4&xNvGvA?*;%3JC#%AUrx(tnJT^u|VmGhQVYrnFv9Ch$Q<ULCWddl!Yxb(2(lL3B zXX!nw`?Ub|*W%&`xmL$IClTZenSrW2;$SGE1MGOGIm&$Zx6g<>MLBg^f;FkHl{wds z7fKA~{IeSRblxdpWJpCkZ@*<8F$iiwX4lM($Z4fzzfE)9JA)WFkxU1BU)>u(Qe^}( z<X6t1jqq)x6n4-35*ahrdR7v$8y6>Jj=#68c#mW##f?liz1Ga<Qy_$rEj57A80u6J zKcjYVrK{quKdrg>DKlw1#O`#<_wmqN9p<arB`-z=g(U0sy(e2Xvmq_wa=$K7<v?tc zJw19>f{Q$GKyiT>44sC;qD6Mqt=i!tQ>6?;T)h4J&=48=E%KH`H-9ULKCUPDaVdJ! zbu{D)Gcei9cc6{~%nI9gb-i`r0|FAzwC_n|5<&>=7l7~~3;8#_@p85rBoj~UX5IeD zfj~}18legPgGj{a0zKsI@vJv#&kyi0!GIJHlI7!y-*rA;`j6KWKYw(0hsh28FJx?C ziacF|Fc0^0VU;zP^)2)aj_Nzv|J018gOvgUl`=2KxS}DDTtff^6I5f*9I=N?{6M<# z0Tdd(t1c6~NbU_<(HOT4hw3o-?87THV8yca98-{!duMcwA`oa77erv{6~A)yJl6SW zi#IS3E5&k-q8W>5kI&Hz{pqA%WayCy#4_ItBa#;P^0_j~ZB@leGh?&4n!6RuCJ00% zPl1@7U0|nq#X6-#{oJgZ|DX8<>WWo)@u3}|<O@zkvGu{I9CKlvlDBQe*~Y<u@qBk$ z6^qahkyeTDhe!0t{i|Sevv8_i&R58znC_8hBB?{>jTp3l&bmj<&$cx<eQK+1*& z3Y%NO`?qgLy9-AKvbt5MTjMmh2tQcqB7#rdtnKE)*wY)sHb-eR(us!fiNSsHhl=?g zJWEsr_$8<ri**ejWE2i($et-&?5ZOjCfDYQxJL`Mun-v7S0C$LaPww_sNH7vX6rDU zVYL^7do%a~++fqL_fv~cwHCs@%Z%VGlQbHdM3W-wdjTc%;Pj=Y6$T>tT?amC(xNJy ztRHS*N1=S_)iU9?4iq`vBi!_99Ls+b2=<&z<kVn5t5$Bs1=<6Y`<nXq88^zB{}mz^ zHaFSM1q~ww_m(=+inYI$>a&|~JV$&71<5X)v0ozLH$$L9L6Gy8E5|;ol27?yG?7Yz znD3oAlXQAzc%0~sNVhlX`>p9SX3s!p7vMISp*gr8dY~pI=Brfc>+rSfv)PUEgMT6> zG;wz)G+syar(2`iZS{*uK*HIS`-BWdqLB==77DrCh~)Q=^zyYgAD+({w@ym;EQWm9 z7dL!LP^tr?Fw7qT2*PEqhFR8`Da@x4^K0uwYP>-Ymy|0TTS^K$!wxcW03uKk<t7tv zj2n-jt@&`XDjG75!3NPw?%UwnI6zMc7;N(^AN{Uut(B*H_I$sGacfHBzQBu9taPa( z&L*d1eClVO2km{m+co(_p~miIMN;E)i_Trp7A{y$;Ikq6Ychg5-88DooBV>Npzd9O zJX)8}bv1#^*BmJH+@3f<^qc4IYEud*GAU->`Ijd4z3|bqMX|#X3OQP+0<L<$xTD8D zwm@Xj>_;$W!Y^Oy&iQN0^`zjV<`nn*P80Q?jYG06yV;^Y#|zD4G@qgFEVB8Q3h8R9 zRMwFduPp@;t7a>JX+Gt8?QakWkHhtpy>VzBeN~;w0a~-WY?_#Ia+ZPQoHqd+z%uTM z<q|2&3>xgV1vIP*c=YwUTFcd`1N)8-Fy@VcS#e=u!B?MYET!%xZ?{$aC*hkoD2Nw9 zpTApdT)#7_lk?}V5_kQi7LoEBO-s}-toHIPb+Mi1e3h0#5PqzVXGNcjw_|WCOuAPN z3_NP~)^1ngw&eg#IYGl*VPTc;eMUDuz_MmT+^pv3AKfJV8#UNc7}#aJK6t-1@bd!( zUfv$R6i|KXwssy$7Dcft;}30{D>NonG;ijqSo#2M&%-B;cTIPhgp^e0sC!*fN;BJb zeb1h!H@@hg1_T!Ik=?3JWtoy7R72e7;ZfS=g5UdV@MO_s2xWfbiK_IKW8vVYCSQgB zMfpp{C{jg7(7xaxRZkVm8365O^7ksAoB+1wnK;AG<kr@Qs-+Wq!K`bH<pjN4-;*1! zUY*T;TpL5y-F1{_=amUG&pCEP^%JB?Oz(^=J9&L{mzj*Do2+D5A4J<<5GDRyEk$-% z>$sh6qYdQ^W0H%2Kzh)x!&icf9eH}@Fd>Sqc}^Ii-SC6)$x&DSTs2N;r~(qtK%Rr? zMN(=6>n2l?PmD9^XkR8>fVPTCm32f)i~w();3!T1=GlOIpL@Bs0ytSc(mj{BNkXd` zJiA@V59*(^;vlXI)b;IE9m~A(@M^wT_hXdpq!<p#sRn7yQxw2E3au|oa|PnBk_Z62 zK%SSq{M@NJP1ms2fo7Q~)fYY5n(Op~h@u0!=@O$3Nw9h$1qYb6NSVAll?vif4X-r| zn~*X*k1ITIqIj))Vy%aB`Wv4hqYnk_on=;M+{#>zQ4oU-d?$0hH4S!dIZXCBL+;Oo zT~+e5`$%!fhFi&x&#ZXeZc+Q;s$htqam<e4NO-71M&ERTtr|Yqou}IRwbfRko9ALj zW8WYMsq<U7T9?^6`aLuDbPm7sS$<;;6xNF={&w<X@i9kOUgb?xDZ5S^=m;yj=nss> zH|hJ}n9f(LyglQBa~&~lSL@B1Fp1hP$ohPW3-jduC}??drmIv6ERRFv+>%lNmP4dJ z+lG9o2>>FAmkQ+XSZjA!6r>MJ6wh|4q%j6%$baNY@uo;^g|TjbE!E4xo|Timi|s)) z!oDJ@Ngk>W0|-#zsDRAEs<=v7!nW2;^{>mfp=%M(mN_D%uYSa<4?Tjs^)C>4=KZyg z(P`FelOFUFeL*{uEg}ExgdN%3>rQ*LJ^ShWWdCB#?81tILW{>^0SkFLDzrEw@gTs? zKnOZsV#~&;da6hq^W`oOa>l`d0Rblu?&RkfI=P<gJwdGFd{ATdD@qck5OfZVD$)X{ znA~hVO){9kIkceZ9;W5xxMS+82M_)Rwri~yE;cs${enB4;S3oza~%4TDR3r28BJK( z_i>oIR4G*Ap~UHHuR8Y&m9#~z>i0JQ$I>-2LVz|$Wbw!9n$gy*?QJ4fiJ=T?wtV>p zSM|St|E7RG-)J(ODsxJ%`R70-@`7PRGY)Ko^+e7k(_Ia3H2YzTq2y=e)$zP+X4n$q zjh)w4^9xL#J^bVi5QM;<b6|FMAM&C>7As$FgqN}CB(&ECg#iizdJsG1QGKVjYnz?) z(-1>YV#(AwU!Wn_1xCyo$hdc&>dZ?ashhC2Ltj5{6XhP*v@w%<o#@!g`SMzSHKI0C zKbZ|%4rK-n3z?0UT;3fgp}17Y9xuNzgPJf`pt24+DAJ6F#CV*y!oP^S4VQ@%A;ULd z8PhvL@)PpJlvn2IhI0*qR%>5Q{TBhFz{V9qW|ZSkPs!^R-Em<l62qQxu+YY}{ib6R zquG0g?7UDM`h-kIc0(ww_gBc_NftXs<3tgl-w~S(BIUh4kfe9VVq?kM6}EfI%QQ3z z3F#l;!+^wA+wyPlxa!bh5i&;quE<eqx~@uf!AdFYgf>&_prnzQv$%Y5-En%S1vHSP z!$sclyf(i^&DSxUqc~S}LB_`L<>=g(2@5wwhLqb=;vo`81N3TK_JpXmvPc!<CwlsF z_V%!cum9ocVZK85I5Cp-zJ=*KRQg0hTH*&NHGSMZc#E>n?^p)O%EWQ`SP!H&OLqb@ z`m85*#5d*|M8*T&*L;KAd1Rvj2MJpg74HJ@t!mwfAmZP?dpCGvB(FKQ@&<BPz@FCA zDHlnoqK!5F4fo}X{)7t$0q-xczS(s>AP%Xcpq5LV&Nej<cwJ#)B8Uy{Y+rXBt*kJB zi(oKEep+CK&=B46k7V@G?<=T)%&obp$ow8xPaOS?XLxuQpT<KnKVBF$8VXPL<w9ns zrv4gP;BZ?qpq-iw34d`G1~L6`0d<1)j$a-bLTBJ>#NPu3k(?cQ)kz^v{qRb+n7KSk zcBW2Ik1ND<9fM|xP1753s-LRNcNhN#aPqkCl@~YX0bTOgaunmYBW1Ed&<62dqZcu! z2|eqZx@$Y_La=u~H3xcatPQH>Z9n-)7%+ceuN(~+YMP!u7ro|dd#8lSvtvr64gj$} zMzD8w@3Mxp_oMC=y#RIIrqoze&8sNBZSjK^4_xo7-~Rl+kMTf7%%)ZMDtcLMs=)&I z1K<1Fu%@zAT5oF2${`^!XoyL1oNMB7{z=kCdi~6Vk%s05lv5}OtUL6cLx!y1ubl1! zuA`%`j;*3nAzv45otYq)ROdqUfkrkDMMAaEESiyZrEppj12mL_f{EwzjAL<CzE9`! z^Kl2w!upeMNz0ycNo>#5>i9k;i=(xIS_43R5wM*iq@{4Vx<t}7Xb7XhbT2U{<>;O& zaU$Qxnw<d$NH#-Gvo@Vs_<_Pb;7fDtC>b;^@<BHdv=Ldp@v$3O^yo$!xYWLsT>i<z z?T8pOB$e4f>zbTH3#_S~Gfdt&9{d(&hqVKN@|Ry;-0sz!I#45zji(X&tGrm$8IaBY z@(^vi&wNhpu)~|JfcnCj%WRTWU^o5Nr!c|;KR>_dx7?`Em_RVtn;16B&Sj#83+c2X z?`J&&Bv+ov!jFQeSDbn3=W!1GA_@<-2S{in?}%DSWEZ=M{bVayTRtR)VV3ffw7acR zx^_m=fd*ZT)vo0ATt@TSB39a<9;cNqSB>Tn1Q3&`F&H29zS0&_)epjfH}xx@YL6+> zr=H?bQnCr$$s=Q-OQOYZ1)(Pe%nEz)ZmDV@H?^84klZqhT`w~q<?X*1Hs8gLRVn4C z>2-2R4|ah^7IORKc~*};zFen$nn*T0veqWUEZfv3V^embl9&3$LS;hfeSg9I<1cZM zkW|9JA}oZCzOmO}Mk7moT9>`T^2HdLf4SHoaYxYb1!xmJF4do9^&NrkGooEqCNk^T z`QDl-L=57J_Xpz)5nc_@E{tEOoOR251nu<n^aT4^B~phw6OP%8vz{e~2N4Vv)_OFz z2gA|!#D_QE?sR<zg=8S<AK~+zB$Q^EWPg7mv7m&T2p)rGDa8XG#hrhig&%g8Xj zE!sEGwX12d(}3xY_aJ7D*RS5E4Wx|uU9mn@g&s`dhzz-RS+v0PtQRQ{H<E8G?932U z!VCD-U;IoHN!t>CAt2blu}C}K1SBtL1DfVg&#-V*Ko#ywGXmKV4lJnVAf4yWADU&I zV?*5=NFuDfpvz9Xf=w&q;0eSmoDanoL19*asXxqDtDtBPuGKl5lrb7D$LoxY2)@_w z$KHn=0hUSf#CS%Q+;{*jHbagAVhFx1``P?~Gn&+-KDZMiE%h~GSgCU_<iC_Z+Uj3e z#FCOo;P)W$EVngksnP$t7-Ctbuwf(j@_8exc_+csGcFp<NgbgV5=oX_5iH*Pj=y!^ z=Em3^Zwp^Ts5Lso3~tcd=bJ7<bunFgd>cRDxxV;0`LX2=6_-kScp@loPq5Ra+A1u^ zB$xAfp2xfZbuQ1tJD{C^zfX%%>p*!sGD^DsoEC4O=+lMKTruVL@w)g~M0D&WCa#>N zZjQs#vr8{PEWrtd5Vj<e<Aq!$MO)$Frxsw$fCj_?C^yaHYE~pBl%(9vpi|oTP~W}C z{d+z=E}Q1JTTf3D-$`Yle*dIQX7%?crms0PGvXVxgda{2GOHmL+XBBsOM~@xn@rF( zw~Fn&8|95?pnPZ!jDUmESoS^=xsbyP{TLAJRWxU7HuL)?<W5jD$~PvS-dA$!wRvWd zV`ws*$wvOy-9CfWelldu|B6C->Dodwpma~Q&ChDUGBrT2J%e*tE{+cmwDg3*JL~H~ zz=9*IvV$0GWIT>J5?V5R8+FLm^;2bY8*r{npwAh+=?-2<N@CqTr!$x0;9&H5Ng&2# zPEBdWq}`B}VIX7s=9@Dr;EKLu9A!d3CE}iM7nK2>;qyyWt-7;1$pu%yr!h@&hR$K5 z|1R{IwLl^->KD?I?B%BW?wwDSrFXH@CMz88kk2a-&xb|!%eUTFK}Bty%VD*DYC`f) zkzD%J>-?|FQ|+w@M~tIew!3}vm&K*|zIRH9S6ScS{SG}lP!U!W)p~93QwUY%+e?x4 z<9g#EKgOw|ciuE6!}5Y@HYO0ByrK4iqr5(`T%O=w=@qusxnpj#x7ee_RAMf>+X&-U z=Ej>L$iazzY3=Ep8nVRPuXJ;;1D-z+@SL3JYX&4)2Y6{{0O>EXl%vAB1c{kdJg>Gc zNpkl?{MM$+O^!dvLTX1TjT5>hP?H5JoJ>mXCXPr#>EtNXG)B-6%o-)K(Ntozpd%k5 zZ(z}<1TVdNzKlSA`F<*d0dv%hz{Fv}&I@PKK!cu`_Cuzu5}OkbEGg2TVfNC3xbH)M z^9sA4t5|0}LCtoJHA@PyiD<~TPK~x!0IP9A7&}hLSQZplsRuACRy$I0PZzS>3Sh zKF|4&_p6P&WDhp@iK*Miu?T0@LPf!EcKY#g*f-~GKlVW>cXa}ish4`i@Qysy9{wUN zimxLJ)abfz3+V6h_)01xlff-+!|*my5h$j7bzV-i1R%jaVpyh<T^b!>%M5CLh8CM6 zil@a$X7@U}KYd0QsXD}#gq4<Pvn5p!Twvh}d6o;rtQ(;t-XEUgB)VO&ba8U#rQe3W zOgLxzfuPiFJb<kBCZgDQR81E%7wYR0hr?I*#%pnaPL(+3LC6CTx;0%X8{IPsp$urk z=TW~e`U~0-Fd=~4a`t+LOFVQxVwL@dW>s80aa`2<EJf5y6wQTiB7%P~!d)54l$9sm zR<16_Tj{gCa}>rx@W5pbqAE!GzJrwIPHz-+e@Q1kzMCQSlJad~?JWM_JE=&u;m4|K zM@X~6;y4bJDXyZXUh~aCw~*)ILg?*I*@}(6lO9kX>93#Ae3{LYe25RK93Ov=A8<qm zQt-bpvQn&Aq8r!|c@T<m{KK<cG)H?bac!W!tT;UuDiB(kOI2M4!T*o+NR|3W>9(*i zxT*oihRBzq7<HO+!DKdQ+M+k(b~smBaFWV&*p5Y{_tgR8u3U51KP2%-#pYb1@GoU% z|0<UqloUM`<@TEj23Xi<9~0}*Q?9-*SXsrRL!PEYZ~39VH;yoJ^x=ckkrK)vNB}j2 zCyUaz#wK`{4X1}IJ-&BsVm3FR5wL3UXi#~!0W*5!K!AkDp}hrbF0VUzn^Vz1Dvxd7 z<p9+{+3EelW?*V*!;_~qb@j|Y9T(0?s-4&GIGAbpKSRBG<#bb>{|{&5Drtfua3Pw7 z&j6q<Hf={^e$9j39`gGI$TWr%&sJC*54Hp`u5OZl&gfF1hU9=n<8jNSpvIF}WsZjj z_3}kQ_X_VVWy)xu9_Rn7PCh@DR})%e|236N0D(>}UH}yVGqKY|zOdcD5DX$0yqTFv z_~+Mhp0pb!<*NdEux1y$d3wf%M85t?!^A3I`^|_cGj{{=kXmHgi+~x|jaY|?fy__G zK&UjSZlD-;;ZCUH-23D7J~g1-WdnVQ`$@0d{{CoJjUKs&0C^nYU{@5IKk%yxDRr3V z7pU_*wkU0ZaUYNs34DgbO?AC0sLTx#XDT#Ez0+AgDg$Q{5%@!BeUg<IFbVL1kvXME zI7SY+h~}AihOws!?PFBIv@Gi*cr~v#$|Z^K{9^A>S>`I$nb}az%a)d7fmH|-)%ZM< z8XGsVVh4^Phy#Ad0KK<`N6)q#^?)3Bp>&60PjMSs$my9I!|)*QMP3-fINcSgCK*%= z`O40j=M%IUiA~t`ZmLAB)*Tzt!H;Bx7Cep%rR>Wt26&%aqaT@i?S4O;`=BmKo%FRq zb|F#a#lxh;@N`Yl&fOGmB)gB)b-eq_bFejg1H>eL9#8N0Ce~-mcVsx~VY-rGzJ=-; zn*0%8g1PE#4$%-gF+;8khajR&a~Cu{*x*#l;V6)QRugo!{~g*c!_Pq(T3#6C8oOn{ zC-OU!9d6)Et^Eh@`hwkLVoJ)8KLpzgP}Jm&S%?f};t*y&XVc70-<?mmtISQ?>v9V? z{hI?-av_h82|u@v*Xa`>l3y;OF-8@2#BgSHs%wo*)E_6azcv5$S3y!LXw6ykmDJzY zRIA-FqT5`a<pa_WKM`cEjxCpghxDD`n7itU_)2yL8(|<fLw3!<N44r)7HA8kU`z*@ zF-F?Ci=C9qL1;+GW217tvr)#V+Q*L=u%XgGia?T+9kX={c~XBuqgUsS?Q*9FQYnL# zwmO{i?vxI&F`YRtYI@C@I{=+ChI^GNY>)tq%3wBIjSr-l)#=uaH?{5rkaBzw6)72V zqIBTf5$&VUWOo`=i=Z}O3g=ef{iNm|{`$RIwY;O?CEqW{@1EcVm>UJh2b=}1F=a%5 zz~EY!>&mb%J&2{?^<!0|n_oH-_=#SRKW+v3WOwDTYJLezTRh)c_^1iGcKQo6=&0CE z_E)`qZ}9U4G!SX>4-5{0Ebj4;KQ4LtfE)Tik=fO30S4~bM?k%jYtGG{9#yI}T9ZKw zv_HTRTf$aK(N52z{-bPFOkA7HOgASBJnw#pfMz!D=I-0io;4Bky%j*>X*=xbM1AB0 ziF2l-*}=3yWb=`6{KyqpWjU8(9Oei1zv#cK=TxJqZpkN}ECE6-68B@cV{z!7nq;`L zR=vBovMHDDXrM7^5rC=(od3vl-P-}|3o!dYaN<s9eunOv^zzJoveGz!Lq9w!gY|Ve zM!cg%_wad_(SCP$%;09%ImLyix&j3)9UXSlRH@f>gw?s}?Oy;u`A)Q$f;bsW5I%kk z`~kO;Fj%oNuw0l0swQXz&%T)&mSwJ8P&jtq<I)wWV2oY8?zuG)Vdzxn+(QU0hwV!* z^#&7OjDmgxF?he~H{+=!=Va7n{idYmMmgmG?v)^Tp2$S^yt=HLJh1=#+!~e)CISeL zsLuTh&T3(##(HS3J&CZZ1^5^rU*9wveZ_D_brFfrAtC<Tcf<t_-uukB;HFwHo<jGj zLFVd$3pUax;Z3dMX1aqu{lqa3^|PpNN(YCA_HN0AG7sbu1&D<mu8$VZU4z8-CK)dt zjLHBNKF$2XdeD$zFVj6b`?x9pVk_ygqzs1#6;Ot~g?7K_KRZep%F)X=Ag%iwFa-U@ zpmN!BHqnsH{u&C*?-b23rNF0%JYYAwK1FPX3Tq4bPW(}RSrpvg3XRo1I?Eneaw_~T z^;?`j<GglUehYj<LEyjq6#VVH#69+@_SLEvGIU-3UBqS9;1iyS%bW8x3)eP5v*9-U zdT09sJt%Q}p*0$GZ<#B7)=JSV_=r-&GnF-BK)7c%G9;6Fz~bpow=e<}RA8dWq)0{& z-NyhjdV|yhkxsp*bi=r#Fzg()oUzo-e(Z^0WaM47T4#nfxp+TN&Y4Y>Xi(KVm9^0; zmtH@j6v$-{OXn*My-p+Lnm7Lrw@4-OuE?T~G~_(G`sz|SUa8Nm*Ds&hq`eqnc=cDK zrDL^kz%!QclaNR7-OEUO>5h=|a<I*)pLyszwg(hhMAwyQJF6Qs6E<~izKlgF*x(tT zYHpgn3+`xtPDhZ89}xgjdJ~`QB|;^T$z{cv)`_soF}e283A)vJm@+<-s^85L%un|v z^D0%Ol<n7&GaM=^^8QW?!<d7}$k!F(1(Vbm&+s^<@O_@6!Enm<4#D3&_1ufIw+DC5 z4);u)`>Oi{j}upUR|V!)&$gT*d#Y@+9Ms)+$}4yN#>JG~MeKI8Q|{T5wIru*39-Vo zitA`vtIvi-!!{q%(d8+s8d3VG@6DKy^=D_J!~co9cO#P}tX=9dxdV*ZiW<(td2NZx zPWuk+HpW$OUeA2td!o{T-#UbI>Uw&R!^hGC%SOG}>f69!`RZa&Toq0vFE7c?uzj(r zm?Mp#Oy_Qy-TH7arSkzbD{JBcb^9aTK|7P-Y_S4vyqJT!e`^6;b5yIiEG*P_%F8M% zGo9@zb5)OZcdy(Z%s11(7|ZTRbN+x&&fj5j<Hvvi7@YVFt?`Cpf=>;RdPh!^8<_u_ z_|3dpm)=&a3CDl9<#GApbn?XWGs0}Ll)Q1sFvucH@W^YdFt5n%^d+{+<s}`oi*{=i zhXac8Y9x!}iRtO9#@Q)I%_r9yd~U0QqEFSNQGIA>uUnQpeC9E!IIY}ytIn?P?W-p$ zDk|YDij&ED;+y^!3E(cn1w#&hE#+{U(1p>Ag^PTg?wCIPF=!~cBII2%xW2nJT~g3= zV5y~*7)Z$<&pLPbfN=xnj-claJ)9aJXLmSYcc)+v2P(Pv>N^$8KTWT?`0<B&eN4Nf zIFsL38^qOV?Xqa$hNwNl@B7yN;6LF1R!g+7R8kL4=g>XdA?zQ_0ka%sPZClz{VmMY zjx{P}U$XezW}{vg4|9L4c@^PaKK(rI_KT{yj_FI3Z3lg6>7<LgXqUclO^%_clLx0L zN#btV{NCx6!jGZ%mV8`?nf?g0q&Kg*X}k2?0>k+S4|edKjxGF3=vR(L8nU?->S=?V zieBpdS|q^0!O?5c)=;lE5QI4n3$qtz(uupDJIqBzL^yBSbbX39Vq!5KvPq@9eDN_j zSiz8QIC5mV;dh=_U+G-q8W$skEv5W<^T#n7vvp1}0)L2JyHEPTLIe~3%Lv>9XrMP( zVk1B-JAxf}A??`6<=qOmotPAyaR&$IyV5ZU+s{;zUY1|1NI{cM^9SFqYS)w8XAT#X zjXT}5ZdX=+2KDRrxnN)^3aWoz$21zwmQ+I3+>eeN_NJy3v+42(!p6%cn4E0Qtn_iV zzJXiaVCMd)+-olGn&5ATK9AG`+)9_eEj5XXkKCUlZ5V-!o=IOa>fxh53@9i>B#%r4 z@IoEexpnCC+%-RDWi5Ep|GeZ983V_{5yLE;jj@5Q;iSkT{_3v*&zxUR=3fN+N*ii= z5WZv8cDz;VO7mr>VMnIH^#nOGYIeDE$u3ljVdb3^HcqW*6=j5R&=XQ|7y@Pf*!P>a zY{uDW+>;<#Q5}8#7xjFWC{_pK9cDeVTpkM?75M9;72bRg*jNmSG9J~quwC4lo?M<h z?D=C*K$?G|#~@ha2<5!?8_js*%O;mVVlGb@B$Puv_(nQVp#N~*OShFWny>!ZOM++C z!K5uaPx%>{8bi%ujMrty@a(U=Iu7lkjH^15t|l(YxJ`8IhE<`7JzGJPM8SAtg})4o zkojYX91YBrN|P<(g{2rq{T7sg(fpQ}$$@vfx0D`a-s8222j^vkq~Caw$A+$5Jp`gj zbQORyc>@BR(k~0@iOZI1N5~n{YIn-Z^=-JRs}EkB?V{3fn!R~b=Ztc&rjXB<deX%< z*muiK)$r2|^EM5=tMb$|y_-iVXNbNxuz^dBnr_-3Xn}0!>fF{RAk1)2x2s64^nm+o zSPx~yJ3T#bxd_RFwb_WEO_jl4qRVYg;5V;cW5pqMj5ejz&*_<$XOmKR_64y2xQ#gy za+jGn1G=o{e9ihdMT!^sS59}C--yLo@(peKH$2Y_zPu}<);3cBBAckkCw)qzo)57% zm^JrTrS*F#rA9m~#|m%I<I-{1lGFNl`r(Af*ue%}=pa}oo%(7jN%g}cs^s(`e<DN7 z{!KAQ+EC~LB4x3R=q$?XYbsCBdhN7V*XCnQjXcql+y}48;X3A?DrHKoTB={1;oB!a zSaX~-pQs5dyIe&f9&ePZoW{ipRfhqh@131@M~IR*OxvD&4yy-OE?af@-2SzE|H5c6 zBvRvSz{WeSD*SutgF@B~)0HD!pX>hD<ohM=&c_>UB{J~8t7O}Maeyima>_25mGn{r zeXge9o%PXy6`h>Pk&tHQHCKGaO|QUGwGSt56>K#!#Z`S$>w`2WIej4qzb9}!JuZ2h zGlo&{+L+ZVIV$oqy{9>tvL+>^Cd=d3{5|jvI9HhZ7`wMOZ{da@!sjF=legnn=5^#| zsv_nfgTLf`L)ulKaTRsSY&`zu(s>Nen3tbvOhiEe_n=|wzz9`O(|&S%b%5gCa?JD9 zVDlJm7p(26il(VrW{{C*9Y!TRa%p=$S#j~HczEKTUC~7_g<uXEPhaAr&`3%*&$2QC z2;J|UoCYuaS?x9_QRGV}WBG)TaX_L6<4SYv7VX)io&vhTu!(Ux+a#%85Qocua5a=B z69+Sm;<B=qrl!Q$CvNH`u0o_i)Np|0pSl%v*ccd+g^pHZ4t@OmxgB1CB77|AsA-;j ze6ml(S+V1fn>Ip%h}Zff^eajzt%&O<H;u0<-%sv|?t$;dSq$&-Qd24V>-{;tj>6CS z?q@E(efzF3D5!$3hNV8|?PJoQnjJbh{2(nQ!;x5F?&9|yMF`hFCv@w<7Q=~4US4AX z!NHH52kwxQrv<A$a(q~dJenEQQ+ejfPegVOL6X{=pvdvcfVM01=mD3c;p5awvrN(? zbljWbK_Fp6IZaSshZ#<E4<845Vn+>&JuJYEx>Oz;8N5hH=RQpOTvnQR^q~LM=;&zq zNiHFBV?hU=i0DrCgoEAobcJd?@%D5|!HXRyq4@`bXE(1W4{j1dqeFBD_5^Z^D{O&b zD(AQ0-#D?qCCF_XHD=u2oF0GbV4&*FaPTxRNOzO9b#O@SsKr5!MDi${kqC1n+mJEb z)goBL6{vXgCQ)-Y_}-;(u5v;A@6#KJi#@ThiD6Kx*V%CzMzvKynPFd<MGGx(IWhbm zm~fdB9D<*`y#<A@hQnmyB61#`_uY`6{ov_DL}X|m8{OZ}Pb*$#T4uG0wyK)1miQ6X z|L=KOr0f16kyzD`qzm5fU%$G+@O*u)hz@4+wq3a*G%B~29OT)v&U@LdV5jsZv6AnI z)agw6J4L;sWKI`%{861VkP4@}v$@qVWes4!)=$@$NV(D*X<7+?2{&mPZj^!8KX*0! z8!|b#V%0l*=^&`sxxq=yop7e?$ju!H?qkmuvjwKPxNft<c?f<{QDS1(e2=#T5%hhQ zc1Z-%iF{HQE*o|&#(U?oOyu&LqZh5;Y*Bdl?jmR5iFMKW&@igzezdfwJeNHqd)JO9 z@-hA)a?7I)hGZ5-^;{Sg<w67N6Eb_21a}78Gj!+*m60$a2JLZQ*7v*Yhd0~s)z`aR z@h&|3(u9U_Fh<bOjfJHqyJueG+I?uWH{Qf^A@I_y>E6!k>EK!zk`sEnaqtcCrrx>7 zNF+Zw`E~^^d;R^Y?w=i%gI~E==uQ{3eS&g0C;52B6<MFGbi#rEt2LY_5Y`T)45d%f z3?2G=X-V$f`PxEL(!HImLo1tzNk1`eI(i`Ec(K7Z@ww;?W;c5^G93{_HyO<@Y`CnO z^6nN0+dVA!RAi~#ursQ#bNKUTt%+s<S-k6?xnWOzB14!~+p@C5>Dch~&hD?)F0sCW zjIN0LDnV_bA;PEMmkf*36Msq=yiF=See>$L_OkfI1-#)&%vP1uT55yHiVe2KWaIw6 znV1kuudp4Xc)~jeNcK?Ahnu@%K^xE>@nPy&6AXp#WG86+ZP`;58?t<(_ZgeL*qkcE z&*Sx>tgQ(b&&J~|Zf9@swJSSVE2=-*`ao^D@v#_m&}nBqW(Q6V0YRVBRFk}>Z(+5; ze!pRxMS>GOyu7JF=sC0=_z_bg0jo7jGQ;fK?U@RfqRDKx{(MZg!IuTMI(t5kdU@O; z(-c3ppE=}Yda%dp?H_Eg+dn`n-jr}CT!fZC;&j$?^H{w+n+`E%DL@wU8vH(<Vit39 zr4Ef-((*hfNr@eB%*m)%pRG2|8<0*0TdEC-yE9~_aJWE%n{f{%)1x*^k-sQcx#!J| z8mm88VnK=7T%>JF1H46nGL*Xq>xys$qR~&dvS7;Axi8WRAFZL&<ECZGksI0_q^LMh z5^cXYYL$wT(MmQ!RS^`NJ|ukxdmawa4V?Di1P?N|K3FUE=}KbU*VsPG30t7huNvsg z+p82!Ail3ARdnxqB|_+PPWij0z-(dhV({YlL1r`a8#U4Tnu>Kuy{4-2TeCiK+?bln zA+lS?#KKCk9ZR(PJsHNi{w92Kax%B^`0wBApF2&>&1K*$MNOaj_Wn<*jkQ+Js~3kA zV@#3g;h{Egvg=WMJahW4T3>?;=Z9_&W!JEO=jG}(XnAeCKq!BVpO0{!v4zwzZEUFK z7NyEH2TjfRl8T<`@z%i%sa*ArDzll6h`ce5aY**JM+@%5jrs|rvV(dB5PcM4-)eX^ z1wV2h$G*Y{<yU`|6n!S$@zs!h(gl-UFkzwoOu;0}N<ZQ3%M%X^9e99XKmPNb(^#RR zL4fh>xm*2Mh2pzw_k?Vw=aW>PFKOPQ<n0ANdg%uL+nF#WU0INFC@xcFibT%@OP0## zJw-aD%;`Wn<@U*8+Oo>N;@KgBbhIe#(%j<8)1ej!!)Vt&|AB$$F9h#XHI-iCYDP|T z#xUi%#jxd4ve#~k&gc>1ljb&LUgVG2l?t0)n5JJ2+`4IHRh%VHn|V-~UUcMCjtR5s z^oG|0x}$mLmiQ_w`##jk(A21xZgJmVyk8Z#WT#>LGA@$fVz+PVkc@j|>vE^@IGA+F z&_dfW=T#raN}Nd-g|NGb(y;f<Gw0F`FbEGM6?`<a$}#CIc^2nP2z>~gHpADS8WTC6 zkJGf6Bjpij1#;1kMcLBaUc)*KB;kH>aV3Vck>jB;NTCJ;=YMnz-K5}))unC&=XF!N z+8zxDL?>?^88c<rWaS3hRc1#0<+Y3g?xUFUKN93q9tjq=^JorzXiDT(grbH86MJPd zQNLH1ZwL}h^q1uYNicEj6`s17O=mZBkVx3A_YQJ7Z!OswRtE<M>z@Bu_k48(h61r~ zj+J)@g*sd!KDa(3(dC=>peE)qN+0;_E9eq_pUHBk)R`_-++^8yafRi{2QB!WtWz>d z@qH~}bOGlAI?=I-Zl}Z6?_HvLtZE~3=&Zi`N^MPf^y{3!T{|%?`)VV|PdcR6F89dj zCmZ5%wzfZ&_o@D0`N^JwkML0^_LR}M6&^hbQLA(%L<EtJ_6*Z6l*eNct^9Z?4EE+N zJ^@2GnV%)VleqT{4f$z1OPrwzqhD$wh36nix;e(@jNmVypoF%}8(k}CG(8rwn6A6= zy~31xc&q~Vx*dPk;QmAw%kVLKB&)~J%Jzl?$#%_a?ebG%PhprPMA^0$WnJ`Ij50~m zxhqk~P10zb+}j);Yj<YPRLm2@ln%0a7|n$u-<?Mfhap;5)y`jy?exvTl7s=bwND@G zx)$3*aI_k2>Efa25rr&0k>YoE%o7I1xeS_i8jva$>6!qq?d)A+)PdzKw%IviYBo_r z;5k~Lv7SJ=;$DT!K`dslJPW2ANUn=R*IOC9@aZ>93;DUf2U%=!CL_7XH%GLH2dOrC zN3w7_>b}bOik}XV%;v44`1vLllvP=*g3-LDO|~RY-fybh)@zel$SdL}c^6{?3*KVm z4%ag=cU$9cH8obFR|19?ePqKdHP9=V>mYB~E|bmG?+AvaVj%;tABXYI2$=*nzZ9u8 zk;#i?khsvFFTH%==0VX7f#A=+VkY<J5ILQdtsCX0b3MsJ(`{|Br-yT+6PE$LNzxdh z%7+_5WP)G=$DFp!PEXxep=i{2HOsH=9KxEAsEOJguYa17b^GeZi%-?X#`_Lj=Ci%G z64Y_ZDTD$IG&e+3xaV9&En{eou^|Gre?9#%Z73Nj;LV^l{h73(Q|agDyG874-{oGu z)E)RmxN+5}wXW`;RFFUp?jFc>bdTS?Gr11hwid&a@E`Y=`d+#%e`&fP=J<IaY>wVK zRbl$*oxCs<%cjL1R2;unw4Mu6R+-P4+a*B!eo}qDJz1gk?vKyyE9=1!T4bJ)`JUp! z=$nkI>oo$p9-XsW%jXss%ZAR4ytb$4h$om|uD&5;<99j7f4hEvF>5^dl~zW0;ecca zQ=zo;s|&4dG{6w4rzmB$Lgkf}Dw_-Q^YVv>COI)IS<-O@s$+0kt{jhSB53joM%AzO zJqHc-^}?(%f@s_-A}PGfFWL|%`@G28<gWQG7Mm8We4`<%<Yq#Z_lFS<!#hi8nP-Ex zsRhy+cmGw0B+4coWx0eTja*$-7F^yeUOBLznwZFG8o(xE;pPzo!|MY|o<O+96vLgZ zgq&<0uWK-vAVI%Nl|<%&J)8>_+7nf$d1Py~fQp$2kMHWDaz0t~jEEqdv)@M0lk|9; zI$?xRlI`qh6&rmc{dlSs*5>T>H?kZ(QXtIAfwdck1|hxEnA|nYi#4sR=({{F$UWH_ z|30@=FNl>)xNEh5UuAKF#7*10Qti9Zs5W2{A+H~E*5I;8ZD2~hP3m@IUH|n<I))<y zp?}v-4|ZX5?@VVYD40o@`%K6}2^VQ)70dRH&vL{wD<QqlIzit-={!u%nO}v`6{ooO z3bkw<HzyY&C=V<+->nrdsLx2au!P5d?QS7n)~(J{Jd$~NnF|xiIWp!(^2Vy2Hn|}G zomb1gUC7$2rlIlYY{UK>2CO5J%FPNL7j#Wc!CRjUg~ws*VQbx|w|b^spio>B)`|W< z?0t1ul<U^_V1NbK3J6%BG?LOLNOzZlbT<s8BBD~#9ny_-&Y&V74Bb6ScMm=At=Z?C zefHV!dB4BEKR&O0xs7q=ndiChb+7e{wRBRdEuVj9s40r&vm;|;lZ{4OUHxT!=y7qr zmx=cn)(!vk-Rv5SL!sbz^BbJO&Ek(<s>Yn7rq*9!o9eiA>az2udsS6cW`g?`cF%?} z=NsTQjpB{hgdBrmN*O3#PP{t6BNfWOh`P50)%Y1<54<LzPrhQ;g=1RfPx>rTM5zi? z{WZL+t0zS<CI$wnyusODL~8*{bh%3H59V0#-qaV!Jp@BaJ&al`ccWu3@k6bwunRlr z!&<J%RiZgnyt{A<B~RPit0MT(f3kVN?#Yu;Izhqn4UfF<YN^%MMC5bWb~|%RPPKo- zTQkPmAU9#Y9`t*sJbxi!4H8EvIQ5|2_lGf^g^?}tbeXu{E5G#t@Q1R+u;k%!g9)Pp zH!|=!h{r`|S|!kKG?{-?{QW&v&?Q>n_c_A6x%BUpg2N-vo;f!IPSw+KQQ4hw-9iBG z`|Z>uYM|VN2~LFmn#1c)eUZNwCVt@e<iT?mBcFVSsA;BSxzh1#t4!nfD^ygHzJZ!W z_5%{<$1ZFfIdS?D^G~o^!eR02XUB#9!G5{K=R|AM7%^Clc2g`Wp34dDn?Zvw(!*e? zlB@{%4Ib72=oPcl6OoX*x8tdc3Rn{Im<r^cC%}N*Eqh)h<g<ghW&FyW<sG$O%F1|m z_n;AQHx-51lFjVi`g3}z*j7N%Om;d*)YR2q=<C;ZrHgOJ31fP`&cn>;Ph)k}KSQRu z0V7G(J^XAcHpzC2cs7nC+^q~2RMr()0mlP>r;0)tT5|64ALHN#B9XP72SfRpJE9Ic z^n_g2WyJ<FHD`RAiHRvEH<!<CqFe*JtCaa<&(UI|R2R3G@T0zNRc3q_nS9X~Sy`k% zO#`JjVHAyyCrVJp`*cWXXmiPYAH{v++YzkV^@m!BTw$}!fNO_lT|5AQDrBpWa?j`G z`9`qXL5;^15Kz3EliJvZ+g{awM@Cx<Hy+|tT9&NA+H{*3wAQ#IvwhEQ^9WGL#;Y%i z&J@x14-UfA<!_TruVF~^kD5cB&r-7rVDCNq>eDCo-kg!I{Wgk3lQ+v$1DCtyYbZ)2 z0o9(9E?RPugPeZIX<r)N)CkJi?yjRS7UMjP$W;4h{e2F@^B{Ht47Fto>mbMJR9RjQ zvu=++s$C-B$v_#4%FD{a4LLztRl5<j-jCn%VAVaD0tkCGChS{p@4J&1jLteQ655N5 zweXrH+Sr4^HA?bO=f$p{%Ud6@U$ehkowSG2U8~=ot)J~JyTpVXS1SL~;mE<y|4yu+ z0I8Vi>|AcM)1(ZCGhsLcm?J46<p&<b>ylRWHXBA|KhJQ@+QG(fB{2a!W9s!AP!Him zi=^jOkQfBqtp-R9Rz<EnfNsUWF@NVQdHn4CA*H6KCTML>oT+XNy4Bzky&VdiB%#Ge zYh2aWPrvoc<D+pYs%@60)BI|V(hP5Zx-)0WHoK?2oaKxxG>|Cp7{3ftPs^=Wbz%41 z&FQcnpOU`Js`FV`-?*ciVVTP^(Q<ljta;ZzMqJA6V*-|9fqKD)X-on-Dua>x1tjK( z>aOzFgW{Q!+Ih^QqiKhWBGypKSx0-W2<v*Reu(}c^FHTi%$-1_wEO-K20i`pFC`^) z1C1Xb#1f{mCVorqCL2B^op~JJEfw|X#A>y;Nc2WB{50mWk&KeCPoP!FQwsV{NeWhx zw_;DMHy2zsm-c)L#?vy0n4#_ESVWN5h9Qn4-4pS(r6uh26;=>WH$f0sWmP54Pl``T zNwEgl<(6o`^b30~h|C-FLqd|Tug~H)St^V)D&6R)4hJPBMqH6aA(49Gx`vLpqj@`a zN6C|uGc~7K7*nEN^bGH^3#GTkj>B^U=rCh4ORYfA>|pr8vuBZmcgm~|A3|mRP;X4} z!O2axi|g+*NXVlE9e7~D6<cA6mu)FXQZ+hN%^L5q_gbBics{?J-4_(O9jfiQTw6c* z4qQ5N<zL<b1g2hPdEpNhLn<=2#?)XXDorM#7EYFS<7*W6%pX*8&PL5iwtXn=R8nuY z=(5eC9gXEV+@SE>-*45k(3h?yb^x5~_wQQcBS-V?Hu_H<XjKI<bQxxEc_xdIrey_s z@L1aIRSF3X50tuJar%A>R*eiPHmiSV$Zl&%NCjUI?(b=F{8!a7|I4}9P6wF#!U_ij zK$j+v@sDx<IMi#=58a)Q?2%pj-rIWliqW0m;1E8y?W-c>S0&*4LxGHRJe0{Dw;Zi* z>7KRg_xyD>zeeX<;_{4vEo74J9+bx(kYY`_%y#n{JxYrmTq+7vdzg#hTJGC)k^=<c zMn)#+z8i{B%_FciFu)D|44S4~J!TO-L?~$<CEHBQbX<Vbg>cC9t7*b6V|UCS05_=# z@{sF&WTcoeSHQm216>sJWNWLpdg&vEWjF<`ot$c0a!)uqmJ0d>Oy$><a+q#Bc|gIu z0R!Jj19sT-L+A6CMC|Ju?%;E9;oTR)e+a9uX>rVXT=YoCR{#e=7^+_Q#D);Hps~ZD z4!Vg=pFXol$E|Nivsxi!(!`+D|L2?o1{R)r{O*W@`5|eYuS@ElYahxpQ>VoTO0Q4Q zBnMJFODtJ^ru7TpMITEw-`bZ+Flg>)n8Vk_l$f?x^=;7?4T@Nu+X~~!k$YVYUr-+o z<ZwDBgF<9*WN7fJ>8VBI^ofa!(6IcO6tZbi&ftf5Y9R$LS5%1$h72aC;+u}`m}*zs zM_Gz&bi{m=jY#(q@XXOLmlKzX<$CP?EJy`Hy&5cg#GODP-<$-XoqZ$rB^Jv}Io#*& zdo9A+S?}qKL-d!pyT9X26$`kQZj|tPHZNJSj2Us`#%KGTyesESI3(sY*sY@Zkz}C^ z?9n``tT*pSUww*4TEz@1;T)>+W@VQ1vazy4+k(=sh5?ezP`pGjl4j*3EK4nJ)(q8s zHFiM}p>l|R3*BL7Siq5;GDPm))4^R2ZKCNFyGTt)uW<zfPLwVcrLbS>Cd|Vl;l*uH zuceZ=t7xSSU<|YYe%in~Lh9i&;yLqZ$O_%O0iEzhCw-Ri-SV|2Va)Qe1Dtm#<AkSR z+~LO3o=C_ZK=ei(Zz%2yh)ACHgw^fvBmzKCl1<B=p{ceKPoP{k>@oX519#?IIeCd1 zKz(OgiyvCsp$MQf??cD%H(3MMsvx$|9E*AdlvvPGsRqzjFUGcmkog9<a+tf)nYijR zw^ouJk)50gll6f6dc)tz$U;KmYA8i*#Xd;Iyl08WAD!u_s%b<n0YON?GhyV=6c|wl zvtC@XWiBAX+2XPTHi_w!J;&*3GY>_O-Os&d5yIOmc5u9MIBv+HWOQC-zwVpqPW3@b z6<_JBY?uLtb;GiM&}siQz|#cw4RG!6iPdI(_&T7S2|%~mfm-yEQ4GI3Yqp1{%9U~e zUwY~QpSLrTPP3m4o?Rjd^*b3?x!L?B9tU@+eq+^?=jG3G?T>)OJxrc@_1npsdxbK$ zW+`@Qk40N>D3Qf=<8F8>7T1lL_}p<nEBVDkij((U#@I|pD&Rof#nEQ5@@~3Q?2(?h z!68<LZh2p@DGUSY8M>yvOtq2DT51-&;Z>yf?~Pd^4(*uLu2JPLDz(tjFJ^JQN-gah zt_ybj1f+Y(bwzc`w?F-tMo}=|)2qi!SHC`x+S2}5**`dBLQxlMB=LNQGZNbI7d`K= z4H@DANT49uhf+}g=M04gVO@JHtS}puZZGYPZpUq=4>?iKu2{tQ@t*zuc4g%R>WoG` zgbb-TuIRp&NJs4xH<)h_iZ!U%K2CQ8Zf5;#TCYu8uBrWc;O<8}7SknykgzstXdS_! zdEv35u(hG$KweznWJ<=OE4HK(N=-3<)oOU|P@r7h6JGE!FJhVlJRVp?k&w;Q-eHNM zV&>hVX%BUn=e=k7oeRNZu}$sdL?<v0(+RFZ%Kptrz4$pXrx6Q#hL35Da)^myy&->p zeK1<XF5uy~<^95cX#tQ>(HXVICxfC9IsHH*Oeg<q%E{z2@!8mFmlzdYkJDGJs5&`% zBH}Mtq-GYr+Og1(*{F@_nqt!^e6w>p+@L%j7XO6?f3E1di_P=%#B>E=JonF^ng7LW z*7F>ew7Q2d2UOlF`RcMjH*g@k&w5QxA7x$B5A>j)XMng2xU78Ak0PRO*G-z|Uk^nQ zUtAlAxu5SCa5)TKgVThkYd$>}bK(5?tAt(fzBN=&=V{bEi`d4O_oqq;MP50;9Bdj+ z>^t#rEH@_z_$NIj#l*_HJfslhvRJ$N@uE$St9$?Z0!Y=V;Pa%ZR1D^L&BTRXh%bax zw9zF9iob;EG9X?M8ri}FyXLl9;ZZ-4Q+!SxWx2DD*`%MB)bB)l!d!T0YW~xjmatbR zRt^pBm#@2=D$i<upxaz~PJn8tJLRo9`Gz}#Yq5y=f$-jzxkoBMS10eQ;pQJDD^eF5 zkA_Z4PE+Qdg{}yq5v|xc|47#=N0u~M3Q1DV^ciuhw_*2WLxMR_d6s-7f<i*ub~syM zD_p^-Ei8~xv(8BG^>ivNKcA74s)wwqJa*U;>C2)rgLA{hChnti`t<=cSy!GDH#zY- zZnWFe%A|~>7wDTC88s|KU6|d}7V|P7@V3uKi<yOD5!<V-lMfXE4u+#R2R)iC#tTEp zeW43fXX<)cGmv;9DlBObGtEc0N$?(X-_jF`e?fRq!wo$`?+mg>vJ0`YwlZt5dl^b& zxwmCvxZNY3o;HkJD9&Hsj4{`$2_CfS>2@9Is*P(CF>9>mQ{14DK|tFk?_j!*N86WT z^3QAz%oPQy6&hbI!DgAPP;KNc!PY=g^w*SiEE_Z`(6xAY?K*I9bN@_FxT|PDh&1l+ za+LDwn}T}AgQ4M}hFkwdIo7wnms~F^nZUPv|KjK@LHzL^O`r{npTFzyCH}Hdg<H-1 zk#wB%jO8&wp<#Fd3$%-Kn|<SU1HYUH_EWdD0$cqBphfXWhcmt6%bZ~_l31OSKI_(X z7)sM~`X^j3C)`hFqe6@X^=Nj3)5a1GwR>G-YpU!ao<C>T;YHdTHzGKNF-bdJvm^7a z;|?ev0TyBNrZodQ+#5F*<x(k=NnW$tRW>MO2@H=<>L6JJS)hJ>w+)hlubB4}8QG>A zHuqKty<ey6`@TdEYFH52y~iuDs&%JEnKcD9-?(`@KlC#oD=H}XtczVbL($!K{jtd1 zE~irbt|ZK`GF@TkAm{>~LGw<c$=#-Y`_GT|Rbh<kJ<la2^!EM*l$ivqAWH5W3{21S zBc6P1@P~5dFHsLB9Nx3qyoghOs{$WtKfBLT<9E$`V>HKcQG;2Rzwg&U9Xv`Hb$Sol zF8HS97qx!QIe&BOuELKn?{%Ygv^JF&wk+G1vn3jh`Iu@)_fz#m(5-)h<<hHyyB)Si zVdqKYtNx1N(fu-4<~>XNG7>_dT;c-{Ln*5Ci0-FDV!sqq&)2XdBurk{{kdIc)heW@ zpis!)W52@{Wg}fs%*H9OOQhS?sAcR|vGpp=tve|SX(<)Oqv?(UN^{3`TGUV`;Q>(9 z6ugF4!D85uE<rcd67_vX-pd5=F@kJmswMtA1h+!_edgJ0?&+&3eO71Wa!oI(<f%O< zN?RU_PFrG7ObcD(o0ht_tEEk)l+kg&Gihg!!oyL~eU`67C7SVcBsOjGiAXh{1)2e# z+{JZ9i4lIQdwTs39L=?jIDTGfUY<Y5c*+TQUiQIgvBMY9@n=<~y7w%a)QaK*Q*z6? zva~X9W_xHpNq*;m3n+k_Mp!K0UAkbg5IuTS+wGt;bzS#W%ESb7ZbB(*8;lHrw3{%O zS#)m{s1d>%Q(=yYS@MhcNBFb0WBNYWgV{-pI(T)R5GhQCU!_V;T_s)X3Ev6~lQiBv z5D=aJ+N<kPAM9Op=8fB9s8(V60|L5W#mr)J{zU5C7P$r9ompylmEcP8a?{cJ%QQfb zkwW@O4?nTJMEkQ(SJu_@;Maw6i?`U8mY%AWz9bXD?R5NdB{6t~>F;<9_uV;wc*ih3 zf+N|=@>6K26nH09dR3f}<wpHiU)#FT3Oc_>x$F4yAG0O2v3&8u>6w(9#Ojz1J==Sy zB?Sc^Gp>MzLG;1#2!*IebX*H$G)tCklW%3j#cu!w*U`}t$}BI4A@{du(MAV@PHz0y z^ES3yBry(NCLe%&$BlK?j%?dYrGZw<R^aYiur$m6=%K6K`Vc6~j(m}z;_Q6v<jFt= zjqY2D)2b?Tw{Jf;+8VUOtVD#31F<0q+MrJD=>z;-Jv|zO9cQ(*5qdfpUUp3ahSP9z zJG6Q}RO&toWiG+@+0%2}$SD0v_^t?KBP;Kp=_Tp^j9{asp|MntR$<JAt09bmjq7ex ztW*+To0dIvilm0@BVDF!dTB}Y+neJ+XPu+E(hw(bjxZK!M(sq|%{+?u(}P=0@WA11 z*bF{Zo;`Gc&Jn}qHopDk_hEWPh?(X0x6bO&3vHvh)8WgX`nTIfZK0io8x&IJTGzfk zya5P7c9)x>C{$RWw;;4MBj$Y{q4Ma>+8HGQ?#i=|s+s@Xn$^1<2a?URv<SMY<v8m} zSEi}SRNj)!_3$XyGy$jYJ6}@IcgOL#&ik%_a;*hLA~g@%9Db+8lXs)UYIb&gr#n4k zY3%k)i;!nHx~$GL`K1K~Ijyc(d$KxguP;fqHQ6*usWY2&>3|Jirff$8&|kB?jN~Mm zUt?qDT>VQf@C9$cljiB|Ew8wAuVNHh@b$xNSZS=MPf)G2QFog^U^*wr11H4CE_^Jn zG^||Kj-Xq7UD0;?pS%d7`Xkb?!rl2Qb<0TAR>F{jxyDrQh36g%A#`nYfOeiBMS1z> zk}g?3Eu>4MOV8JQV6yl9*3B<PCABRrxYSCc<~%<%OcJ$i1_v5}?ICQ(PY?07mG{|7 zKn=1}X>o;n#2MOX%nt4O*fY($ZY5hYE3J5AfBb!DCFYrk#uPvfKmDO;@WZyzqXZlV zMtAUO$3~3yuPUl1ME6v|q54Mz56R90h8}uY>plyny1{YN;$Xce&z%?A5jVq8X41Pc z63ZHJwjx-oEQPJ=h<ghyCBs|qJgt+*ek~5F$Gn-YnJMX8P%AKJg(e9vXV=0AggE3U zgdmzK5e7X?*sf8Z4vLI?CTD$u0ECXEVw&TG24;%;{$tK2L9j%JH;%f4H@?YR34=Tl z(BK*KJGh#Xcz^hG0%Ja>$Cy17b6s$4)hLWY)=Qg@SJuDR^-yS1QGqLtZ{9N=ShNmE z8|;_*dD4AZ-xlw*$wP4qy)KCpRiv@kSpCmdL}-;&UnSh-Ct!gCuIK0qsO9*yqE#P* z5^)EuDF*q?dytX+avG#Pv?JP1IL%%m{p82U6}3lyn+*DbVO9*oKPz^jqNUDP;<-lc zu7hp)?R;WDBBQx29zmi`00Idd&Ll>)0tAYU7Bo+UoL|#j{C?kLJt04)><uDgPLTpo zGmt>tuw|>Tbh(!kf15t_rQ>AiMT4HdR>hNJ=?dyw(~6IRn1BPbJJ^2;C%sph(?Be1 zE7R=i_?@@!yw6>{_<eEc+Y_iQAW&G_IHs8obcQl$f9%sK!p!QO`p@fs&-}@Q3j>S9 zxksC{T2#wiFpN?8YkfU^y6<`uOi-s6y!qx=;#o_Q;}<BAK7ei~GAuls4W_%Rns)}I z@NI-Qv^cQ4Oif+uPgMr|hF^NRn9LQi_ga#9nw?jyxzD`PqY3CA=+`qa@GdF2lz2v^ ziTUKlrN2G&fB*I-m4RwvKF*FI?mq{x{&gPf_nZG^)b5`z{~`J8h`aZnzy0e!Bz%nX z$^SA@``@3>cH{qcbz^k5U!(v1;=li@`t9v@)xU4UKX3T^h)@4z5cHqdw|f4+Om_eC zZ*S;4`oDkapFHWOumAhy|M=DRGW2^l*lVphd7>Pw4$~_u*3*DgRj-OV%=Nlpp5xIX z<n*&93Td189V3=Z?JAYDUX<e^vFjG?#D<9{tIlr3sY%T5c};&H;1w$E8|}+bP~JdK z*0E_P;+n1lNQ4#9kN5^lcg_Pl9EJ4Eg($*fKKvcHy4d@(=`?|$ZdAxM4YMzUCbtGd zo7%C$<87&)`EsA#__9>jKdX1qUu2mB%mIo%eJt85c0=H?vGG-I>`E%Y>B5!+*GNeA znB9qQ6wX1&0`})TNV-A&kv2tzR?1(h-IJzF?zkU4+#0-o{1?C-Hrqe%jb_LblEWyi zWuP1n4qQd<$i&gJukaI;g0_<%?ZL9@v~|<a-4HT51t3?XVAFpoENtp^*R+i{G7?G; zqnbNh*tbwq@R7u`Jy|kr<g>KI$Hm4r2gJF;RH$p|vU?ZSXU_Fx@5rUvJ|%#{$4_5w z*Yy0IG^tg-ZIvbro%3O|(v&2sk4EUD!Fn%stbh{{T)54bvWC7gMs$z6bAF>he}81F zu4&^cVU#fFsQKIn6E57rBQn%J3xeJ|5Xy6}5@`C_GPgQVwR}B>#|qQ@`-bPi{yvB8 zr%|);YqTIS5fYb@Xk2JwU}(x}Y-9jf_*3LY=+I|!M21o?ekWA!@2fG0iJ)eB?In8l z$`vbnmk60f!epsYGpp)>yIp(BBSloXH5}B{=?-IWX+<_>jBIy?2SPG`Yqrc3#_(Eo zrE0PPb8=OC^fSH>bd)y~C*8N%qiImPe@JF9;3fJ>(h_}D+i_=2xzc{#U_%XbU`5ZD zxFA?ljyTSjYM%j3%S_?NOVv;`3wocr)ZA@!_GWfCi*6kpcz&!*Q_7)yMfCD1@3X&g zNVZ-fsH%*9B?ck5T*_`h=6SDjbkv<>R>V585ib?RHE1knYAA%fh(Y5?c3j&$fQPtw zo9m2R>kzD4d9)iJ<SEhs;DtbmR)lQ`UKbRY=gS?IJ2aZMstxAXn)AG2%PZMxV>eHb zTJ9J$KLO*!(2OH26{GrMoAL@Fs`mEj^oKykadFaqsB{?BYf9;uI~02|nrgI61a1o6 z$^!v^Dt0$xPv{?}|D`#2`~oCz0PCy@EW!<j-6oa59{|C(%XK7nyl8GqB#PfXuLI}L z=VG3}TSnI)R_%5qkFgI~CwQ%(sGzQ?>6Dq7fwig%vCDr6RAUtawAMjnaURFM_S8kO z#?_=s%?1OxwLU%Q4;HNxuU_L_*8%Ix8nPHIe7u;>HPsqt4b%tG*I$SDA7U)gshR<R zrWs>bNf7WzIxF-whd-8|zj*EYSZYls^&C_J&jvVBaiyd{8L3+EL)Xhds0kqRPBV{E zfWAFn0FQ;!;3#+(<RG=bK4J?qA6Eezo!fI*SRu9AR=Fj3Gq}gBH~X6(bd5@sudPH5 zy?gt%bFC|%2q6F2?%z~EK25HLWixB6Wm66p*o;^?Bj=2`yGWI?)xO2B2_L=%i8922 z+A+GCBXVg{3?7>32OQoX%*&81NP6k0<6m8+Dc9wF4JR<u4?suL9A6|SRK}B|nR(@< z{?g8QIEx_qT)S@_DXm$WogZ^*L&$mNuDgc<$D9dgY-J_C-O4X{9?QWj;!C-Q>#Eh& zf<+qxkeU(T<Mk`d@SMJVqcOU3r{tjB7BZ#{w#RTl^GPlr4Ud~1P;WDte77qi;7JwU z{afMibWoMLZGfhNXCSpm7><hP=*mDkZO6pOyNSjSA5dsV)jZFvY?G!sl$-Z~yaZ;l zn5-4S9lK{Zd=U|iJ|w&4b4V^XMlN!&Vdju18MvfPfYsAK$PN^3A!_n<NFJ<{kLrUW zdce^QboDdsvtqdD&!7d*oKuYYBH+|tY7s%XzX!p4c1w}mH?XbetC?1%eci+=5kdYA z1suq^roWEnUZ$m8wQb6KpgT0J!2jow^sng9USJmyoSGG>Dj&`opUaD~XyMK3%0H9? zOUjSD5m($1l(6}MN9A4|hXYUIF$`)?ruGb`zzX}Y<eKE=Rt2w<C=_PRagmphox<v{ z`;|~j{90$e*XkxKD-FQf01IRpQs=6aoJuI$jSNpHy#YQLAP3`LAci~i@AM=V60n|} z*{Zohq=Q-4PE|bYEThIkEcj6RtooBYruaDT$iq@VxVbUPqoT>FtL*Q9r3gn=+Kz8v zMGmp5Z&D>5vulax`>?+g=Jy$mR%V!*Z2WR=oIoPNM`QpHL_s5aqfl?XHx5y}KXa5& z5~FnhutoP|uNlmf5xD*9zi#$q?`2?GgmgC-MScPqVo>R}eueR2Ic~1UusP#1bTFn& ze7WtqjH(B559urL<P#+2^jjglK!X$bV-QOqRsg3Ue8gyuvKJ6xM<fsma&jl2jmWRE zFf)R58AKqRfKpUCnk1xtm6U8<U&xs*wtb9Gh^rx$oU_h6^!_=*%-7J8TLbHIpg^%v zX$W>|rTu}5whCPFB_`*t3Nu-N&exVFnW}XP1QAxfSwTxi17(MayIa$_!oWc|F21Au z!S6bC+Y~LYtvxlacvAX>*i^H2b9k=64)&FB|9}wHwtnL(A95juaw2BaU6acy%kZvF zk>f4xN;k>RZ;rF@3mafUd5k6PpFSBi01+SpY+yW^0f9e9UY-c}dxkYuvA2a~0?^rQ zweAk`p^gTvN8&O2ow&_AH*VZe+&dHaUa3gKVX2=C4)il+e6|b65Eg@Omh3F~P=s^; zT<9-QL}H-2Qma~GL+oxGJS2^8CrGnY11;fAVQ!Y~vWHUTq#C%55C9#{9cMWLf{#EV zJd&ts;|EAMyA43=k)xd-IzHr>+k+s<g+^Yh7FE579PPs^tE+7RslZdQ>Y`751xO(i zE)W_5eg<m{YVBl@HjSWj#=!x4cTLf25_+dXRa1h1Ni@Zy9CmFHkGxNfEoz6;FY~<o zUVhH)KwUCq@^rbiI14tB$i3%*OfDQ}I}2Tb5Z_j}$k|IzCqp4c!K0T$IUxXXGEJI7 z641l$>$(UkDk=gk59J#H57(}``}zsA&U!hntI2`)2#=i}&~7t9&EY&94|td}Yf}%d z+;l3MxK@^OKz61&&5+J&7wtiHTH>-D>?wpyyr9LG;mDMfms72pNA7xQGNN=IYCG=w z1@oyU+jO7S>oFZ&5W-nmJZDvNbVC4ddJei=Xi~Ui<40;9C)+#$)^WJv^xS;g_%<SE z8%O?N$5I$y?!8-C(I7VA5!~@VQrXpE77g}WBa^b{6A%*VrEw!>vw7JidUeaMIv?i6 z9On=ee4|@0byHaQH8>#@juJt7wVg8Qlk!QA<FvZ11P7wP#s-;xXt#0#92D?SP1*I} zA)w99zBQJzw?ESm!1VehZKPTaBx#UXUO49xag>B?97;$8?5d1!#LGN9@!!@)>Pe$G zo$kR~#I6ZE2DppJ`q$SN2yi%MYGo#MScn+!vVs7^W?`EFOhN!Ko_rAiyu1UWIS}Wf zeNf^PwV&QBo^Ugft04pQT)wYM24m4Y#Ug+(K(2oG<`(TEcmVKwIIaqEeU-zC*SEyN z5M2N$XBc!z$jAT;a~z%{jvIdBcQE!<m6s(Zr*836UnjhwjEpy@n}}qqo#Y&!NKKJc zG{5ipI^TQF?XnYg)^ZX5_2KsB_Q8Vjw~UF5JONfDyEI|U!BLV5oAt|yFTeGqS`Z|( z=JrGBvLW3yaSnq*k^!>L&Tj`Vd+y8IB@bO@TdK=je0P*OzG3wwd7vDLatd{h-qPy1 ziiH1CZ`dm7>D~0qQQ@zm;>n1~WSCnXK4~OvYM93whwhobjxBbnqP)7jM>~I&qns8x zcc_2}D%pO^b$jI=qRBO)#}(hZ_#82Z#$V>);TbM>@#QpXgG%%`;2vxBR6Wp`O_NQn zEfn<mb6Bfx_U7*6&q0xmLRu9$j_AGxvOqWR{rh8I0l!UpD&%LWS)4%vYS6cD-(}7p zo%5LMaiuad8*fl669nXju3hpa)s-vL_MCI|KLp1B>p`G0^H}(F3&+5y^@`(?%RdVH zspcp<ts0w<J|>l4U|zf{pQIMP83pR4>KzHu+E(hJx#K%D0v;cARr98PoD}&Z^MQ_3 zpzaif)Sm#*N{?FnsIMutX<9y0G{yW94qOU!I^A>y9c~zA_!1-qKu$o(6k;eH^K$Ae z>imD%qK-B;X?n-42#^UV;%58Gsz%p9sDD0a@N!=kPV`;EEd~bYs~=7z!GrB{DBSs8 zR7nqK7;5i;(AyA+DT#8D48I$YK3z2aym1x!aUBmOqO0?DwE-D}Oafm6)Ncfxlxc5< zOiz}wpP^6N()dx6!X1y!M^;gPY}x-(Av%ACwBf`_((%>t27>gc@KQ~-;zuL;TdZGg z<H&4BU?wl%GjfNl+G#J-Fu1LFylK7ch=~mmz=I^Oe6u-W49N3u-wlu$Xt(_aQbFia z%Mr=SmkZK?Y)?Q)>HE42XDgF0lwXa~Amc6DzygjH_NkrS!F>du5`mX26Wm%FNw=SE zrWLute9tI8_;nk&ANZ|mGSQZeJHeL*U+IyMknC<!HG@C6$3U}e@kr>a)RW_)YlCKv zQG?T~7d%WizgeLV6x`hb!#cB#J%Msy(?vG{2aMAxDlANrU0yc9I~bLMFdu+2DPj{- zb=!DNg*KN6CNGHi2#Ij!*9`f3e?MGVP%;*Mn@pgHYy~QxAWWp?GJBJo%K~^%5y5N4 zWvN7a=Yo2R!{X3kTah_BZjgeRP3;Q;Xy`YvlG1>pbQ{X!hV&sgHuOg+wPz7HM-akR zsUr7(29Mh<qitE_L6rPYtpRc<M+<icQDh{OG)48!>to^i_FL~+a+QLzwrrR@GJeZe z<i8*f)pF;~IqejO9dMxuB}w=D!{2fAAxZZ>zi|5FoUC-@S-5UBoFNR4<>rmw_n@-m zP)>s$fA>HMf`9}ap^MEzVrpw|A-Y@LUI7=yu&jL<`ow@Y>MX?9yb)xP^?|*XmXz#B zHmM*aiw(WK_7S=C+-lcvb2TSklcA96$=1%()^!qzwtsWh+`_`f`U|99I&2Rfy`MJe zTSCq8jetFufa_`-!UI(Y3GJLCewSPso8LNQH3mu+pTKL=V55Tn8MS|s_oEi#8Ywhh z9P&K-YAc#cWj+%Vk)QPt9VbvanS8m$dF^%({_vU}h?h;De^G&Aq{oh9LFPULiP?W{ zNv&la?0T;zw~doivOPoBYjnN_K4IkFnNwl12m2O(32dsIeTN$s=-Fnh>*hKvZ6rpZ z_%NCb>k;?c2w-!)B|*9ncQ`;+k#%dLee)nOpp(381fF98@QMk~@6;5wY-XqA&C1`3 zrfayvp^(`H_buZgOqMdpgeEOzZ{BQAC)`5px8v_zZjKQx$x`0fjM8o(c|LGzvWSu@ zC&{4oe+$FIV3&{N(WiM#a_Cp(8f4$6jUID)Fnj&5Jav_9ttpJra2K^a5;)edgeSNQ zd+G+BOX$3^j+^zQzP3O}9w0SS(cPQ=bq@B96d1Y)aqGvI*Tj46$hC=+2<VS4UZz!A z+O*LWNGqbED=Fm`UCE5k(^<4#+^yW}Sn3M}I1f+&Sv@_y%K4K))UCS-@O*R;8LIg_ zEF!xPtSacHB@Lf8{FuSllsTzSwMI(;qDVB;wMSyus`K@u?&0&p*N>seLd@ls7{hYx zr?UoGD;nJHJ$;Ugqkj}G$xx{D^wpTG9}n<8b#E==B=KG*fE#d_TaUv`h@<W-d~Gb5 z)3B&;9QTasFj|L3$Ee?a_?H%7>px0#$$UlGc>dbN8_81W>EP5FLf3p4=M`o-u(=@g z6~qYy2Fc78rR<qwFjve+A0ZpX9|IFx6cy9)#S_~ztz-yx;KfkPYY!jZuwUqm1E)D? zy<_8sdS8GViM1_n{K9$4`d!i(qM5-|)VJrCSnMFx#djujJ^WXl^k>dn7**wZPKIU( z6XYc@P`<<q`6>~RU7%ql81bPXj~eE=eVa>>dLjzCyh%dfdjG!K7o-VAhB7H%g8Y1V zc-r11(+AL|UJ)dc%eS<s1oik=s8b+2xwjMF+A4z}*mn5%1}2c?Ni;`(eZJ5?9Uc98 z@c^G;FB0Kcku6itv*=O0$4w84P534c>M6S3e(45F$IO5$BJr490HyG=Wv!!_)`;f9 zQsia+-@s1g%wFh*Y!wXhImF%DJ8>=D9?Qe>g(v3>Wi~{vAinyvV0qPQkR^=7`9y%q z5j}V^F>(gm^$*lUQKw{Ar0VZ=uaCF)dRLnl^k;YlhXZH2?DNC;mTN-AzS!`#=@t!c z1g!DA=*&?_Q*T4@aRwY@Oe!lpm7{<7>U+Ug52OK&7}?SU6sf@UpZiD4fljNhat>ep zQX3kYcGcT0fkq|pkx;5rh&bL))Up~zQ^zhgkZh1-yLA>;bT~8%3E$ibd7%6E%JxYB z!Mxkm<&}@#4prw2HR%GfXQeOAg1$_>(3}oBkh>TPdF;PU@Ste|fSxE4x)4Z&-?g+K zft8cJJg<q$>Tnp%(>~39=Ik>`s`3+OFRcHZKtghRX?P^wpxoY3z7!Qh&#A6KFx@+B z*|EhTPL8b2ge$&ZxJ>EjV=1yp2PH7D&6y#hKoDAei6?9-zWetxJZo@<(m;w(<bW9N z4_ki}xh?5Q(xZvcVSdhR@PRI*tHkqH7+-FqUqx$kTM?`Ke=8&aSQUQNjF5jE{;fnf z&~HJ485ZKR(LgX?wR$!&O#ZIz?Y#`<B+#F|0}aHn=e-Nw^cb)>>XeMkcV@;l;-;Dv z-@G>4R?!EzOX;pInSg-6wQCER>Rl0+Fw+370s_>Qh3(54Qnz(mo5Z9ajC^^aojjzR zxnGH-PO`|pu@@i<!f|K-LG-ICkNRg!-}duMc7d>Q{tFf!H2zPoDuR23F&7LaK#Y*3 zU?0X)z`8#}buV1e!w7K|@-c3=>?kd4Z7nH+EkCKh|LU?~&&<m=)lOLZvu}!I(tdzO z8Q8gs?(1GRpKA5=6%RB5DRcqM1NK$W&=Gz;pPOHm01n|OH`$T3`;ww!tFf@562bXF zSgNoQPftttVUXFF;B~qpbMu@YyE@J|zps@3qAZ7C*`iodt;z@SDya@<cn~{({Wc#p zRrbq@7Aa!Qe^l#*V+MJLMSEp0#Hm?vHD@bg=%&l*aAl=<w{-cV$rc5WM*wqoiV&Aj zJkm@+%Mzv&$mQ!;G)1r(6`z6X#dHURIW%D0C!W85sdvS4oEQ<?n_0xnCv3^zN4#Wd zDOy%Sa0kzvc#tAPj9<7fjF5zsMj7;|!Ur=)ljqfJ-JUGn`JaTu`{}v0$!zf11%VYH zO<*LC#~L#@=*&A6Y*0fq>-5P;6j-kdciLV;SV92%7YIGO(yRV(O*R>Q@b~AgZ1o01 zcn!vtirgAuAYpIuwVz<&)V_1~?%P-0c;##jb$1lFy}N73_wD*;N-Oi{^YTa9!2Suy z{JqLWfHx3yiPCA7SK1x}35?o3L$FbUK7lz>z<;a`C6#AINd3@g3F04JM*Grv7tUIr zLnJVUL4I2TKGrOylO=8%gTK;GUpeGf!zz86$IbH+tyuHY#HPRl`(H3z$vG>F_8i~r zRU%$Qt4v$rIOXZWkpeqH>P9VXwBExKvn1TrN!&f!)i`R_xaxw^bHObm;>Hu_NAY)Y zoJx60^6o+c0f9@;!vYp-c=*)ng8!GSOi<Nw>1ltlivVEqMnjt;qJ8kae}jwUYf+}R z!wA_aLriZR^ueCc0E5Q+kI3it1K*!w)XO|BAcU$s(+z)1$bzi7XV&csvzFx-LGV|A zzlccU`D;gQeS-q%f#Wc*f-oN`^<`4cpIu~v2>(=41<`b|nRHGhMz0?vzy1p8*K|tV z!XC0e1i5X=HLwKMu{cyZz9PmYxW9u}e~OLGDO&`iYPbGyr2|t4k<+8d`NohZ&~L^M zYz#-)K^6-Da9Wi=#3PkrDN-6zz@^;x$SIj?z~1X=F-k0WdcXM@v=ktM;m<rzD|uFo zcbi=V{XD{PY&<+FLQX`$TNA;thFR=hl#F1F`t7RmN8W9M*#%z&st@oit46C^i}wmr z$Rc)i-w(G0+YJZrR>{PbA^K6Sw4fvx#gslay8bF6B7L+lT{fZ6I%q8(kT#hzZ6_$E zfSX1v443rH@IwakVtNUcnNSqJTS?cD?rg)xZMT<H$8<*62-Y%K-sBDsaT0BB-m(Y@ zCyJ;M5=p<Mqs#(uDil$0*!QpGScV2C?ep@{Mfu!oBJc0Xd{BB>>hH&TkibMsh!4oL z39@c5Mcm}!Ap<KyY+UR!DXEEHpKqO^6#UqK-vGJ$hqPbNWn=T6!!9_gQ13*?e*#Yq zE&%Qw55S_fH`Yt{D{Z-<mwwul4|;Qj+-AHSKm-#~@>ifi6Nkwy9iGtkxURmQ_|;*N z(=-uBpXap(-6AvUc`a2-+uXf0xr;Y~QaV5DN<4kE^y!vStJ2-4c{A6=_-rv@Ouh!{ zzHbfs3KldLSj`+gJeynl0^)=W4I@&g#{)Iig{C;MJ02qIcn{&_w!IL@Y7N@rwFMj( zdOyFqRq3%<dFtZNeCY5#|LZftpN3Q1XN;5Iac@N^j7gP#pfL2Vj@0_pA#-DNYIm6% z-=({sWIunt!nMBVvTISnZM*<obd<oAy&$ZsLra^xub-PID%yk<c`(@&CLcdsVZX2~ zLMdz;`z9dn({0ijEGDu^y--HnZLd__V~=cR`$Ndb_vKljWMh&HZyua?dVnW6!+GSY zXyDb@EWgwTrco_6lsx;K7DH&o;O=xMUgZsz<(0uIM|`F2Wc3BFU#+;{b|B*Hx2+SK zLS4AzFZX@-K0Uj=>S;f>L6M97qQ0}Xdsi1-{gJc5WIC^g`+2*yc9o-cFju0d?4&gN zaiqed$8Baqn{gj~eY<=uG$n)G+%cx}n{k!azk@Hc?Pwc$JuU|OgY?0eS=|0sXu)Ep zqS3_cY^GJ3XMTJ8X=I*3(M8TSi6!mnyk5KDjrH$zbE_Q<y9ON!CB~yle0EcxHmti3 z^Wv$*sV}I`TRWAe9+1$S$<rBM>c&QK7<6Wd^v;^TOd+E=BbTW_=Z|E*y-|(cvkdUi zUaPvDIpW)vtur#{XrO~@;MY(58X5FBRK&A0%9xH}U!r_}bBAfB|D-nB?P*{*W9Bu! zLX0`jym7mY|ABch8FgVe&T9*+vN~2bEG!(XlxJ?jg11No!$U@`SU}dZ-;bK+$CEu} z<2swwMXq{1fc!brC|Wqouwi;*_Br7#ZfA;>Z7HLWYn<fec5a{UX;<r^#D2zcW(x`l zzT}94|86&KdzwaC)<pwfJaC@&H`NuRpgKMIoSo9vw`yV!l^Im;_gI}m{OiZBn#u3p zzK&6X)T^tF$!zrg@{`9D7bSXMm8t5uY6f@LV8u)iZHHcB=jUg!R1_!;K%qNskw_LA z?wWSyNM~X8$M>Tc6Rw|y&8ULf^+*zO-47m4GYTZ%F!b4E2!9$3jX5{umx(@p{ODMo z52eUl*JoM`2E)`*__T(#>qlEUy?VfbyK4rXiH#m91n+W7RGK}_xF)8|iAQ=zuR2RL zKX?L7qzVYMCiF3p!0mc27q-2eZpG<wnyhiLXca59#0cfyOMXYM;jyIkp5L=w@(P<b zT}2=T)*~~TJ1cdLGxolXLVnFo{B4tAqXf#=m51^Cxl2O3caRAl?v+e}V_AkR@m5=v zfwDCCO6xq^>87x(Er)4-r_}h6lz?S>?zycS2^&QiwQY7-II&cXe_c3BTH|@$*x+L4 z#$`&8)$ErToEFCL1F=2`^Rq0f$SR!~q-4209$jb%lyamE=B_&2KB;TE)6~<L*OxEr zgc?L^C-seFiWqr_$a11(V^{m9GV5iH7b0JLAPy}@y4{}bI;W3on8U5X^O?kWNZeyW zRW*=M$bMaw6Ib|f(`8~ZN}N7KoQ9^AWH-3u%D)~g;z1=Q=vI}6P~W5Q`@VTP{z^}N zDC?_#JF?SLZu8ik$23DCf;G$-JPdKE$zp+x4R-?HkyCv#=MfWciepOe%^AAO#>VC_ zzZ?JY64T8_N<a2xp9Dqism=WAjA~&QKTlUAGRwf%D3mQfFyI*RfHZa}(L)He?nr`K zTRWY}=zIGTU=FfeZd%`r9@{TzWvn7QZhGT1_8jNBs$7E;N&rP>#2bryzl-ln{er2V z4`bZTl3lh$qD#hSXM}`=ddfR4a75*Nb1G#H4OW88%$*0B!Kj?|sp;0Sl+l{>R^t(5 zLzf)3Wk?`qbhiK761P*{m6#FNefzt=-q-q}gF~5AWl;U4B}qw1xaG{QkNzl&(DcSG zf9{oWolLT|u#{>Scl$|+@*_vRCd%4$*-FfA!8hK4F;l!cp6ar~0}s4u7&2hRW;nHx z_auJP&r+;Po9oW{d}JrL%gM=Y-T}9?^VxP%!d>c}KwkwDF4m$79Pr>t-k*c^!i7d# zJmErTa5YTRqP7h`diaOqEHV#YlXwaAl{4YWZYyUgJuER*QG~|=;i4{M{B|akcF1|p z{7lWht@AzKAZPDArOAWscpS#2J9<$hp@h{m!ws$(ze^fdW8I-PwHPOjo9pcbC3JU^ zi=xj^m7-^Fp7P@oGnKyIx5O4bd>NHDdVJZ0^GAh5l%|?LkesPNx;=W-W(H(Ya0<+k z%|@1lk|>nBx_w&x^p~ac^(YfPz37e4(_wd<EcJJXitXoBa-jVVgJFwp!z9!1O1GVl z5@F20+3$XhDvWF~j1!_t0vqvtcfq9O+=fCz91Cx$Xmf>|o2Olsr&ss!YFGDBia3Ej zNz=NzItH$dYCV0c?3ayWGRO69+jDa$SPY``GBS+0Ejrb_h&N>%3`dK{S{>pCkurt7 z^Ex_Fle4oyV@Psa{Bm<eP_+J-47CiNTyS`}qCPIOX4w${?vaoF%CNw?P#)|tEvHWM zv9(FXGiuG8OZTuE;S=UfO0wtKj)n2LIfM%>S@g1n=$WD{s(Zwp=+7;KKy)?^I#6-H z?7u4BYwqSnf>T~Mln&Oyn)5K-95c=0xOD`;k8v1@^Ot|}i^v)l9HAi#1n%(Lmsk|k z2q!HZ9ZEAnZ<=5ae*d0#_m_2|<HB(6+GLaIl#}krw8BvY;w!burI{E8Z3&XUyd6SZ zp@%VSqw7u7?rcO|G`B0d)%)$7*0YS_y4Br2tKm-r<}zCh-{7J@tp@$&nIRCrXb8`x zHJ-F1>Q~VzGU4?5lCf(Ot+_B^E&GiXAx}8;xN;6Y%JL>m*8ca8uSW^TG1NWz5Nd5} zeBnF3I@3Dt@z*c;$EzRc9ovP!{Er_LXJ4cL;|~ys2gFYj|N8!fzy3sYZszpgUib3B z|9`vxm+zfiTJfO#*VXpo!ApO8aw`d9qPl<kv+GACiu};ZO_yY{wg0-K2rnbgc{Tpo zq>z^5|1Y1v-L?PM_sWD$Vm_U}giS<?X6gK_QM_t<!G+m%VhA=OgevpSp^!t3?_VGH zE1#&Cg3>6hfuAoq8udQdEysn(ms{UZXYM4S-Rv#Hy4}F88FVe8mM$H75k+%uiHUb^ z7u*V^lbqVqN=jKAM5zim;aO_jNiJS<Q-Q-xC0C;dXTF{W*-ywqsn3xB<JxyEgGEjW zGO_nF#U#U&da}YcbkfU|%2#fgsMIs5elKyv(=QH9=L>o6Wx^D}EY<YzxxW1L2HI?R z1EaQgGl4zx#a1;nM*?XS>rPE7XB#>Q^%Yh?mJ_^C`uq1eO7O!qm$guC+pt|?oY>|( zew?~bSHRJ%4ePN6ZwqX3rbO6BWYJ^SFec6V$+oyq%`!a$4sjhF9g|93-@2q8GoG1c z)LyYsV8ZQ89n@f!W_q}W@SdL(y<*{zRe!m<fYU*)cGY1o%;?Ed>QE)*NYtaoY*x$W zG7$}N%Ru^dr8FvDqD1OgRc{u;V5-H9J=ztK6pJCpro-p20ur_x?mJQPn%>pL+BRCc z!r_;zR-)qJu{Q~6%<<C`s@@+baVkE2N+{%|^rmx{F6A23<aQGsKCZXP(5y;}_t+Kh z$&qInDRr10tiU!K7VU1*-h`}AAObSL$T8@5v``i{Scqd2SD1!sCG{hER;4u*nmS4F zT0Y6NT3%w*sWz@et7>V*0+o<`iK%ZU!SkTU+xLocwevmYd<}IdRNEE(6YQO-^R>(5 zv-`~D!Wb{%;4yWU`0?n<MCC#EtC`6No%Rc)w6Z-sWtMewbrJkCW2x*V?w`Ym$>(BP zQ;!``o$oDU0MWpkQP2G3)#Xgxwsw)j{p>Vp%K4q%Hu|c?-?gu!`Q}MnTwF{*{L>UW zfF!ry{~@xw8?#Jp37SG3<y-}ExE8rtG0DcRF3zxoQ_jv%zs`v~&lnpE_C$LwkCZ8; z+SWbEud?$b`}KRw(*0(|XxfAfm6Vi}UpOA!l+kcIQ=#sZ=}4A0;TZ}FE=@eU@6NBL z>xPpq+><nJe>IAn2zq0pqViRJy4BklH%NNw#EEXu2l(?ORyvr?Hr|=TE{_pCxVe$s z5hyAWy@xj@e={*iZa3YU`pBC`e#h2e<4Nr<MI}wSro^;|h9D>3_~zn}2FlP2nk(NX z>;x*RY*@Y7l-yZ!72z$x7E})DY#mVt{jSQi8W;l=fJX}rTcXqU!cy=gWOHpIWwTZ_ z_){lODgz3joQzb4B-r6&pN$6XQ75#M_^!k1@~&9}YfrACB=x9s-RzdrG{ujo>GjZZ zMP6*ahqF=tuEJ6{izd${){XZcudrpMCm<DouaYU+lCsLo6hOxxpaN(Q?+oAt@!cWF z&n<Sd%FV8No3Y3FooB4G`m8payG(If>re7^p$x`&=w^;o;q7;&zJNg=vLeZhN8W45 zOl_(#wum*nibj0bYq7xDDhj*X;)D`leb4I79-2ud53rC2i`ZqhMkHxphK_PusWbh+ z-chI0Fs=Lu+8+SKsTF(FCJ?rymk$}!?b}KYbKOe0ls!Gw16_=A*F6g-rIxX)uM_;_ z;8|w%9VV^|WPz+XsV^{LTTC({w>#*Tm;*o(293c_fxLy5b0yuI-YN_pts5_b8YeU? zb-HrZ?6UN|SuXo>f9bzjR~L23bts4P^SR&@#>rDvO0QCmQ44%#)po_a?0kG~p~?m0 zh@)kf3NE%-r=7LE5OsN~bx&MZ*6G?cdFc1&&S{~LBy%c8+S9V@)x!k(isi<T`V{e7 zw#GBZ9Tt1VrXM|`W?hE5VHCN}?SpyqCLkMV0H~T}ikqRrF_b#wXnfUT292_1Yra8$ zvuDA@E7Jo|L1jLfU;JljT)00X;-*WDMG7@eW}b82i0sW7xL$)lfMn3jEuIj$^q%VO z?1n4*&nYXHNYF)KYt4DgzNau~RGNF&PA=-W>CkS?Gsw362n(#!>*zM&<T`BdCM&~1 z>B(1wR_VBzna?}CGukqBUpi_x*JIb9;I>KoS7Fn>Qim+;kY0iDD7nZT7mH_|sv!+o z54{?$u?jfM`GEr{6->`Q7y;CJTBYM`XjY*XiZU}0N!lLt^|}wplBs4^L|aEJMk*XR z-VBvlWglE{5+2&f7g3EH<W?*hv1=>iMOPK*znhIplTFp+Q|v4kXL|bdDYV0|q8?32 z3H$N|1A9912pI`|MQd`Z#N7Ia<O|2Ic?#$UKxLl~?Qv$a+3HipT`uD*rR3#1kZX;^ zjEej=sJ+&zk&D*%<!Es;Nrw*3+{$~^*1wZ9YM$qEN?c@1qpLaiL~n5XV16mjDnt>b zamigo|KsX1x$puUQ3n8wXyTT)<O_!^56vQwTlgoz#U^;$Nf>GoTx^w4Q|Z<(P`8z* znqMlMz|L4Z8gg{231Yq}&Ta2v9~GzR`)FP>y{%}0t!V^}@KX1k;CTy)rQ&a3;d%^6 zZxB}4(+4x(otK%9zG`&lF8}$f1S~>&4YkB$)oNe$I%z8jb>hoFfn6XmDb4RM)MCN> zHGLhH?bL{u#|Xj3@Ucj=8AO|p-KDfhS0lwTa;)lJ#L%dhLd6~KX>?VaR4cSdPZOr# zm(VO*vM%2z;0_x<Z;*L;4$n&3r-|^O=4$~^(<t)@DYd|6a(*-N_YkH{5X@4jNMcmE z%Ld1fY5y-9pFU&L++F>+cY*f9S5z{S^3&Y-bYRY}ZMk4>;A;VF)k|t;cH@<2;tK1A zvStvdGd-*tQATHt652w>Wk%d;c7Mki%u9+lN-hp&^oh~F?0031>F%Yr7;<>FHd>zs zh?`matI)mo9EAr*-<hn3FJ|f-_G~V81AJ1|7k*Hxpx+=Z<5<<3s{!FySX@Wd#6>2i z#Sk@6;0sv-LnBgJ_HftEXP%fOK@ofKcmu!yvIyP`UD@#lGAC!9s-oNpBx?UUO*WOh zJS8_W3B<=^)<bWOubI`C>1G+rH+bzY)!9jpG{jZWQi?dfjTXeGtS<NWt4Z&>WrgEQ zIR+MYxAtb@hpmXOmG$b<oth3(rI&Sac9x)Tyq(G~{(0i1sID2kuJ3KLulbx-6U>kT z;YK#tx>L=TeHe?ZL`$tZ6q0R{p01}6qG?n7h$fNGQ5=q!(}8|Fhac6ajS1h6%qYZ` zx~JQm8xqa9#2l$RRJz!0g;8Z-WYloqCGG9hovsS=Ufab{&GlzygYR%+JVb1y5`70g z>k@^FbPel{c1)RhAMEK+CL<ZbF*{NU2i8nWfc9;5t1;~ShR9AhTY92?0}j8i1A{o* zW2mcU%IHonFlGZj!~g}Xp_>R>;{)j!_q~1p`VVjBlV#ujOABy(Z62P8Qi&-Yeh=h6 z=zVhPlV>`MtqimDyw_L_Lh;iR4DS4TIS|%{P&&oWUOas&HZQfJ9(PhWyJVh6qVOQY z>2O6T!g3V7ZCYt_bQtgqp`oPA+a@i8{u))5$uL#o1{+)c6JF9_uEm%r(eWoSy(|PI ztMO*;&`Nr5-cSaF7~Gz72H1Avv#4xUYqmbMudi*9w|5#a`T3Zs?r(SH*O$mwsW_na zJ5MvJ6u*D;h|PE^$A#Z!ECsnqk&<w^S&FMu5YS$J$GI#(BQ7z2(xnzaf3`J{!~lK{ zXA+^ZjutX{4Yq|iJw)b!c`wPx?p2YwWyjrwx!%0Y(^uF`ekY|8wkpV_7+_eCqsa3m z%lWyIkRTTI%A3ls(L<%nQmd7o{aTe5)5-+gGkhby-xf!sC%e;dMR07@0Qe2C|E<At z6W;?N2MsI7g`CC<4H=G$l(QQ2LoO;Q&u;j<M&~(0(m~1fC2(_by-#v6UN*%2$d|sQ zx@qMK1@GGt>7l>twS`>W616I9;og$zR9{Uydf-#sXH~Pgu&S6Z?6omDQ9ywXI{i%c z3ab{^0Zn^NI){<taJz278@wO!l3)ap^Zg2qglBnW3>96(`aChX7h4{pN8JbsA)FqU zkO$QV+xl^Ucbny7J>0nsD(@jOtv`!#*;^mJ46L1E87i^ZlMz>Nv|8q3VEUEwm`JR< zXzPJ^?|Lqr@Y&{3Vh*<$HELK7qzS9iZ+V&lFbLDFn{Bm-UuSkZX2c}#-ohmdW$2g> z4gS;tDQ7mPQ7d?iJPF?c5It_2&Wp#1iA`pH9mp80SF6VIZH>4X+Nyki-qyP8&^;d5 zrwr+7spZgT+Nr}Ns9wyvBR^0I*?t*u%-f{nAEJ$k$Gvzt!R=3d=naM_^FP2}7b8rX z-Hp$Ku+LV9Rni@$NojemHxf}c4s1;G-1=Fj@KhJ@+Bg~pwFjPii+wo*>khZspV8XS zCm&xoynTvMI#B;t(-sYEH<EpF6HItbvD>6+df;n+fwt>;f(dsTdMbB3aJ5y*qPVR3 zh4(f#Hm8I<A2tLY-Xf%Vkf+lDgA5xj&7J$kW5X?nv?cbKalh+WUL99;gC@Z_Yt(tV zkEt$v%O$Eh$QyNt#;3lXoJ$Urf;xSc0}Fhox$sp3^)*8^!zutSDugpf;g)OCOIG>} z2-~?y*~|efiPA9~H{?r~i-prY)yup4Rc%3Ev|-rLTL0=bc@;W)t|#kfSC=BJ((Y<n zk6s{hxb(V@`BQT;xBM&fq7(P>@#}<=NV0G=P^c&4v)kJ4%+H|YXpThz?dpqZPNVaA zVKr>kR&Ct+4QC{6SKhZ|+`B-hPV!zk)7D7zSkXX^FrL^9v}wUPTSWQQ!zwVhK>@N@ zvg5~0VfO^5d<aRqdsFb{Ky#x><4X?pkOhrfR&fC+2gdfkC4Yne!`^#_HJNs8qdK-x zM|dotpnysML5g(gs1!r*y-1N>q)Q1nHbg-rH0et3NbjH`ARwI(dPF)Q)PxdB_R90V z@80kD{MkSDkNxB0IA(@9NbcOZ?rW`Ut#h60T(4=jRAr9tP8i?RD~L{)(|)g?JD)dF z?l502D!u?I#Id7SG$CswRP4LVnjp2(6wVNbvn^Wge-bZu%$0wWsn8OMiz(6ycS$nk zouXz%&-%6mGqdH^BxDAlx;gktbE@1OV^m;Rdrk95bKk?k8z@N4$To|JXdYuDG&QTj z<Qkf;crSkhC&6P{p(Ry=<FtyU_0KZ!9U2O}g$h`=Yw<B>V0DH8OPO;<BHCNw(lL}T zhfw?vYv_OMcI9xU=@$)uuxOGI+@!eIia6{z3DVuv`&PADq@b`k-KI?~y9wHKVZO>M zmwU`Hhh5&y(bi@%tv=_X<KUd^ngi7c!HG1BXRVMp+whnd8-YBgZdRql4OcT3t5I-- z`?n|;ky@37D+`3Tu9rF(g&jU9MF)_YV{!A}LLx^tDpQi}wjaNqaU=OtHfx6=+qjo2 z<D=!oDoM?9q?yD&Z%=UP+$e%}j|B`C*9&3GNR5|b>QtTef;&WBd3F(B$u8uJEzc}F z88HI~(HAkB88p;wHpUXD#^2)umAx<)(%BT6J`bJ*h7LxlVcC_S9&HY_#DS&i)91z! zRiy=aST%(TizyotVO$kNE|k6Nfuev*JNNL4RcnyN(H-%2k^L6@V9vtJGZYob%;Sm8 zLi=@B7o4yRhP4$1N$tyLK8tzb2kMFpd!Rew*Q1)~nVWi4L#Jj1rnOs(5YdbU_Z?<< zRuI_+L9|)m!V4YOxh@ZeC&7_<q>yR91hj<nEkGQcJ+B8!d7&3E1rNC$`)e}D#LM~4 zqdpG3zi<Q98>3JWi46!?&+gpdiQKyac1!l1Jck?%Wq{JHdSuBTU2sH2A{<-3LX<3W zyb-Ad$wcUqEVaW1u;N5H8OD7(5rzU5!X4cr7oK23@Ru)hLe@ie)I$>N5}fw2tQ5iJ zW42u=pX9j2vkbnSe{Nn8+dE$#u*qO$NOI8C$+bQi27Tg=Sm%Lv>g17Q)wLtB^G-od zewg4pcUm!7xCd$Bd4$si1G76ZfGS|Km8pikk|TKPlz1Vv$WtG<i#Z_qfP)Uo8ZEKy zHoc1EGOj3VNESzmxm(8~FomY~*j``6WU;m^Q1=LQu%zN|Lj;$H+f7NRv?tm|CX&bA zR&D(Ct9`>)Yb+;WMPH^)qCNKJ)Tg9hEn%1Ag?!`n3XSqUe3)Vsom39n<zD!au=PgJ zs})l4&_?4*m&pOw&1dWxf2%>V6ZW$O0=A(}ai&MNdzQ@{CzcktOtvE=F3a%LlNzz1 zhrYuNm;Y>)53$j@-{C<91iT?pz!Xgqy;Y6tWRjqW#8B#f`cIkZlng#Rwmt`tNq-q^ zCX_hQsul-B&;C14q@(v9{&Ss4=tCt;3n{+qOD(&&*6;rfA<~6M+piojbu!(;ocp}4 zWRJYHt=4_N+y_skC(Y@3g`WmcgKs{L@bV5j9K<90E1mkJ#<!*yn3+Gul?L`$kruQ4 zNL;+JqUGEr-x1jJcySpb&mE^CB)hMl0dB8CtZU{jqLqHhvDiSn=LC~P1n-JR<Ixi- z{V&53%K1VD$k;+tEc|{xOuW?D2Z{*A6K|Pnh5eVq$yOx4Bx$B49kJ`z3mI9Z&4LIS zavdE}ycsXoWd7y9xm;>Y56d>>z52N!B-1||P$a%a;#1h7-*GaZbKJ)X06?)BX1%#T zblbwp{}$CAAh>P8gPx&L9nlBbH_C+jlsApQpQ$3;@muS|(E&M&`=)Nm^F{d1TjKQ@ z)uoNd5+{Cs{+9b`P$cDuSL1LT%x9GTA&&0!)28?=N|zyksGR2ZYpr#09{a)rv$J0b z_>X4o{J~hYdyY+*gCAwQGPHdU!aUNV)P1-Vk{}%cXwjvht(DQHWhoW*Nb(k8@{uXh zXeYS*<IPEa)%h83zHB&V@jH)hdCfh`!}){yg$^WM^#g@rpwF`WXf%o%IXPmBI-p`{ z=1<Cy3sZvqixupa<UzL3zJLLOq4a#k$v!AQA7vrN0Wf<%)PSzEw6EvdFE-PLbIDGI zPPFXc=qqaPe2TVuKrut-)0X(K80%L89@aLmmv0ogwBDcftlT!-Ja_BjSvOs<<GwLp z8GG;sWpgX28pxWOy!L62+cmXxLT=5`HuAaDWuLt>ZYxb>zZ#Rl{WT&2OU(cS&8p-! zf=sf{To%PcXs$-E>SmU)y5R9<Ru#h*qNyA%qo>#uO!LmVpnH>`?(6sdxmpU%;Ol5d zA;-;t{hDo`ogF3(6O&)Nub3pZsGrv2MwEFxw5?j_#=6k$y`c3Ta+TC!kDvjVzO|&# z&SAaFd``{wEWNiOwR#v+5QId#jK7YCv!|2d_7Q^Uh+IEBkQ>%eyxVROG{>$0H-JB| z-+A}=qo6Y1hKyYOQt50aanEV#*yB}=ce~BsA?V!Pxis`wx(`d%nG~p-IBUCCo|(lq zHzLvEb!)FpIZ{=-nOVNW!+_m4|MN>z4w*Zla_^zgl8@RgCVRh%i-$qq!cPSr0C6#o zup~YN2iU{TZ78|oayIWCsxqHf^q|?dqjUzA1*@+8k{5QI)xiMZgBA+>rT;p#ZuZeQ z0Ibw#a-Y~?x&P^BtWNj9`$x6MWO(~<{#zV7%t$1mny>oc$8`RY6ZzQpz#FK2pq}s? z_1s4WUj<%L<=<ZN>{)$G8uk!1LP?cBh0i)BDEwH%91y~`LRV4P+PMZF>qZ)Slo}5N z^i>mt^mKH}Ag|7u;y6H(c6V6*x+UHEIozM&PJ>8yxs%IL{P0^xKjtHlW{g#Pv|%d~ z<3;_A&bNd;@?CWINxsv!zB85t(H^lWE0)US>Hm0ysMbn@PKTC6#PFPRvBC5T%Lj<} z904~osyt9nqlk;yYX*yJ`<PTcZgZ)n<btAZ7_-%xt}Q@cpnzLue6TZZ--6QyG=OFL za(73EvQ=w9E@0qM)=3YqUjLOlE)I#W`upu@M2^zT>%~>_&9*}S?fW07Cl}<FA<Ob? z3&Zq2i<M2m;hDn~%L5&>v&G_EkkNA)rGEmZ!1dk=Iv8)cx!{8p9I6i}M0Q2roMhy8 zs6$X;%sh-oXV^p7*`ZGs086q5k)e=wPGtB6?hi#-YC;E6ZtDY{H;Z^O2m70>S*G!K z15L98$VS}gHiRKJdz{LkPe)Xn_N;Lw9ZFD7tiJTN`BR<8?*(@Yjq24(ZMyZJkxA#m zmZQ@@f4+K#QBn(yDywm>jp>$71F+Z*loLZLyrM$*IbkGAi_VGWH)3i@u!@ZvwXO|L zqIY;wP%SP4+INqTw+5aZNNMZFOb_H5s>;8iS6kn$jMhZE;2NCwoD+V@qoK=UWU`_& zUb?_Fvs()u^Cp=f+BeyqAUJNoQ7!x9b6RU?V_vJw<B0-;;_F-nR~vcFPDN6_JkbgJ z8WviYss7TS`)`hv?4pn<MYi|}Dq7nf)pp>{3#aL97g>RVACjjMOvE+<l}J0E*aO>B zp|4LovG4}$G6x7QVv0-(gz+LHVXKBE-{KFG$~OsDmL)uF_-d^jtVCMv$DZ^38$Lp9 zC&x>Ue>a$2+?v>L+KSwL?@iBhpenOZ%u9A0{=v)U4}|}67gC>fMU=~U4I7fnphw#A z=b*C$<PtpaSQU=o#^IIRy|fLi)aNGqOAncE4oUjd-be}PIKOI3`Zwm5OO5)WvJiOi zFa+Soa)jU?+~yWZshL1!cwLW@7=HON<sxtIG+%=nk;>u_ekAKEbzs0$i*4L<r~%Z? zVf8~pyu?bDT>s=_f7|}7dnYpebmnSEK@O`unjvOen_Zc(SYiRUysZg-_*YbHCF?ew z-aeV6Q{iNv1neA0u8~6Mj<b*)oK0(yxRPWDn5pWHd*XPMtCe(ub!c5oI+ZV!Y95OO z7FZ&TbRk?;<EDSZ9<){-A%FAZe^ZD?>TPzJr5AgfAHNs#U5^3_=A;Jifh`y6u{&vU zX*1MNSUvc!M?(g1Zh4VCzg5W<$@CLBsc1v-3QvL_o6(8S_1XYq?a?0Jvz1Ujl(6x! zLM`*In)BS^zSxuCSO^^R{teWbR6WuJLE;ER{r1x-25D$yO13nXy=&u<*bvtJzV8z- zMof0Pbles&W=9b-yA0ZB)4-d9BX4H_nlUqbn-zNeN$B%Hp}C&$P27^A|0NI>MpA)D zwH2>egfqo43!dGWOA^2>!jAwx-51^8MWx4@1x#45Xt<A#Ck^w8<w$L@VN>D~qZ?(V z0g8-RCr=~Y#@`=pbNC+!Z?Q=;MO6p-5rv=4BrdckjY{M5hMi*CtV{4))RIpNYBQ(h zE#)pC;yu7jvIoeEeN@z@^x+%fkIKLnqT<BCco^HP;=j2~Z72elY(wO%_V^3E*zHa7 z56WFT?=3hn&eRkAE(Ld3m24Rg)R2$Yp6znhR#q1Oz}UVk3zYULcWE%+UtK7eGA^>8 zEK;U}WEXHBw)PADaESSBU3NN3U>i7?sUUw)<^TYdwYQ`!_g+$t#5r~^CEmP^CYOa0 zx)HoB(|~Y5Hp-k-{Z8Z96`Cl-8Rh|fI<6>ncNuC70Fz&dzdBr%&=oGYk0J#H!yo(C z6U_j=bPEd-$X0*d_Q}r^pXhYlz}Vz1VrRO%Xk~185aYLVM@ld3varsS!kNhNAkRII zI}HK81hdB2ZsE4LTlTL3ZkPe8&9mdg3ge3XBGVRJiux78t<0uOlVJfyX{Qe_!>?pP z)GK~IU@+q-nlt2WNHoItVaY_SQR~O|zpNfPQ`DHU{y?pKGI;iyM{8CkxyBb?@wG@H z!}vpy^%?LVwFwGulRp5ux!B5LBfh7(Q?#}r@c{~nm;QbZ*~UoS!&)ll;otQ~G@rf# zoK9+PGNA9H?)`kQ+z}h5S>coQMFzGz0{^EWSP<*qcSag1AJh)~m7;Iz>WqsEL)3dx zRC<PqQ&*&R>ZT_625*_wi&Ki*7l5wP{F=_K%DLE5UI&1=q|+yb2Yp(`S-)N>HsF38 z=6YMqYf&Y4v(|=i9L`R5uqH;y?4sV=Za~|S`9YC)95jgC-JaH@7MpT)+>RYRnoH$K z_C}r&dL+x|wJ>5_I>+7P(JfM%ATGcOV!r5fG6~OKt+r40DhGVT%Ct?~9dEMN2+=k* zp=N?gC)BaH;6Pg(%*inl&btYdenU1Zp=KMnJI=T*;_@}t`^<&Hz?B@pkd)4I7_!LP zbdm2ABs;oXbb6n-F~>)(@m`79AjXxV(>X2=#%5(@QNc8r2HN-WUa)SRfhMNFxWlF9 z{j`bFzm^Ot-%fo{rKP16b{NnAU1FEezr1}${oM#-j#N?@6soC-ZI@|~gwu`Ckm|_# zpBVj7`^m5AELX7wl>R^0N#Ng(lM3#PgEtt2tx1~SDW3g7Hqt%kNgVl+v=s>yo?Os* z$~7x^&HLhoJzmf8$u<;$9Ck`l2nr*po{Y%rMP{Y7AC)dm<H0$oi{yjyl#4x~CJYKd zgYPWT%ID|A+9Nr9UbnWykWyX7jc62w*?{dy+<3a8J!X4%iX-sh(H%hf`y<tbG#)&7 z*L5@n17IaN8!Ov+5E$QksDE~6?g9ftj{I7hZ=OzJwh|qREwXJgZ0ae?MNUb{yHvVr zyl@_;z<T^z9DAU&E?|;c`>R*LP+g?RHvwku7D6cjd$uQ8Dp365x!eL{pLwX-g}y{3 zK&D23YzdQB0Q9u!IUiXFKJ^~#4ct4l+?W>;f$nRxVER7qw6*-=G+p0jqjwveHN0kZ z=`gq_*Sm9(%d{q{$u@!5Aai2%r(3zSTe)gmlF0i~+j|H@d^XURZgMY`fZ#(mbz1-_ znOf3^F}2jKm~*ff<TBy#<HCC2Q>TXI7`pq85Fe1)8p5U)vXWIU96ff3mX+MQ1e&^! zHq)f?bM<o4N6K?MAU3aXDWxS!L3zq=Yxmoq8bNyy3K@KOvbV|91CLNOQAobhWuh;E zX=IcjIO#nxF|1QmD7@+n<p*?n@l<0E^dp@c$JTaWY}svfbLSliipaZPzn#cn;d!`6 zP%}>z>`RmW3vzE*r~7DNPdgF$<2r4qaFKG5vBi%DEx;Fn<oMBhnQV;7)zi!JnHUIW zsmlW@I`u4u$y*O%>27gWbmOu$n-E8yoo8-Uj{O=c%c>uK$9;bowtv_AgK;P7;YmeR zBGo06Z>&mlwn;rpCv8;cd2Q@32CKUcm)c?}69Kxo&i8p|5=0#5-yO7+Ko3ssRdXoc zQ0WH%Kc+ot`rD{%TNG>`6C2q&Lf8nzeEhifjE$K`R}0XEa&UU!-1M5E!aqJzu9Jf< zs;jH(BT5Oz!$T61mY#A<m^04(Vj42*&G!D}NAChg&Sk#IpSe876oEfb{fmhWj0`#a zRx+`O`u^f)fSyln=2td;v+d@Az_Z`W(0#PVh)*WJ)nV7XHgq?p_B`W6$6S266Obh? zi#kV8Y3j<yP7QHbmvufMOht0&K19BUwzDp&g>&=%Vqe9L%b`cXx|n@kxS4`AR69;K zQuK}gb?>z*GdnQrVP>!k*ScS*i`=-D_X@G&kJSK2M<q%`8iyS`&6Y+=2LyOvI0M-1 zh-YD%+Q1%ONK#{21S}D7v{)Tsjr8dRS6c>|L7x-N!(4o>uC644j9d_5$eG)i6fAtG z1duo(i?RC;yAlIs3aM3<QEEB6Xbdyt&bd^A$bpuzw&gVVHyDmX{z~ZUlM3HJ0Y{@V zK^R%q6%wSz$eK`Ssyse$tYb=1u8uV8sPM=f5?Sd*F<HfPN5ftOE802l-4KQZ*S{bh zgDFE=Iggde*LqWuERV>;3)eIf2mTCw-T|is-TCur`G%!jl6zftm~1=8cVpE@McXQl zzbb^yrRM7MY1I6yyV$8$DoXA+e+Me$4Z-{ZB<a5XwjM)IEIp=L&On-6=oo?ZM6ABI z>58|tCZP8CcY|Mk+TO^P{jx{pTy(w{!@BGcS8VbiMvULz7m`}Pzdkn$MiJVGLNkQL z$sAk}OZmzECCPcEx!j{Dn%mF>#2oqoP^L1aX^x;o_p3XrXpCgA*V|-qaAGOEBPc@w zFbEeOdSU>2j_p2wm|T~+^dTaReZF-^@SN0xMA)7ul5o8eu0FRI|Jd83nSbVjLLil6 zcq%V<Zj<vuvYwY7i;o46_Vg^u_UKz$#vx;-i2!pzn@CN2=0weK-Ztjg%c3rqQmQQl zSocgw{oRcY!>%{k*qD()&=%p>*r7<>=TLp^{jt)3ZnM^k?HcU;ju&+SInd{T!mtH< z<*CB26L@0Gg#Q-Ll>hwt!6>!l1}jg!oVc*kpoFnV=MMN>4fl;%Rcb0jMblH88;8TJ z>wyhUt?gPnYs8T;N7H)QfoKcde^Hm)hsVrg`ONtllhA&v#}95g^?w3t`+y7M7nt!C zYrU_!YcrBAXGn~Uq^H)4B?|{R3M;6!8IPUUB!+6aHOrA=t4gS2SyzsS%j|O@$$pFJ zI-PGVA)z2wo-EnX%Y9HOSwHgT$p8>!sSX?j!xo{fpmTrHHjPzOSWxBg=cXrtWfJp> zyRP6X=V1~h)FlqY{dvDV2E7&hB7}1AEp@3CUe!3eG7PSUF0aizkXp6C=jGsX-O^ri znT^H2kbpC!hBTiAhdGc9`sdCo;v=>>f2P3-ExanG1~X7eRClGK2Q6AY8H$%fOCdWe zaGPq30u)l$6p}WPnCkx6`A}juE!KHk8%+{q`(Yry)8QIwc-@(ru9aAfkeA$nLbJ@` zJ@_1HZr?v!kaLPyjyl-$c_^-OW74e-xUkTFqJze_evUg>dXC<mNSZWm$Ul2)&raZu zRhQ(m^qGxniGRDv#*0ca4pJ-d<-CAfJ@eh7zzRY-Dv;UoSJufBoc~qbzLM1l9XbHC zgyQhKhQT9$Ab|Y_1-i18jRQ3gYJ>>t0fL34!KzSsQV0^!M3W@(Bu%Uw9`V<8Rf3mU zff1cEc(iNR=EAUji;2ksB#Hlq(ie$pCxY?m(*SZpB9}oex)-~LMf}V&t&J*GkN~Kh zwBF>N59&Cnc&zLE`pnId>Rs1Ph%68}clP~Sgk3xuQygJ<3^tp8(D9>Y+HsoE3a2At zxq4oSZWI^Laf<>}1U@XQ<3Z^6%ltLW4?8nc#z&ReX&oP}Bpo*EI<_aC)Qhzi;Ow$Q zou`dN#z{&=vHH`S*1BnbnQPL`*I=Hx-}<BBzSAnlrZ(#ZsEh)_7$bdI)KKw{XV%3A zV~mHZ00QGNv+Q)*(cI$o);2ZZrk^@oMtNd^widFS?nuxFhgkq50uuJ^IHROzRLfh2 z7(0i=vVTE{aX2OPo%Q}6rPk3ilP8)oZr{9OW1M^o5=bgN$IAgbVAi-#1(>;X^B;&V z?zBfgf>{k;w|$^dD{Xw}<Vh*lv2781cU$Y_SDNQNp(+PZcK?UJ>vg|W*3oRU^sRJI zZvCNuE?2)Yh6<TkwNj94QcYi%_b#!;9u}G``Sj@~mtOv>ujlsOdEtA_q1r%A{2^J) ze*gZ`ez{d8;Kf4wqlWEEGY>^ySAf$aJ1>NbdoMj_94Lyl6w8Qe+!_#wQ;C<@y-b)W z)faZu(~sdsVl6;1W8l+d%5eQ4IBgQXUrMvxXVjO9?@g8aksPSZ?44cXtkaF)8BA+7 z2f^<s3H2ea8K=cn`czmKT}#;xj(mRR-m;TFUt!YjB$YJ>PLv3XDDK0H&^&Hy%-R7p z7Pj46)CYhZToJZ-S7a^4e(%H<wxh^<pfO7g8j#lH`nR^pF{P)W?_s3ek%|XV%jywl zxx^qUjzUO{Z=bAP>KU%D7bfMM1ccKjm)W7vq*}0EX$O(%<<a_D*OASzD7IG6JPJ|} zpvGfhSmaF5Em@#cUOIE5@p$<EZ~<JqZU7Qu`mP88Vx@P1!uYx&W&fF4;x;yCpR_RE zxjY6s>2LfzSDZrsIDPVDbdjqVvhQI3K;g*O`G|W<i_hTna)3AmDiGntG^^%R?ugZ* zisEe70lVf^6{C{*F3%{)ifY{1OcbBJbzCfCXepn!Yghl-_|>v_9!|0;9F<81-4u{# z#Z<WBa-hgg-4pfXfYcoGFrVAw<Kumc2Uk8nYsQejC5f>4j6C2qEs<v31(;9#EDF_; zW0qtj&UD4e`sw0eT8d4;ZU*SO#4OF>s_aYGcFwCMIYcrO<Yi&z$)(I#GvAKoa=_sR zvd^Ym>MlLBYA#DH_)su_Xx>@d_CQ$BFHo6zVBK}~rS|QyQv{pCU5UfWC_k_MLen5T z{NZ4%MAfx^Cmylz`R{u*msmasxctcS{&ExIPHJPEY29OFrKJ_!1<x_wrUZ$;v@<Pq zk?iV%<RtRuf{XqNc+2-j3%V?YAt}fbc(yH$kk8+G8qgZbm`ddi_S-%!_ucTOqNj4Z zpUTg(oRN&l?Y7*#BHc#3W&`lmpI1tl%zfVeEx12?l5MMABF(3WR<|)wijLRh{zD}W zrg{7i!TUziDYgIR2yXj-w0mlJ26RiJSQWiZfy@Q8wnzkOZO1mm=DHop#DhQ@EsD+? zbilCSLuGNhy1`0XcJoQH1AzSGSv0j$y`}#?&5axLRp50o<^JZK@%)$!>Df@1wZ0iB zSMVVjq5M^gle%o&V-GB_$R9$1m9OdATThTP31amSzsD3A@F2<78s@P<SaF{P`$P{B z;PYVn)urNWMr*YBWVl-wAq)%sVk2T&>!}qiYF6ye!zzhYdB2^(U*+D@TF+Eyb$YPC zgx?F*0}WIVgAan39wAV<?<*-gLEL9D7r|+}$=yD^zzGhqBA|hpJ+e18$w-Y!b2Pkx zz%zyLz26?usocw7={b5OOM9;HhEJDMJ2d0fmD=cK3MC#mHn$5if}ZCoIzKt+0lVJ0 zxqI~{*v7h8)!*Fk-!-4<az|eESijGdcc4+l)5drP2NXo_4%QV$RXpBUtv?IpviFI& zFs`cInEXFX20YAm3yWH@ZwBt(_fNeo&-QH7g4uHSEUgOq_tJGjhGIqseFk?|8mJ{d zIw)4Dt@vP-`6@Jl?M&yn_Z%qIj{0s{0|wW}8G0un-GtPS6X~tps~&&5{qcUt%Wyok zq%*V0bben}lAP_8^udZlE1-L5w73P=##HpY!=+U{&2y$bDdIc$Nxx!e$1{vQquCNr za2!aRJ48+3i!uZA6v7yXGNkw*!hcPV9G_1e2w3U*9w!)_Y){sCjrV<w2;7Dtd2ifj z+H<7qrOR$My*L_1^H!nBdAx$kf9s`YVY@b&3IPr>O8g(8e2CO~P3s&dV0c8zb)qhg zeRLwvan8(9qcIr(?i-N8Hu9Ml0EfYm`}8Ssm(X=rtjNw;wZn)1MyKoXB#0$0mq5c2 zwd6^qj{p2w8uACq5t}=?s!$uSBS3YA<MY+&Q8$eh4o(~)PIWit+Vx&{7)g(CV;0}I z>M<HHSF4OyNQa=t$|(J<YyI-0q}k4RyS{0AKnFB>il=y`o@4T~J0`a@3KL19{1*3& z9B#KC7^iM0<)6IBYbL<R_V%0Tfsk|Gki~GRzki-{f*!TSM=km=V3oT+f930SbFe(v zKB#rgAU7O&Y_MPUAd}bhFYV>AY8^2Pkq?LKNhIQmu+M}#mHsKSUuTds;VU?d${+zO zdE(7YQb?_{Qenjx#E*(=NLFbk>)8Ekx3?1~2xIrCwDwzeRf7k`h_<&HfDo<N7}&1( zu7{A3YSHn71o<ZtRD8r-ZAY)^WkCMd7cAAd=EF}s75{HP_JZdN@@oSy!3qd#-9o<Y zyq_l60kIbLt%;bWRB2?XAG=({BIZEYwePLVF@0C9da$=6<l03P;%QVhs`yg%EBIKW zU0dG_Iz3rR`u>HXIW==jhYUs3<K0bX)=xQVg!mS`@|5lSD*&gRO*a705h^oC{jW{s z0@7k(s%w^mfk{*^P8jhDzT<gvSh|t$7{R6-!wmq5o>PAL#G|cC=@l}g>=`TL3~>Sv z-ES*9I3P%Wp+V<ld7yJEkLAGZ{(D6G;6<n1f|~|cgV0~9RFhrO!AEhe&L{ocf{1Pt zKYFjIo=hzj6tqHpaMxs%GLkWYlF@{SpBn1)Hy%iuwm<rJ4fh*T8-e7ja4rD%I`v3u zwBE47DaSQ(%l(}jX5523+nK;9I7ntHbHQBKEq%ylC|&ezCIKQo=nd;H?DDZS_F0?> zo-q)6tsf^!v3=ORT%bQ%DQH%U>lTJ`qrh>_0D({H=s1FNt61K7?A=-JI5s4`a$-V8 zl%;C|9n<-|Jgk)`DPDLjDk}>qR^r=sZ%|H`x#W9#t>A9v+XcP+;T&df$DlfSdP6}g z;JicoW5H-;=j$r^f`sDbAiLihQGVWu#B^v^d)Vk^swA(kw<FZmX@S8w^fh3{DHV0m z9bueRRQ#>kQ2WmWNocm_e8Z+z?P0A;EHIGA)fH6Te)H=WH`*j+5n4n3@$<ckdwum* zTYpo!Q=A~DV~ol=Q3$B`+TcqiRoL4sBifo+12>K5emNx35QXDZN(}NTmB-hOrY9$_ zsfVkSJf6@S{9y(@IOle$p&R`hZa24*&UR`=oz{5caL2;e-y71lVuY75^hX?Dt9LjG zAlYeY9c7EMvIL+a|13aCpslIN`rDY_<FSx>ub9&esDfjq2Kfumq$H&f9*I$H_t?W# z1mave`uh>3!|At6n;8cji;wRZH9h4KKq{>A760C^_5IziDN|K;d<uJ<wN^k+A?E=u z8LIz&-}|k#*t=EMU(p^2`(ASFcyY-b$$OkUqU0iAh?}q!XcKHWnw%Ur&G|-B#jWJA z(Xal$l-*)($Eh&4G!~?ckbM5p5(q2WXZp2AKa#owB&n}aWq15g)HZ#MmNxRgI=`na zN{;W0+<k63>HeXp{KKH=CXx86d&n_Nw&MQ!t!7SMX@6IfMBy7l@#9$1e=b_EyntaT z(TJPg_wl#ZAMJ?9tYAq*n>9K(Sa=&tKkeu)oK%DWK71+L3`XllMe`=*Hd4!E?{v&< zM~$MhKOND_H0$LZtN+pB_pgv=o;+(O{R$2@qUG6X@#4&D`1nw##^uJw4h9spzxQzM z;8VkCh7<z!m&I#Z1rdg|`swv!|JXx^K0o`8UJc*AWEjb5A^U09FyOorhzYedJQ@68 z9=T=|@Sp@Cu>IRc`1xfz;_4Hu<>}2ZT1q+Xrs`#T`uPM6cg^qibRYlv=k*Vb@%h}f z?B^31WS!Cd?N5is9RELVQ;h4g%A$Y6cEA@&YGhaJ`0ewaoCxN;qp_6q&OkZ!p*>sY zAE<)Eb?n2jy+*55w}&kQqc>UpcfS?&-S>msD(21JOy4NP)(oL-?ljt;n+FR?dk38h z-1Lr*i;zA~gQh4Jrdx#?<^p@aE!0(3r7NEti+MhsUMxTG<tQy;3z2<bTTM6bcyxVH z?TPD;&LI%MNSV~salX<*;Y{zlJ73@2lb&;x?ZW9(sZZ(d+<Dz6@#@Kay7X74?$c>J z*45zD%1~aZSMYQFTjSpS(XD&m-?JsuBrLrgYs6~_l$Mru|L95<oBJVX>$y8|<i!hl zE^h8$jXxg#wh%v0{#u$wh>Gf0*H+&!wo$LHwI#bgGST*YTOgdaEB@kzV&;wWTWbh& zWDRqGe&w>{eYab`T|(AxCK978h7wSI&CrXju{OVX4#n1H{g-gSvim3Im-6?~CAMoi zgFl$p*F7Wi-gvzJ1G;km@pHvc&N}KY^YewxdX4dh%Tfk~wY7Pt=138Vi5HS4@aa)B ziwUW6=B#a7y^VJ&mv3%+zXG9C-5V+4byDM6^k@EYF=&IO89(iteOljz^SXc%)oF{? zRvsv?s~VQLmIRN2`)fHNCWfSKx=t4$A&1tvEra|Ihx1s#zdBFDj0M@(IeN|S68*y% z4@Utuf2WCQ4ziLOWS{~_0c4HWTmzzwBO$g<^8W9}B-=7gm|;)JPe!MY`m9{uspv&E zw6XMw4u>?feEI_Fh1XU6E-`Z=+hc}VhgoQT`v#K85}UVbMARkbob3CNL_36e*7V#C zJ72G;&G!fWY3d&C0-Q^lseEZWzi+d&4bN@_^3<DGQIU~IclXy_^_ZaQDrEH1S(GY! zWFjIiHTA+n0S1=&rNpN~R=<5LY=%X~q~yzVJ2$W*TwLN?B5}wDt&;Pov`AmoOvT}5 z%{GecZ|}LvdP`oay;>L@5Gne}r9_b^Ed9+I9dak&cl&vx(tB@*tNLUEKRS9IKTVu3 zwbs&!O3%K4V*l-utJ80^Ji7{11mtO#6S&)0da(<QL8=05RX2Wn;X6&x;^?SXErh4i zLZ0W~>=wO!+W=d1qRraxsmT8$zwuvh+q4omh`nCeM&@QcIfzvAD^VaaNzEGXOX7pt zV?~Qb%6H|QjVjB0?yDz8a;V!kx9g%2=H}-0FqYo??Vtbr=&Pjn)_y|oT!|FwswSeP z%Uny&p{%4^H2eKs$ErTIX=g3~znuKZ@Vsz9!5uWtI88yAN%HZ1V3qZMzH?8vQq4K~ zhNdK4TBpHvR#r@bKObSZRvj%ghc*1q4<jI?>bGRt)QHiR3Y)5Jt<5W|5owHK?kcY* zMhlE>bwRZ0eBk^1oc>H@w1~@CI>A^p7Y3=h#em9e&qz7thU9e<!%`bv*-plFB2mX$ zC#qP526u&X^k0|XuQnl|u}K*{{cACG4HvEpGO`4Eb$7{tOPR+`Q?%^tvI9^k%xXE= z-QB&<)gw?89ni?IU;f7*4kKb(|6G(OWj~{qA_A<^Z}f@|&W*sRsZWFXrm?A8BCZoE zXy_R{S-Qiap8Ps;{_=$j=`>8W4jVBAEp?eJbw$9Sx2GH&;WEvQ%B0*jlpZe4x)Jlu zq`_T&W0vPu=FO-eakV}?R24fno9q3z`sGtsGL&NnDoi<8KkB0y2ZD5;oj`rOb}v{N zE$*}Ufn9YX5<wU%Hy*8AxfN4DS-csV`rB!gd_`||#3*(i|6nAr&j>$Q5R0I$qp*XH zpg#)Nu<vl-c6l5+9|8l}Fva&I&M=AGZ9EXshyN{iZ`O(ibs%PD<{bK|$tFdiU-;e@ zB8=k;ysl6Q?};=D>NDF~!Raq(Weik%oH(=X{waosVjN7vGWhjaP&Q1xwplT(b}wgF zi?>vfnVC~e{jHP#Gb>Hxym9t}J18;|e|sZKEx|>^***@<rgR?-D-W^sVXF8I+)QUo z2t4EXay;?Cf93n=sBubQpAt05<{FmP1d{D5Anz}8n_`C%dLu85qxqi)2j5)9O)X+d z6UN5I{{0>Z6ES&GMK6MQ0EzE|;nKelzc-Ly4OFw3jL1yqbrO*0W2AdXh3p?&KkqW7 zvSH?8`E>sX$Q|gf38FOcqt^Cv9>+>~&VK^6UPqM^1Nk3;m=(u!o{lafNy29VgpX?6 zrd}%T?B;1@yasB7ej@3`OX-1JjAQ5mFdB0mFkChrAp2!{=Z<LTLae#pmtU_wfBg8- zsNAmrK&FpzGM!|;mM8HJgJmIzoP#{l^x|T!H$lRF4gIi1pw`Dl7u1YF1j*icyv7t% zceOc#f^-YWCW+ljPAp?}zS__UA((mkB3Je)x^_oWe7WE1)q(fsS>8_|akZ>iM(u9m z_g=hd@eDcF+==#ytZ}8<Gmmkl<K~iinQw=lRUi!N(8*|r4k8}>dH#0(e;UE}_cTn6 z+(@oOnOcGBs`j=vB<NV85gZ&@h@w^t1!DP&lQJp-%J265hp(3+u&j#VIbI1B;y%j( ziCgr1dMYxViJ8!UaCxIESt<{{7eha3vHk)_ug~;%e!%J~`I(ZUE{pbVZ4xAG@UM&E z**cF^A<>?atM5!qrvlk%@3LgyX;J`Y!js_unMQQHkXxcsESYauq!{&Rd-ZJTZKJ?3 z6JT>-r#bt}yzt&u2T^V32Ug3E+oWK#RxXOeqvMzIXc1!V6&2fsVI>6mt>(};8ON3% zDZrqXKlcwM5741_Ip?%;sIPrN&~{+@SvWU)s#0H0e->t&u;sOGy~lcdRC%SF+=2u| zbgET7TNhv9w|(o!V)x@(H`dYxFN)Kxga-GSTtjqGWo4y<lv0ao_b&ZEm-Msd!&h>+ zpFbbe@49G%eKozG!{hT}SVZ;LESp1pMP0@;rYdn*@C#1N_XhI~2lmoza!n;ZJ2j-3 zBZVDD<Ur#-;?0|x!!cG0BP0?jY-0o(=gRHY&gD({&qT*|X6hFhrDbQ|u=3l8;jt+a z_1p0BeO#4ghok2*(4f8<u2brD{OEvAX{M@9(S)*|EA2mTQPwZ^+BuY{^F%HPr(Nn- zoe0wR_jbm7`uMEOV&B1QacJT(0m$1>Z;0-+S|t((UQOP^<UTxIx&zGm!R&}8VTb8Q z)wQ*T0Y&f=!)^BA$ga0Te@i*lBM##!2fIa>wVCe`_ke($%8!ELA(IrnoeK1QPdM#} z;sQ*y+BcnFoSLCtrnEaUU5`Z+%B)S8YV8wwmA_><SL-|e7199G)q)9y<`g>98c*n{ zPQvbNT>KSUQv0x@qU<j|O%{<|*=R03Ag10l(&>yB=J($RnS7C*#Fns$TL}}NEFuw{ z*RS8r(<|Vg-6fNA9irzD85GoSsmaf569SX0(NF~{c-Zqz_$Z<(VCk#_)187R@izV4 zQoEtUo^saDRi)>eFXH1>iwtY^2&1UfdN9F*{oR&5p9vRkeeC=_j`|hjf3Ei-#pr7a zL@Bpl)+I5Gu!*_k(E<|_W;Xp@yu3N<VsV1DdT9n}WGM5P`m9V~TEY@KWBjK`*wDuQ z-G<-to<}+imU1}Tl!AN^SY+&<Y7L7n)!q~98ZLQQdRu1R?;YHv+;gDU+9X`nZYwaZ z{E^9LR+IR1-L+w@hMw2NTE!KxG@#ZAfLq~B2e)#$zhb2Fw;R3{%YP1);@iT_P;N3@ z;<v~tV>MzeKt1%@6U9ow_oO-vmnflO#%$+csqKoiDV%*f>$A}a=ZQL9I7}+JDpp@T z%A26vUilH%nHfu|*E)PyIBdZ@aEIs17WPy&Clt)BY6BAl^@C}cM9hM=k}7AWr>#}8 zJaI;r_}{Gd(7WVj8RFvkbj#*-oBkBiLKZ$;VJ<8*bf6L!hIK3w)g#pK<*k=?=TV;A zL8rsm#%4o(ya++a_23WHWC2wve-hH0dwF@;rXT2*{b2B3q{VXUq7F2ax#LtR5K}R3 zV*cbYZ@9}O?%fOe?&ks;gM(`s>vwAS>)mG@O0njyL!X_*Gj>I0OD&D-9_R3yHst?o zRk-#Ww(<Ryz_(W*FRrUCE35i%S6AkNb<xc?kq3+iv(Rt*E3|#Iq*)P-(AU?m-@a=K z9YtM_onc)U`^s%!TXCA@XAcv>-sv>(@^s)}FN@|Q*Ziy`DFK+<8|<pdG5KCF3hdtg zIzI9ChH@+y8#qmy4Xqkiwj8;&Up7TNW+f_bV!5?D!V?^adhYxdaDV?!y**~;<@mKJ zYpJazL7NR)Ch;pAXT4TG9Olw5%;%T-`KDp5u+peJ*Dud4&AJ&a6BLNa+tNzh$x=%h zgzXer&Z`WHu-RJ^D2WMdBcsUeUN1@W^4Ab|P5lVk8n68IqtpgBn4@hB`ys3pPH1lq zM%I6Bug{UoA!<Y~w|&>omLRXyN%nndRPJ=m)pg}|2l%alM4U~YDn7<$V}DP{ft33Y z2A-z!gWgr0L+{=_)#Te|E-rCDV!ER^C-0zP#ut$wnub}Qnsqa)eKdJDb@UptOHFMy zWoHPVrWmGClsw*9A$aveCi}rHHSk{|#)BAPm%75jLchGV1h-kyfP#kRZCF8&p3M|% z?9>~tndMKCMkz!@M9|Cp<|3}9JvwzdT!_ufB9hauH~U5;^ecR2W%XR{<3VbPH3sCI zx8VBo^yz*~9?aSr<N*~5P9Um57^^}=(K1W+?C)+x3)-qBd^-!YD?IiYu&+LXrniAg zP5EGFg6Iq&T+q>KUGKUcWzQ(?^qk)mj&2xm?~=NrywDKlo063k3@bfDG!PK{=bFm; zxy^4sL~2d$4M(>%>#C`#xqH9u3R6*gn@$i^?msLlDoPb!gR-y6;4av0WK>za4lgfn zdxB_q=b$a}?G-U}os)*fJ0MkkfPVV~wjHHDMV7#K>0arcxR$!#j*vsW0@kT~+{PuI z)#M=lTU~pgYXKWZl<+UAn$-XLk!_iQ6ZhwB7~g%_HW^OMmQb>|VUyf%S@mZ>1o`Wu znRVSMa15@Hh5Q}Ex33Ipo5fZ-|LbbhUl}6v>W@5`GN^ZmyL<O85Z<N<1m~4Uzr9L8 z=p4$T1w;iWuKo5GS#)XrZ=ZhX(7!H*{GL`nIdc6UT3Xc0Jd*v7aPtt&E4kl=k3Juc z_z!8T+gE=NMh+c1A@_SMedy<t`^4W|{-G;y0{-?T{?E<*pOyRPmiYhmo_kVg1VG%? zLrA$hI{&Y4blPF%kN_Hj?kI$A{%To3K*^{W;~{mfcE*2y^DDFjum4(ttM)MUEIm)Z zsExuYL&vH0ePZ&Ew_>U*BP0L1@v##)Gy;=js(tS`DH7agQrcaR>a|U4U=baDzl<p@ zbr^g+@%HTD*&B|BuKLDM>W#EByM!`#x9}Nr$pzM}uMQphR0O4Z`-7*=RQ`v<V1B07 zK_CDOB|ZkSHL<-TcwC?i5|TbRrs{H~%;f>RDE7Gzw|0LH(xRfmaT(Ff%TULccIh2> zdzLL664xw3%>tQp6{%HdA|~wn%b>cdYDi1~4{byGX)U3Vt~4yVd3y3d)P9#>%<doj zg5%q(2%N+2rYRcGPf^tr5i`RQ>k1E@Lw#RU<vYsl+T4*^ZRloU_itC}cy)TZG!Ji1 z3H<E%`x$zdJ(81*yP+NBf;$t9nAyxo6XAzgQ5S;5F7v8vLEG-O(NSf(o085epWgj7 zIXSsFynEWT&eISgQSF_qj$E(2S$FS>?ql6I^$Q(_*LB4Mrr*=Bh{25761U!?QNps~ z?i)6rK!kVnMk@#yvAMeP`3FaTeE#xfuH#m>7s2lx%%#cV>Xu5IWob|sIDg1mBM-Zm zMs3Aijj*bDw1%dt_piKLvIOoX*{#J1s50iK>3MsBRYmMOT|P6pHqDOs!~R-YIran% z^T&FBT00;?g9_qXck-;pLf^qA%}pen!}JH`IwxqE2SH^4KtoRTWfS<rc#Rjnf}Y3B zr3~dUO9Z@VVw2|dAuag_KivvUEAPO76YZak9Mg09ce}c}HfcI$?IgaKDTH3hJ92^+ zzdY{W9?$lMOd@dl`1ruLvW8=o>zzzWV1k4?tWQ6Pb%W5a^p1>f-^545nUV6VXDH;$ zOp=~*9Tc++F^{>Nc8~5GK81;!G-npZBGUe5Tq7Bb*ZWi7tR3uKp!@Nzn1Apw#4yal zEVr17ncrOPm6e*&zdnu|i--~M_wN{PHvF5C+|!xx1(NPMfR2VIEDpDM6K185S{2;P z?rz>Ok&%%R;qMabjw%pUpZ@%5ERG`QL!Y*-?%%sc&-}PFQ{Tg!ooh&V|I>oI&(FMg zF4+TBKQ?4CGqX*&mdPqsi~6|HQ4;!U)Yb`J-c9@m5dJN!ZshB!-so-BN*eJO_M84! zZF6M&(`T;GeGkI05^ee+-(NlK94?)sV`StC3X<^;eyZ~?M#kKC?@mzTopn2XAW#5^ zq+6KS06~U2m*RVOnf<*y>e`{FXJ&Hz_!=L~y-HTux_8%ecasT;u8fT>dD!7lx4Fx5 zI!qID3Q&*3`~Ggp$m?C5k8}VX(Kj%7FJRl1IH^F>_I=dlriFzC<9_F3s~YG$XDE4V zm|4~cHm2i<b%7hd==tj#XXoC+MX!~?FB2cX&}jAXc~cHhQURCPA;f_6HN*Y+f}(<B zQKkL3NiZ!7rer1$As_x#2T0g6-zTl+zMreK-w-)N@yqAmZ`$Vf4rSj@fL&)p5zyE2 z9NmH}a7gUBWC#p(<DsSX*&)w98cK+?T*QNE>Sd}R^NM5umINWHJkOl0X@Ya((VeJo z$!Fyi6zqF?B0ymz3VQOQZ3n6}?@1^|i`z-CE%nXZJVkptHeB8N_&hT6)vG^E{e?yf z^78TwQ|Awk1ebY_D_Hpvv#%|<Q=~Uk<h>Tg^rl+WBM^|}+#{I<ezB8)t1oP(IbwJV zdD~-z9qaJ!7pT@=t8VOoT}F+R`xo84%WSv$E`p5e`tc3-*F9_Nbf|5!>g!`YeVwuf zV56NvZEK*TnmB3=O<l&eDamDf3Qc77C0{!ALhd-h1WcSsViIZ7*cIW(^tO-vK8^9r zux_EronxozdMcbHs0RNBMarV-27!ZZcMgD`*P)@%(KWmjpLKlKFZCSiBHxbj?j}o_ z0~3Uw4!DZwh_Px|XRnoEbuCZJxjGpewjrb^X;Jvh70J6>%fWI*-NT0U{$85ZB^km_ z+m}Ez<*Px3%lM%@OVyhf`ONx4QvxFpJG;9J^*)TlVyOcj(A4X-G&XvFHagw4k)beN zIGGB!kea^Px9k;LH7H?TV!)kp0U`idz~XpmDPU0tCO`nAc7K*TjccNb-DFj9&+Tlg zsEdQ!a8o{|vv>QXHXD*f*x%e#yt3Rw4!JQp=Bp5FmY~-e&6h$zpV2PO4`K4zpiRiW zA8}XYjfAjDvbc7??T;8lz1E8Snah2+!nH(c4?WNjfX;g8W<7F($Zxj0AAXFyrkPI| ztw`mMKMLi5g~$q1ueH91JKNUSaP3w$@@<;Pwsbvb@r9nrG<13css>-sQj{fM)#eVb zVr|n$zx-<vdf!S7%e&rt1cMd9kjhr3kLa#Mu`HkkG9)!=5#`BT-MZBLO&B%nWOXpF zd9P3Ph!}qkiaQ<aA-Lq)G00?8>Rpdmh>kS}VZQDm&wbzkY9*-G-bZsq@nx+v?ix*) zF<7M&i6w*_)L#a9z%d1hh<ad7av|ey`_?p2HXUIfZ^E#|%(sNm`D$CP9IMy~bgH5T z^7PxlP-~$!!o|q+wAKUNTAFdXbL+AP(1db3P^G3pR?L~qZCdTF3mal_s3B}v)hZ@E zw&6?J{EGidl0u(EnCI*dv9!O${Fm#RILHbL3JhMRoPH9ylKNs88ByWg2<{z=zVI4f z!P{y<RRyN?-sATH!2{>ff&CKxH;19$vgmE^CG-7T3yMs)9~;QOxiF~Ahw1fS5sIm; zO>i0eOE1!<03L3oT`t@@!hb)<^u%zfPh+pGLGjmq#;x)1a;|p3e7nC=hr4_28Z81@ z8Wf+em62RxZ-R_K5A~N0wcaHd3G3Ya;D^RRTa=7~AurOLh;nzmp|0+nHE_FiqK+Zo z?R=&kEOa|sj2d*9v7oja+-Hf=2rvAEepYv)Zd~61*>@I^C&QOk1@N@=il_n5#06%( zmbY`_g9hZ-Bir)diadT`z7x%D5q>N3At^qn%xe@Rb)Zcx%(03^1f>p+tRDb&su>;_ zmFcY1j~YN|!g%XZ)q!DSn}Onrndy}SasU;0tidQc^i4Zse6Nv5uz-lt(bIQz&Lc0J zJ^K;FSnQi#@}SduS%b5Ih~xd1iv&=GSqgOJsa(8iBnP;Y77Pw3d)NVTkEP~lof2y| z(lTb)%;FDDy;M1Vuf^36cFA^O5P;#RAN*j3c2!f!6Zrxzw#>g<8WdPW&HMXj+S4DK zwh`0=wr{DhD!j#nL}rEgx(WxHx&p_RO<CXW`zOtoJ?!O%_+M4|5A!xXmB_{y;gmNI z+g3mmTks@IqiZ+Edd{``W9Osi{eS+n;4!KjTO<kjQh3s=HoAR-7&eMbY5QP&D)H{P z5k1al@+(`pGp>_6LJn<Iv7F5r*$@qk1_Y>f8jaUf=)YLsM5W8BNNRm;lEu}aT8D}b zD9MkuU&<*lNo*F4NZ0&}&KQQ05#<}rxXc^!8SB^L)8}gyxX0rX2T<`BU=*>)!ScZ5 zc_1hc{{j+Qj9v$Qr_jdS{2M_Tl|9YK!0ndYZf`^*rTBCHr1WlVwY!IpHuz@th5d>> zHD+^jOZ->^DptgGm=~FA%<<XgqMcT4zOST<q8bt4E&+4^8&vv)7Y8$vdgE+pA<z_7 zIAL1i`9j)>oJ=)5h|w0YxC0@xn;;uCZmGgY-P^S^QlSZaaCGN%W|<0kkZB==F|S*Z za2M*Knu&Sfe$%z{sGvmYj_ukz`?0#UdS~*m47+1%$OQVeWC?-S5dG#TS4z8e5kPXF z@6)w?-FyShsWG$ic0n!xtfaoGluRe~Yi$^O+8hfFB@h=%6-KZ7Z#s$8KMsW9?ySAK zuX&I7Z7vqAw7h*Zbhh59Io`R_3kB}S_pc!(ob-4(><MaI0uQRp2X|OE*I;78A|nUd zGIA+TKDIPppvscy#0Pl$-Bu7lPZQrD`_|5Lgdxm1$-S7Q+Q7_^^DXJ4mvaYQhw?vv zo<gUK;_Ti%NOkpFysYx(paD1A)jw9f5hjupuD<E%=0T1xr_56u0aN*^JeO9H@c}Ll zB-UnIOs-dp&-q%Ju|b<3dns#M%6x;p$~3p*U5&88OPuwamlMTN3M{CxuJ_XJLK=#1 zk2`EqW^+e2y6v%r^(~Ge<5!te2J)Z5<neF!qoPw;aHDzMhr*boxWBY^7MYZH<*Qq* z_0icU&nNVO%V-UMk<Lz5kdw3fmA=qId~#5)UC&)vN$m43A&G5HHU&FiG9wKeNktw9 z1Jr*`dmZs47`@Ysy<s+1ynC4msnK)B3qRbQ?caKd(xhWr%bc!0TBZTx_jD>$IO%S@ zml>C=*qtv93KPh9T%4+a8iMi;^unVdyLh1}H@}%wTjMcT=to?nrZ;f~R>b#iHQ?iz zM#{bCYuZ15VGT{U;S}eOMBvgx0Be2ncN45Qa&df483l@WAPnx%`dte<hMRNzF?7;q z14?Ll;YMYc^pm*xiT!^GJFmY*z>$1eY7JHQ*c~;rBt?z5Vb!>9Z^r~uJU+$;4Iz*# zs^Au2vRLSb?r=#)ff7+wEyxn;xPDtZeM{^tNNU9VLi+IsZo||Qw5#ju10VQg)CW}` zSJ;3*aNjkK<uQMV0H`XpxnpK>xzJ2XLc+8DP|h>rvK)*D`r;(sAaO(;?o2PmQ$T!u zG>}|;oOa2vZlVI^Q(ax1<I$>)X)txH<=A-%35!zs#W0FM4V=&mY2l*`9Nz&41wtuB zoF@1TOB!`Vx-oWhaiZW^vvod`g!kp$QmR>)sjC(kqtY$q-`q!2#c#n#(ii5kVqkpK zrEvaim=M6&u=yHcPYxZnxp?wdBxCDNl)VfCo*GQ54#r(sD9A@T^YV82H7u64c>cY& zqeb|tqqQ@;%3s@5fh-+#AnFO$Pr&%7siH?8pXO>b<k#O-xd>5P+9s3V{MgRC;_&AD zgr=EU@+q2z4E0fO48V`SP_Ap1@-s6t_A2`MtDd>72_}Hx@++)^YH}gS{EvvGa&*5u zV>~e1&)ZU6KhfcZX>h(dMdEANQyTSI(%N!i8mKo8_Uttr%vI%>x<Y(x>uOZIIrdk2 z3|QD=Pfk|)JXtnN@uXPo){_2;wE5y>nqs3=NdCCD;tk^~s*u=XRyLShh_vT}%B+Mo z&z@WV%-yyHkxQOx-mG`%pPT4`Kz`1edPZ#u+>%S^cF?rl2WpGZ3EI2b!g|Klo;$DU zc?@0lE=u%1fZV%f?|sC9Wsh0-&0DKgy)>I!Tm3M~`O1OYN;rr88KyB@J}P8d%;(^# z+qEAZ9oi|RMf7)xKIZ-Dg?mev_v`B<!wwoDJ2HY1Oq!eIZEO8;@wX&IGpphe%tG(^ zbJT2OlaQ*&JOM3JWFk}gr%$VoamEM52Tdgp_q6#mPUnY6u^NG|b(_e8o?TPL%gQ$y z$_Ztj!%C$b&svzHEFmkkd8UEb>K$XiKwgANedwRIY?^O(wzP&wwUTYD73L$#k(!Tu zJdttg%o)rtwxG*|mqXZdLHh*S(u$XF-n{YKT1*X0+3LAmgw==W>k>*3gp9OT47{>Z z0uOXyIIYg(s;QWIXdw|gUVAdzP!-6z7IUxqg1>*iafU%e336*zq{DD(Tzk}8={X-l zuRhEWs<3^WbDfJzX)5TwL(KGOxrYQMmoDk^#VY~I1=0)YF#g~Y_R%HTlM8Wh2glFs zjlEBnwyFS<aYFjmNUiF-b4Y@E9YiFc+G>T^8HCtXMvcjq*c7n4kDy{H;$GWwQvRM= z<Kl-G7ITEwkZM8rMPZ8F&!1FbT-{{;McGD5wFWLcCDHHBR|_dkR&wB2s(oGf9UP25 zZ`gN9O`nf|aYBp^Zeka0ZRt4oaP!d+y4;6UYA{Z4P6v)8K(DWM`M*uMZ69;LFHeyJ zm@dZXbZ$d|JjJ5<*6(}<RdTpc#u)Z+zk7W=#trQ^F0tiIIu^~p39O&~^(z&i6*x;Q z(CIn-fqf+W9hf+h*OVkVHa;!{LBDX2Q0|ujdzp;gDW~D}XvPDQ0kRJqE)mmn*xlPZ zCLtkVmd_v`scrMUvs0Bt#J{^MB9p0|v7=${mmmZkCTGt^<eF31g11qdE2G+w-V38y zEq%xU#%QD|(D+&^)_r;*;j^3z5phfQ32ly`EG4=Q{ID%oE}Y4p5Uh<<tQ6X7H|T@i zOx5A~`|oLUpt1m8Xyfqru3z)pFPnHS*W4gWnz@+5X*~Fxh4N-PuJKWbf~0ux{a&WU zdVg;y8kf4yu48&E(%6uY7Hal@@Mm9jl8H$bg@->eVKQ4SSv*aB)JOaN_ak)QQ`EKD zgR&&6JwRnqlB$#odafA_`@we8ukO&Km_(T{_>O9i-Xxg~EDGaEkPnRn{d@=WDk3cw zvElg9tlE3hOo#1RIrlBmo}eKJVHE`3Njp<VVW@<;{3$xE?(T*jz%?*w`a!7OPJJ4g zKe}^u@u97pkfZ;aX_;rIDs;W!8;Ftfm*NNKMaFe&FEJ^gxhekTy)P;M7gui`6?GeR z4Pzi8Ad1o@(k&oeD$*d`%}93+jiP|Gbc1v^(l7!7(%mpa58a*bHTUzp@A}sF2WzPa z4D-9LbN1P1pM4g9byU5h|3~=O?|)l}?T6yiXK&W5vkd^ijeePW&V7aK?ulWH2L43_ z2cmM^c)`K=teF|WV#3L^i}?L5kZxEaDgr^Zn-79!l8{3&YN(*e-O&mhO4PjJB`#6n za|3Tijmf(Btu!_b3E-TQ10sLH^{B~+^G9nd$e{V_*RS6?I39<+1}|@OveqnsSdW>y zCKXlRUN_s{vZJ`5(_O(|b}cupQmQA1hpKli!lNCd*xNfmPqjIgQ>zrurU4Aqu3W!Y zn)DZDier(Q45Q%ra;LmEmq!9H={82@FB6{cVOB|ocDaIsFwDye=1xTDf%iZvfEzmk z$8QEKfT!H#cZaOi<aWthAo0oZJXYC4{pJ86ZEijP2Go18bhFWT?9G~z)Ge1IaHDK2 zB_*XxkFi=*yrU`5i9fZRIMzcYVVB*@#Beek)h@Q?u&vJue*63OIHV$-Q>N0Fmg|It zXNOpqzq)5hc)UX6SoAUgn`1fK(%3>FGGy-gU_+}SQ+y1B4{uSQO7PaM1BhLq){FbX zJ6(A8A!BUJ?O$-nNmf%{3LB1sM6Cf9!X3lX^9uC>cN<)VrNH2}8nAO3&%D5}XeKV8 zE4V4y;<Z)>2D~)l^cOx{mia<LLMw|K8Cq4y^>~B3pE`8BF6IaU*7m?uVWpBiu;H`g zieWFA_gff@%cSS?9C|DfE^dTdbReY9p#0-K?yNnwLZ#-yP1t4Bf%dz8%Orsd!Tw}Q zVaL|Xuw<|!3tvElOe&mAL;?bKUdwY^39*|Y*FUEND(aUXI@bC~)>9uzsaK&28_Eh6 zi%oZoEJC{aPv`1ngTcF0qE-9;9&ked4LuY9KS<sHAq4eQUjY5xApFLod9esngy%^5 zgBC;!mHt3|b^5ej?sR+l?M7h5Obev;{)33Eo^h+glM^M7oYg?J7;vs%T;VeNbafyW zDD79rBq>|$ob}IvTMA_!%JQF!M*6N8Q4B@6k1h#Z-`uS1?ZumN&}+nhvKa>>c>IF= zMSyJxg5B$m0{q?b-0tFH2FZ94384nuT+^T<n1DmVpYDLwf{(X7vcv!;J*ZmB02pMD zgWkJ4BBNgF#Y0_Pc?7}~QU#WWkO5!`{A?NlKuBPeAajuL;z(=P%1wE-KUoJhm<aTr z@n_vWb8qnCVthEHXUZKy06)S?NJ!|iH8MbCk*8j=d1-q5hV|MCnDh>&-E1sLKj{|t zoUa5$HJC2MUD;UZp05C#(B~QMIJKwKNoH!TN(lNzf9+ruxon;X?anur<)txM%n99j zv}=rm-BExP5C?txp2X3~0j189vtVus?`E^J@J^g9oJ|-DA)#4`X1zM-)C$<|+ovd{ z8b2H>&i#@!KEi1&T?6v9gNw`fm^7lBCc3G)Id-;f0Y$Jd3cdbdo5;z(a$p%2I^pVZ z5=*F7W6fyNn>1d>rdMF>egmv$QApTmaS>=OBOFSeV>-FIPJFo?&I%Od=P#H!QVWf| z?uj{_WUtEI&|H9>Vsnh6Bbsss$VItxfoF+@(9@<5{*FofHyF#ggwh^FmqY(mSOTBG zOFir!=+~2WIUKV9>L3+xqW;_Qgxp!T(gy|I@cEwPMzS6KIv}65Z_hUAfjqIT*e4p$ z%+%1Xjt+5v;MGB%eS(D*olU=+5)``gjm{1XR;~MRAjtSx*dPT1=4CwZWoUCm9aal} zGpXhq9{ZwW<;!nHgnAW!@PA^y78(S`W*fltDj3+}P8Id#fPbGlMqNfLO1=30#8D05 z2A4OF6xQbsRNOs1w}vvP1so1zz@%}Z*Ts7KAVb<U#p>IkJm@6f5m4-*97N<2Il)SV zLj}2x-l%{7q@=@BA141q7KxCW>2L3q$ywad&<D)w0Bfp~{l)gTq>OJb8=*4JFaNGk zP=mpo5#FqT4y`~?i5C@Zy>OD0afC5TvRfJZN=^Xzl^p2ykDTOV0PY=ykWn8zH+s3N zc60jr1!tN11!lK(eF;0K%vv8n2sg?5m+9~C-`n5cureg%?wEH0B?fA~A3vmuAPT|4 zo~K*sC&@I@@}h2%?j>^1P~U%d*H&7;#WW1L+!ylW$4|hg>+0$rJJ)l1H0Tl+8OsbR zJF;YV)bk4o=>mdEUGE{NhJbsLTT<9db6~f!zbFPO3I4H;WB|dyJaw+t>&E6Sv<Sor zh3A!lM@6_Av@ThW4!kJ(B5WDig8H3P<06k=tOHdbt1zjSe{r}4f=gfKpo*H7C`J{! zK!BhvnQ3anqm;4kv<rdL*+0+)m~W_7I2n`;GL=WDRpss_^@mK0{=Q#Wr2g*YWtm{f zWvcP!^ZulkqBDe*b)Vfx^>2>0t(YK0VPBRcO{d5s@|<SdUdRZ+m9R!>N>37Zi2RJO zh0CXbIPM~$Ibmz{fo$Y0T5`2F<^1=Ugq0X43$;_a$!{1LV3Z1siH}G`yZnVvvtHpu z^(r^><bL|89^vpwnw-XUB<{0*oYv-@j1_cuF1E3;u>+xM*<~9d@+E->Q0$FjV>lr% z8MF8If4KRIrC0A*jxpBQ=*O<}^RUk1PE@+gGBR2_V0TE_@+T?I4~)E6HwNNbHCTTl zJ>WdQeA)EaotDA$8Hhd?tN_zO%1k=BG1E;`H>BuTYZ|S7jO<&Zg%re9WxcViC1H0g zTx-6fKEbysXYn)zJ9(5_?YVctIIL@Ro@<H09-VChkWJx^5PUTddsVo7bjEG~=r_+Y zAF0`~3$amPl$~s9YinEG+{^^i#^%6AQ@upAq=uE>#hIO5A;hIIVFzsfttrG^ge4T0 zQ3nPF%F4{%gIEv4D_rX1<6Q7`I?^T(dY?bX(8(v3mIoR!X&3*12h#_Qf?EqH#~O=N zj*_Vc*4u$uI}%=A&C3*^AhlfhBEoakG!{p)v(Ytpui}bC$9t}C^Th0XQ#5_#a_!Td z?Ue#95<a)@GzD#=CgY77@j$TZdz-m-Tk#Gcdmaj2{a2s^brnC>%RVl@|9T5hY{y$E zqO{_o1iQZ<okUe{Tj6YOfEAOU4o^exj0$V^rfi%iy3WhRb(Z&n@zd1HC{pos2fL&5 zPGAPUlfb3BpMqNXcB9gAev>)`$}CFZDN}m{;0y`>r6;6b`b7)Ju4U*TAkaboZe5TZ zVL3Lm1d&v^y!pK~1T?IH>+pHc&L)7Q5_d*(<>5--F4^gcATp^!E)uZY(?Aq>62g-T zrs%H(WYdXEGa*1V^c`E2T&{jVd%^(lf7qo*IgqHJ9G7k8TU1DStRsP!3yLyTD-tQv z(DxbUt2Y2WE6{G7{9mp!dmWMuhPy4t58G+xEgH=Bd~Obq1_B;$hw}SYKyJ;E5zVP3 zg=K)4WL5F4UA@aa6v*E;j&8rvN(0MP-nF~KSxW8SYm^WV@Zg!0gl+>|L2Cqn{!ADF zJ68)cW%~A^Z(%k-7M0*bIf|rsB8IyrZe(xWp|!R4?O6mm7@;pil_x@(1@CUXJPtZ$ zEEQq;O;<ept3AuN=SS=}zxf*4bEFpi0MPpKFy0r0o*e;a4Y!Zr*@B!#Ab4DSq1Opd zt4a4N200AX?YX(_@*)>LMKx{yfua_eVvm5wJe+LT6lY%9Op6>aP=v7ukc^Vg)C5C6 zm!JqU$+Fwv(BLSV-<NfX`uRG&Zq4Gor>K9)3k;+SB~3M?6*bk8PU75{b?fz;h3=XI zFs|KvNtw#;IlxB;4C_h>Hz$;rc@1Ru+29G4vQdw4*0aEHepjQlF~Gy%RXt+WtW%{| zNL9DrM=6{NLEs14v1;JV6}w=EP@j##1MkT3Y>K;fy=BP(X&58Bi1n#YQ+H{1!QEf| zn(z}pAesFiEdXfTk?>>#-z7u=AnBrMn$K*P-4LYd07ar~zqPAOn=8t|?oH4rW6GB! z_H9;&>1R@R2Kf710rNNQX4mF{6cMYG5TFex0zBNtNkCblW6qO<IHdvy-MqixaBv?X z4QRWIg^2mgzjKNf-qrC5ZXpw+@pKhrBK*6wRCc>W)GaYoC+Tgp*QY9cxdAB)gv(`0 zc`Pb327|&HTC6&6<wwL1fz`alz~0eso7qoQHb6)k4A`rW7l*4sD(T(8ge$6MG78A| z&Eb9>K>M8v#))aACA`<?p(F*y{&}o%t8u4dGCl?e(>31lYyAe<sAWfU7g!RytLbb- zfZ;CGzBgVX^Cg^rz}xA3{mKqD0czAsn*kw!Z#vJtfv)wVNpGC;Rvabm*8RTR{@J%@ zXBPnUlq>P5GZ=hA-HV8%=J@QolIh#7hzQUPvV!}GYuDKqC`|_Q4<t98xn>eBEpfT6 zOOg9J_q}yHq2<0=n12|Li!D@|(cVQgdJxObIPIzv%UWX`0{Nqk)Y3^6RbH-*dZsg` zLFPVd;}AO4meZ?I?RCLK&QFm44I_f+svbN)kCXBE<FzfE(8xUFsv7pst!=adfE^VP znSLSvrK)By8{G2o>TbbKt8RWft-|(>YWH-{(n`2*twWSx#2Kib5O<p9>d1V}MT=P9 zhT=5v$&Tb2m8I?Jqf47zp`E$<E(S3ta0XCb?H7{rG4u+yS-LSaP~5YJ5w&BsWjckU zEIKX9ptu;_1u9+0AtNlxaxOnZ-=pGFCEJ_qYS^GPxq5XV@SM8l(>alzYQV88^2yEy zjmfd}quY^iJ<n>ZN&PCsexn_)au~^A7pbRZoKuZCrFK-*ZF?7NuTU**{Lbe_&uMLd z%Lhfsj1E!VELT^M{Vw~bZqw0KqWk+()h(~2vU9T|SY~oS2ScsjS@ub=l#3t}88SXB z<%W&NREm?YfM<SrGzhD<xnj#=31KWUusbi@Y}Vy%J)z0-ZHwyaRW~y;yWxY>-0D}% zSSNRek`#hxIn8o9w)vnANEz1Hb@B4#DHN+3;FfcWKp-MjE^liUcd8_p%9|^{wz<g^ z-TnEx6I^3k8tZJeD=O}ptce;*ylCyNpP%RXCz3?kRq_T&x^iJKgNB<_KIJ<JY|nA( z=n(~?#<2B`#YDqIyIvkO<KhiTsezODsoqYgyu8fpQ4{xU8p$M1TYLNO-Sn_as{==J zQJ<0X9YR2G3<{|z?X?``UdzNuo!H2R$DBq?IX0?fg<EqbR$HBkfFO2%N7VjbF<Gfr zRg%)3=k>J>j?QnWwHi_`M5KR=p~~i9UQ4A$_(WA2%s25$E4NST2Su-26$wCOKv@Zt z5d^5_)72T}NQZ2E7{VQVUJZOi=9w+od>z|XkSh{uJkRcMano6)$~A>!jt~U31U<&V z;ofqq`U`Z+YYH&)kr-ki5Ov$AWYcdb20oLPtp>8=c~FfIXcdqMaf%?vHn=c-^tVll z)GM5Q4X%OFiKT<5@nG+UmHUr#A|N|ZDN+z1#@{9a)@ma`FY?~{wi*L9!7qKU3|GI3 zJZHfh83L3pJ#-K_f>`-USJ&FkPh6vigl%+5;#Z$ug)pK~5_+b0s?u0*0KquWCJCZ0 z_tMtauU+^=Zn{8rG!|;{LN)Va#Y^u2e=Nc<n|jBSq}<!{D%b5Pn<fg-GG*2%8SPQq zs)p{}!yy}zBxKi92Mxt#YiJ+G;TfWc+h&t*bufN%$t(bLQ@*@6KsE8eZw*TC$x;l| zUkbr33!~tt`Gk?p8h$j@*4EBa$`1JWX&%6T)77PMK<J5}JDvJnH9L){L&~bxqMX%2 zL1rg5NMI6HqIpH$ak?C;mBe{MA5w<WjR2S4;o@nhx1SY7tGd!Vr9Rak){W$(kK}U< z6Sh8h5K$y{#nYKp!!iw=Tb`1OSjxpS*xoi)cI<JUo~8&w-yf~9k4$E@aOu#|tb9eW z=Rg>Qk{N+Qvi!5b7?W=Pufx@TNN9tAWglPvjZJPxK<nS`Q5QfKXRkjUWExCN_cYdz z26XNBy|s{LYt_#&9VR?B@LUiIw7ghz$r1&2=y52fc;Sb42bIh@K`mgpiSp!bIw^Sw z2TBV8?A}mxP_En!BYb%@4tR;<eh>qs)g9le#`a+*2slfjL$7H|Zli}P1E1cU33exP zZLF5i*i1Kw={5RNnBD%~dXKVZQZLrc0{V76P=w&`LDnZhFRDz!3vzHx3TW2exUvxx zGE-lkJh?ENXK|gIy{!9G0P?T)HJdR>sI*ak#j|#TRiAALZJymza(<G00@h_ZX4D@5 zMGeM39KCs6Kl&-CCxEU&XIH~3GS68Q(2Zj?D8O8nNRGvP&ug2@Hw*=KtU$sQ!sh~; zI>}&%oy$Ruy}^Ei#CXby+ZGBa*lq@<!)CUxUka8ccm%*;>A7-b$txlH5h30wh!!VF zKsfzS;YkBR1<;ZnkIG>_29zTzvC=ibfipq@XvjIN?TOk;p`0^Ez^D5Y%9eJ%fcft( z5s^}i`Jp;Ym1@UvfhrSYN~9g^B;fLRH);EC(o#o=W%mevRQ5u0D`1!eF-sw<g)S1h zCNfuD1=QMAJ2ebC)*UmDca`(*6B9^Wom+K0<B-c>YP&|(@aH;UDkC1y^5zF*&zyFX zE=JiwaUIBK^Tg`%!!80=26SxFGBfK^3Ky~Eg@f5*f=5c1(H`*NvZsWN{er%?#@_He zPe17fT#E0TAz#~BCiqe2k-$>Ka^h|+UuzUPUca2D9%ji2@;?c$k4(x1xG)=MqJ);? zNxsMPQ_rQfHMD<ELei^BK|>iRPB^Y^0p{d1HIPr|&=C!#OwFdZ)*MC9Pv;7!s3TXV ztf%RXws@L;-$-?X*2g<xPu~o%ai;6a9WXGzlnii{KnH%QN%VIQzfLvoa`gY?8647D z^F;&M{<wM&r-UGS@1QF!uXU>NmsPSn@WY4&;rTjp34HxaKb(P34~56G2A(NaC3Vmk zSosz)8rhJ8V7JjlT*d98Jy!>bAAdpjY4m(gqSF(b9+h3DOtye7iu<&YGW2sb5de=r zYtMX5f>@0e!bHA+epV4+rwJgzj4yzJP$_7`EZaoS%6zzDa7~2*kVwLFjI}deg>Vx- z<;hjMYMt0o(y0cSg``Un+iIX<;+U8sL=C>yvyp7;OCLT4d)`iQ@-O@J1zl{(jH<Me zjpzr*QrKVp)7zV8A-&nF?(i9#+7p*=z?!vCC!)n+DKc|#5WJ=#KYv*;>StHrIeCg% z^VP;hn3-eZIO1=4hwE%ZI2llwef=hhQUE&WhfJ5Akn(Ib+65$g*G`m+d(v}nrWDNQ zS!{96sv}alO=b_4>BA-u*DlI%>9{vT87*F9|E;F<ofxC^<w+*If{NH&4gv{EXva;A z`c05UteKg#r9oh=3x%=eTIwsC$Y7fX2yfBuCE$K@-=-^k-V%`!xErWh`Zw1fEU^BE zK(G&B3Yn&XT<S+iI*<<g1#D4C@M}R`r(KNg1-C2r^Ru1eIhO>irt01J9h-8;q%;ZS zCZN9)0r1iC%b5uu-&m%&c<>EU8b^%xR6v!1X{Y)ml!S|Ipyul83PlZ>B8&iG|9fvt z1vCeKUvf$Ma>1nz0ofc{6@j8?4_@RJLh|%Yq4UB%p}L?8YzIp=Kj8WxCU#<RW$VDU z349iX20T#bJwnH2Xh#s*x2EHnB02!(FHx6ID;?;~s$A%t3Fp9j!?VSAcm_6f;0>Vm zP8{VKEa?SiflB8*+?YkXN$AsZGoaH^9E`)n$?C7gnM#*HoSFqulinCkK?1OH>*vBD zNK)LlJ{uhZ4s5p5m(Y5z4$G<@bs$e&ej9uSgt|cHL0^}4e!Mw7eSWo+)0=c;{%~Rn zr70B;i6<R3INr+XOH_%YiF*mYQ&@EV@^Z8ueouVJQ8F>8gF)xmsIbHFblaWV>Q*`> zz#34}OEFXiPf1EGM$NQzBbsXp4DP5TR)sHZh3@!}V73%#-U}ggEO7uvF(@@3$TG~* zz;{=sQesM{(e_)%BR!zJF}>QHIeFzhm08lkx%f9oW%FbjtqKbVJg1Xwu2|I!Fa9d; zHz4K9R}9s;(r~zxboKsCI4S}G6eSW{5GWQVu-4k`;`6!AZa6vLdu_M)0ev}T5Xdep z{=^$FE)6qmMkMoitEbQ)0F9mK;`9BxkYXNNGg!dX@o-r>805V|@2)gc@`SikB(V3b zHc7S_)HuMzbpHiU_qK4Q`U?s`@HVIbbymXodsJ$jG&3NHD6W(!gFgtZ9PXlT?7)%} z3kVzW$BG9PJrGm$v8ABIIw%@gXAQj5B%IFKnVCzj0ePLLzM$S7E+9I(5z&uN=k<+L zFVQ#K*ug|K06GyM_z`EBY2y(S=XA*4@#G@Bvc67lP1rWF_7LclpA!AFhNj7f9R-&7 zFk@DTdv`?E&J%R~U@g|HmjH4M0wftKEKTn*0Av9cr^T+z|C0Xgdq?Fx0sVPU5A3O> zj)eiOYpHk#8)h!v;gSwM-?Rrk4qibY6gnHw6Ah`QzCuYLCNn%!1Ojtf@_<T3EVaRl zz>H=fJBj1S*CEP_vP|+J212=(!rKMj=HJydoz*Pj-DzD#V<3CA0f4q8yz=I5T5#(N zQzd)2FJoljJ*HQN84QntgRP*D+M?2(BrAF*o*HB5q@9Z%;Ht`#@vs%&FccstS&mF8 z$`Gl9ZX$PY+WV60p|)vGgTff;qP|L(ECiP#6Nlvq5XVQwE_f^^ZUi1Q@(F^zL4W>f zz^|`&o8Ms*3E>3=1<AoN8TOEx{{nl4)O_n~+X=o#+DZ5#wQ^$?W{ImxrR18wmXxqw z(@Ep>hm(tj{RxcVny*EsKk#$!J9nVwoQFKVp$g&uckSQH$-3Uyz}H?S$Jh!D4-app z6vkK>Ud|K9)4_*y$`cS>m}Y0`&BpnacNUKhe86}$=*9s_>sA;|algmsOH~z#VKsIm z5s@w=mh3wJ1~TEb>$}?A)8n0+aQHyhee78SFM$ig1Mi3mVqmU|qf?tBIT0yktyro{ z-0GrYN#B``_!%g&7MZk;$!^e6dgxyKnaRcQ_bw2Mh97mto&8#Pc0F7LdnHVKBE=&N z)Bx>&ySaYG#nGK<UG|V--8}B~GW)ef#!pL&Pc5m?^O=E35X0+W3EzvpUonZm#fWzA z2M2O2@DtYqy(??6m{b<Yh}5<|Ev&jD67KBh&K(I{o8Lg9#tQXX?WfPof(+H(DGu}& z=dL?#zj#nFxu~^8(orKwb&TPDJRS+QRyvlJemy2f0>!9UK@_c_g+)+I%u6yMFEXb! zwnsljo&i^F>1T(s>Bn264{k1x-+lOS-*P<miHcy2>8auCh`Ktrza1T59UBvosO!U& z)KO>_4K1zF*6AH4-4bwp{kC@=Y0b4yDI!n0gzyeT%VwT$@d}clK+ot0>`y;=t@W^K z`ErQ(g^3$<5o<`TNVV-SXXJeXH|p1_SRU~LOLkvCByjzsvmTtmJkRcPIQD%6KQXT{ z6w!=J9mtG(PyjaU>c4+o@%~TS^!_0e78aJ1*Y(RFi&3PbgdQ=~v`qZrpFZN~I!t$G zXKVuW;+2=Pz)Y+)nfHBSlWH-dPX3M5+4`-Z$H{t+KZ(4Q)So-oyAZXaQH+HBA7`3m z<;n}sKTLYCg@9K;SmV~;&_7jYA&B-%Cq8_AIx9qb(Cu;?od%CIl;VU?`>j=*f04(< zCJx<I{}SCho!T2*o7w7rZ}Ul14B9h8zudW6T*=Zm`#&N06T0z2Dc4zg*B4leCGfe^ z)ympj^tj~fmvB}!B_t+hsL4_mYyPHqcbO@6W}CVSCnY3|Sf(GaN3tgKKG!A8(lhl! zie8<*8>G;ypLeICGD_f-Z`iU&+_tYzwfyeXw@M`=e`7TF*jBmLc--Us{O!`ie`8~+ zeMtWso4I@n%gMshVZpbHDxY6oBUzRP^z>3VOb+=}i`P4D_BN^r6NI50XEp>Zx&boq zRi&}85{%lI7}dUGgI9{`p(OkdZFG2%*c$EBaLDOg$K0bIE?c#~AXgLj6><amR2JI1 z7*xyAuIVE1AAbWVrR_NJsIIBspbq=$ZoZXf#R@zLFoe>UdIk)`b`U;b0r#lc!14es z9%)}P7dcF=@K4zM8KuzQ&oC|BgkNe_JWnpafB*h4^emOmZFg>3MXB}^E8CcqwJsR} zM)3;v6tC?}_$Trih7?Jnq$KXbOw+JJv@dY)Kzo@zMxW&cwE>k9vvqAk&66uH&Yp6g zW^E!t52C}>UM#fp+Zzl5cCBuAbW9x2K%f}O@NQK1L%`e)WPXty>@z%t1wr^sjAdk= zlp^ZFq<y%agXb{BH!pNfLqlV@`L;k(H0bZ6(Y(t{*OJXQyu6ay+9dEM%r-ZK#bX># z`X4^8=&%S_Uod>Ux|_zDZ*X3T!DM7C-~;O@CI=Dqo|Kbi2#KAUhLcs?`;@Ko%?#Ic zVXHA-;J-{YBMlz1==IOnI-Wf0J4nym=O@PM6TUqs_r7vQj*yd+e{;u*TiUJ<K^wX1 z<}zb{Oc3?A=WdyP@KxlLVbq@aTT9IdE8NLaL|ZknQ@wwme~88}{dsM_4tq5|et}<> zu`+cIM^DifjuWw-gjqbG6v1Oj>hVw*<KAPrBp_JV#?TC_G7h6Go(X=f*{2aIyw@=C zoFF?p+gRz3%x)9-av~mQv|xOf<&_3dm_hapvhHR39*G4;WT|x32*8r<o~>>!g{rf9 zk6r4G(&6weqw6`-ZN3r=baHX%tm9~3P-|harp3$7$yvO;3EWTK91Ob~H63U_WwkQ2 zU{sa0ovBn=$jElD>Le0zepUPD1u1C=IAxBN2dRx`4o7R`s%84<N&A;4I$tyAz&n@w zi6StHRu)YP*Tv(e(?%|hQ?}%>d_dGBS12dxSlKtQ{g`Uc*CgfV&oA?yr%sNx;1J%A zEA1>Mj(#a3tKpqagvwK#ufjk1<zSZ;QAn$Bj=)dOo~}>UV(?Dh0d4+-%~UY>(tA>N zqB=FVxS+Q<vf)k4u!%}rg@zgQ7+=5{{AD&+YVZ6n5X@(LT>;f#*OZI6@fMEdcyT}g z&gN3zG#1)Os+9G7by70qqquixl*x$u*S+sbes&LtKKbTvk*)NMlin9=+Z<<t0CtQ) za|r)k!@v$mYzZ7zB4?>Lx#!D!dZgSlZ%P=6_ecayiITW&zLW7=KPM%{;^Hb$c*QYN zTJ-c48=Htq`Wwj1$FWj1a#K@NDOuU}*<a7jKc$3&98@o{$}+r0YBJQ97ujZxW!!^X zyrLww0e3DD^EwvpH2ss#{*?IIEcet{X6J9hG3ntmPl|$qG{x9^FJ%*D@QWveH8Tbs z;8TZbQBi&%)IJ&E0@35`k;UJBsHnJv(e&Z(xtYuQqj-n&b<AqZMd~A#o0TwspYJ9u z7wZC&@Y=gKW?N`z@+7=}_A?$V>?1rZyu9w;UYwx;SJFU?uMuOnroo0F*>NLZ>g07x zPKxLtOz0!9-7%ynk(`|$E7n3UUuDU=YaF+!!Z1_P82I^#Q7NN%8tY#6py;(3ds_py zY@N?L@?-wfApeBJYN7^-ik(l7Z{7m{^qFE14cHpUBnWzv^mxRr2@ry;QEfGPzert* zkP^B#9jH-;`0No^u%I`L6+(FFl**5$sil=+kWR5a)WUrR1B`p`75@wHwFHkR3Ee2n z&%J^}+w{^ruX5!{9+xItUeMCfIbN{usS(_A-EcC#XI4LMGuM~&0hyd`Prr%@4WHS= zL57rG5~D9|HQoZ+lZjsSuyJ>LXJ>)eBJ|hXXDGhucZ2R<4p|;V0@<Rqb!ge1&b#wf zqz$+5uUCkQ<-A1yf6t=Du}m}6uqaz;@_>E0Cf+M-^vk7=Ejbu>TtiP~XeR8heKZ9K zPrdQ|gpa{o@#dx<@n|;1j6TdK<lh~gQ}F`xk^#)8=uL6^@2!z}b-W-Pre3!Oydu4) z#ACQOciXg&Tb1hU-?Qky)fw82*-6rn084`(J`!ejgL6cr^R>q&e>DE4MBOo;UFp-V z{`FOr;Vt&pjHf?af(&oxHvH}YWtZlzJ&@MOpy*nvTZ0CMK?onWl(G%%r*mj2KJ9V~ z!24o!L<0g=dxJ@$tJg%ChR%W-z0i_yOTN*cUtlh0V0|nD$Mwz*^<JxAK>?&#Zi#Jf zCclN(V*<2*N0h9}VDOYHPZsB;ev_NO*`R?Va(LK4Df7D^l%m|62bfE@hiRc1GDjL- zPd)cLSciLW=u$Cf%IZCHvM$xm!2>(-23U2`-hug#Hzt)sLyGXW2MAKR20ZJeKael} z{^-EBIJlow!}PL*hfKiHPlXQck1FgSUnh@_H#a#k5f!v~>~srw7kO!E(eZ-5Z+-J{ zz9aWN-Jx2KW?|_YZqZ}@`eFUDe^vmd^SYvSM(v(o>NNqu+WJfm_2u#Hw<}8DZPkx= zqMk<U1~=#%HMO<h?)tj@$j@*oF@<q{B;J|aI~uA}^8UJ%<MF%4k6#+Zt=F$b^1b3% zuI){`6jIdJgATW+L*^X5UAjEXh{D!7HU4EojyCmQ_-2_676Rd0j%u%A>^Z?l35h2J zxnR&Tcxkueq2s(=ER%ik*hr4hPcE~y^3$26MI|!u%D>v^OuT}!owVfwt$#q!z(;Z( z>lwC$_7bh%MB_yoi){x<0HGL*vs)t?;+We(4l};HXOw@1ODSSJx<)?d4igc6W7G5S zD<Pqdj!r0%$m7^1X8XI@D+Harye3SE$ko1ejyNTf9ZgePJ5#;ia;n<LUwe=%y9u7@ z{^ES_csbPT>v6pnz%~y<3PAHr?LtKF*xR_f-8j74c!Nf>XTM=RvO41~z4?vfU&B^i zQP8I+5_WuSxsSccYdw?8=@&@%ZwnQdFAdL!z7l~bS!*;iGNNqw&vd)twf8!XL<Ct| z&PGRw24CCJW*tbeyLC+(TGf#UhmVQWee-w7XjoZsz*5-w+`$gws+&A}tV=XQTiftQ zCtHts{sl-j5xQ9thRBnu|56F$(f!K?eowXt<6J#La$r9#iOzX(T+jl<%#V0QP+(4T z`1Mq^k^eepeGTF<+Dx@=_=bu%zHKp{j*lT#1c~xlt}J<!I0C}*Q@;fj6Gu9nh6=<; z>(3ID1vy-A0uqj-COkf<bH)mkYo8hVi*&g|danvbk?5CB2+S-_n-&+4aSD8vAA0PG zhiJUwILKT0f8|7P<_;M@BO@lWy7Z)kEC9o*Fo%>32DGWE&yo?MK3&HJiOms~53t-N z``nYKoba@&cdBrdT!Zt$<p3?vdv}RGXn#|=HbYPuX*%lSzHnqt4y|^rWk81S3G$Zk ze4oR1ZpeD)eL5sv^9Q3sNRHLZ+1>9$xS!XH9<b{-En(xMa9z6KgXzj{#L1aX&J**g zUu@9Z^#iW@v&8!l2^_UL(r<PP&q+?7GBPfGA9%~lOZX(RYgOSR`~HW)x<*2Ahcn~3 zdd7Hz#v0a&I|TVug$pYIYeEj+JRHA%8NhS_Sgmbp5<`d1b<ZC-{L`B+zb!YY6+eD9 zw6S4*6ON5bn7h%2UhsMr4u87bW%_hHu65zPH~JH`mdZaw7K*TNLyoA35GSAN1@}O2 zLN;u6TRE3l6JmGI_^!*}vJUolY}-=}PuT`8Rz>pc7ybO6(H4FPw+ybTivDE{f*Z|Q zOLX3VLl>Az>#5d}3w5=yvkSD<6YOb@<BbrWskR(Q4Qw7|V`=vH=l7xyT^azP^V^?4 zUFQeX1hVmEi?^aa+mBn9IIMhb<=P5HN9=@*r(V5J@9*m1hrL^`_gWQb@iD3W_ZW>{ zLAKqJ$71ePv=Q`?t7|>SxZV9GW{=j!%=lO20RyN$8<&4=_pkRi0)AG{u{$5X^8R}I zrzI7f{{#t&py;Tmhwv59p{9ODb^(ySzmK<vJ>vStv%qj~d;2^8t&08W*n8{wrlccv zM%fx`_46HG3!PBaXFhyIzy1rD6dYdVb9W%>Wn57z?`?vr!*2@#yZf`sJn|Fj6Wz&l zT&g@)^25-lkTnmy)(_w@fTe_%z0K_4f}X29P?%^iG&1^HkrlYq*Zn{f=E{hg#@mM% zs`)I31KhBAy}Kxe@mhoJLc$v43S{{5(h|TmMf?1xr>^VMdOpq%L8g8${1YdcP5qXX zCm)NQ{el8?m<wp~mlqe40_lL6%%%gKfWRYMiqEI7f5yaor|$aXhy;6L2y}TrPghCA z3;c0R!MD0L99MtYYTRPH?LL_kUjD(Aiji)uXzohD)x6zXGCdb3v8hq=3{e5u(muYc zif`Lv#O31Rs$L?NwaDU9LZLe{L7!kjgQg+Mi=*E3_SJ4k1bFF=NPy#?l%^wzYxo6L z#LCk2Rz<q{`mkSs$G*vh7Urzr;Beq)AI_C4|MBa6Hpe|y^*;F=GgGnNt#6M`@rfq( zi3L^^TI*aEGrhj;VLK0>1ySLK2-AgRL>n?*WQ6|yzgmFytxU<0M<BP)H@ZZ5_Jbec z6WxVL;9aV3QuT|uEFD5i85~v=!qwoa#AZd*SSm&7@y+Yv(0J?z)!fArE%U+7EL6zn zF!bmXCR#Loc;qYwv5aqiFWCyH{rntL_#t?;hODw+@fkYBRm4GNP|*8X9@ZG!9s;hN znN2jb3^_Ou=Z}@BsO(lbu9SEDxowWk71MCOkSOG#{=q6*{!<dCz;iU`>A~<BQF3eK zw?+=DPMVxy2DyS%qADM;ZFd@3VJZM6$u-xXYi9lrlw2$!kUATis&R3uKhx6EYW3~> zyeq`UMp3&r_d-Ng!5xx8X_ROu($E*V2giEJhnK(&sr;aT0Nlbxla^m>6ZKk?{5C%( zrQW5rcYNyW`vm=+hdD>61pG;odM!oC0Gnh;G6Q?IM3z3oyTkqB6#sDOY>J-1xO>!i zgXF{r`e7Y|^LYF#vxc30*U9FDUs%}TPnnZV8UMnc3yQ-dv^=&l*ic>F?=SY*4W>v| z4i-HZy`G&vrWEz*aUL9ojNHq#Nha{K%GLJ)fO~(Rq13rzucKGP?+6^1RJc}mV^f<| zxRBjT@!*%rZj`=1Z>hKr8vp1_U1jOe=eSqZ)JP0cD4SSG)V+m>$7;yl(wy8}Mfh2D zs%msFP!l4r{pPJIy{^xt%LTQ0oYAq)Nio6?35Yq*Pj?z$?aAY_%vIUOr<uqw;*fUO zSycucB`Jb=isQY>Xu<SGLrgI5)w9!A0vHA^2)ekC*RiHz4Ge0VcYJFq687-LO7fjQ zsquS2@UZDMbf%tdQu!Luqi(NJe<5127XFv_4=(NRc%9Q^4qRt?j7?1+;ijG8xI^;6 zUfT5nLnNI+23rJb1RbH9_L>{qcfZumN*X%4rB&Gi$)|ew&pX4}T;BIpOv`tBWhhcv zsD4>^wx~(B_4^~wN;-=duJg<@Qc~u}8`+!gU|oqK!(7PM*jW4?&sa6{1Q5BHh&+vb z*Yy#yJ=5p0UsLsLzdrvL7!gcp0Qeon{9kC_ms2wR1tu=ow-`moK0opr6sN3S7qqdi z#ENmv8%P;+9^4T;s~1rMMA0}??21V5Gm}9Qz0EH~%Pd<5-_&#>F^Vo^9(5)`32wfZ z{@dgyVArFCa`ev4=~6><D=bDdc~gS~z?=5*O<?p%6Ac!Edc8=)4t?^Rg2nS}lWw1d zO19OnRM%U-X~-ZWqbT$3(V{QCJHug3+*hhq7Z6a;L*^?#52lgZ%t*x^Yq*i-tYj3m zMEn+FIZa5pC!6|EmRO%qIEv?b_;>WkP>K7|RF=3?!S2dhiJ$;X<$3X{SOtTD{((?v z1jknJaSpHfbS5K`<~6t;R+DzEe*V36TVjF7l8bHVu_9uKOEJB*SD^M^3NO+qDy|eh z+no**1l33EE6QS}SOSjG(vqhOKqBCF{jtH2b?}HQ9ndC><diPrlXlsCSUG^~{G(36 z{e4${R)8j?rAt%(O^&N^-z5$QGP3yOJBtaETKNQZ`N!@5YCup@7foi9BEdLL?%Qln z@EXvaj9bVG2b(quQCC*WIg$DZ=LgtCUr@~kpyS52=J)^qb*1~kZ#IUZzbX_v@c>YG z&fBlZAFvk<@gEE$r|9Ya_llZ8Km3Tu+0=O~zOUDgf$neEJE14Dhtz3ieu87SU5C$D z?0m1It?fR@7AX#zj+NJntSqPs8hl%RNJJHq9rF>gyxji%I))bY&tg@d$VjEfPo9d~ zOEI*yBdA|538#s859l(kZ!#fz!&oLJCZ3dOF(`cr{4Nulx#{Nj5}W7wUSv{IVVvLm zGls)wG4~9H;?>qjRrK(yLVd1(h%4GZ_VfF&zpMA~HQe`4a_xJ!8|`aMom2tthZ|m} z*ExSYxqTfsclBS=27`gTj!ZoQmS38$?!`=!%5MxeV|_{y3K=Sgy4_rsEHp+?@_r~N z@Ar!kdOy^jRj0iu1y1@x%za9cN|go)aZJLJSXMXY_91uWmBqK;n%s}<yQHNX#wqpO z@7^a(D$~j`;J<xK#c@FYp}p<d%a?wrZ+v%4{Xq<Y8B+nf-!O(=ap_(A+CMgY+O^)v zsjD)0mLZLhsLU~q>55(rQqCme8$^%-T<^T@&49NwM<(tWgX8gg85v*&0H<c)d)P{q zaelt|0`4!l@P2`ME&20H_sM^Mx`&^?Z>74+k*yH=wW)Ks^<G&yYQ$4()nME!es5kx zOBx<C+@u8|6YwHKvtL>v4kbQ`|Ai3j*CDeSEv)YmQA+=xdzrAzQuKfCWiU%;95n9c zdkv}x2i(1`X1i>BX~u9)4XO+)RJ*|e4|s7c*Gre{A*#46UH5N18)>JpDg>z-w~1fZ z*!Xpg?N$27m5NG^zTr1Nv7b><ZNKMh-&4(Tn_yu!w4L3qf>uM1qe_j`Ln3v3_R;{| zo^;p&a;~y`;;iCl;0Xuakr65f|Ce_Ij5}04d6?8ywbQFHol4k@y90|CdzChgtwC+E zfz#LD&*8pA<h-8J((N@UdR1?=yDP5dA+eUlev`rG^sJ?p&ZQ}Uzqc=0#OInODWkAZ zzQ8yKln!5tCneM*7C~_ck_TH-YxMwPT_yWf%3Df~)j({`-mJ@!<_+b*&mgB3vE@#E z3RQzqtqDc_PWzc7m-D3J_%X|Ks}$avrrz8<DWeXFTjIK-wJoo*(#yW&(#z*@7jfe8 z{G0||`2&}B6~?wqdrFU(0qW<^6Ir7nULP^rYTSPN9#{v6C`$5bBuoZmWkCRd%2xND z`2So%3vdOoh%YzMd>s~0SOFbRt!ZKBGdFD|<3YahW9{F^i`d=~<f5#a)dF2kxCV`` zCvsFs`DU<P1>&%>E=|VgEXN-3(-?&G9#*1zJy13?#g7tNC_FMXy{c|sYcy<9X~g29 z7Ro6jFW&(uB>VG!n9Zag4=Q4%hCq49_IV+(itu4T3;ib<v4nkSL2p}wp0@UeT|!OG zK!EfMNywjHk$!g(<Xmz&@4D`{ET&01Kxv^ejQUMPX2nPR!KoM*gF<_%fP^3VCq_gm zhU_N#PUf=cTXdi4A&$#quX7?`#DaX;4-=S~K<DT()mw`(aC_q7g00)v*Qc0oc#mx? zEcc^tq|XD%Krg@f&0xisrc&5#)bQnnRtTT{dj7Abzu(pF+Kf{mslMLFsi1w-HcUk+ zA})~=nA+$afi<7_^XIF_M#X(uEmS>e+zn&*I6Ac^mID(`g2ugQA3*vWMUd@1M4b7Q z@D>~bA{MaE-2cc6*sx%v)8P!4+Q`O+Y+h!YU{MYXX{dm#v`@IPw6s(Kir6rpJ78K| z*U<1e$%!w7FZ?j<)mWlrLUMBZc!$<A+sFuzis&UJW6$=Hro+P=PYA^{*RM2t+b@Zt zwYF$9Pqi-NkYwa)?5_@aPl7h|e*E?_HxJd)$R6}i2Q(1&HiFb@!iM15HwodUsm(MP zO?4btyjI}#z+D`e&15+<;@V<gyoP+tRro8@$hIu!9O@jtu(?z`cIEcSc!1XVMxv*! zKRHUM&~Bcz_qQ};JTb{wkV75Rw<dks3jbtsl`$qf9;&ZHP>1+v6ava9Fm0KC9hRKz zWw(4ekj(bKr?{Tf*Ln@6@VvqHpD`c_`H^Et&4S*>V?EcTR{-cy^6~TMH%U&|zZF<3 z(ne^4$~57}_@}=k+$14ssYB$;39X3?n3zG@cRU<QR|q`i&56hcDqoNu|9tsI=~pRU z)klRZSAPxqXKxJm8CZ0iK4kb!%{S*OfBOib=2okFz}y&Sxu~hGMHPoZF9u<8iFF~) z$<F@cJMjAaQ&NVa8`Q-?BDxc&TB>C2t=&X|porJX!&<>@Am0E}EF@8tO5YkBebe!0 zOen7ULar{V_Z72nMBQE5C2&@W(7xjB(6^ta_sy#1h4_sp9Dd&3KPt5Rs(_DyOD+bx zZGXx3c4~Gu12o+{@Ym(>Rfv*H#){b+wwaK7x@u+_AJc{0FUj=o)&u)>piH`t515dc zgPc9>28m3$Nxn`_PSqBpeuARl|3LfFolr^B9@$i|mP%U;6uzXQn*ADRqrHt(|6-Zx zCyKSP5eL+Zi%LSHCt&I6_N6Dgfb(vU6Ox_umH%NuZ-{QDoY}~nq<eytIL+;Kf%lRd zEI!p~U4T;c5#mKj!_i}tBVw_hEeneRroG6UI4^bv77lUusVQf?06JDy`Bh=BK_TOT zBdwmmfX<h*0SPOSRRuKAU0oSpNU%+;D9`7?Qn(N|#^6xLPXSwqf@h8OX1}M(`1)vd z#}q7*N%LP8jVKZCr8PY))8`uqgt2ltPgzbL7Y|MH*;%_I^XSc<j(3*6YiQ5J_Brg) z1CwFmqHUZA<BagdG=a)!PR(w?ToHPsFp-{5FXWoNMwHcjnWw|hH$A?NBd5%Qi9&3i z88s!;<o5kp>5Y#U+#SAwR-2dJw*3fu8hy7X>SKPRqw*ouYpo~t1&X-oRx!JWW;Uqz zaW8Fte@*@wA=^6uI8Q9qIBzBtSG)WeM@^Rj=`>d#DCzLlRudO!)IWapEBzPG%MQ3g zuoS_X6OLU{Tnu_R_KVQAHh94?!||@(_k}sl=8MhXiZQhb6JU}m>UW9a7<fvOvcOhk z2IabEDJf);tU8ykl~q+=B7<aDm}1VBK151Lb}bBN<pC#v71xaW@4`0K9<H`_jm?@^ zS~7vQU(fL!h_An*py(?-u_{O?L-NAW)(Gf~S_-rC@x=(n)oNz5x;72HY;c?9$Q260 z#4?J$D|!9WO;#lkbl^FxPCvBXfw44n02&ySnurbs1s#GjaFT0`b{bf<Va(r($y)wu zcA5IrB|{gV%k0Y0)6%MC5Q?}gAgSJNljFVcZPWH2dAoUJmNPj{dn#GnW(A}G>*HqS z3%<XtG$c<7W0fjDW7hE@kso&E8VP^g`zG1r8QN{Ud0{tFCo)l@u=fq90dT+(jTH8D zO%bBiducUam^g<>@_=i#I;L>{J<nh+USrNpfQkYCtFNv$I+*}JJjRXq(=Ms-98gza zPK)lbyC59Ov<6sF!0wr!P{j3E0y+<MZ@D(rvbhSBgsT7rdbq!7<X%>pur4UGgGfqF z%rb0s9;B>v3J0ub;oIvG0-q#AlUmuHBEiVi&qEKnK8@J3?*TGljez|s5%Vi-d%0=^ z8I>j?aoK#~OQx1hs)V6-L&khDMD(VkhKe8^_7T!uIi7ec3cbYx8YIcZJ-LdK!&ymt zsr)FxoF<Qx0KuBtDiz1PIwHu-ML4D(KrwM~j{qx?1AAVz_omY>o3R0P9r7bYTmk~X zjY#@`H=_9Xand2MK=z+J<{lt@z1MSz=Hv099bSOHD?;-&RM2(7Ci~4tc=dQhc^|JV z8Cf>u3KR#b@Vmuj`c!zA47~e^6Q15MboxMAPL*vk$>SnFi~7fpXFg7ibDJd?n@-!y z5GGgGPGi!KMC>Tuud-2TJ~-bMqwKL0+&0h-(Zbw()*Wr84eJ{E5jkioPwE)ZA{m~7 zx+eCgbK<)mA*S*xPqbKi71C+wZeMPHCx2Vc?%}%kn)hWFE^Q}O=Z}yOF8c2e(fxk` znl|U`h+f>7O_P`eQdq>&yM7rqJLdqn3c!a60X8D`DuvzPFRrAGkx}@mjgC=!t_|83 z6|;f%-rg60FJIiXn9eMiLzw!zy07m$yw6V!^*;r{4b^UcL7>eS1KyZd8{FdI?O| zdM!;O(p#fugX12PRc0ed{`K;I3H+=d*gHY(pw0L!lu;qc*odv9ahU0YgoxMqN95T7 zY<#x1Ra-Q$Y#r6=1QZ1R6E6g;fPKh9r>yFJCm+wzZ0Ecut}4^mH^1sK6|_2Ze{6U& zmL$MrGQKa!vNavDq^~>%xSsqJuh}ipZFv^!Tf}gtucBmV?pJ_>DYo9<XF>*n3wRF= zlz1Oj5ls$j+vvM#onf2ZHzftgRD6~$t%^=u4kK;@j*ceM2c@NK_AV}86-EO<-<ttA z8HRqLEviE=c|kw;1lyZ?*nbW-IPtDPYg8g7ql`}Ah0B6nOOS%pkhJ>hAb%U&zxM?D z@BNlYn7~n;6s<(d7o$~|mgi-!Ik6k=0lcpi<D5_^WNj^gDfWUOSHk;A)C9m7Mnnp6 z{~hn41k2fHA*dgSLw?;)u2DAs7eq;Xk4>(QnjSmK&9TLVgtGhWaqcHC^<*hJ6I`dw zTD&f_H-xAd8KqVA!Z>`W<%h*7XfNLXs949wnf~O%ee=lbKk^74oNF{gBgT`Ii<`!! z%8Lsw%!t_Hvn{I>vqY%KOj#i2=n<RH2b1X|-g-fPX%oSU!(6tcbxF;&WZLVBo7-=a zpb3*Ta%I3UJYDpF*`1!bPukhvW!hq-cD~-zV5d6K_#z*Y!r~e6u|MCFrK_db+{{d_ z=KXhvD6OK8`SSISCUwhT({d3uCK+Y=7obq6pF9s!o3>@vLZ@PO#xyI&G+wE4G_kWC z0%Cx`_%isy)WPVS3uU^5qi<K`_2<Pvzt8=>8fEB6APtBqdiChb6)r_^+*6KxU1_F2 z>4Lt}Cg<NlvUTX<wo+BQ@R~T$HQ15pYbaza?qQ&%6@PPY7iduM7KOFT`55WsNhXou z5oE$&L5ch6J#FL^L$O&doQ;|~>sh%oJ`@f!P+-AH=uHKB<c|e^lmU|6O@KA36POG# zEHmOX;{#;_V5Mb7$zGDZ&L_Nf&144N+IVtFXFH;q$G4z<oH`ox*}gD?{dqH&aG1?_ zJ@1$PI;#$y&wZ}RTLXFKe%PXBJ|#HUkaL{~-Gw7tE`;It#a<0+HhW*G%RpTYV}BeP zDwTD7EH3Y@{2|O^^-aUQpu#~{S16o9G-t)u@M>UQpqX8P!n3Y{&k3nf3Rm>-HC%wa zH+R<3{9P6pku7lw+``rCp4~@-?ujV6^{aM2xj@>z5^&#SDb<gjC;=@BX4RgMM5y-( zD~lojKqZ;zF?!KOFyq?1B51b9k>2)!QWl4Ftm9|vP2HVdotyYVbJtG+O1r(oIpb=f zRO!)NoZmjKi6gZ2%Rp8HM0F7|dkWIht&?_#&HM*QGT%LT-ZB5d0p?WI8Jb2OH>Rvc zQv4c_L4AU&{EdXr$LjNDH~FkgN&oHaU~EbQ!mb~RDixW8(Purz!H4A)n>5(nu&bxc zsTkMSiQhxwOC6D*c154mI&~^u5wkJM*#p;tieU1VYpvgK@mh-r#6hTt=dQ6=WEJL! z>Z~PtTA#;754S(W;88rA!E*S{&QA5IV#j@moM$*$jh}qitm}2j@hy-FJr1SOgoGlb zNULKdrG4IfO3lca4dU43{p<I?1*5vhL$rT`vmf*Oh``tk;ghlrC)C9u@cv@$aqgHb zgolUs(8;02x{K3pGqVKMyVp_%dj;Po!5KJu<YZ*p)>s8yJSf4vDFXNAtIKr7`Yh+0 zlS9z4Xz1YxN;j3y^sgYh!nQG^f7JOIqy~CaY8Wq)7Ayi1gzZ~1Seqv(1K&8G^NkhG zVz*0v`jaC&`EW8d^~k9UDDa|-=463tA(vH<D4Q(tL(RVcEdnf#Lkl2M17Y0(34BkN z+qejsG~c~Z+&9wlK|_P{s!e9a@T~MCMuTKotFrD65C=Md%`aHVjTK=&HoNDY{en|h zdsO~sX~IyYa=z(&qc!qY<1r^EIM+B1pw9cY3ZIrUQ3IIVI$&m!LH3kl!a$f!Ir|x4 zU(kNGtP7$ffk_IZ66G~DaaV#WcJU$i)g1#&QLSnK4r9)kLV)I_&eQaQU6oH7)NZe! z#s7Y>v9OSNo>8bK1T?vC18+uNsEETM_TSE)GxMV(Gd#LaY2B%f_>7^Mw&E{EbV$!1 z;ga&$v?B)%R^ag|DWO5pX2z|VtD5EJ^@h-fidE?spP|9G&5|t@9kE5cs!UX4RN&UA z9+v(|Et@S@%UHlWxP9;lhq&MSD4}d*pX2)3AXv*>`S6j5dI8aAr7|su5!JkWaX1Dq zK{-XT7U+&YZW3nIt07UqXHXwVh0#bw*SxiO?TrXl+d7CM{1Bu7WKBGFYNag3<1LQJ zrSUVN;H@k0^6dR;^V8J+J-H~;s3m}U?OvOFHPSgU4Q}VC7-*ydI-+tiGp%sS%kLdt z9jZsA3a-1C7(0TeUlc;ZHEX;|+OD1)5?rA@=IL73LAG~+yJ@4%jU2cTc%eaP<`&18 zv!2J~VE+%p4*p>lC}3jXFw1_4x7KryggtTFYIZ&>fAcuW_BIB3vpUzE+%{yfe${hu zD%$<Tdn-H#eLnZ*wn!QSk;VHouxBT0NRx+$hd`%hSNT#1)Fhx2GgW(6-nIp1GoG^; zqna6cXN>>Bv~g*oC=l=J><<dtwyY*?2#5;CO7-;YQ%yv>WJFX6D~?xkr+EGXkqyPI z6M+M=--~3iRtA4xa`ID3h8zfJKvEXFQJXuXe(?wc{G0?X-gk@5dvI~X+`Id`b9vHY zt=GB;BCDC?gOqyUla>~u{;C(?Zp{kIW(JFYe>7o{x#p}9QP+ks0%Cv4cm8S~lV1Ae z{KxY=WdTWVVUvm5_15zY=7>`cYX5ow?}pC!2ATGX0kTWh`|XjXtdP~KQM|n3h6dWu z0Sf{}O$C1c>2I`@fI9oVUdk%$-6CBzI6n69;NSkSP0?y=G!1_mwl$A!h(G%uPFHME z`cIbXHh+D95#flu{{2y{9NgssCwweOCC=;67obyek2HCEee?=<SIDrNX?yNOA@?gE z5Uzp?@uV&8Fa2X-C_c-pxkwH;G|3RU1dhua5Xh`&`f?vs*3<+vdMfRD-L+CP30GIV zEA~2Uwm%dbthL;TmexwX*L(N?Edp<M4rGTW^Hg&{Dc7em0?J~__tnurQ+76u++nhR zkqkj+Xk=wtj>)5w9LMIZCZ8L1!!H}^+2wP3AB@M2fE>)e3yggMcB1anpbEx>iyEP3 zY-D00vE_JvXKERO!QjVq{T5}hc5|fK;drKt)y8W+*#9B#ExfAky8Y3Oh$0~%Ehz}n z(jYBJmx82pBOomyB_JIlt%QJpbSNd=9U=k((%s#0=YHPz{oQ-c8Rz#8+%X*E89oww zfA?B*&H1S%y7O#yr7LE9A+vkrdfJ-@VN{)@+&C12se1{OlslAbd|kvkLUJ<AJ`k5o z?6`<#7tqYe$OwKzw#(%|`k9E|)#e(T#~`d+?0NB_vyvaUceqQMXuWG~q#{s2>vvFj z!6!`du>EBo_FqZ^-@n6p{x0!3$l}+J#A!<7u4sBt4BQgpE`YUswJzM@<{A<j+CJ%x zV>G`U+%x&7BJz7GCV*75QYU5@-##QHFlbW8fC4!$>-)nQ%s$YZDi`8<ZFy0jVv}TX z3g@r#Adq-K-pH$_)v`~;=36MSN6fx(SxU#xXgT4=Qs0Boo{-0=?vCxSP?!I_!G!?i zchH8=K*<7AUMo-w?2|5cqmOp@L=Zk(Eh~uxQnIqL2_lXuU0x|_XSwsbDS{#n`(GyP z?4T!J7Pa&LIvIu~sovoYxh`lk%qLw3V`aIWXSWcCZX;i8gCinlPQU%O;<KEWRK)_3 zAxk@sXA>~7xo#u=pkuUiR!`jdO4HNRKw7c!=MCa$-aiScz9VAOhWjz9iQfS$<Wgvx z9Lb{iNsc)Egi{HaNrF{{p-hebR}(u6%p)9*!`G_Pc0pj=%s7`S^5(6}jJU)P2h(o! zMe=6p6AT(O6T7)ZigVke`U$tCz76g^iHgF(rx7!FTO8hvD#!t30-x}J6!k`=%A+aH z?=^MSC)(>5e0$e+qqF-t%u}53ItyeB8;=|BsKx|_YdtWOX**LQbe-><p3Tg=)(`3f zb$nM&)X^hHmU#(hJbC3;AvO|NARlb%>;;Wg05%0Wq9d*s1IY?+3c9UY(-#Fnt@vi% zA93k@INR5sQXO=)amlAzdwP06cAj;Lc{x%dL00?a8D87RL!#bK=wmA&>g0gkq*MJG zKh1Cp7e-l#oAR5gJ|NV+<Qj%qaI7n%-uL`7Mx1~|97$<1NvM~Ee(@0gwe^1q(r5G( zv`3(HaJcuF^igwx+67>H5^j?im95}Y$|bFZWHqXR+{{R7VVDx0d`X%j7qyov&KdwV zbv~9O%siG)t#|-AE;6&Qu&{fr+ijljM4K;9IwHWh7y)~o1}Flg(7HGZzgRVRCWF5C zy-R6V(i39Mc#6<ER#eaU$ih=)xAn<yH~=d4#VkVCs<0a^@VmI8LgM1bD%t6^^)?ZS zHJ#Rmfge&$$0giO*A$XPYA+j3_TsCObL8QIIY{7omZO3Ode-Sbd-0XdXN3la4Is$6 z%ZuyI-<`;H^AuFKa2qhn`@(ZFeiH)F*HM?0;H|6gvZ%_<QK;`CB{~(ORe-2e+Rb2q zA~^J=nzsamY&v_@3AJ=(155(|S(0TS`xHWxGQSH)W~#GCd2iW1dIngWKl%CW76$rn zuRYO#p!+sAn?z7e^IA{91ueO>wv$3Y<Y2#=sL3FnqZ$Sf)_Aw2#A5uhfZf5GC>E>{ zi5wM5F{E4=Kwi3Q4f~dL*Y3T=S#$5xcMS^-m9CEXJEN6FaOVzwiP?ftW5nyY;{3cH z4W(hZ&v)9IpWO2Oj}{<}wjBl09+BDx65pq_+Jpqm>esiXyj%WO<6QUjt+RMq#Jkv| z%W|9wdH}HBWK0vUBp6kPg@?C-T(W8p#>QKxOoG)DBwQ~U%xfxa&ZaD$*56(_;P;yn ztY|K*zna;tu)Q)|ANM8!A_Gl|2g%X}v=z+jqEL)gEE44^rwD|;sMu<Pb8Wsa8MCCs zp8w5e`e!}lk^1?G$ve>Nfs!Z~z%Nu8KFZTtE2^QddT6FyG2+@Unb>rz*q(+!@8ScR zv@l-fkDL}_R9NIRx=x?!?HJYbwQs^S+31>=tMfY(kgD&Nf0M>h++qJZEkls4_nwsf zQTj1#lL&G_#;2=?>p#^7DqQzoKfZ|;_}Ord_p8nyvIU`TYBmu{mo4F^KO~ZH^4zfz z6}D4z{xX1DEq}?plj;7uD~WR!Sghmk%gC4Uo>@bQMQ^!ic4X{c+i1@<4GrSs{-iKj zuWyxC1v<5lH*4V$ASsJvp-z}pj7JAhlCqHuo5f(h@K~A6Eofi-YcW9)bW~Z+0)yDb zp4Rt=@Kcb3&DQ!)D{3L3kc=+d$>Q&&EzN<-`*-P8rc7eb`Hn2Zz;O=Sy<8C!$YR|Y zTg@fi=sG&?^<*)|HoosX*Yn%7;^qQH3_0{Ue%Dwv!3_HdX9cO*TfO`0$&Te1I*Po8 z;}YtPaDQ04&+|^n$jNu_-M^3Z#zY9rsf@-b&C4Fg1kTL9p!(x<Yp|V=sRD2-7ZfxJ z%@hI-<mP?4VgRK)t9<&{U%I9}oUDS2)!}gEx1!yvSFdhQ?PLt3IVx{@&v|Ay<|RF- zsS%2z4P>Phb`R;+D0CbFtc!cW?L;FUsde6t!moUNLFD7)w%?b0W-<2Vp2Ph2*6w&) zyNy%DS1c}09obG%!%uhJ+dPaXeKYw1BkziTcvG-i$My1@4%$$bN*KE|HMK*sZ}0+W ztm%9wpa~>g&<2nQzvcwxQ=0W3&SGGF;J7jk;pBMjWH!e-d_j(R@)W;iF#40xxIyPH z^M}_lSDOQ|?~quyzKNIKGYfxI6wPJU+kRO)ZfM1fJ#Le0Q)Yg|#t*ogMiKZ4T7DX5 zKdpUfYVxgI{P_^^d9^YLhxvMfA;Z&#R@_cPgD}gA($Xf7jsMJ^!Y%AwhiSSHr51#+ ztG{!nLEoL8*-la)#cM$ud5N*>$E3N6rDe4I+6e0u+cPaE<$bEOTk(gSp|`((wA<FJ z`MXFyoT!a|wM+^XeC+#LfH)fF^jRd;1i2zj$=llG<fijAn95>Z)IG&ggbueqaTC== zn;~S1q<ghri|56Obfiw*vdqbW+Ltm-8gcuC-KirreF4NE`?M^3y&nM4L@E@M?02#| z7~Te|iENCOKfkLhO##5SmZ?%YCQEmO+Em<Ik#1>?i)<EBf$Z>4<#Q8N^2Y^GR|N#7 zZJyd?F?_^t3x5LRB}U49Ds|)3H0MGiLlz_sA|6mDU}Tewou|Rplwj|rlZ|`#Pzkpy zED{zU3uXc)W@t}eOts6}{pIDi`w>B+K9KN$ZfR*Sh=P=c;e($g`GsrC8(3-5z!O^p z)cLrcSVJRZ;GhLV((aOr$|+gg!p$#aHdv&*af1CFb0GdtynA|^a)|iey|jt@bE+oK zvt$tnr>$Wv!%<x0OfeK<P_W&F?#RJ;b~kp-x3vZf>^Uq6eE6BJdaq3lb^C2>Y&ams zvT^fg*pI#WPOjt!iXjHN8qROkNO`{M-&9T!YA>umx+cR10rZF0`Z}H%FoBS}v$NCv zlj{Q1H|*6BJd%R4m%kM<;~7+~<Ds=8LZ_n*!0vKVhUI0yJ;0&#HD#q9G0s~=gdPnb z3Y=cF?9Qj;jkYHjHBg0#dOp2v6WNH#vfS^u2g>}pI$copYDk+{f-*AeG+dQ7du-;{ zcf%}-Z-AG@RAbhIq%VQjv}R(7L^XxGalG1tK8=r!P0zqzvqDL6AN)(F`)8q@g6)wM z5#aJ67f33c2nF*SAZ_+4N*3j55~mqwRLN*pjt)*8Cg*Nz!+#Ype?c#@I+7O-Ml&V_ z%x?FK%Vz1#1S%9URoI4s+B|vo7d9}<jPQD&2mRK3uTDH{%*A|{FE`S|ZLi5Tw_bei z6MT{3>2rOoQ>*WNTWiCav_|Rm7&VEVsu(<$69`z2F^32FV<WyNT<j*xnuR)`(WY~G zT(Gu9L2xLTr2swRLf2#>R`bcdb%I9Dt&jVxAf}p)z$9e(?9`~FUrh4P^e8m~5YCdW zZj;-+(NIFiU&luv@X)MgLO_Q$f0_NY7scmFL6qD2Dc`TFgMz)NOw-V;YZ6m(lZ4aj z`8ww5Y;*0m10i*cudubX)m-J&9BGmH9U|#)zyrw<EsNpI945;oh5A??$C{h7UtdHu zp=-`ZLble+STm5nk_dWXnDcKla>}u{nNJIP-G}?^vW5mmp6;F|Jd-H#Y=3nfEf7hD zCt_7`CGeRGfL48YMK_oI-!;pqv4#}+Gk{LCJJO@pi1R=$$QPW-hEt6{Qh%w53|;@% zK&c4?5R0b45sNBD!3(p)yL{_K;7Od}gf<Ni{61=Vd`9aeIUH3v<-e`}<QF^qxfVt# zm?$4zdeU5+hWdSypy#f!;v2B|7B6{!;&2P8rxr({f}`j<OA700((iw!%KuMQGVb_S zRZ0&|DgFZcRku!RWlyv7`D%mF-)2x0f-+YU(k9VN*_craG|Lf?8KYr=mAz%3A~~sb zhypO0q=$zuwTfQbga#2PNlNY;L>NdAtihxi`wv>g`MQUlfK3G*Msiix{#4I5pB<N8 z3qWIMJ)fM<`QRs^x@mi^ZMRtJLPp-DYMg9c#!mmFpDRe}pcloUSP3KJB0pIBJ-AAd z|L;yP!P*af&QDGYZTL@VPR#@8u{6O<Vcd@8mlyhN;te^)uHpJ}nr6Kj<1Pa_^LrqL ztjBBaUYs2e__K5zU)-Pii9~$2`L5n+jNAZ4-DtU~BE7AYa%!!Zg9E2aVISYqC*{_O zwG2VA{ZiQPPAoQmX%=voGKo^_!nLkTQjht~5ZW6CaTmNE5VZ8pRDLl7s;k3Rw2bw% z=r0_J8%Mv6YfHaYyQV4zy3@$7s8Ehp*--p&QO*BsJ5@;d`qhibu6niSr!3BERrLFt zf3O|Rm3s-Ywh3)_5nr!1OrGttY7MKIevN)bWNHG0RTS-wW|wmrpnE%Ov%Tw6G^;$) z40eX)vh+*J%`}cUEq>MnPwT|G*!k#I5Allf@_zhXfdp!6&8b{OoMgQD&xut&M8eYd za7!Zqs|T~jt<j!ryw}#cpK`8H2V=FE;~#cB?^9P#JR;N5);4OY#6vD%q3)P2CkmOV zC|=Li>(Ke+7uS_?3cdXG<59V_PR>)Aoo$8)P=B|tYk6TzbuuZhezsnJ8j$Y31e@dB z{Iqk!(fwdOg!C7E(}a#d@{p<CwJ+Xzo%rnr5mzw^DH&Wyg-$Ex#m|hhEeGsvGAJq7 zYjKS*Q&rX5LhE^W@r~lutHHI9Q(g4~0q*BauCa`&Dx1|q_g?TaBP%)dJ5ejOwv#t* z^=XZu5na@kJIa~5<!JuI47`1ggA!_%;nM%gVz3hB;|X_D2cBQaYc&Ma++a`>SRCkS zAq6`7MVJ4)Q=t&^A8b$#46Y^<IC_cA7IP(nzFFwE{tY!;DtE@<i>az6ZUs-;K(V3O zyWA`b-E5OC-En&*y{QhStFgoCA04u!NEd@d_3%VhhJ;A$v+Ia*(<0fa-H2><mMt~) zg>MUurMD65ZCdJcH}lHVZ~f@g2xHx1S(AZFvBXyNRFtj?Zi5|YW-FQOXHBAquphJ% zkV-nerTd9M%50#bPnzgYYgruY$J_%!=hZ9_-+Q!2wltk^p*^!RS=njd8r?f0ieW5p z6`6-|;qcs+3rs?fH=SYQf43dM_{3M}lb3f$X@S(~4*FD)a9F?BaT@|f3em%TX;9Sv zc2B9BcNT$?I$C4@u1P=xP886)s~b)=s7$rXQ4TL9SX(6f3z4RjQOe?j<FC2TX6<QJ zX~o1^f%dUM`>?ZvX$F?&zlPmsFO&-n-N-TugUa&11|d;sB5ltHVIQiO6COkgOWmgG zN#25?-q!C+T9#IsnzMnha&L4yrIk8s+t(<GX$I+~8wj3UjYe>9#dM90#U<wMGx|x6 zwGN<wro-rBEE9Gt_Kp3mcj~Mj1E0Mpu$HGV;qx|Lia5Yn`u_2=k}kW`$z2sn)0{V| zH@XE{+`~*Wxwscz(}boSkev>1SbTZ#+&H311*9fKYm_j~l-O?F=8nQQZ3V-4zAoW= z%jUGQo(bjDIgcAGyM4Jhh(Xgmu)}ol1fdNs)ICN$Gumq-w6pIkVzE-#&B7o$#q&|D zYt>ZV0G|?DlAteRbbFdre8gA%A|hbM-ys+MNW{VNmHESjPbC~BAXiD4O?nb0@<|N| zmme=@cxbMOp3HYdp~6;t5_nj!pjQNgm6ZnCXXBeEBL_LkL)m??u|fq81)q5SNya^G zT{l;e`}l(|J2P|Y<HwHy03hAZyidzb^A}_CTjhDkK^`a+Av!{YhLaORzpkZWQiKoG z0W<T<2++=lryM})lE>wpa8L|VN7g1Qb;+rLtCNOhokB%L6~2o4qcp!;ahJJ_OagVw zT&trr&!&Y|oIXhCfG}<x8@qdwoHTz|_!~7358+l5?e^}16;jsvN)n^-&m*9QT4H2n zWW-!sZhD+=<K<Xd+BrD*<b{T+`+X%jIEU0X5Fw&EEOrH-D@C}UZL+N878WyQKp1F^ z>&abU|B+$_3?de4?P|PF`IBsFI{=RZ1=-xybw?@Uwj3I{8q#V9?DY16Jooy#18sdY zKJ<wM&I-?4Mr@~W@pe#BMI@X0*!biKTt;4|TPe5=`j3uk`b&F=6(&8Jo_??V(6hH) zIqG<Oh8F2X2N^!Ys``_RqswEw(D)*~xw&>30;c5<8c7Vx+PxR??te$KDJmTIVLKw_ z)CGgo-9S!kZ=AWzmsCi@jpPYJsuY?Ly{G9)7mE|O*C}3%bg4C1i34Je6oJAk1<L~p zNX6{z?H9*(pd~G~dGkX$60iA2+KZ8hF3R>Vo)^FcRoMFB5|Cru46LzZR?#dvXc{>0 zIx$anG4<?5`upF9)Xhof+90x(HN*aa%re$IT4VOuBDc5EzgwnK(yM^E?A<qMrxeH5 zwl<pCi<?iRyrjU@Hod%z00=xhHA6W$vhL*k1XIN0-2dy>{^HIQ3MHio7$BY*SNVu8 zu~!uPNZ)dK7h3-V>6-w>#_=)7o$~TKFto0j1TkmTh#18@T#8~e_-Q?q|BMiU3!G;* z?3A^NEjzo8JV#2W#^(z&`Cp<3VuA6WgNCTM^t*p}%MCOg-S4|8z5nz&{{qj)c*C$& zZSnv&4GKE;!J!hp2gv;GlijA)R;?KOaGtD$L!?yZIG79J!;x_*zN9qkuEx`9+Y*vb zFKU4*uUjed(?#&vP1WBUUkCADqB0|$1o>~iWM$FN%%a}G$DdhV{#-VP<{7yMySNkw zB=Ukth2F1hnZgNO-DE?{9Jlwc)Yr7S3^I`lWlw6WXos`5NA&%s_qNWv9Pc;}d|%f* zuptdn6ERvAJwcLn=KcE9Oa1pjgNl5WX+KNZitnD4ruY3uHYFQw=S+X8>)(e`<g>6C zf;fKfid@=KMY(ezzJoJgrxpchhimUQO`Bk#Ma>Q}kOismhYuf~rMq%SJa~tj2&oIe z&IEjVVR%Of-Iv|1&im@^X}C6u%+x!t*=0TL4$~*F1KISe3hhR`Z#;XJI`d2XrNtZg zr=P^PxOw*J(A7QQ3iv4a2N1F{VC0Ls-=0p7UH@B42raJ3<!xVsPQd!v9rm9fRt#Cp z6+T%^6Wo$jI1iSNO#S@4^Nv;@_3T=Ot?R`qYga5YDl_vOUjrv00qN<T>yL4>8si`S zM8AFOoyH^O=ojyK0=}o#+mXgHziC#ddFHNv79m_&T)wxcAaUVdb`T}x%Z~9i8Q0%3 z8VV8ocp7i72L)kfw>C})NZ(CQKaKtAk3=|c;b)^FFbG+Eys!RbMb6{N9slm`8$C$9 zE(pQ0I~VOZ@AMjO%>~4!71_V?yN8Y)9DLG6dU9>$9#>F)bLoOriRaQQgcuB59AGts zXNntoe0<$$c?cCqX#_%^xc~9Nsv1@jlP@*;#!Mi20WeggC!Dhjd3*`$e3;N-!W)vD zn*6(f@favY%~ES@7ia_q=<m>UmmW>|B~%zNA{qeW7%tN78XDz$1XqvmIy>9b)9N?f zcip2866EFe>wv-qI8^i=f4yh--53_FriL7&W^fvC92fmW4DtzVoS9ea(MsdNL-glx zn3*LEqYy<CJN0nypL(ItM8;uo{9RhQ-2g%qfNa8e`Mk)t>RUDw)=AA)174pio($hC zb&x*F%LmsDPhoMVyG-3f=1m|PYzH;Jzg#h%etvN`>Cqb$t_xx$8O0pWDh30U!`2yC z%ktE1=lepV{W$$3OwA`wm3=8bm9Mv~@~k*lg5^@PW?-s;kp>G*>n<+6Jgmma8)$Qo zlX7fz%)bfpZMV<h??lZCGmuqLxnn+$i2!@GIEb21vx0D=VdAxuszVgR%R$Wwphg#W znXHMudpi78ii}vZ1OP-()uSNtbt}*^+LhWscOUisJ%U=75!}hlVV~Fu!P2?lHF6Qz zXJV~rq6NTpGsR62kFcdH(uGprdUVZfCB>|Mdh`<4lT{v<^A~grdcym?;CFmPtB>IK z*#Cl}+8hV8lwCVOL6xp6xhSd<xbTGA8bz-t=OZAMVy-QG{Dwlf8HoUdF6uP`Fp5CH zB>kjf^THmWLywEY@am<xY#A2)lG~7UvUs@!PH*T24nC^;vJ(s`p*QWj?e0H9zVEB? ziy{=&y|ryPh#*k1ZN(x0i!2oO5;dS|P{0s_6x2F(4iw(E$=L>?Uat<cQCrdvrj^RK zCm`2y`KxGwx*G8CP1c688@xo95U2FK6>WO%Z<+M=W~!k#HZGk4t075#em>G{?y`k; zO=e0f39h|H%?`m09n6%+=o1!}Cu5+4_h*g7#awi%IB$*Slkl05=+$}j_M$!1uZjTh z4OQldoP>fRdW8?!KW!zCt??vZPg7>nIBdH_U1@WMVIPCg$@KJGqi7QBO>4tOr`Eo> zp>PQ(1R7AaE&i;9AMCrwnfXnrqik1i!ESZmZF3^SzxqE9_i^j)g5BD%?&d^HO%SQT zhK)8~yI+Ge|Lb#ZpMAw3i7UrTBM>FFv^;6N!9@LcZ@aRj`QW3HFZ=y}o+sm~x~838 zp*1O*%N>?ZU_azh7t^JS-cDQr;nXS_t^R#-pxT_zLB!nP>-r#v*~Np#h?i>2bN?h< ztd(bE_`OwqLW04$Pp9x9l1j9bXE#~I`C3hFHyO30e?m`!$Ssg<OT3h0^7zQ>`wq=* zwmTPugYDqAh84mTLcn+(OgPxd_n{ml+jYbfgIrTAc(#=wpqrNa0oawG`9%Z9j%Irl zQ><{-3?SWQz%$(T=t{Z0u`lsKE-vPzfOVHI|0ak7v-&HFi^V|UYhY?B`>6yyni>KK z2${YxZ+zmlG?*ST$;vmk1Oz#fjBo3+&YwYWycVWKw;<y%-V0ar=+(OWf#K#uAUnJo zU&KI}yfln>NSO9u^|vqhO4Fjh@CGPV15*iTko2<(8YDA3{ZWX*2Pxtbea-Kf7(^XL z`cGXL9UC(`i{s(<JiNBM*y~5s`;kOIwjK)%8x8eW*2sLJ9dUZOkJeO7Fy>4qt$?xj zgGjUt!?eajLE{ncJL^b$w2;sQ?9m{IFQA4QOX5K=JFb~%w94R6?ITv!i{YUmZV2kQ z$4Ez-hPRTOVQvqwk_@f`Qb-w~IKBhYLO2%FzkVVE{XYle0?A|KcD$Y@2qW4Yya3mO zRcv2Bqy!U1TKZ-TgC17v#NVgG-?%422-GjA19YmrFe532(GbsbX2W;&Ob<@IkPn8s zl-|5gui+D4BVv%)4uhBt&a8hbsn^Ll-CgLy+JKMS0hui%$OOZkHI2;~{1bme(<|RR zgH(XNfzJEre&QScP@e=<R8{Sl`aF~BUC|mF(;)5C58|XS2<#pQ-`Rxr@A~BALKI(Q zZCbQkhnT4}u7Ani@$WYXv3taVnp&Do0ER3snn69^$N}#I@<jZ<{gKclJyluP{^uRQ zoA_V;u#0yL#Q$&q`0xK8h6~I6fBF9Zd@HR#mglYi^|$=<RZZykB=rC9U*h}!=a++| z7XS5>=kX{h-v&meqyvl`!>D^_aq+uo@PD54e}96<Wz-V-O%{*5X0ag4uP0ggBmWJ^ zE;499E>e<*K#~KW%AKArf{K94xqJcez)oWNi!_)3$AgA|9d8IZJwrLV%?&v;r2>#` z(R^e(W%$Z4q7n5B33b3W{O5OzKY*YbDR5>osWSvZO{9f#6`*tnVbGd;!0)(t&85zv zRUEo>GIq)TzAg=u-luJOx3qY)!tq(T2dU5vot-~@7*ETPQ(D8IT2Mp;3W6J8@7S7d zGJdsL`_=tN@a6FG{`^UU_>mh*c#pp>LMBa6kSh+N;}ahaL~0mM6I_g~i@FlL#i4Rs zax_!sF?c!pw9ey^(?u=nZE}GSkkf{dE(PYrD}9)uyT=3uGvmLftO&%?xzh4PPBK*T ze-#Ka(Bn!0^bL87Scq*3(K|p-aNFhjuqBVr4b03XZJIZ?*(9v;O+s6Bv$N;FzdL4@ z^DKqrtd+>Y!NIGntjyW9qw5GCW4*cU8|kdT`?iAO0mvp+A#@LaHeCU6@E|Rlm|7am z&Ef*TKjnQc2158!^NPj7jngSTof;=X1k&IG@@q1<2$<`+isTZI+K^Xwt5CQ89SAYg zy#8u;M7K{4bkaCM&>0#BhkjH{43?FZ)o)Sud+<?byeWE%B)yPd4`QxqU5>T8b7YuQ zA|5RjTcX?0)ymxGg`B9Hh;tY>@iIJ+-;PKSvd4m)k(V7`IPaPFku&Iyp&A;_xbE?i zAO><JRWo+P;?!U{Nh&B{dC}9|dqcEVJ(Q-f^5Gb!xfEgVU<k|^NYk~_d}03gQ4r%D zz>1HLU6E5c_>cpXl;UV%9P~K3gYD?J$HM1*&mZ}_sYHzoEiG>WCQ#-Top6i~#&sGn zUTA5H(2gQ&>g?QH6zeBK7FNrms<h(1SJ>4PRoklvFAys?zQV1CzTs~V^q{AJVZjeV zpHLBcb?$yQ4qjsJ-vgXcLPv*ub`Br%7i>6<uZn260IisTM=2w(C>cTi2rHTVzip<B zxnJ>A2%m{Z-<q2y$l+xt6~4ev<|`;g93L~@fq<#Sz6<(rNxe3yIFQ^RPuuc4w*qj; zz8;F_-aDDv^xiqGm;4NY1`U7y1poQw=O=-L^Z_cEy{vFJ5r2MJKw|_Nlexu>i7Vos zR1`SF&9-=@;J9i8HyKh6f@oNE{#0yn$%2~Q#a{&<AtXDXBP<5Lia-m+YZo#PQbk`R z1N^;jC)F4D&Aa?+>!YO`-V-IDWP*Io*p)rS%%l_GT@8N4B_j|xk+aC~ns4Ut-VJ|$ z3?D6ZCO)c18mimA2ZMUBtxxv~*|dwfdk_9l<1*WdlMLIj1`RB~o7}2eJv0#DjU<Ms zm(RNGn-f<M-63{)e&Xzvnw4PWITZI#99wE6G}tR_%9a1o0-zwW6cc?Gd+)+t7O(R> zivST50s%OQ@$&mig_JV@f54}63xN#p0`#K|l<JjUbKqrU2uzigEiNwhft<VOBfPN^ zoAxQqIwK0i=QkC7@YOzVRZZMs4TYOB56_Mryy!@zy@`y*+4Odjs`GF|LC{K_A|)R% zIT)-h{=T795CeivgOjfPQYxY1hmd*Fr@NQTjS3_@0+Fv%hX90?^nQ3&OYPZP5_XIG z2&AwdND&-f-aoOI^nhJa2pr8Xl8;y9KkocM_e3!}fpeuOh-9x4v?WFhtJtoPEEPh) z<{yB)maZCDj--M6_0xCWRMa7S^n|O8IzD>|)IVgV$s&(>oPFEI=e7+lIeAESza9c1 zF5bNVqmlpKJru}hyNN8sGewQw*AO*bZbm@#Y8Km(A`BquPm|sD2Et%(I9apIo%SdU zZ1U{j>(taD_4dapF*WnF1KGV!y*(LX0O)#<E7Dbh;5Psw+?ybV4H2})_^}Q3zpisH z=h81}w%P&RGgnVdPiidpZf{l^`u#{JnKSj5zV0J>cJQPxscmavcClBm(tU#-fsAbH ziCKm^YdjjXGjYxShD1O_BaqM2i|W^Hv@;)0XymMiL#4TXw9_5`?g6plS||w!$P9N| zIF^Sp`G7jIUm4^Paz7_96_#HUW(^Sk>wt}cF;jB^c1vD4zv`Hnp{s8$!-mgTZON~i z<XCSo1o>bvg`kH}FuXR@7c8kpC46CxTin35-m*C6T;wb%`HYQ-n$Fj#B&PfFa=N1V z(fB$g(RSaG+o79MPa>C~`D`-R)ZT3f@{;y{D^`e*)K{ireer{#Hf4>o5aXoE+(VoO zTsw+~@edE?J<`kgh0JB^yv~#ct*=g5&GGmD{Q09<))tTcuyvx+jW|{GO@qsY90|#? zG2AsW@N1+w;aT&S+38XR`@g9+Qzbanhu2FYB&F&ezg*P_qu5Z2=uP0ogH((gk=c1a zFNV_i<D{KCIy)N$QnB+(%X_R?_xI&K8wZxZOW@>9OiY}2+dh#>y5(7MeY53VXgmsH zZ>f*^TJ-)tmeb}~;3z9`Kb5qbBbU;qY$sK_@^$>Ehwsm#eCpncfTBe!D2GYU#LUcS zD1kBP>WXtVCr2Lw&t%C(-0#?oSI+**CU_#*jzHw9m#GoN4s-DG(#u!hOsztI5+sJ% zDg+cy(D{b?=ULe3YRa<k)}VV!KB+@&v#cX05iHTvSd3bJ{VMlpo&Z7bol<S_sq?UU zjF$?h`tPg+H$9(o2ZSex9qLOynN@po|2DZ$02pg#cIL9@br$3Zd47y+DLf9RO(1{t z8lycTnSP@_Cnq?@;@juWzDvo=2MC&dG>3N`qTc5%?O&7;K0v%0o%MO<+dn|)U{r;~ z0NPb+rWJKbtwUyPW`n!4WwqOrt6mbz#8pH?6Wl?J)OkHK5Z520ddfh6@lHJL|NJNB zN}xV-zy*HTXzha$+VvP&V~z>W_Y=ibMspn|#HqIaRgPJfbm3QOaA{`XA4lS-iwFqL z)Bepg`oj|kVes>VS^}@LkXc{C{k_w$Fs#b*zP;xs{eEPe%?p9&G4Z}FP3c05Js&ZO zVkZ$k4F%ODJPj332h(jRg)v&^Eh!N`Fvb||No|QMMV-#i&l?<Q>-(R(VI!tRtf^Ck zZb=+>qxV2@C%YJF%G5Hh8X=a_o3GH@7)yT8mBjw){>$gtdV3fl+;0(k!tr>vQyz7A zi~Y&Ly48N$_jqp`_BV69+$XqhefantM(G2A(3cl?f}f05x{<*HK|vIkm$s~`$xnat z!f(=-ng(l<jKX<PNycA83yUC;+Un+krzP2sLr#O9&>WxMq(1HeFbA$?-9GJo;V*Kl zxv7;oEjt^WeY%*BV$tOD;(CJzTz<uExE?Uw0bh8f+u1`JYpd}#!o{m2ce$Tzjpl5) z4}A(=l!<kIXafj|^Yzvvgr~4DWOROiuc|2ovo8jo8%mW;k?U1kZ*_jLr~A>s%dwcB zkSG?z$Jd-aPf!yQ^kj+6v!gBnGK&}w<j(Y$U^!)-PqBT~$)Wl2dc(h9{Po<=jHf+& zIybh;^ae)aS*7w++oQ_1G`sZ*xCvr+h$S6c`tdr-RI#zJ-hVtLMD7E|d8S9^FJJDC zkK;)ucXaT5sja9eijbX?wv==|r8y@&@tFrUAm4F`Z9dq`hDn3Q)6L9`D9)|G)U$=d zrOyeO5U_JA*ma+QVD3S0(~YU$Eo7e0GAbhyxi~rP4#rr6-k&{|8hD#AKQTl5;AyVY zWIGDQcm<?;luz%42NmdyRF%KRSNMOI<-Zr{)jcoyG+QqN_dVTm6A=YPMGOv}dcN#_ zoraHPUMBU*Ta?=g!q`G7Y&|{QhOKf`hz7VoChEgE>8~s$27><Zcd`|Q$##%1dG5J& zk1|lC70hAJie4o*DG^CZKB2+$@ZiIb<TILS>QA*y5b$J!RbX)1bAmoG8!CmpM(FVJ zH!VGV9Qw@qMxLsn6v{4~$O@?o!SI9-4z2ir7x~nBI&)i%p{r)~OPb7+c?5;~opl7a zzRYn*W4|d<_X&WRM+h;(7i6#m-&R$TUaL4Z+B~Oo-QMQVlYHXaztlWpPDgk`#Qx&i z>)GRA14P5}vu22bmHCowZm?*rj9g|DC-O5})puDx^0Cgx5Rt?B@o8VrK_C5rdF`=) zyvH>Jko(Qz{g2+wo?O-UWxi+DyznL~wIS2U*DfLX@#Dw9$VmIj^d54*?jIa*ILTaz zD_Q=0uzT>L)N^tFp5_a!*_Cfg+XpxX2Yi^q=2m}yWpK*HaR(d;JnTuX@DF;ENHev_ zrpRu7IMgJkS2Eo@?gAmWMAv<t;2vtc@oN{5wHAOuv`_+M9`ZR8vFW|#$&35^<kpG? zT3PbTM%xP}A=hIPNQz;4A8W_Z8XEub3hljBH^pc@w!6DKa@q6VT&Je2%o`muXx&9) z&?;Sa*S~n!xI{KHeYv4sJr$9B)*&7GA!rH(MQln$ct)rFmZ*1Dqw(Y&q1(L&H+q-I z47=&6hF<5s8!q^0y!#vnN;x&>E_Og<QcweHU2#dym)NUxrdGEe@{?26lVhC^%AJh) z=EM22w4n7gY#+w1bl9L*P*fPmsQy&`LGFJp#7CEV;#0x+QpS~M)XS^OL{*({r^0s^ z%{0HgyoG2O7{Kk-{fJwl5c%rWS0gLGFINwLX_Cit&tHS=*L>|Nl2j2oR78G3{+A}G zaqkyc<nNMYIIXB?E7D4e?Cb=~$emsvA?h9YVvh<WDVbOyyXl^kZT``C7-&PMFE6B9 z)t6tS`JzQo{l!Euycm9-h3?;kov5Wn(wIQ-+O9aTES3(@(DDVV{O0M*rJr|)o2Rg6 zLH0A<6k)hnSoGIGj<F!}R33}jVNlKDMl^JE;MR%c72BLq(oDOPpAxX@>SAzp*7J0B zG6sc2ytN87`?{t>w%L5+T8AgmWt~;=q%D_<YW-|~_lUPu+C#+t*3r!$mCh}DOEWU( z3I07j3ed--y(A<X{iDXZK7a9`v#+o1;FHVrSUPEbJ`0EO*!97qp1p(!&P@5ajp`%U zU2ZHm_vvkJN%AHOmic8EE5Zo>ai0;QoEjT1#z9=;o4;<Ysb1_;`0D5RXkUrCVv>j( zqGIbje0ljFiim}k`E#6~@al*Q+xk4A+hvUh1t_H6)zyiZ^(SFDI&vYzh%0VS?>O0? zbYY{v6BqK{xpT1A*{2K-8eUc+Z?qy~lR}~p5v-&%DQtK?BnZS0m$fjqR}?!tbJFm4 z0<FlrD;|1fa=)2PKZEBjqABvSC&+&vXe~fRd{(lN-Yx8#n7|Trv2IBgJd!!iU(Xkp z&8E4uGB$g2wpv_Kq&M36`Tv}?|1N4VQz=ttHs3HbWB4@I1fpd8^Yg7qNG#a$yP)$a z(ig9i|KcF4uFh+I)Y;Q>KiVyqTAqA=ZRFwd^0H6+Tw1v*D=hR@S;+dO5~ZK%_^FB; z`~)ncQOx_?i+j(iR3s6I$o6P~)ZG(I_e%~E#Pnc32k&W-nmYu?S#P@vg+Cz^Ps4@I zO>#01hBqQ83K*?(aP5Qo_KSKsGk4hgZKZU3WhwN99P9(qP`t_t2{GQmZ%I;cdb##! zX?|XefxuyR=j~I5>(teH-A!Gk*Ya7IWhjU%YTMe{T8E?c{BAh^{QOuqXHHA&&%iHc z6i-iKg--%?V!z%`Eu{rDS-Vs=OiU=`ZroXljEcGk;)VeRFE$%`HCzlwM9`2|Ii397 z=GM$x{!Qfb^LDCNRb76t#9|np`9?eBG3k8&OA{6JUH7Em0hEvJ13gAQ#c28nbwORD z%HrtfnZ@1WwLhHa3yJO#d3K4b396I9XNhbhB}*fSoFRL-ea!rFONnAUO||{?yBN-c z&aH&!L^@+{;KedL6BpdL_4Ig)ZvIa?94z?-nWEZ+d-Jj+ul`<QBG^HT2=|VrZHwp# zEy3eNj9q-?=i&;DHgA6S_vNcsS;fgqckR8-PV>c;lwO^BpC1Ra{oSkCnyPgUwhq1e zRA6H|I;I{MqAaAup!$OwmYdFd*%1;{RL|$R7K)S3me=ApqG?*nKf+|UR%Ja=Ljm*) z8X}B}@0!HTC1Fv;wfhYP*lm)6kN-!Bl1!YES|%fo_c_6gM@8%eU?2h`k{W)mRdihL zW~O{q{~foEL-h!+DT$nf^sW(<%i;Sy?)9v$M2FXebah>ebZ_J1<0oN=1ag_P(J%?z z5G#xy`*@p&z1Ta|L(w%m%d0giBijy!xt0g_uR$$iF$4l3P2z?fz3aun8Zl_+{ieBy zcQ!o<piubs^C3Tj>G^pd-hvmUyApV?<g)!9POqQHn^@|rs^X816#Kncx^1^Mp_k)I z%gjs$-k-KIvI;y3LWvq45KDXpi}Uhi0oUq?W1M?u{Ud{$lp+{(_&P=bxBKyZe>)e3 zKl+ySbzdJNy+(%SHYQ@c;&jgQIo53|;adpK+GHWOy8+;afQ$V;#M}Z-9rUrEEu#aT zFeLYArdP_v>NGA?AN|z);en0#9Gi#P7C{=}edQUB8W=H?+OFJLno~x;{`2cI&oFWk zlD4+4c%|@&OP`E(<+(;bZ_S18THo62s0481;)qlZpvA2jbZu2g;KmpIb^Z8c?!lwO z=^5i;M+z9GcNS?Q>o2{0jNw~PLgR7K2T>4x&PfAbWF@f32K5X1wUS;VG|OF6#BIZS ziocmF#W8=7RlEo>e&D-vyrWv<b{6raeXI+>wlZ<ziU`g%at*gAs-YZ>c=5sy4nm;6 zciI??axSQxh=(a9{L%_pIzc5m1LB1*bs8mQZ=tq^Q9i;VWbPtH$fR#N_B|{q+2Map zLlQ~(?nC)xUm?@#&};wbjOMG_$sAt8vrS!s+ms>^^;^RC51x{bKtu9W?_KAi%T|Ux zr29On^O7IaqpqM>nH@$+7ATjfD$P<EA(TqILrbvOU@L)WN(qcMzFgCg4aS^5c=mfE zw-IVL7Fe=WA2&h!Wq;m6sxJ6qq>2}Q>l3(*;OBQ)iP$-&p4Uq)o!|K1h`3yv%yN)~ z-bK?;n~UokyWyaM$<-+uVmpZsKceiV+`H&l(buolp8cv5I6XQ;z0G6AplJ1YR3R5B z^B@;;B8ME)C(F_7h^mdkZ{P4CLeuXf#$exkV{<z{$a*L1BijN;`4Ls}QX@GVL7RUC zGBWc*2hF=pDNRgG=f(~`p^G@;6;0L9nHIo$SsqPeg<Z<>>qf^zw4blN!6kxhKfw~U zbGY#aQRTKW)`V7jwH$DIkfi0=1=?W(_gk^14}$l;^-~ECz<aBriSjLto`3edTm11@ z$p?!urOt0<A=(tNNINK=(>4RbCp$0nV3K+M&=fuqBh`l6rS-24RA?ehM3k4tBDNE_ z6gPzv4Q*_gj59~Xs|-b3+GgfEzae|b6Xd+}@_7aF+JT?oI(o;e=GBFV@7%8c!H$C- z&1C$|?2c>Tq0RHl1SUa2GCteCt$+6Jxk4bjC6JA|K{v2h)AgrPzP{2>%&eS$MldCB zp)Il{dVW(nBKg|;HAQ`OZ-Co$!A^7+@2W09?EP(#DfBY(m+2B`!*HVlv#U^RlNg*} z?P>jX=TF$-qyIK`O2qmR?~P(9&X7N{dFiPNt@OI!O*a-1qn1HV=R<i*VcKQuKYtfw zbfql)rjTYJE9%4?2U-mxA0LQ%YlO6?Dci5}3)XLJ<YlOJFTy?(%e8qnG)yqhfA7JA zo6%W4ZT;LRh|h|7L?ps56DEo=i3-GYpb<uv41j0Dp7T3TId}SYgEb8atEo0FWm=bk z6${?09<r~2hjz=>#Nz&5BIDgDf-l%@YTjc1qn@_DgL?WYHo5hVSTJlzIX!YzF)67V zYv*}E9X0%=qm$}@*T^PyGNzVTcE8qv$=~?`CNvK@rAFul2C`jnpx-InmvnHKx?$F< z#SlAr?EeI6=PZnNc2vAiyXI89f<xsS;J$^<`;{bbsVTgt-UPv}YdNGin=Z3PnGmSZ zxH|<Ux+OX=VQ8ob`GHdkd4z@D)0nP({V43jBXMM^ZjVpBV8>J#$4m$c!mLV%+WuvR zAdJ9`UG0%n(Iz7LiyV+@5PNx(1MQjKeZzoWyv1q#wu>Ip?s$yrE1EUdgjOfA95WAT zaW6TqfiX!ca`ROJk0Ym2s)%ym$k$iWgN&D=W(!?N*aF&V1};T_6zn%W(0Pvw9<$zj zQ?-I4U`OzYv<a01CP030_p`mzX^c}8$#?&-dm>-wUpFiJLN=jaO5M%SVPRDf8PK%q zI=W})FO1U;qrgnHSFA!Kf@^~+T7;2cf}=U>!dv|52i-Tm#h&dViA%HickrC18GLV( z$7(HAc7&d%E7i)u$I(|G84~v+PHVH?^D5$2w3%$#<7YoPpm_xWL41kHPn}pHPRrdS zHOc#T47cheVETz1szN%6z~{qH;Xw&c%jlr1m7Ry@8Hv8r{>`wvf|9FMoO9aM?u_6H zqT4$Kv0lDb1xkF8PQ0543==f8QwC=dwWHr0F>}@OngsMoOffo=vGmtABEbsz!MHoF zC;nrQ#*lPy>e@`kgBgxDOsD&sInR62f&ign(f*-gCU^#LQOdhov4O@663$90=tZ)f zW^0PalRxt0HNWxP+=0<Df!iJnj@N~@z5cle=-#A{51G}zn<Z<+h|cc1&&-<cZ;fN( zw?&HQsL&B+#maw@B{VXg<8VIJp?P|Twmc6Wf9v$)3&`|#ty)+H;7L7y-*6!s7FhDA zz~SNV65#>mEX3P2AsLzTpqyWea=-Bq_l1>H0@5`43t7m-C@No7Q~d+Z45oZW^L0Y% zCEytZF4ZK;DEEKU7x8$1nL2AV|3|jxJRdfb$Xbnok%|<P&f`(p5QbdSH0pItH-7#h zpQF=o#E?~XuA1qQrDRD&S4Ne*F^n_{r=zTI1xq|~vY%H%2bI6~M<yi?1`ZaSuRRWV zSZYlnPiWT191()A<;HVi!d<~Z!hMU_Yx5XC_EaMhz6xG`c=C%QhvrS>BT5{RH+XwO zS<$iTCXhWGN%~F5bhsC%#QqqUED*X8_Rrq7JxL<ZYz+0Dc|1(BJi)^0&+9fbGu1K< z!=ai*PUratlMO$lsAbyc2C`jY5`uNnG-95q^V1qOdmNj-AE*N4lJP4JkfR57U7nVy zHvZ;cZ~qmpObxq}m?ZJjI*GuDW|(m^sT3?YBcAf=MH83H&fUOhW}@NZ!iUi4)&sJN z%)a1umZMGK=Wg#l`BFYuhP${Gtu)|qh!2jI+sG#}kDR-m2&{R#^(EgUl!|uIRj8zl zWSX^KR_!^|ysy><(>9bCe8|~o`5@`279#)iIE&hbUGWU{zrcCO5rgrSg}JaStAVw3 znD*^M6@2=vEP5D4l)P5mJ@yaA#p!=J2zQRk*FG18<FHV#nsLp62$RS?iumtrWr7~3 zk51G=?Hioma?FU9mKLL+GtHdfD5i2=mFQTcjkE9XV~n}+Dl5@7v>yO|Fye3`4=vbX zoJHPehr(c9?D=>MyXtZCje}{O_TYmn<(sMPuY+$bGpSj3aG5lDl!wq8(lIXY(sUO7 zeLPC#MAC3o8}Zxz`g_3@j#sl-j5{I8x@tM!lLe`Khi$57Cf?yX^mKMUUe&XmtZ5F@ zax?Pnie-|!)d_8;(as08;{)#^%Ma@l6!+<N%gRel6wA@CuOx8xqC%JBa8<#%`nv!X zhB1|e)DtWMMZLe(S3z{;c}7;WJdcP|-=h~1uD##$E^<PH_`-WCG*j@i)8X7#>34vH zr%IPAytRZZx3t?jBh0dkt}OI6?*W+Y=@bAsGbmL4DM@5`%D1Zku^d@7Et`E<LL}_2 z1R`DvAILPUt;x-LcJJe7FZA}BC@uHv7n3tGrkb|R)Otn7bc{^a3Fv&}F%u?+!jGTb z6DOx^7{eGPbA9XJlP1knYpBo{q2SK73^=73V(F=-die=Gls33c0l;qhlBlwgpKtE4 zynRa{kyoRun<qMbU=xhB#n&DAUQIqDxdaN>q}sE3m_hdk!JqheQCI;g2Uo|PT$)v5 z(w3){-xFi*;eIhLZ>Ndt&`=+DhQ5wQAciooeS(e!<zA}o^(6r%i-}4U=8dQ*TXyr! zJEi1hLfpN6^Ya8@Bs{XY5i(=?pw()N^GU||^+BK8rrI>vqjiUUJcDQL+<q_aJ0eup zYyFG4;X`(#q5B?Zm%4^YI-{~DY5ehM9J}k9lKjKDow<P@zpFxFU}_p2B?%>7{QXw` zo`x3XW-GKC0S7uuow$+q!AGZxDm405%<{;$w`vBw0TzV_<-;a@dv|ZPHvNwgvM2`4 zZ3Uc?P9HWJGNjWI_$`SBua}B$hr&q!th8qTQ=Pc`XP=?{Hg2SO2uN<#ic0M4p`Q2$ z<<t))?gdl;3!)(^xvf|ZdL-ENje|Wl)^p`N8E_AU$ls2??yd=Zn&1btqg=2DolQBE z=WU(k%%4|yjzB{KFa|p;pYxRQ5gPES@pmyfXN<_x6dfEK*t?CRVmdT9>ze^mocRzd zH}`9pKg~8Zg@vrWUsQ}q0U6R^JtlV;h_!iBTKZ6sL~+WQW5z)!HwfAv4*Oke_+*AX zYt-H6HvgWz{3`+Tse#V^&Hswt!{1aUj%|cawPX0eBU$xux?*EA^zWP72n2++2Lfur z9U*#ddi~ggmSsOF{PxB;E)Mz8CZy^WmCa{fLT_R5Ym5+vXooqBH<S^u_KkLEaE6=< z6(go9-EKlC1?|J}+7Vmv?Hs?8LmE1QMT1r*s$uyvEv^T1ktw>J_qBl_QZG7ahDVQp zn>LT&-jx*2+RrFelRWTCds2ANAT5ce8@tYH?{+9r(f#gQn>Yf#qVCSdiY=xlCI%@> zoa!D{8V@Dc)C*ho<UWcaM6VD@f~m|#e`}Wzr$-y_O0V=Iym}a1!ble){vjAP#b+N? zdcUdLl~Q;dPb}NgZFsF=Ue>tNakNS>XyI>%=crhi9hE{2otcTrbVrFQ`UI13@Ct|d zM+Lkr*WiwF8yz^B@Ah17Id34v;p4bIn8XiJI}SLV4=3pMSN{4rdjgajhu#2Nl;~lC z1U>OP@q3%1$2T#Fi+sf1N8nuhLwWq%&`*E!PK3g<r*L0ViCad6+(>AAyc3Ls8PeFa z(JFwdm-Ly_CR%$C;srzMa~i-8FSFI~wldO7jMP$&3mh^-wzcaJFwuN4hKM4Fi$U8V zDT65&ssjBIPcNqP^bbARUFa9q*K>__#Bn%-nFtmklS*}aDuK`NZm}~lBtFvcQQ8PC z-Nd1aUhsQ6;ZSdMa*gv5D}0?w2cc`hKK+r1{c65W{~Da5aDs5VSo*qAa>31UDAXfw zrY=#XHPg3~tNo@Q+0w6_LckGxn_B7A4>io5L}5arh2GAR2g*(Cj(yjlq*isaQ3-}8 z{@SadwX9YMenJC>m#=E}9{o5mYl0u;-wDkb2Zt|bU+F>@kp;A6%@%G60*ZiEzTq@~ z>iWoHuZ+lIpzzu45}`8ZjX}I$*-F&nZ=uOrAFWFL{wq=<b#|t?-Ok>UhN}+B8K7OC zp&>!S++u}6)}!xHIGdqiML*fQ`)6yi41eu>@*+^{gv;pIz{!3M@#0h0z|WtLKZ^M@ zH0bhs?P4LOq0fd}v)IPU?PEWQ`~xnHQ+LPrfsLjh*rhWeK@*OCv6d&<e*GD`pW-Z7 zW=i_nUGU`<IA5)!W04L;3cUafA2e;$=^4n0<myt?;?H1a!*0Wfs1F@UqJSIu>Cu|x zdf-ESm6^F}Qiyk>Iq+xZwycJx3ACya>w70s+uG#_z*awJWT3*Bbo7j4Tc?;D`c%%= zNQK>;*Z`FOXaTGqv_81s1eGD{=sCy7G1-&M|CCDPgOGONv%b|sNM$vsMA#~ji-p9B z>vXMvkX*aEGUPhk`XkpS0;h}CEJy#zH%(8Wk@JHi)Hv!cpv-y_c?e^f7TjI?0bYcZ z(V4QrPy79$@%c?Zo2wt4ZAXRf#M2wAP>;|X#hJqohFe;2`G@k~-l3BNm~VFd1UFx6 z?Iv|a?dT619ANUALZlf8jNsBJm2w3DSX->NVCu0Rt4a3w?hLbHQvGpujBbp6$gelI zw7z6{Np2@%nt1nExa6?UzV=?XaKUn+>RBC$XX)N+cq4Eubb7GDNJk(<;gPa`fk5Ka z3aJ7qqlqgkr2O`)SiH7>8fB|bfOpBMv;F&V!D6VGk`YHaRk%I9m06aGpwfoVilyVp zFMI#;M{hRoxD{QOS*n0N3doOv{IpW0-siGMO4B>8nw18(K?;mX?IPs5)F-SyRboDM zPbIqx!2k2nsC@oP*AcpawVkg*oSdA+PJix}_5-DGqN4oW$@wiL@&Q!@lHewxep6^H zrN`9RrU!5Q`Y!rEq21XI+qs__WY)X-fk2a%(pSQ64j3s#GZE!EV7_xlgeferpRcKq z;*(~yB~pnXA9s`uW1+`0V=d5SzWU~mkMhZb9YCGo`vrjMtGlrpxvf?1FR3v=Q%dLV z<VgE)0OhmP!OPL<`T#;U&Rte3_{n51hl**>F6;6jaF}^`H>Ax&WYMk1pw`2Cms{bF zJ}WQK=F3AR6uhSekFV-#5%VHbpHZb{6W}Eptj^o#)BVK8#^!K1#>Ju>jVDZn*L$B* zi`!-pcWs#E0saHT)7<B>ELz;efLnENXk8=A3QU}k?J{M-5f`Gw0bZ(g^6wy}Ery@H zv9!TzjD3Eo^~;yOYRp6>Lg>QYjRhK<^f~%<A5MGVneNfs#sMFlUr?ZF(+Zqo)cI9# z;S?dj3gf63S}7k~g><nfhj22aZqv1I{?*u|%coBLCUd`O%=yx!9?HsSnI|o?9;Grd zum^2$n`lP~T;~FPw(6@I>{UTz8$SHyTS^LLTbP41Fh!juP~zou;T9CxvF0CrWhF0L zjTlj$UYzzN^x~#W)Lq0gc~^)5v^`pE&m578PTwxH)GrQq8GUJ*taJ<feP}(o91a*! zbmtrDiaKk|eF?wQzWLF%-tpb!LYS{1qUUj`s2RksvL^QL-Y|onoAlR%bVEP)`O(f_ zA;Nxy?_Oscw+o@{z<XU_>+Q+c2k=3D{$tF3FnR&PU?O1#sVB=F9m9Rmp3ooIo@5DP zasFEs!{bz1S|PQj4yIf=UF8T-sBs<I;*)JzcZLh~y4)u}-LLtL`A&TM#ABD`Zy<Kd z=+Di3^X|Eobl^mnXNTXCS6^*YWm>B6;m}-q_U?x8xf<wK;*fQe&UMA{wB{0q0@G#Y z%b{g4_&W8GOH>d)!T`D4U;as&e;W~TJ6El&HAVNu7k{k}U#%YKVpQcik-k=3zwgXY zX!<yeMNpkEflA=(_&?Q%2|!Ewm9Q`mKTP7Q`%5iUFA-H29uG+`=ro|+%0K$6a9B{l zQsVym4$Ur_Lwt$tNI9YWeX7*=LBAT8Fj;h0(>D_c5W^?)Zm(@2cLLsDz?f3m)AT2s zNBywAkk_3~6Y1aCgg8dmy+aD-6u9%Fbc_@V-9YUNbDGub4w7%dL1G%7;c-z;&BeuB z@2wRwyQ?QoIjkPHJXJv)LGi~AexgZ0B0TE0aEg1si_T68&3<3S7hRg_#wRC-v%Yon z^aL=2MOP@^)ch_fX_M!&7>hpB##;@F*PFL#nw|q<O)mWXrs5}Vlh{Ca=QZFd-<gOa zQGrWORz4-gHoUPX3<RYj+AwKF(1nhkAUR3k3R(2#?=fQ#jgdb<RN1r#&G>a*g1E)R zgBTybyHp~MEfI&7_An4fr*@6$>&{n}KHcMJ(>zvPAsnE2scmxMqd*@2Tbqc?@{a;` zmVTCl|3kt-AZPE7;i>io`hC0CuRpjI!Zyh#-rm^>iBC%va7&t47#uINX%&cX&<xR5 zW7F?_v04knhf2y?OF}|S<6!IF&(C#ScZXcsDr|S-1zsUPp6jhGK<fP95VCD;ZU5Hy zLR;IQH<zx`Yk}o(>u(4^X<cE``uaHGcYi-P>y$Jgl`E{YJ0wweXEkvPs&QskjsZ0R zv>LndYsuX9+<9TOo=18!7iJ2n_xCE{Jq2L*?qw0dBM`WnYgeAQV79evYsD0vcNfXg zZdI4_$+rQnpWP$D8plA0GV(y**cejm^1}eGG+H_g=O^<Zxp}nZ6Kjf=IAd+iR1z0` zetshVHZzBT9X!y(gX0Q-`bw0;ISfMh&hYHdsgBUmwQ!A%!RG8d&|4C5!iBa#685s) zS1nZ8)DH`7g66}|hriI`oBch(CA<0mu=ka5Rj=E+6BJ27I;EsL1VITYX$2&uQxOoP zyA(vaI|KwIq*Do{8$sz#kuK@DWA1(S`JH?Ax!>-`!-uud#RBGkzA?r#p2*~R=hS#a zGmY=LMvJ>Oi))w>2ULp9u+OS*>IL}?!Y=*UtFLdExpk(9yWD^%4JLl;&SjC3u%Ef% zvQQA32QKcqCh}XcjW=CAyd>z@tL?fao^bD;sqzy4;NakQ|C0(iAB=}<NkOb^o8j;} z;=j$GhCSeG(QmYWV|{dzjgHTc@{RM+CG;hsWjMSg3@w4Uw3}Mc{^U2NV<rg3uvJ?B z@rUQpEuxjHWLcz>^xH|Zym8-E#I-j)*eYSb2%ZxX3Y|KGb3Dk}M<L$u2&He&_e2l5 zo}yFl{#jcC1$h+TfTcf^&Czh7n_}D1=1)Rcc9G;yfS;o9v-o|Q<He~>oiWPaP1yMT z|FQ8oI61W!(VZspv$SP3+IowqEcz0a4le|+BQr{na8*4CYTeBC@;J8M4jX;+@Yd&@ zXBehph8ANZpP!XVFD8(s$A_RMhsxi%Gka^`2ONj>qwZZbB@`o4XU?CyE<<)OM%>C0 z3}{E$cW6Yv!a{rU1h253B+3gq<tq_ydj6sUqP!!5a^z0q&%^s}+J9I5vk5zYXnsCs zAkG%^z8;JuR)_C!H<>Pu4G15|ll4$;D3r+9H&A?a+WJry$qP_8T_|2Ib2ts-XoWRg z24wu*X=5qx-|q#CC5PUr?1DLk&PhYJRn(OGFeDIZp2P+Sc3_%75S_w|8z8)NrW99U zehf;0mA>e8)nW`RbkRo>ppHZPskuHleG_toW66tQzE8&9vRIvKXa4`#wgJd(TOISJ zd0&Z}8i{}6tbf~yWCGVU+zs;AjI8e!qoLygu|&j1gi1Ni%SplFF_P5?8^6m$A@A5J zyFHQ3Amhhl5Zu#+^Yn`&YrKn)JRd**?x|CH-c6b2rdgC+S0tCzUPb_6WMuU1*^p+E zZ%(j{dEIX|tzx<AY*Vq)etCCg%hBq%<};oKOyV0b^;&++fa=S6ho<({I!g<j0zD6s z8RX?Nv}YU=W3rm=2w06odh`R=poem_gW-fQ7VRSS>dTR@b&b^|)^I^L$!$bkOeL~% z*t7s@+j8J%df9peLQ~V4_c(!jD9aWo5o42DT4RFJjTYQKXE52WGsX@EY8bvF&%k6H zT!HopI*^iO_E+_@ZZ`=^a9Ks60@DoaX3vXLPD4vmcVTK_6O11ARE9V<otWQiHQvNM zgrqT9zqTBob6j~v(NPfYU!37-8vd+v@EAEsso9FQ$^9Tt5*QfxVlaz*JR&Sk+_*od z?<3Z=vm;g4Mu|6HioQ@#oGP(}Lglb_e>9%G03XXi`!DBao(ZK)jL7ksLAuLNad&48 z?N@z$ecF;YxKwI3FLxK2n+;dq&&Rs4*bLT_uP>6y-z|@MMHHI$5x1?5!%hOGGF{d8 zH)9jC)MfXPGn)4`>ad7`A^m3HRC($ASJ$GE=~Ma5V~zQl3lWr5#fo-?4yQZs@aQH1 zchRo4GS2QwJSb_}-)I1mS&oQ<!ceYLdKdv=+9-*cnOW)DN+-UQcDfT|Sy_H-K}xUV zC#lzN+?kk<!*T7~>JXD7!4c1~Ba<Z8VCS(=rTkf4eQ`d&7D8I0J>wZy)w0+TMthhm z;>Y;mL`YIs#631)wwN=S)q23u$!Qs@7G*Pnu$7F0!o=^lbvaF~)4lKv5vjF0*k!p- z(mwFu0$@S>%T+xZS~wAG4~fILh5^gr^17)AlwSetl%XLmvHt^D!ICM0f!3){t%ASY zogBSsD4DrXyW}dz_&SbVvAUvSpLs$--uTHLOEPUY9x*%H<yCLORrgzqq$C}vyhA>H zA_Iz*l!*y}m}iiwGB{=gokTJtVt)4pVOmM@)8W%c$*p{}2g*W#!FQ$ZSh~q*$)7}l z&&dJL!eai6vb>!2p)9{ho9z2}$@qA1LelSOV8`4dzWoNib88zTE#2;&nTCkw$(mqM z-m6!g`_>%oS)Oi4VrZxSp$0W9^(0gj*^cCsMgtNJYnvr389zO4b%598F0S}Go4i@K z?nTEuy+wS1GRR8<n(LsqZ>7Nw-ZnGDw%TU)4N#3EFCg}WU2jBGrrBc{=G`BzwQb_; zC$)P91-zFhN6Q?qj|irl3~miM$z-W|@cEe_^CZkwf{u>_sK~Bj{$x(WycVRV?O)Q9 z#9?X^>rNhFtW+y2>ti&X@sEo^U4u68*3<03+q+AjI`@+Ry@KBX$%neXaxGfSTM`Ck zFoEbC?I2HHLitHp$>yx*6rP}=S+g0>A>Q2@0;C6^yY<*~+^vcMAj@n*DtSzPO(nGl zm9+9@j?M!{dDTzZClWx54I$~3m_@0h{uu#<Gq52FOm;r_8{U5N=e-8;c1}Ej%|o>z z=720uo2;(HyL5B|9xv6^k?N5m9<JQHu_M(%GhO?78>>5pl}zo$&kP#b_ZAAU+LjyM zGN~7^7^Y&gc=yYP;;F<|K?m~rS)6BXxbgy&(wS0y6j*581<ikjvS{T`W0?^p#m3%N z9;x3xzRo^f9jPMRt?oakHNBil!V(uW$=do_>`xZay|AC4KGInJ`esDO8~6@Ic#rP- zDN=^^{7=hN?}MZv@%*l<3?G-g7=L{o5ZzSgud8~`(f0wR6gmCsPs5w1m1(1dLP4n) zCAc9us4VVQFQiE8uSmx?qT1SaA2%l+tD0v$1`%Bxy9UDotIbo%lGVG$!otGHFz<fD z<Cu!~r3<)PHu@6c&sRQ{^L>9)@Ino*4Vkjt+}0!Hu%#A7{GMM1NXGMT7OLm4v!}1w zi&`wd1L?HTXjFq<6+`r9kvZCU56kZaIQ(KcERozKJ5~mlu2q1X%C0;5@WqQ;aJAts zRqOPg3*Yt>Gd$8fD8e4<kCM?L76}{IDD;OfM2RH%h+2o*TJfBF9>%pro~ooy`_TKB zzr7jl)dZH2-GxrvZl6*Pf0ekMSlF1ex^!7G?X5AAIu9Lfiwo7n0C773jf-bxUuPlz zyz;41u)=K(bjlQkL?Gx^Z;ticZ?xVO0rt+07uL^y)g?wXoQS*-Ku%qW@iBcx#aOKG zy1mMX-oO3<MvGlnPXpuvnIEsXPX79JJx3u<-Q6pWZOSd4gKL}dt^}cO$an|;zCLww z@L1B{!Yl&6@`4v%Glt$0J@VGlU~KA1=@HHAd+pC*p_CE?qnpyx894kt02?xA^yO)B zA#Hnhx!gr`LI<Go+J$#Jvr%PDS$rqU_0=c2|9z4oSF7r$7L3zGmhK!pbbWB#A%VwY z>TVq&4ea<ATSFf^T|?Mj*xQd8xZs4vJ}H&MvcQ^n`Y}DY`I=0+_7yv@&WfHbVh;ou z*vm8`n~`5-Y4J}VsRo3GDwXT|Yu%Mj1)PxAdx!(DG<vNitLIu8nJfi7NNzCXi?JVh zT3F;xITS=jCFR&_cR6cPniMpD`|N;T?seIm0YrI}NOngz7z+!Jf}&`|DcRkpr?dCR zsymnJiWfDarzPF&>SS-YiA)4kTU+7`S`Sx&Ir%s|I6;vcLmi(N+B43N3_h#tg%)pC zI^{iHm&Q~ozvjgLhsd=&EyGzsNwqk;KrMdWTtg{|FQ>}hHaE@m#ix2Ml!x+xu76$f z6?;89xs}cWgu(qot*(=_lej*lt6Ob4KJ!JO;6xwCql;sG8)X?YUTX)9%cf$~6y=n~ z>pF0$eE3+#yPlY&Bb+n(dbe0ncTqL>xvqv-XV!mb%MmFIE;QXE+)XiU-g&8|F7hxC z=EmK_>pC4UTt$I%{gY|~1)KJ>$gY8Z&WszI<(TqVbSYGzY=q)+mjuG-JDyo+ki344 zS>)xEkfVOx!EL1W_&OS$1Kjer2DEXHT~?qyw;#BD-_u{94B5IEh<?d(-h5VCm5+lR zviD<jfH(;<gJ=)rwf*uEvhMd{PDRKkyXh<jGxliSfi7?y$(Ih_ocsn{7xf~un-%uU z-xmKYjFuP%tT9f*LPqk}M{TizA#n{+KWZx-wl+Ms!Lg~@^Xu)V+u!5C1~p@%D4LS` z=*^9e2>EA(8m|MgoMn}=1OImJ^}!<91vS3Vg9q~?n@w_LfYN<@i*<UsalU(`e-rd< zqCxUvJ<Ur{fGZ@ZTX1~^>9&DkLQ>Lu{A{MO=4$Ids0q1YsudPDwRJRU6|cnH2m*Iw zEbJ5QEnP*ZzfLiEMYG;Ai~carx1*;za+f;|5K6#A6lBIQ?X82dUNT$8G;?6<alh6t zDXtiDE~rx^O!6<t(v%&ZheOqRtWsm`_}TW&vALSS7>|z^N--YcNhNRrst0fPrMQ@V zWvMz!{??0rWPEM#vlVk(iGT^lLgL~k%xOFO`z^eb=tC0m%FHIu#rKTa32lPg`ug_M z9kQ@&7C`JkF&!~}uWS8hFrT>h<*!wDi-zFfa8(L}kpe7}O5w+mZH*VQJFLP1P8&=4 z6@Yx80OPo;9$Ao2P(<+AWFvn_Z?C@}0Xhn6hB&*(lYb+65N%2XG&Yf2;AAo(7?|^j zPR;0_{(50!{=Sd0K{Y>m!<^H{bJRLZJ_U?Lm|XHlf_x0w8)mw@qd_T<WugMq_2!-4 z_ikdda(~{I-%sRcN|ekHd3t}Bu<h1kVp&(ly?T+0W4fjdb93`M=jLyx_K#@JrK)vn zUi#&P{LVC!H%&5b@*MQ6v&5?5X<%<_ZDqsAzs<*Ap-qj;{Fp3kzU78rM~rjx)l<Jx zSxW1hJ5p5z)!M*P0N;5<5l;7BLw_lW2Om#q<fD@7l9HyrG^6!83kq^k!>k{B!=Rv9 z<Ezxd;x6Dll!xfIQ4o4{&V>E_kC8w+X3IftS1S}a^xZ#(2PKGgmle54Wfm3)RSGK` znt6K7NBesBtQi5aFxq#&`%2x=f+{)KSiNl|mrqAc4CYENg;_3bOAPWG&pjp79yj0c zf;7bD`+%r?{$aot>>ORq+FAY~|8@!uz<LMJ)jDrtqSAg%Tbub@p<v01<#e~{*cOAq z-zL}fY}*45h`LU7>|#5P`==Mbxbv~LcexiAY2~{U?lDhp&$8D{H+f&Q@1=6+)P%4{ z&)gl}+-K;Re7%dQu;_lo6>P1m9jmq8C=+%bI{>mX5=VQC-o49%acsa7pBNv@p*hJC z_jWIbWoYCZPCQKDwK%@Kc-LIYtx+mK{N2-MXDe;*iUwGSN2%2vm`VWm(t8mh_FiKl zICL9HWN|l{Xtwy~*Yp#r+p}|Xt$CfmZ4qc7Sv$$AEW={A{(V&`e82OV;<WD;mVj>Z zms(Zm(nq8h|IA@ywfF>uwd@jp7xJc06d3PkG&bh$bj}bHU3%<^u>Ss$&F;c8u1yPg zyybldy$oG2R94s?t~E}Vn}<9Eg@l_8P(6&l8m!MBIv)OB_bNRI$zA{(T&xxvA;-}D zyDz?^dU}6S5wp$Gk9t=TgmKbLo~hF5KGQOd&U))4w_xdyT&Uo_f0xha=_13~Bx@RR zw@3M;!!Uf6`$|s9?o<9u-=N8@XM%?BQ-%`czKeJriWt6j(9dm+8M3fgo~!5&p?acx zfd$uEXSa!m9lwBpaaA@RHJj~z6AOL>i~o2(wW#wm<1t{pP>H(*is&jQ;KiepZiX|Y zk<*s}NGNS>EwWn*aB$ZqKZQV%Z1q*+k;)&hMz1RahDmgDgU_a>i#ml=FeH|*&S>f+ zq^X1Ptky#eL}uo|UAdgK$`^y7*4q=e88jjifupbh!kr1Zcr_p{TfBe$2A5icOl)bu zii0<kL1ysrkf0tEC!1sEL;0q<$V;t&Wn}Q&Zu`o_fOow?%Vgp0pqbC#XX14iR6kol zk3~d(E55D8M{+s6u%mQ)`_c&y5|OGMwx$|ntCf|NiNdFAAL?Exq}>lUJA=`z!gfk} zx*xRZ`HRtuHo4DV>Of~UcbL}HCH8ZRqu)+LtS%P-IkPi3xpyA>9SZ{Z;Bj<&Xx01i zV_dT{DQhZfQMGeJns;K1)hjWm&z1vNDKsj(W0pDs*5+Dw96h!#rE;1V<|;^+(|;Zc zNrb8-w(NBy`IF%^<Jf?kKiqPd_L&RnwW@O;&H23hV!S-Jw7OgO`(jBG4GRtp2}w8{ zfovWBe(uHkFV_&AuJOfVYC5?M&A#tXn~d3nJ9LRF;uxB84(&=*P_V#gONVj5Z|$2N zTUuRF1p{cE6=Wi#6(1^c{Vc*gVdWMSjO(lxiL!$C^l`dK;X$L#WHrMi9<^9|*VEri zfeoNo1xga*8Q4#&QZ(Hs+dttbF#&r@#`GnII#|l=$`s#SZ<NqqE;BtQHsX5fb1=r5 z)Qk>vrR8Z^0)2h`_~%qHe0vF4;vSdLd(y;`21L>gY>)3+PWe`q$bIwPAJGRl%=pTb zz`z@+d3lccYGzP5N*8O{WU2&J{0@GcWM91a_Qc_N<VET4`JGuZ7UJR%UG(xz;9*FX zwEA3JAkw}ZNQ`b>l+D<NNaEF&zxdf67nkmV)mo%mvl$4T`p)ijsA<QW%#spUa$Sh~ zo{nmTE({u;XsZTI_ZSELsr${}9y$x#j207*i^1^GpfTD|jDRraNA@Uf<>rrTK%CKJ zp&As-dz>LPlxLRo`>iBhJcq9GAuOo5Z#%)ya__c0Vr8FwgtYv+Gz<ER743|3Mhi0| z&x@Kls3O$nktS0>uBeP=(l8#`1_*p%fpMG$r@@0X0O(Z2?HWXz3^pxJI&(weecaX6 zaqneKx}3YAR;=4pS1rmepa;IkFoj|HEJzn%&%Mihb4JLU0*ub4n?qiVw43rrtFOmt zijZ@|fCb6i9aT6~lB+K5TiV+gkwgFT?U8&@SCRCooi#PGMW+M{<xXdHN1X69jCe}q zng*MM0IPK_h#C+BrC`VX0qb?tnk~&$V(0z%+d)s{7|x)V)nY!8!7c7)9{p9Q`%XYm zx2{_@mrR|7h~8+O3t+XuRd4g2WSE}R<K;PTOmJ&Sr$-*+!z_<!F{os=(bCb@P5YT9 z?IiTQX5M5h1n*0q&q{=C4;NY9Dd&XO*LVM9QxOD%Ipz{jX7YZ2-d`~j;MSjkNf^VI z_&e%e@pzd7O%Hz!Surr}9YiMbpU#}6!_(V6?R$_k4@17gtx+Wm!(ZT7qA}lr_;>i? z*D+^6BLHBuP%fV9(^8X$@cA5UDAY$Fe9wX~)woM!=<z|+*O?r<F<hbO_wk)@UA_2f zkdo@pm^@=Le(&U=S{xjlphQfB|A2wY+PpG3Y@kDdz4#B_Af2-sIU(GZ0iryTQ3Yvd zY|3OKAZfaRGr&2seve?lLTRSaYk)vXy{t;YA%RJ4zSd;nILb^H-YKx}E(6<lII5|D z_Jq{oiLKu=269FJmZf1!xYLuat^@yOXtH$(Fot+N`sw-bxe4AQfe(nQVLfpC2m|WT z6*uZ5=dF0rIuBqLU4J$G`L6OwUkEga#_NZoNCKrKel|T;mH{y{4vY(7N?zV1zKVfb zz2y&Q5>~<iD|t`-Nc05|ER4CzaPE?hjj7Y8*8)w8{y4Pq`5}<~fc&Y($Xzs1WC+s6 zhoH^tyhOSlLo-vvBkJKu=cNt^Hv|We4h{~{X8_~842-rAb?FORV3EHzsh$av8_fp~ zyyBUA*7Fj9_OJ;24l|!`zB6j5uEle(G1~w#j^2EZvu%?0pv!=O8j-sGE70LKbGbO! zLnm#@0qsU)h1(C-JpgfZJ_c{1qKq4dw0?wAi0Zt|H-#hPo6T39g)scBHy?VmU)6)) z+w2UwaR6Yd)TclmMRw0PP;$FMPpvAL6X+>2he&!`tR*$lNCKdv_Vs()cC1TS$UvWG zd|z08K*6i&Qw~yQBufT(b-VwRrGoMFYaA-RXO`Y18V}@C>@d_R2>-<e&?l*_G#$>& zOLguJ+l|U%0FG2acewtUoWb77BT(C-A|Ar*1$$+HejZHbxPBI90bpDhHuJ^i9x|0W zHC69S8rB3nSzdV20e>PZ9g1gb!|rrEmLGSYZS?AZ<O}VNQ{HZx1fq7=Y0!cp$E|0V zl&G)ajc5I;&(iBx;)AfXMe-aEaH?x2sHdm31-txZ*dsZzXOQyTjwk7KXUO+Z7|s9h z!ga0X7%S)`R@{`B&tP-%SRcEl0(}oDsQ9!>HudF#G`BA`Lh9WUJNtpb?7eOc;Q#g} zF0(F=3-a^FFrNS351Z@WndoPXV=Hgy?%&sI-*df$p?{IV`a4k%0n*cWHjU`vC;DJL z#BAotK>*w=82hSHWB@AvaO?P0+Q6f7@s~>~FbBY<t+6$kpfg}^$eF<Yk9`iMuhp!> zcY9V|PiJRA5WD9MX;;+RpD&R+ZVjP>IaxC(k+1TPX#V?-&pB4hDkW68#belxef`hs zv@KaG)otj;-`k*gbCggv-2ogRQQU=T*XRf+VDOD3VPD!gI{LCOqq|&w86Y?jv{u0b z4Fs{AI|Yx(6u@vFygCe!)VehxVadq!@E^<rMD7yNAA#rI8Z(#K!VIomhCKZ2??4`I zeDKNm<cXnJch5JJ2GFWw(g!1%%RpFZf$OK|YbLDgBoiVg(0FQBe!J##(3e6+#s7*z zPxo%mUqKdv`RTJ4`R0iU-1~3S(+wK0@(Q$db&bJGTf5ekQJAFEDWSI%M*2H|mFJ`< z#vw~oVA<W`9RV9Jqvu-0r|#~FLdJKkP{R}{1PUT<{7ri=#I)fi<o=f$Nx@v`7{~z5 z|8L6gzgpiehlR+;Fx|A<lH3~FMKaN$+yUVkW`Rb948XOLQW;$hn$hPgGCSiTt^7kU zuC`NsI@Rjb!1k&Z?{-k3mTh!-J)B@uwXe}{QjWX<@`H(3>%!E@tr3B1r$=0+2T=6k zz)Qc@sXyW|x<w1Y$sb_Q<9c>@8%Xg*cJIxYCW;M#3%uAjdGt~L=-HpJm%|0Oo`gfm zs_mr?x55FX5GstfeD$jeZhg#K92Cz~qc+V`qE4|b@rOqU`Vwp}besXjjNg1hqp!i) zix8=V1GL=ksN`%(1f=l&x0gdq1p*44WuqaT^m~U3|9T?)q9A06bwGoDA4$`S7Dqxl za6-WxArPcDJ7J+aOO}bTzIH!+#lT5K?L?gPF5nVkjCminedmEvgjV%(;?5m@!h5f# zj5+UF0|rzu^GsLw`$Tv2QUzQq$T=5N7{!OT2ACo~mjpnRdinPX@h!G%5h(lquETg< z^cPgENZP+8Hx{L+sA$o_v$v|IOfiCNpjc0$;Q;oBo#n`NASgwXYpGVnRNhQ5_fveJ z3C=K<?***J)8EBaJ(Z~nXIli0zoN8|*MxNZw+fhwfdBTLUH8qZA<FN}c;Cjx5{U;| zce8nnAwhP`<KmGu<`hcE-m=bNP5E;{&oSC5U`&WS2mT(I^Pq7lQ%cP~#A9VOv|GD7 zX;lqloln|jMiZya6eST9yhQhGXBgdTjDKpT;)+FpFUa?-dSRHQhsj>OEw|=)@U`H@ zZ1^T)y|vC$ux3MnUIXC^b?oX;gSfk+ixfD#-CACn8x(({J@B!<jvR>ey0lk?rE>+I z_R2u;`q5;|O<#T)o7%jm-uE^{tP&U*tHTxS{izKYv`5#<8?Oaszs|k^!WUxXff%5e zphI&9m`Qp@UK+rwM_z6~OT&9u>~+t0k0UWT+1J*rwVX4_^tuzd_$!8DgC?2F3?R7I z64?j1o_XP4277*Mw;nLh1n5!dvk8({w6ycx%n-m|@Tib(@~cCg(!!5I64Q{Q>1Ml= ze_&p~YXw;(b&8-ZdgP?H)7lU^NQrRaZy}LzF~cW4^7qG$Bw|_bi_-u^dp7~p1q(W3 z*iby>-FhnXZ!Kr{38&~O1tq2FQ0rikDV)PQAW^FSWk--*J2z4%O5)ycar^9SMhf}L z9=M>FF;Rlh0nKMtBU;riP{z#xG*>}R8(<!=F+uni3}GTGVdZc<iQHR-ndXS5n_@-> zGXp&w09#WU1B&L}-HLz->L>~Y8$Z6QqpQ>WJS{=ts91Xt>+I;2IVZO}Y@0DCxS*07 zASi)vg)vr7jf;b)jV9B9YXdTb3|Hc~0AT*_0Ep#v?NxkDhLAUr)z#+Y5dgzF9~N%H zq!8F^8r^3Dpx7Fb-T+leY1L<rd+D(IjKN{V%n+`*s`VPAQUvZBNv3w>ri;mbGvv6; z%)PKk(CJ+DQX{sV6R&t(<8{lohcvp^E`rF2J2}zeBr$dPhCA|+4feIKve+lX0Ub^C zR36KP7x5S?PwlZDr-{7-J}dOxU!{HdtUD2L3qLI``0n0)JMfHKvmu$cCq^R=Bsv`n z0n|n7APx;Vz>bbNLe4}|Mv7nNbO2T7a0}NchZ!Cis8?j>My5HUY+*D-C00t9qnMz! zZcy+|<Le!HNG8n@Y5BV`E|dS<1W@y_ng_nac%s-IesEzL{obNwl`uw%a>Q)>yZ^Ag z0IrZxTX}%lRezetShXoP3{*H6_okPcG;=XpJ0?T^Ucq3Uc6Cm5W85QBLpE{KQ^M5D zEa>*6;9P{kG*O`Lc0<-T5!3=jfRTi}&A8!_#Z$I}!tm_ydUJPy{}j)|K{z8Y;f%0) zAlMYk`ji5UzD#bf4@$W`&>&j>L=Vfcjez*R@cj?ZUH-&9%~d8J*wbURT7HL=lL2W$ zrvtdA@j>NIg(M1-<{<sOZoOwbo(Ut(QkN?_>)Em=3QG@c)?DKg9v8C~?SAp|6RW;) zT)rn^y=^nyh+gyRs*T`eVp2=?8xzfr>rja@m~)2#t+YHGGy#(BlS;-`@EA9y%H$O~ z^{3_wJV~xoJAfNNxCwWGsq9z9I4P&3-@IwdtOC$LL4_0!CI0KVAH4Bl_nh{G;y+Z< zk_mnk?`dfiQdauD())*S5V(|K+Zr%I2Zonv)lb+ur4BB)kjx)?L%{Xc8X`F=1s)^W zq*ggG0qGUSFFFm%nn$YnfM&*g=6#706fr>Q;{cmFWpR-1&FOcb4~_8ddckoc*DaqH zzWJl($&;!r)mR{Z`1$#vtS4UD9z>D-S0ff=>2cz90{sPo2bg$8`VB-dHZr^IbBCAp z!wWa@u7vXflMmdSp6buZC1{V#o4$aJ74exfI?Oi4V~}7UuT!^BkwKmIijT(8)q2nI z)$IqBZ9p|tX&ZU8A^`7U^B+QVl^kF&=<Fhp<eBT6lY!y4$I|1#iUJ8$!*p+W4;2C3 z>>SuG6y+$iIj)W2qNI3f$LJwG<T1~>IRi(E3Tq-$rF0bZZSdK92&C!};V$gW_s_D| zX=>!}PZLJ<nH?q*_QbgFWc?22Q9KUq4AyuD?*_gQvuG52e0CHkv)F#q?%>C(e9yQ8 z-|Sauky`1%xnDTwdb7&V@+J?Y&tPMa4LbMtcT1TApsoaWnd<{?{5k0jiLXrq?*JGX z@2m2}@X#!}z-<?xiV-s#<+C*vQjPVv@^h`PpJP~B^u(WQuxO1CfjtG74@f5sM1dl? zC!Pyq;_J;Y%6pObOJ0dyw?`9#Au(5&GG+ZBTo_4i$q!T;$zqtpR9U?>dScl=?S*o3 za?Vu<K4FPZK8>s5;EH4?6Rq`m0M-YQluzIkEA`pdJlLS)jO@mPp*w7+5<PrmNdU76 zzlN_hod@c=M3c959JhX@S8=m@>wpS*PUQzK+%ybFC$NKzfYYj7X%wzh#*rZS)SHKo zPa1y7u_{x-byGB6C==Sl$iwv~?{(`>)PB(yfG18j`n3x5F;rtUH#aBQNm}gE&~Mzh zq0Qq%0*>~9NkBdXk->}U0<@`jxUInRv)es?4YWSJ&mIcR8k3yuV8`S9YBuPD*Cdbk z6vn~oN+9wuJ+H-wQ#ect-KDz<laaN+IhsD$UT1Csu!LyIJdnz>HROI8QFVjbKa5d& zKUG{YSEUl}W)N4s-v9vd2JqT*n%(+S-UIEk$9nM*4h>F;IrfLb6w;>5)XOaRQrKE8 zMM*Ks-o2w!Ihc_3@u9RaUzeLf)#<!#IgzOIg2zJlgSg0wQcP0b!{X;pBF3MVIZQr^ zHFq_M{|LTj7!x(h#o9wKOMxi9_L*s2BlG;@mK!oe%SQxyaZj9VIPcs!ar+7H<J6be zD2gO~NEO_V>M(ZXdm)3pGPm<RjqINDbw{UKH%84YX-tl1Jm`>RV2mk{bobLXPSf8) z@ErQ^3msQ4{EqJwA7P~nJ3M`^zr8(hn`i#E1{^uUD-5eTR|Kq;+UBo4(3yFa^vk|f z_Q#Bko%(#X)`z(cOqlL!uWvp%1jZesi#g<%U(;FkSU+qa_%pYqpOCw#sxde`-1dug zvGi4+{aBCdyKle~1RmDTvz7b<Q>urrDcf?8dem==yF3o34E7P=^OLV9$og-c3D00x zH%YMiO%8(P8+~2)5)1@%y2scw1oomaLK+F8@|r||Z=(|sif5_+f%s_Ebb-MG!}-ah zZ8^E)AdtQoo2cCoD41kTC1RKJzEo;izh?{fhN0bYMaEXTIyT#nB#m)FS4i92<p-rf zEJuD_!bk9P0<Q|FO{AWbT<7RcDP(9>lLndG0-+fFA5#K*X?kt##FmNf;0nyY{vR|Z zLD4Y`W*+8`iIx+<zX9ov1BV}*wsvP~JqHGm3nC+T@WI!M#c)Q?hR(s>9*f?vNyfs0 z$=Zf3TP-K}<rTV&8$LMK8+h3#+=V95Zv7N3j%guQ_152lS~?=EDER+@H$^8ZdV9D) z!w=51$9wmhz+wd=<WNcsn*uU3=?ca)19QyLs?N%r3k-vgPxx=XrxB-TWd++f$ehO_ zAxZUCq75AHU)ysnEiq=+`cQJS_N5DAZlg|7yUtzISC6-=`k@b_mRw9+Tv%&s1k$TT z!u@`4U-x&|OTE3_`Dt7>(Xj`Zpc#jhKt|P}F*4vK{Vufa@9u5~f>BWLCBk9f9_b5X zzuZk?6fE%WWJ<T%(XZsF8(go}ICQEh0ExJUfLcf955ccCz^s{0II;C6%O*Yuji_?T zD=JEPHp|9xX@JM6#Y;{Nywc57VBI99#J!1&Gtd0{E<nHl*!>a<9SktQnuC;c9s$m4 zFt{vbu}$Buzkr1RGTPlgPx(S|ZW<e_Qjd(pgO|pGOi$H!g?stRCMG6>F5m3RufVq} zwKWBR9Hg^IPlCF7(Tjir4Qp%xaWS7u{{cfa)nYxJSOEdnAH2#SwWu9){fK!T==Bs$ z9z!ca5>IQrMsw13KglsjN-oGUFnM2(=#T=*H~0;cbk}N4B9ZY??s=a*FZBO@^$l{( z+uElIX;$<3QI}kIbaaHH<BVEReB1Pju;MY4OKd;PYeTM?D<nKh8p;W2wQmQD5Qpj| z(TKd1lAJybI`L&007ZriChVPUrKF_P3t#qFrmjW84D_qdwAPo{=L+4=NA{}qFuwx= zr!rkk!Tfp|9nfX<B9_g*eV>hK7j;4%${RcAw<5<L%8-`Q2R9rUXpS}>aygIAv;`Wq za2?J}>$_~~YnHj_>&vJnR2g%BGQ!4q3!@|R-pK2yNkls*X^T+|F-sPFb<1fkTgt4@ zf2Z0x_hSY~`pwPVG8?!=b9T;GOqF|SD1zldf3BbBe6#CuJNcqZ+{oD27_F_ry`{c& zi><70$l#8>mBGYauBzU@X9@}{y-6x#*^xlGXZ>3gto|1_vUI69_;hcO)%f}I5YLmn zx&7Y*b`B1M_gl&sd(s||+W+p4Tl+mZKA!brke=lw%0*7(q)QZ|gT>N7#=Wl1%d_pq zog=(D2g<M7?!qA11~#Ct5}!`=<aFaj$xcl%dBU*H#P+Cqs1t|Wbc6t!;%Qj2RIXBz z%E!`qn;gc!4v77*(a)bh&#$ayIatibs(9T{B(qHkQSZnjnt9tKqdi8L#@|pl<+EdR z!!rML0ulKjf#3eOef-8>oVYu(&N2E#QSwYNOACg?Ps0gu7;TDr?*6Tei;MgI_k&u# zbm!(*yZ)qW;^#)>UaDSX<rKH@|Md|i>`D5*QTk)k)t0F5z!JGD(IJ^Jq#`^i*?LAO z7pK5T!l}bJ72ieGd!Icw=Y4SSqp!FIu7sB)h*BY=`2OXGPuIV{k!_w8uu_jZsCv(0 zQ)j<Su{Cv*_|<5>{+;0x0khhB#d>u&5M;d8v|pSpGkW>u6kfl6JyyDVuSmZMtuEEU zWI8#=?)6~$U3?06JmB&XzaqW6FGGQkAC)Nl0D*+~!`3u-JaRMo8G@%h@D_kg+HAv0 zSTqz;>B(^mKdGl|F^^~3hk9v`g~N~!FOFU7$CqiCSeBYByU#ltW6P^CDJaG&FuEVz z_J_9(1%V9oOBvzp)nfxUlYf3>9dzBbG9ge+E?XWI-(}h0MHu}}Rwff2L3g>jz=J9i zK@eYi^JWA3_O7>({Xy+cJ%|{Rt&^rJ=gtEZC8N0!8&eI2dq>CHGc`$PY#K`L)ok<% zKCfmQLqIUG0G<S74`#G#XA3>@)VT@IcT^K2!CpVb=b~lKUak9WfarIy6-6-g%8lh) z*=~rF1&x->KFn7~mD8s7I_qyh1`Ds&i3_|m+S@C505W6frqB_{c(gCh+Yum%UTEov zXcjD)eQWxsTp&^4!Nb}T$rHYv9lLvOZk+nh#7KgIdg+*$NWjJyUo(wd#F`@>B<S#~ zfpsB5t~O`^Aga}SMzyQ{F}R!0l5%>bEyvToW+GqMd85-iaz!cWe|^L@zJ6p#Pq0hP zk8^e5Vkmbg>aj)t55HJQyMZtI*zSOga(H}uBDpd(zSwm)D{GQbktE?<^wm@?8sd{) z9qRL^OsD<urCHB2zEd1M5EjnTO~B3fo)&raD(j0u!SXwKA8P6?;N%inT#Dmsaz!*B zknh9ONw>ANEve#6f8fDZZq{WzRL(TA_S>Qs-xK@YwKoXFlXS6`AM-N^g77}LtFXGX z*j^QL?NC3MS~6G09@;B=C~b!8>|Cu~Zzovqj(clsveJ!R&}Ihf;gM^#Rzxw2VY(M} zR;)d@Hi9qd&5tH_-Q3tD#ecnQY3W$+aizn*DbYjB7e1)0t?Y}t^G};OGV1KjqAHD~ z&7fsCMCN=NfEO?X3%sX(+P7BtYV3z0kMn^F*sP`$1X)VPb0n#jdFq(;MWcbv=TVAg zUliRN$5GAJwl=zhrn4QErSK8)ds2;_dV8s>9`=V*XsJSOj~p|UR(yxqNt^rn1cpnj zOidwflkJXTJjW-UZ16-_yMg{LG>{}g?UOc~PCE50&?fngjS0<P!au^Q$9`7uj1)f$ z<uixqq(llxTTp?M(yX$kBd+NRUzFtbZO&5;#E*}=5g3Wv5mR;cN#%)_3eQB5Yo<;3 zIqu!dd=!7%z`5zKM_C;NqbYnz*HBjmq}Mh3ly#)D99u>NuN7#04(-+9gWe-~b$&Rh zjP76iiatwvrv3^C5}z6GSQmXZHaACOXJ<#;x*UC{p;RQ9zujKIXtKB%r@|H&q|rLx z74mjmMS;Y5@Jtzw64xCb9G~05fgVTHv>Y3l*4EaM><Rox-&;v)G}QvL*F+qVvr}yh z^ru^pS9sIo@OCqFT~UmR7DU`D?^pUL@5Cs<@gMcJ(fcA8;<)Cv3$NzpTX^cd&Tw@q z%w_0~{C8N?Zv|ixO9Qdm$kz7xR@O_`BQaDzKZ#ne--aTtI~csYyq)o!>>{GrEiEm# z14O4(i>)mkNcsEZdOA??ql8;KIu_T4*M%Tuytz4jt}7<5GnSQbZ|Sv66g{;aEG1&L zSefvR$17ZH|2lHv-#MmqM+T^fy}J9&BTU!e9Wk=$lQ#U%hxT7TsfcD99Gzgvx$|HD z@;^U+!!wu=^gn!bqVoRlfB3(j%l|%-|ND8spZ@oe{O=?A&nNKzbupOpxS#|D4MoqT z&>@51MM8)kU7ox3=~KbU#dqfr`#*o`KR)RkOI%fyjzv8?LN~ek{t)5&?%e}WM*Bn7 zZepFfv~(ACBe_4gFwjP%utV5<U{-nn+$82(Cipp)8>AocxD6ZIBaLC$%z{8bv`s7b zg-3Foy5+#-H9rhoT!|?90F^>br`j*)MqBhb9$@y|3?8tNcfJw=;Vg7-x%*px|HxDu zeRL}nM7K&`2-`1p;vV^<sg%6p>@>q&;Ud8&m$0_xxPeO@298H4h^c98TBF9MB*nP7 z;lfcekpo@vGVg{7GQk5<{)Aw7Ni2Sn_z^Q+=!-4yfXYzsHeKpEZ>_ECp!%FXtMb)I zYCx^$2^#`_EbjU!mkbmIeR^!sL*Rc5QMX}x%L>`ghPykH1w!gVq%D2_<DyhBZ_eG_ zRbYuzXk}a2S&{+Qcr#<t#n{LoM>V#%v9H^=AmIT8(H88MrQWq*!KHEPyg6}`>XIGf z43B}~uli>-d{A`?IOGonLKQd<R#6CFD&g{MNLRMt!XG?Z{`S3z$ELmJv>Pru2-EV- zHWlQL4`#73ZKCx8GhbX>>ieh&sPS5>KU0Dc;fwfkP-0Mkp#Rn@trAT%x4qir91hl; zMjDiV`i6B;3JQwUnQ=VH5R*+goDP_T!a<Wm*O#CzB)Lqz-Q~_P2{caL%{STED=+KF zt!<L#QfE9%I%*hAHdrmE!~-WA9k^He4C$w4$}Ne5i8)Q$3Eta`9aCx+&(KcI)Y<TB z?bGr_cXr|lQ8-H0BHO>E{<NM@MtVRa;uHX`zXgp3!j~WweSzm+T!6NaEa~?q@N_0z z=9|rNXapo`MSEsR#RWfEwG-guGjeivd{bWTpH?|o6;P=aeSOYS`D%CyzNhJnUmtJ6 z>J6CuSNot%&zBqNfmx?^qIcWaDh5SUQ?s=CabhedV@$<=REqbmd>XkI;&zXBSSb*Z z?CAVGUC0udo{bHQoZmuew1PMt@-@U7FOdOgTzd8X;F8?Z7bbr+0bjMSHLbGLy=?s> zu851PPPOs{KGg$fEW;&x�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�FiC1{hJHxzX6JO@JOjfn5kT&p-AnDP3C2?fE|_SVP(K! zY$K{-_v1Fg<z!VKDKLa;Q`@kk78LmGW=AT^)z{HUCx>gL)Nk009fVh)IX8?L*W>f1 z&(HtDcHJaHS!*(3wR~{2E!fg&hAOr-&aK(|Zg}@&tuBD2;6>c#u!vM)Az9JQFz$Dk zw&4AYtW%@tKS*t;vEEE!k7NUIF5kyGlB&iK49HNkpIuj2O*9Kp@|yC&eCW`Gv#9$O zzUV)S2bEFQULhf}q&$YGFujx({3XYFx39SC-~AK1_ocmCn^TmW*)Lkc*9efRCN+kc zx#nBxPcLf_nY`9sYrNQO`gQZ0wT`VLB6#99yYIp&1u+n_n~NPR5l5>jV)Ai3=xb|h z&u0oFJ@F{XT5tZ_f=RXgmSXeqOd7VChs;pmee2a}$l+YE1y!P&tJ7{IZP&)Po<y_g z7u_b$wp^v)B5l2>qm_BVQ8<H9)qA!D)+VUgpLc)g>9P&mJM(UhAA2kjt!MY*ZUhD9 z<kQ6Wb8o*GwB{vtJbN!2Lc?YcJltZ)LhMQjJArBy6MFS)pec~b<6ang!EsxPN`C~B z;Jjgr7O*HrAb=JOIs2EnG72|^4LnxGy5PdtL|g~U!gY6j^S?nzza5pC>U_nzgB8VK z;JXk5Zb+SCf4Zyk$pz27g|<5+mlkbjuU9W`J;+GcTnX50SO)nhXW>c#2V>+*c74mg zS8y`=2S=C)oPGdi5Y8};You1IHB?s6GU6V;WS(N3*xc_MU&(}4)w^Ov@IZNB2+~~m zoyrU^d_X~gctdX3vKsO}^7@gA5_eN;c^WJGpf*+%SWtnaymNg~(CP3AXg2VD4)r?N z>hJi2v7d(*IS!Ef8DN}{_W4g9V4Q$rLcP?LAl#jb{%uv;;C(4MM|^(_EeH}@zq1p3 z`usT*c1^MC-?vEl7(cpuS5iG80FXv-76TFeLC-9AUJg`crg696=OB6Q2FCfBtolNZ zKWJX(mdY%;TqH2&UG#*veJ+Ec*s@(OmWZ<%I9xPEMjDGCr(aG$rpFXc{-^MR%I5CX z@ryLg>13?s<<=+O$!uqL?_(g4YNRbHN}zlrfpcwySs%o}D|3)Q5b~)81s9m*K#(ve zPFu?Pq2w<&J*H^`jkm7D4Iq}Z1#QM)f$EK|@d~D*Zot)^ST(7bVkF+#(l&y-1;oqE z!0EHwmEDERRb;cNQn1N%RuU=)bMbu(!3E+B5{1)sSdFc6>Iei<O}WD+y1rEl8VPor zUGwE?fC+CMo|C~~i$AFQfDicy4jKUPA+dM))CqW@|J`Z2$>qI-q7b528sZt>T}`e* z*@d!JpKUap*jnYaz@wz3)Neie47y=INBe};<*iy=Y^s0c@V}9uDQkjvF#LRg6`t51 zJ(vU`6@d7!0j)^K5IM8f`cau`y_?4?Un^7(a%C2s#daa<fmL!-o}8wE<P-tVf~M=v zt0NG5q<XmSbyX=;4gFsLL;Ns-wTv1Xb~-86?Oqbc@d(M>?=6{i8v}Ui@S*|LMjm73 z>VEjz{Cxi}Xp_L>C1!tDP{c&6?=R2|G<VGTe~gd6l_Fb*ysKfXD2zKV8q&ksP`|0% z$1eVr`-U7DmJrKjLi{(a>%YWy0pQPNKAn$&w44I89jQhxyb;t4gT#a175&w*w?s09 zystfR00E6UuUG!o%USwVP>`P^Y5q&US(kc3Sv}OdP!yY~>BI`zvYZ`mqkt#rV_(?K zs0a{J`l~V%6Lp>oj3YZ~sNWi!Wv)>_F4K??pQc5d;Q;W0ZPcdF2;yZxGunKfW)!_? zW&)+&1Do8h3uoihO&z~~H_d0|#s0kavFGRXSgkO8m_SJyepp&9jw*7QW9d=j!Q}*5 z-R4ZG)T%M*mnM8OUSmSn`3^8<e+lh5A+s7bY~hBU0v5zt_%o0fBj@Sirz8t`s=aP0 zreRX=K?%OQg^Kv{*iw7dKNjewDyK^xEiP-+cDp;VPrL|2iK2Lv7+%~9hF*8xWcS@q zk5f!I;F-+UXeCpy_uP_1N5COxU`ZkIJ_VX$#0dnJ5HUn<$w-^h=bLBpS-TybP|jSC z{CuQ4t~NVJ`nV=J3nyvPqpE1zA9@93TY`D*y|$BQW6Q{P$-EPuCUM5jTMuY*@w*lJ z6YFW;t}Yfynf7@YXl%3|-pkS9cVAAlVPU9yNP4O^J@)DJ5~8bzHzN8#8fZcZ(geeq zWL7kRN6{dB7j}1$sIB<%#I8&7r|ZETM3Kox!Gr$(<AW8p@2{qA*qh3l;pfdNQR?Xp zkO@M!i&S_ZXF}tuKUf*tZ?r{B$Xhh7RQB5xRo*~2n9tk-V<lwGfM}?7rh#yA5|*T` z@iIv$?Ot0LW5?{H9c(}&PDe+Ng82QVg2+ME{%tST2K=^@_(W_mt>u2Du$odBl)gJv zPar^snG+?FOO7w0G&q0dp)_Pg=Nc+5{~O?$Fp_R*3yb@RhOwMk>MS7aO))m{Tf;KI zJ){4tKd|oXaLK1dJuO2rM&OKvoCN@hn>eThQ4lPwtVO0nO33(FxLc8#YL17Ok!fY> zj-Qf0`KFv5HoWl6q@Wbet>OIF2MXk3gDFhVs`Rojuo-Ks%VR_BOoh$3?0(Tg26Ie= zJ`RpVJBnMe*X1zOq|JN%0pbyEAgm^9{IeCviN_XlLtthFjupzJUlTVF0Qq-1ESAG$ zqowu;vRX7f5AVW$Iv{)aV)aBrO^rC7+cLmZft>x#cg<1(#2XK9C@#%GZp+E(Jyv3J z7%$>U&iVGyt;1`w=xYW1r-Kr<PPUJfvWg`ipuD~bL<M)n-_4+<D)wg0UVBh&eENi8 ze_#kuA*+DXtZAo7LFPBJ27m*HcX)Z(ZpG~PJmKINn24C_>XL`S;D%9+(>-MwH@6z; z2sZHRW6>1~{-*`6>fqdw;uYJcXFw;=)?nH>9bJ#r{`O&t=DB!@*^Wv?^pahSj<B|t zy{NXffR%@s2XjQcb$NU$b~GuL1nc7yG4{vkxV}5+Gh|M^V^aiz3@?-Q$xGoMPU~*L zodn2xy^;W-qzag7cxN{ae(4cK9lU;_^Gu=JL9B0Rdk)r2W_I@Hj#ohl&n|Vxk6*ro zA0Bcoc18v3L_K49S@Y$W^uPYZ7mSRepO|CfdIBsR+kPe`nc~&NUdXZx{QbMPp?(i< z78}R#It7O5A$rCazMY9Hz;x!_gS=HN{E)z&H@MwbY3w~%i@kRbCYJ@W7{<llzGcdk zm4zV1daYi^wMj~Fwp6cr93>m3LDF`ACntSET24*nR&hxg6!2{xij;5OtPQSydAmc< zYi7UF69IWY8&X%l>~~Q3DMg(!UlR_XqU{^Cm4%RUEwaG|`EKrUenf$W`JMOb^ka1N z2S;+A1+(8TzA#xvDhlZ3FMn=CG{7+occjuIwuL+xDNg^Veb270BGvlTw68%V-+uYN zHCWp;O4dj5Yl1I}-F^iy{D#?;cM-2QW9L>UYHPnAn;08YKYWO0RnSxAwnkW82QUx5 zr`t&p%Ie=d@@fWhqw(PtM-;Ld1Fv(S=bv~kdmzMyn6^(Qtl6t&{23sl2;X`}x?!}1 zbfNu&N{*+_ZH@Z4%%4*=uB?++_3u+<b%SneaY>BSFtG0K;hUUH8A~{(76>UsnGFoc zDk~|ye)~3__3)Le`9R8e#rfZlg(e;x&fAj$<pyhS@At){b8T^q-?B{j!XxI7zWnLg zd&M^H=y_4^r!aehKsde~X?TA9@Ls(f(W)J*Fa6HQ!(L7mz4T6(vWmyp^-EZqBgQ;Z zSXlNhy@%-oJmY=eM3Qt5RmJQna^E`|^z59Ra&mKOB~@3if@O*h!Em<qO@eCs6{XJM z)467uP2gY2$jH8fVmntoFTb282Xm~(YDZ7E|ChFm-7lHKMmo8fAcS{Sm9exHary+8 zWnHeA{KPl62<7i=z<a%U6K7vzmlet+H9kT#_)oKs1c|u9Ex@D`)Bh3m^uT^xcgVNE z{C0OWN|B{)P*94fa?YsVoALH9zWn;CzSY(I4Bke+GsjGn>2a=JTk6JI%oAbhMsD4& zufBib^s98z8iz7a#5bgvJ(@KR9pK|cVG=*Uz~+B{CI1NPzR-$wFkce~5^f#_@X#L# zA8iW<V9~_Lx~ZWDb9`5>y#?ON{z6QW@*X5a5jW63%nxt5BSFcJYm-Vn{V1@q#37uL zKj~Vn5T^x9b1<HMPJ3}Zw^;Sr9Zf#@B&O|h9}*Vt^E=^_Jl2txToinkCHu%wm-H)h zZF6fYhNY0!Bi*8_Q%)j=7fFq$AOF0+9Z7d-41*ky&X57TD=4aTjr{hPEpIM&{ZYxi zH(clsm)F9KxBh%elDqBkv;^IS=)I3&r3BzO?&o{yp7Zk~?1UhR;1@^|{Wg}n)cBT4 z4+`av_~r~%&a9^3(VZPp8@hpkzpuWh5~-cBJq3A~(+>Z8zyd$kJdY^}&U@#IO*yK* zz?DENt<c~dqI7Y*AZoV-Z#;i*Fi(c0Bq}`5vN!oUtRZ5;W?`8^sjW0A*w28Lo0|xR z9a{Sr8eRUa<DAMolp~ZG%Kh3`F6YiC@MXzzBWKorw48x6cYHVP1{4mK0XjcJJ<spX zp&7*lhuOOV<8*sVc;b<&G)(7$#||wrvmz}rrKC;ams@#%r86(sxH5Z`l1fTT8yrvj zSGgafOiM}K=-|2qQLA?^&yK|U)1?T_mEljm^E9*L9`nC7fzLgMvmLPxH>cxD6M0th z=(*&s^hdzKNYH7kIr$fQr)WuOxo_`9-1ph#^s*Oa{3%Fe6PcF|W|4Fz5$;mFus$Nf zskCq<5{x}x8(4kd&hyX=^}lc_Eh}qjY;Lz%?2v6r3DqExc3rVs?f+4l$}UBTfuWC_ z=Z3{5PRK8)O%C4EfFo}sf5|I-bMe|Lv4!iY8qd4vcPW}DD)EdJ<>-jNYcvue*Aw{n zx@`2D&Oj>g2MA7@1MRu-G#}rWr>&R;q(a}>Ld{b@(lIa?b?mbE_q6O~e37OWaN8t2 zx}HhP{^BXi5-X~l7A|5O1VbwZBgy_Q7blEhbd5qCMWtG(hbCO>tj2ta7h#+HahC{Y z+uMG*-`!jPN6taHWntM@_C})Y$lMo_#2AHSv>!uWb8A`L0m4VJ6U8T~_IP13P;Su! z+KWtKolEy4o!b=<KK3BtIUO;ns1sdCI;~_>?CfV*6Nf^#e@v^><+O!LISQJu$XYrE za*uFISr8T)E4_LC@6(iX#k4(+8k=8kirN5m9`LF9VMa)jpc^uuO-n!aON0U9Q8PRG z(%iZdWpmISF*mJc?@ud#IBM=9?0<c0YD~kn*6k{Zq7Rp@w!1S*Sw=2qI<95%p^ilS zu@Uq-2(iUmh*(Z%_Wk8QScoU=JZ(omHadhIO`gzmWf|%0WYMhrT_<>K{`@%3q4Sp? z^H2K7B~SEH7OLwnPowx1^Vk9!vaUPFm*$lyL7_``rayW81`RP9GsuEAS7|+CySr<f zDCqsE)f-Z;0wE+j6?VIt3IfX>OK<#Jh{XdnMLVXI)MERF-jp1OK*UG-ro<HL5qN2q zKYus~AuT_IwTkM7CMR{~CR*3yf+G_f4oD1uWl^y?yga%T{6KNH?eri<<KpLY6X!3^ zc9QPB!|=B^KURNazM(FucJGL(_yoSrv{y5rS05i?yq~@F$HT?-vxte5nD995UEN)L z$MF~nV+n;bc>-6hTLq_R#_L|dpNh2~S>B}GFqdHH&XgrVLeJt+h*Ws$$og))+_Lqw zdt6LQOW@*4Pj2AN4WH}%z@JzSToz3}%TC^8Wi<NUmuEP^9}-{AM*Z6udiw2y<*Td` z!Ef@}jOO7tR2?&Tt!axOk38U)M|Zq4IBJ`3_1|aJ=8~dGepESL_UB3Qb;GOs!pUnw zrurp(#Ahzx4J~^bf|o&0{cnT~5qE}&IS8+C5cd4jy+1pEGo_O>x4s^(#hv$Q6<l0P z9M<I98QDEvQgRLBt9-3C-}BNPl_<etOXH@b5^)RnJdZ4D%kY;VLq4*~0*X1Ey2R)I zIwS}Z?vs?22Q{b@r&>p)50Qwcrb)2xZH%zN3FOx-qd4C^VUvC>An+wHPtNslZAzi< z=`;0rO+MS6v@PLzm2;m0OzosRm*XS9PBNz&qN%IEJ}Q5!_O~h}_N9rgdK(oAb)~CS z;9h#fX;xkZCms=zKTrk>FdP}s_Q(7UnCfsl&5k%s=WUdVEr@m<Xojj^$9&VSd>f=E zT#M<Ytue}c!lHEt@r0ARwWgez@QhEeAD7<z1DnDKhNHp4;<@NoX4Qa%1WxdHO~n^Y ze?z5=rgNZLp}4ucesP`8+0>I=W^q;Kp`{X-eL+)uI)~u*viEUXo!AMO>FMVc5D3EV zxJxBUWAoQ(vf4gnGUj;{h{&XXrog*PC4wx(-iLTb!Z2?X22C?Kl<l4U(@qreq$Izg z-Z-31x*`Y%a?zVVqPHij6y}mu;sa#TUhF<P#2CJ5(Xw72!*siVO2osMosled1e1j6 zyBkBt988Rp@*2c9{d-}%$7g?p+LQRpCrR)aDc+w}VM3BBU>QqzcDuv));GW2Ih9?0 zhxO4rf3w3!%t=5h&2hTi6o@&08usLn>N_d-GW-kpTm~7n`|nlG7*_EKGX8L{p1Fs= z6g;-AUAZ#{mlGeE2l1cit_7m}Hy+opn-)(dj&~p%@B!XOW2Dm7MUoELE{~OFo0nzC zRoFbfyX^A$`i|)Y$a2_U_dN<+At1=gKluKgG(3e*caGdge&HAj%=;pCs8h9$O#!yF z{DGkX0fm{mJJV7N0EuaoY+9?4<#1sjoj2g~wq-iGuXgfyR(DZOQL!!2H4M*gFSki} ztg6~$N#IJa`2D|b!`<GVUmE3Z{{ML{qt3IpdvvP;>Mw~)&6O`!*jQxrO+|m=MB;i- zm0CdT7yln~_qw;@rHj}9zUJ}TEUwC`#l?;u(+T^Pi1ZJ82)J)Q2oY+NTwVBf8+_0h zUL-e$E@5%=@N`OGTN)lU_NHu7_;u|OlU$Pl{?{-DgV(*@p<(Ucs$3v+@kWxMt6}a4 zUzQOKBR?4dL$AuoHGA<69>F;!4M}0T{tP8%zm<wFeVH7k;q}bK?(Gwn-G_?l@=(Am z*28^fDB(l(tuOyaUF3V0;HMJTN~^SS`F5+jwvgc=vt^FDyuAEKr7x6JRxw#1Z_wA| zx-nys{M|@yfsMXCM>B-95KS{K$iM}t%pXr3VO#e`4wvU9)9=6%H@~Yf|5Wdz*H@Ed z`Cl{;p4Gc%>o0oF@bT+P&Y1c6;~cv-XJ-Gdu*2IQK2Umt?{)dxPMSDfmSeXwQ@+M| zwa->QLBLm;aU?tc(M{+rm^_<R)s{7W-^3Bf!Zbh7gpX|6o}^^pb7w<l2yE#F=QR%v zE#kiKQ@IU2!$G8e+mqFIk3+5emcVj{-N8n5`h5TF+s6#HQVYX$Lh#9?ISwUKP43y5 zIHpQG&^!{>d8vLY>M1tGf?J^mf6CqX!w{jCK2LgGrCX}ML*o{>&cttfoKcnP!o;M{ zNG4dxl#nSV3P}9E-Hj!JguJ4Dnlg5X$S3q{YAUPb$|;XYlG}Y|I@z70m5$s~THSzE zhrC5V&k)ep-utrBNuklLWi<|jckkbOpd&Cp^%g?Wf)QnEGi*z<$niKprwz&U^|g~n zN1y&jyBUWiv5zPJW;Cy5{`{DVRJbk7qh8X`7dFH0y^MdX%&6=Al&-6OG2h4QHXo3` z9WaaU_=~u{KrL~ohbj+AWlk#;l{pTK9#cIr-6T{zPuUa|b|DP~x16FnP4Z_iUbKHU zxys+;bw1*1M6)aAF(`)X!u-z&^eOGD#i0qZnFDm<qTgO5`DA7q4_^!smbLkEOg#eG z2ZX^zK<#N$LCdm9)YPPBATg_EF;;cU<WIEPqYT#CaG}JcKL%s_Uo&;VMb9_s2afe= z?J;GM@y`;IQOl8vf^XK<nzv}CcGpTtT+TMpfK|BJ>qHsLXTWvmQq+VG@x|T&LH*$_ z$J2MLPl@8fpaTjNrW4%7zqi27$VgVY%rbjFlA{ipyy&no0Qs1A#YKXQqL}(x=-bgO zf6(0inq`T+G(1wXBsy^^D8g(BvTfJvOUi?E-S0HK8z6Pq9!$1hC@B~Y;GD?Qp1IAw zu&&?6S7d6TM-U&$;mT~@P6?zvk&*OW0wV5LLyo#8sr>aSXg?}$#Mx~RTM8CiH4_KA z%WJuT>%RQIdknEe5m@m(?v9?s<`=;OSzEUA#@Q6ib8@KQz4G7@d9twcCyxXu_*a&L zHYFvDQ~B#!@(JEfv@srf7tB;efRTcc#4L|qwfwF4BX$$q_`)v7dF95HB6D9}+sD!9 z3JIb(Da5MO(W1t@qW7uWt?#71nDOEzRomwHy{lUsf4c;F`KI{+02qth6sV=Ix#NgJ zRHmtq86Q(#d86;vnT_qMVz!AuRa;dpP@4XSj?P0W<*Ipaam`+B3|{Zt;^OyRy)kZx zrzsC)AQOMAH^&uU%O_a;;My}ZOa{JGvo_5bQm0tyU+kGGr~$O7lBY$sO*Ex3;{xZ0 z#q1N0+%WaR>DL!6Yl}aPL*_BB*=XjNf10ti6khN6tu(hOOlY?J?(BR;vpxrxO0naF zV$VwX-euIUpBTk32DnI9b3no(;oy)zP_y`|T1g6ytCDfFqILo*dvqTRf-%&Pd=}0o z4Y(4{4yoE6RK?*{Cla=;0}b}XXxPKp*!XsZ;7OP3@O(WK6KD(O$P*TN_Jh;1G6(rs zF6G82>NQ`4nH8SH&HXuEhNZ${Dvf$~d~Cev%1pdT9WD?GDzaLlatz%r^<pltp5Pfy z56@Qs1mPY(N?-g7$dfeS5BVKQL9N`8v{OpBwieGk&+$G>A=fZ)=APmEuieV7_rSK6 z9a&{=*b<v|CH86|oNb+yQn{aAZ#G6;Gc&J?v25X=U&Fp~QHbm2P=O-crf@ar9(QiZ zGzIYyCfJD5uU(vo<?UoZj*8d3!~CjJOU;v&`MEN(16-<W&7#MTp9C%dzd-ZwVPK^N z*viW_S`B^vvAQN<`u_Sts<CsVbxhVbIA7}*3Y=UowNgfHy*6En{L*zwBy9(CH5KOS zyOV35Jv~ZiC0Xu_LVw(&i1`m>EhX!V6ONuB8AtneQ_~w6j=1CmNAsOKCK{LIaJ>K? z{i?=XMp<nzb85X~pez-6F1PHDfqM@&Ilo>b?!xR#X#*V*Oiw=)f9W~6#?vRd(bY%x z7hT{IaXFyZdAEb#1peN0r42EOBR}#yie;s*m(CTkn+5p!F|#j}RBsW;wJ*}B^^o|D zilCG+&wRg8Y@aBtzx$Npve&uwEth3~vLta?NlAbL`_hL^dE_As6r3Udsof1~P5u9+ z1-MK&#fqL=A4>3Z4Ed@sUS=ixq4l?H?ks?<tGqUuezwYb>U<6-e8Xr=_m1CCa~(2* zy^!2ly+L!$;`Eq34Q3cAh@aq7X?v@WToz~V@ZJ8AJuiShEbw0<&F(0Gc1E2P_#tSh zBbO0&A1>lT4q2H)0}EV2IE)#_URtE&FulkVs7Jhpm@lXn-VaoS4aqLd&m-%VEUq=k zSp%E4jDe%~Po<@AMYHO+-t(R={dqHEudk@~efhcl(|nKarA6kv;IZshxl7x<&*?WZ zYWkM=!070!Ulh0{(t^`%<7a+YMBx|j@R^y2NzBJv7NP4(9?Je0rhfBJ3Usg^5&%$z z;JQ!tx~pzM)Vz5a<dlMx;nE7@^P?fJ?Yg@abli;S9jc?n5{@^1Q$Fxd+s7|nU<b$y z0ECyMk?;&K1$ydk$P~T)#5NeHk#Ik?miwj&uG}~CLo_P$jh7IJusUV^UEC8O19j5# zI%c(n**T-<8-vU7MM4fs<Y^c@mUo(tQgt&eL1lzGn-ZzBK`rRK)vj;!?U8Y_GSPbe zhP17PVjqKf<>k)T4ZfsXOYL27GO*hXO42>g!ZZmKGn&quFBQANnqanOk}^NPw|QFs z(*ziD+l$3FcGJ_P+#6m_Su|YjF&f&5JeG+b*WVl%-O;W@p~$e9yx*dESK&OCY4=)C z%%IM$Qxr-*$zwf#zJGL{6B%5-k5B!XI`$I&=y}=Kb9&Xjuagf5{N*QUh;qFYHoL8d z0-VUn3F95GduxP35e4y7@CebN^K3UxGzxbYZg-8j`e@SV$GUYvyw*)bP9gfWUSZs1 z@Y(ow610D`*#M3i$*C-}X-E^xBG18O-Gq=?4&#@i*kpru!A$b|%p*C{(PCZO_Hcm{ z@Gx3FWqG&)>ni$jaxjFeMkQe*Gd@{%(CBVDHJo)Lfh|{hu+#^>$z-V3xc@#NC@Gtd zpMQBiw^C2s{=w{?E|2vo`c#dB*wf@g&0MkJWcrAW=63@cpFeN6M_$h!A8VE5t?R0A zeV`N!>`4-G-Eg~lfDONqUf}}EQoEAwm8M>uo4@8X)-#Rst*5m}i}d02(u%t4SE~d7 zX80b<vx(;q3=AL>cuxwuo^uvCP0_RH@o5KA{_(S5Ao{ziooC7oW3%#ED@KMh%{{}& z@l+`Qls*YMKZb!8`k5%exvCGMi->j2dgGg(qwT^Cm8WJ+eZa6duX<n9^<J{2u*(cH z=WlF^$-9^5{~ic#gCh8eyVY>PDKKgo5CV*ez1cUnV61mT4CJHiFkOZ}L<>d1`CZD! zb#7lelM>ROUYF4iU-I*PX-w2qetC8MCeiEiEHI&R+i-Xj4YQV@98I?y&UiT<ry9pK zpQ}svG=NPn&i-M|K=f@jjy#<99A*Jto^D`nRVPU*`|Kn%tBx62ruoRn+g&w1EHf{t z@h2x~>7#etJsiV&Mn@dW?}-mVF!D}{Q&q0$_A6{OM)uI`a9OEPfwJ|dW1xsvC?Mm_ z?$IPn)#}tE5|8y7g;KH>XC7<UVFusbe)%pYUSs^>(e-J8Myt|h5DtaUv~cZbH+b5% zi>ny(-yMKEp8V-b0@f{amIOcQpdY0EN}pzx6d$|JP07O(*Ta#MlQVkNYZYx+VQY_@ z{URw<DW#KIF8GoA$kxQMYyE~0Z59lO(lQH_)EVE(e&yYGp^02nb28Ug=lBQ2EVK(o zQ$eiekP4Sd;1_Fq#Uq3&f>nxr4LiL3!j*G&{qvFrDFHzkS*gcueeGX7A0N8+M`MK% z7t=F_52IVPF0)=E5N^ktp^(;`s{=`ks_b5yw;}lW9_%HEQ!!(e$9$?s|Fx5B`zsT5 zq@-VXIJS_-3F)*wF+Q11L9fz9sim;ILiG?)d`Wul*05xBHil&%Ba}V8R<NDzde%lN z(Qh4YNIjTCVrc*;-qwg&TO@<)$?NJJI~2TuHRh?>F&~USaX{_ic1Rg+AaRxf8Y92{ zS#y8c7YSf^^x3vVZ%Qk`^zMD3c$T8>qvUih4))Y|Y-#@wof7$pY&VNNQO(usUZESV z@I}<k`q7`IV8=Pw7if7#!=NO;eQCNs^5f<;6Sy~6c*DrZ2r7@+?gSh8BoUIG^z@Lf zF7+6VvCOBJ`GhNmi*%}U^>!3;&KK_nUpnjze;SPx@s{=3*;lQ?wTtWEEyFuIVdSp> zG}EkBUieB`M~E2KMGdd}Fd-=2iIz^Fhi1{5|2F$&ZE^AaE85_X_7bzj&_j?4dNHLv zg{?b`e!?7aKi^vO6^lco+!vbK&Y-f@ypKXZIxqHh>oA9M)x_flF3P0y6>FNjS;Ocf z$b_+{YMiLK*8arYJSotKfLh{Jarqvok8Xfb-t25zzSOQJCq33U8Ooj$$vr3U$L~KC zW)0Axo$-5bV}pqwI`|F3tZ&1_?lbum_PcX<pIG7x7#+CpK+hNkHEV}!M$o?}t^=fm ztcD5&!Y;U>7*S?oObX&~n{H0K-zI2dl;-*Do2?*EiF7WsSn=gXiTe-&h{B#J-sk60 zxE^Oh{MIAc4>#%_I|xgBOc)x%iQA1AQd@Y<r_(p2<;UYv|9F!|o|K6VPmmJnl@m(O zlj_X|80ZJ3qlX3%fFPMeh=P*P(H0NaAvE+%@mvLkcI0nH7ahujQn3x!2wBhRNX*w? z!V$fzxtf=HJ)El<(H9JJ#vmv860Sb8l=rgU%F?iO#gAtsU?~l2=C%TjT<{$PSoJ)- zHvdzRlz%!32sOB~`SD2sL-oLB!D;^ji6@*N2@mFE!1^K^)E(ib>$5tCD^2q{!|T^L zDPJmY;-46QaJztAZFA`IgqUsb#>Y-~<fLUM!L?F#H`nqnjubSlM_OgKL2B?kaj`e4 zzU5sWj^{<dP<t0k!r0fKzWe%I7PjN1woF$kAq3JHAYBfiY;CD)Pk-oT%yQFeG6-_E zOF3`{$|7_80A@j=?)d^9%iYuoaB~g-;K8!Y)}iy_1srOZ=#eEQ_elMOpA)QxihlP4 z0%miC_gHYD^1~_?V&lfetE^B#G99Tf4WoWk>%gQWW)G4gY&571c9Z$zxLuZ<onZC9 zJ`EjOoP@JJjJSusO@x|r=pD>5X<`ilGGPn7fjK!jFFKyI2@oX0f|W?zGT&wi36Ayt zj9V0f22$_h{Bt4$oreVA!i$sMtq-^?2R?okN1hNldJCGK|7H!ouO5x$YU0R|^wPFq zA|M|#Y^-!tUWdqk33CQ**J7jb`7e#0VwS5Tvu`B8pL7e13?BnLKZ-lsJN^l&t^&}` z5Xi&D@rZ=+h<mMQ(7;&CRNQe~AEXQ04a6dO;OPwL8nHx@h~)z$q<T+XDj&<}!!hA7 z>e&Co+gnCey?t%N7>E*L(B0BVORA)FNl8j064G4?DBVbxfOL0>NOwz%ba&S?_qk)- z|MPx-8Rx?p4BhVi+iT4=*Hsg>k@J<rDc#A|0HvQU2vYOP2#$`Z|5WNdH0$l${w5_O z(-P<T!g}lP#wVT`CAD4x9Gs<<u`HCO9)&=>^m|+uGrhdWT5QR8>yUsJ1fSVE{jOHd z*E3nD2Ru3>Emf?Pe>j~O$Egk8y~`;M6}Az?Aml~TzanTQu!Kjgw!$8O-7~lQc=6$z z*It=r5?XnCI{qM$C_;}z5QP`j>a`e;A2m>L9evalfRez4T%d<9cOyk&{?1NPEVc{{ zP-G1&O%Kvmucf4<K8jF~_Z_ZJ-V#PR)*k`sP#|;y>Z=NtGYz?AGG%8C@30*pDyd!Z zs0R|)pj!d^Z;~b$`^m@Vy%Dzgtl-V|(^#7+I<^}{IMWlA`rEHZxiKb6K7frfx96`o zjClUI{m6a++v$u6lXaedu1j?<0dR|v+~{H~L!_e8Qp3yZvBFu3t!w|d)HK)_YNgir zM8uup*V)0s3z<yUMFxY1H{8D~Wzk4n>cMuVSDxDKJHjxSsdvA`0o;8d|8WWfgSD40 zqYT=_H>FN8-@eX4feuid>j&Zs1V(KQPE8TrIzJXGB++Uwhmv$#Dc#?zww6#V7_Ykq zr^=M?P35|8YI7U;O0s|>v_Pg5gDctofLMc#aaV0+KL606BSreo5DxLs>)tVB^p_0- z%S5VoWDcJr!3b7Ddexloqvyei&t%ZQB0X($p@%`;;tPf#9DpXNX|%^Iiq~f-R0eb- z1F3F=)&<!K-%z#d-J7kWw?@k;VYp<6H4ek;epEEKx&f8mm!G*nBZq*jZkub!4c@bu zDoZTK`&;{7(Cp!@_TiQorr5R`6}Y{<pR9|<CKsCJSD}~rS#@uyLoW;-t0yPJpYHzE z(@;tV|FPxL-1oG1Iu}f3mSgC{FgZsgbYO42|BCFXEl`sJ@E~K{>!K8FoU?8U!kcAY zaQ<G@TN58`K9??#N#;@@x5gpmD6cgc+F}uF5VYQ)3XtoKXNUB}Ve0EK(4QD~MgD}? zBaY5EYD}$Q$YjO(8NyJl`a_7+G8)9bue1LKOQ54ffLWI=KPFns7p+@np-`uBQ3ko| zA_i9GyQhOc2ug@(F<JTLm8KscE%haOS!nUfpWoLipf(9OUXNSGr(k)=PV(ISLWHOn zNf&b9@C2;y0>k-a_NzFB*VsZa9@n?$bd?6N&)u)El6fSwR^DNFVfspE!IcCc(4wWD zwWuzH%LT^`R$9v$((~7b?e7>=3vu&Q$IO0C90WbM_2t)1pf_418(TgVc%1BnMfq5^ zr?|tIQ38fN(<FYUr|wg)0Nsey<g<F^g!S49?{7^(PRjHV^ne{7^5aH|3<e<Y#fF@a z0cLshXA5iG&g-x?nyTG?0N*m@68o?(6!AEduJ#oy*E1r^*ZpX?B`0s7CMu-7aJNp< zGQHcgo3U*tM6P+ay8G<8nd)g85TA@mZ;j19`s^DQuPj1Do7!Q2SqPml;*Q98_+%NV zi{?xW26eL;=%o-D>k#Dgq5$H9Bcq}i`6kkBJ4j!@44$1zUgkD#KglO{Bjn6$GyPTx zCLlVGq)mRc2q9nK5lRD@Sy{K$k6}ENu=M*;&g4_}FA8zFOwyu<So$cHTp*S6*S#}@ z53=KJSumGOu|frSo&PsD2ln8VTQr-6z7iHhskHi(iWkG!HkIM$G}eo3`aZECLu7VU z{H-B`El$(0RNT%DHiJU~10UsOnMU|B{_XvgFT)ybjZ6Hvxu!6Go0Qw=wk1|w(llR$ zK0v$B(RkYpw8Bi>4j~fUuaY*GKpuw`uXKEZX>2&X$)df`flSpOdsb>g;Ra+bYF|6m zTV>@>>|xS(lOvCsYqCgcd8V(=1GsN~6wh5s!<Yt)nIV7dqMBX4u8PSRG(=MA8e_p} zGg<VAqKkkeoewwC>QekuIFrH9G0@0z%&Z7895~adVI|_|=87o5B6`>I9p7(*!cZLP z^%ZZf3<Ur|rB_Up!iWRzSWkb}CVB|x*9CacA3MqreB3t<)}8l_!ec6mFHz}PTR2hD zOwf%tIl6=}4#yzeZsbr0g#iMdET^(gNhUWqZ+bbT-@YwW^Q{NzQ_0qP#2vf!i7@Vx z7rTGoFLJ<z2&XU9@9PKc@^{qlr-~lIker{vn_flbbgk+k^=|i~*{&gEWabF(W~MYr z?uXl5I*snY%BWj!Rl1V<?|!plQR_#YZw(|{4iO?n8<mk#S-8oh9*0vVn)TWXPtavm zar9>`Xht)ggO=U;zK4BOw+%Dp$Ow9Q%efg&VV~+N;EO;bA#&|SIX6&&7JZ&Sr<I3` zc8wiS<h;mcyS324=4<jer(Jg<MPF~hRqMxt1wyyp4~G4(uWxyB6Nms=#mul+Xv~Mn zVLIhms(E#B`V{J1Q;kUn4F~kbR;zn<)|!CIAqEDh_kwZqZSzf;12~-cDlC5#rQW)G zd40+r6=m&u@jJ}QmbUA(4zY@cCV}HoNnVX_qoJnO2Ml<lC2^z+8|T@{PF9z{-r?y6 zJ)yr(C_j^tyH>sZ<JktcWw%1S#Dho8UV{i0dYByA_CP$Y&`J!wVxvtlm9k<}rPkbp z9M!;S(Rh0g);-P$IeSn(1rdzS=RL8U;eUM<z}yDJ>891mpZgoX8*V@&M5fAYF==s_ zqt4GK_T|0U5OXs!VSHL1t3CMws&O^Dap{uda&S`K%7QN=N~bV7CRRFOgS#+yfEV-F zqq3HByN-SIsF=?LA%XTI*;==R@q6p`RwlFfPPsvcAUeLv=~XcL;FE5<t$)RRY*(59 zzYt<}BB%oM*?qSmxsQCA+wxu(_t;`wQ3Wube|`<rt3fOP!{A@hR#!$4tK2#}{_8pl zJCQw8hN^}fseJS$x}BCPcE1JRkUM#pn(lb`>4mjwc_%`(&*QOo;8W9si)<)}#xYRz zQp-94lm;OrbYih`(A|7dGH!Q@A7xTIE~Ugs6=*;oSM{oPYBUVUWPH>1DZ}ta_imEd z3Wm~hCW7TetZ3f8lMm^RrELf6Lyu($#>7EdWyP#>pY*xm?%ak+$RM_dJT~y19!awa z<nxvG2l*=HkGAV60;m7LAe05BHV&@qC)`#RQ{8$s(Br&7=EiM0Lf@E;C-U>D*V}B! z3IgJ+G)<p&GW(h9Z=^iTowhS1k6xcLK)j0URu(}g?j6HYT6bnDT{3v{I>VqNkJ$HN z*!Jypg(ID>zMqe`pIb+#US2LDr~LvJNq6(n*^WY`7$2_jRZBiVn&4|I*U<apIpZDt z99lg!{q2cEjXFc1wvmU@S(mfx^g3+GEQX6n7;1d^L1&GXcJq5cn_N<HuSSK*PbId; z9F+IJ-$ZEk<g*o#b84APd!FDLKhZYC(G7V?Af`xACQ*KTH|wVHR>RrOZiKG7vDXJs ztlfShrbQYxEK106l?;WCzIs2T576sR_1%)C;U~#EQ>o*}8OVdh6B8xaB`i9_s&(`# zR)%zzV>~N|PGYx%#W2=)35E_|evBMYcj9G|Yl}@`?KL;|zqgkL!jj^J7vydFZp|>p zZ0uABo8NsekUE0iCM~<`=|O`tb=_BSM1e4e0%0-)mu}xaHrzgtF1O|u-HJuK*Ij1b z{r&mGi~5>!tAl=KNLLSHUsOfh=^(Rs+U34?pODT+sqw6P!(mM(gRHF94a~Z)_JRbL zsvi7W^H4=Tc+N~kLsK$%$X1GDmHPH$P2Jwz$9jell3Uo{J0ygv>^Et6w)#_pbSI7} zMt#)pw@<XrKao@4uM<C(^<LC);V?dInyyvntrc{74_q@snthI0k|qH$Zob^qPjIhn z)fMstleG+mS><Wu0ups9uagxc(e!K;X)d>aH()T(H}dD@qnS|;I{v8Xp(^J<a+Cq& z3Dud^9s-gtIim_aE>1#3C{R4_OQsQw<!Wf;n<!}ZA3g)6s5cDWN}2f)>EqdraoaV; zG-eK=9&X?5h%m<5^0>bGn1NgVcW%~~2F3a%Z1fC5#hKeV>*cpS1^-*QM`6UTT^G67 z|I1c)-W&99Ya_Wbz3FMT>npjroVS&AKim3e-j9Ms%b;ozx-W)N#XZ#i=a0OvNM3|w z#LnS5_e=>w$5&x_+x%(zJ|<DWMyPBg?OSnMVGsk3Ogyt(S+5aFnYLeg<2EmL`1Wnn zb4#`^gC3vuyVGlmLV{>zu;GhN`p5Tiu{+@y4c#&M^2>X%JzmT7bH$Qx>M1?oDWz9^ zp6*j#=>{f)Rf4J9lzx~LW1!i4-BeDfzF!W9IIV`SNB%QaW_FOrhLpwQ7i;-$82q!9 zaS>ZN7`AfrYp1XcG(NtqX_~$EL_Y3qfyX!IIc;#i)7LtiFW8H@UYtmj6$fE%KR1x! zU*221jjJ;9QnFL7F2G;N(UA(2Ve^;gA&$q)apid8w=$&0(U^(UaA;oyN3r5HXo<5u zjm-^x`yl1`(zVvWfcDL|yPyNO;mOVUsY2IO-Sb%6m4DJHFH+#SQdm>!`_ZWf{tZfL z&l=@#+`Y~UK~K}}4Raa8dhDt|s*G&&q$EDKbWoI;+)E<9f5cT87slRydqbLkYM@i{ zNmoF+CL)erP!v~Yg6g(mUC{%|mNgdY1K-$pUZu>fjWRMLbv<#OONa}V`1=hP@a<7h z>=6sPpL|;Rs>YA%mKLojoVzU*Q-b?iQd(LXQl2Fe`rR)TlP&QG3DcF@?A1uCu#v1_ zT%rnUCzx>)c%!hLq_CT7nN364c+K9wN9R^GE}^BzQt)1ScD>ywg7_Es`5z4o6n}QR zzF|4zJ70e1;r&A&3hQjekrotR={Q(DfY~B<Wn~#}mSKQ+0%m421XZGQ7>Y8RNJVEN zzp<6X{ybM2wq3%d68Z3V5!tP-Irbv~&<U4^`^($`IVnO$HcG;TP>=IDkp6+1hoG=? zr;6vB?z)^3tdE_M!(sTwETkg!3j#3v61H!5LpajXmZ!~!OyydM`{v#<%e_1s!@Wev zg8-~UpGW`ROQrE&zklNqPgK7AliB^+w{zi}z4;ru;Z)SGb>i4@t1D_aO>cT}sBbAP z+gn>NEcEPIeXytKCGNHy!VQrLr)e@<dk<VssOBVAm1K6928l;a9<54pUqMMK9&JQc zOK%}2>1iTx>)*Pip9vAl8Cqe*3P_Q_q@O0BFWOI`uNkqgdZ6zxkU6cRboxdxF1)^; zP0$n_xK4#8u>+p_;JtoGvU?xShX;@MNs5cNcP~yG-??GR#N&|?aCQ4%;Q+$Oa^=?H z|IIOK?$Z)5UD=xx@(VARKhJsT*)_v8Du^AULwL;Wo^=18%bF!8-%hDtfo&i{S~vlQ zTQYq_lr4dVf?}pPP4FFI%^P8P6km}n0HAiQA1?R$X?j2Ww0hqrk$g`JYx^vRdF)g9 zCgDrM?o--@4N9DGL#-IJvPlxc_;M9e5|S_GlMeTyjg4jpRhHNV@18Q6+yY_RpI_J9 z7GM!1iFk6=Qlg%q|Loe{WH#E4rFQUvc^`)Gu5xJQha8F+E3Zs9Y3!#T^{Q$HZCv~A zAJJ;<qR52Jb043d_u#X+n~Cd~f9xpov6pKH)C3*QERgWrK{}zR{G5?rfvs9nl!Gb+ z!P>AQp4s!O*=psG#rz0Hw@XF+sC;K)RxVxU?1!;f<SXdX7rJ6pSJ^Y9ax2n*4@=uv z|Kj-dbhZtp`2JD%F;9*zItLe*Z(@GXpsjUT%KB-JC4laFttmA9*u*KPB*K|m99KHh z8!kiw&Zy$SiQgVohpE5}nlC~o<7sps4(gpZX&T(FWd|t)oX!#$GbKQZsg--jQlKXD zrF{h#J<m;E-e~IJ2BABy#n*^=mT)(O*<3^Pd?c5>x&-n-p5<v(O5`s;cRgu0O&L9^ zOJR~4x@iuiCP(69P_*Z9p>Fa<r$#1}{)A@1)~LU{f;kWo`7g7M^HsnM6<B+p9u0>F z^D00mcOM)zfnJ-}G(_-aeDLa<Rz+N2s@WC&V6>O<XQa4~8VuZQ9<Kk)BR+SPr(Wa7 z82<+DmR|#^u?a9)({9H3Bs4m@^=x_XAQVkh)S^`ZMY>^SVTDYd4J|m>utP}9RdaOz z>~Ar^%M#9t)|*-!#;+a77ux;*hQe`YF0^rRMkJ?G`Oo0E2iYPK{x}0GTCTdhr#EBw zm9;*{7EY9%n@tpaDpYs<**hxs^j#`C7ez_wiarsX$bW&5d}h6Y6(wq<)$Zg(^$3xx z{LCkz(dx_Mic4JB&+*bk6ib1B&bH(lgpx9Q)wf1lDy8S#t_RV=noJbHh!RJB+mos{ zeP%yHevygmETWhbuLVqTBj-)#skrFr={eb<37>`d-gdeo6SGjbBdjxqeRH#dotO_U zqLh2N^mp||OfQHLvc!8ilu<NuThl1t_pce*fhH4~xrG!GEu-FNq)L#MU;Wmk0acpN zxZ_a^XYh&SkYMK4d8E0u;y*_bwTC?7D1!fdk(#wXuv<|*$qLoCu~|fuM+%K8ekw*u zK}G7$w#LPYeH<SGBp7l)^!^Ookw1YnL%ZIYl3vI&^{?EuJB>T5z2I_Ju4@=>JBNMe z&i=C8nt8Y%eK#2;rSLG{*8#Sk*9kfk3ER>Ofn!7qFWC8Au2{q_IVG$r<3W84*`LLV zhF7w*+EX~7RSKQ92l1Sr@npB?_s~#=Z<@6gB<)cFe0y=^Lu54dqf~3f^sm6f2?(w? zYB1bPL1SvQw1J#o*3=(L5q=!trmfT;nPEy^JCF^JnxDN=zJR5Jk6}g9JsieR@*uo3 zFu;RC_mXB~s+{zN5$dw#Y(x4BuM20>80JvnwgVL5g!!7$>#t!qUw_b6L@qOU>~j7n zZv)BITJhXI-)WJG{AqghP2Xl01KmAQG;E@x8%0Frv3-P(LJ}Kw@rj5!i-=0fz7P?_ zyTN+%Ub+~>v3+Z%<O>3{A1&4VHTI^3BggH!?e-o>?NL(YEe*E**P@g2WI)2S1}6I# z6{*%4!i)T98Sl^~x?^B6#LI9tx%)Va)p_9ooQLzk%~wI#J>6KHDP`|6hQj@C_k>3= z$^{B+96fN*y<(95ntON9bws`iuSc{>6^K?Ttu7QPT*>`8kMd;bGUmiECWe!iD!xgj zRk9ca2>n+sKqB384qEa4uYN=fXfW{vOvfcg@?>8Y`kc<9l*ypgsZIXV1Q_IruY|r; zvh8Ib{68cNmtXZJ6lT)I4YhC3M688B|9(rDXtL&4^3|p9?dGo!$FUG-aofYdVJ0Dj zW}c^_qzsFe?tZr|&st`e0mZ?tl26A(b;Oe?hMLp_eRZr-I!T;8F7taoeSeq}G<H4M z&GKmEXT+bIm=zTT{k^hjoQ%;MX0x!`*;8HfL{41bAYtb}CKYslblBh>=<c}BrI}%D z!dgmtec9&1VqCXGh7t$z59C{Sg7mb^`cv+&4d-|PB#w}MN~rGsc}eRV5|<KUw00YC zpU>&rv8CjIkb8ld2rLcZk-H`%f&1!i17yk$BkZf3O0sERAS|R5%Mfa|?aup;sMwnF zoefm}I7~tb9)IWOKU}~3t}^lVmF`|Q^y*Lb&qSh<Il0(IHR3qll$7y4ko1WlUX6t7 z3e_XDlDk;g*!i|wqT+2Oy>^L7G9=a3v2%qA!XR3{w?`b3%r6Yc4rdMvH6i2KLO<&! z`EH}gjEgUCn_d1j>+%KM>%V=w5V4?cJwEBX2zzSMMFXFqJ&iLtVc1_>R`HHg-07AU zN7vFX<T!=0NFF)1)#G^XoYfx>AFA7zcn2;YHt8E86g70(^G|J0)CR{Q>W$ut%abt( zBvyn9>z5Y3|1Q&?pi>5i+s`x!c*crnNov>|AJ!0-BZkWuU6As85_CsJjFqD9<capF zt#uBo;`Ab)xI}wnc=>VX^DAIHezd=OMqGr)o4fwuDQFF%|50VU;V?s2joG8s{(0XA z4ci+GS3o)&S_L;mF&K(^NCDjfch=_VX$**Zq%?%lgB=}{7|MvHK7?Uc9li5p-(C0* zwI&n>0g_8qM(@PLwTF9U)djh72IBEp=ERa$vs;s;%K1llie)c_y-Lbv_pW!E{X*VM zY8Li^K<zRGy=<~K;R(W10ohr~76Hf^GUI2SIoGL%0dU$JgI-rUnfC^0JfGQceTrP| zZz%t1gJ6_MbbQxxf57VRAWAd4Oytpd?)sX=hT!p8sDzK}o5+_j7hYe8o)fuWtj=1R zw0}6j_M!;HA_aRCEz>pJO`;zue3yTjUxtQ+irYzXmQxmlDNSJkSmp>r%r3!*hwE5^ z8X^7F!FG)J+iF%q;>Q7l8J~tUSbc~lOfL*{dt3ZMl2TOr3cMG6D1^V?%zSY4cQ!_{ ztBp?KP7wYod4tC_x!O_e4~vzA-MEiLCU;Jq>g*4#hret4l;+{JQ1PWGG&_HVGKGYg zYy&j2xZ^LrH0dZt1)>7xMV{o5Cm8+#0jg`#zb^VFtQV?as0|O|>b~SCCkp1fXI<{6 zY1dc|HAqS`GLo_?^xSx;CLM!&C(v{+bhQy<E4|8WFR<-|!JK%#Kbt8Pz<Z$Ul=;|4 zL@#wXRbHzO93R}**U9jmi$u|HNhY&$a*8fWVoNyZk6F%?5V^@nm!>_sJZYLe29qCR zm{1&-mT`Nk{#w(oXHvm(4_*ymAYG%bkp0&t=-6L|U^5ub^kygavz7ZY!$gTh1Pw-! z$rn;2cb*OqcbN*f{?E<FfY*vHU7>UEPHwufpeybBAI5tv%Pd#ej10{Ixa#v0am7zl znMiWc5mZ)Bjv=r&Z9tbnVA&(jZsZ)G@xc(vmY)^Sm0CQm$~8=5(#sM@Yp4_cZP)E= z!$<M#=%RX!&O^DWrre!YBNHo{G47+bo8P1Onz6F+-}qSH%XM$E;iXOMH1x)>=rnh9 zgjKo%g(Yb(MZWTm2sW~Ts01O8-qW+=&5l^b<L6#IN@s|D!Rv7FE0gIZl4t2M%TL%4 zO<8>rY~Z2+yh?uY#l%ypY55qldmg;oW85rrx0JTHxY*A07s6%-XhfC#!W|k)m^HsT zG%S&!#RW6qf4v~5=M|H$czA1Ky=L#hBqrR0k0`9I54J^anO^uo_;XXs_?MkRu)(K@ z9p)e|G;~9C>iRy*B@F*yStF`1XIis6<0u>iYDQ*b_c__vBvZaUHR<?<5a-`ux(c25 z6GrhkJ0>K+Vxs1e$A|rlPYKgVyewxM(V`o{SqNu9$!h{13MQF-EH(>^-h~qo*?=IK zMePc{@86ZzPk~|yL<y82IJ^Gtj?`aWnxz{bi~iT4X?yRoOfeFdHZ+-fhdup~6*=g8 zpjUXZobyb{#2W!TPaKH-KuQK!9_GmSJ13(xcgWDoP=tw|Sp6NwZ#tJImodSOtsBrF zIU_05Gf}y3{R8<;nG`<6<%$KbgHX)u`)yB<53fS&DBR%cr2f!_MZ2MuO}A|McQ)fk zLBw^F5JU(J<q2pZr6qWX)+ONtI4Zgn+9wYv%XklmJ{6d74Y4AKT0z$bGj<8l(V4F^ zN0DKZyvUr7LGOMQqiMH8UOSjgFj6vsZ@ue3$dLf;cIdpbotc7VU;gCr)1gTe_IkIc zuEV!M*(I4Q0rnBU5RwQRCzJp^(GntjpS1dV$JBacsZ-miIH5^f>6ny}C!Ie6b3h)X z{WNHGv-ZMPB;H0-T4&|WH3Oj9_7&;_W#IavRucpT-;C%k%kW^d4C+E(NTv)yxQ!D} zwy+<U<obh~rH!D_qIty*2)$jV@l8*Lk1UcI5_d7MN4*fE$vM*WL{+V&BieFq<$9}7 zVK|oOM1iE}?kL~QQS;F%3uWCE4i!~f_S#Ng&6E*ij%8e#VF-hpDC4>N++!~bFDNkZ zr%!0t>sglcx6l`OZx5a>I0Gmqoy?<CB*2kkUfW319?y;0#lr@Y;-)=V>H)!51-Tz~ z_D0M`owk#-coJQ26dBkEBeL+?cfUkrffGgeeJikKh3@H=T5_rfv!S-aTKUv?upf{Q zdZbPu7~0U9adMd96D&Zb^7K_};+B4MMZI(H%=<vHcdQj^R7S0T)`@(7a;f!FU$f)K z0;bCm$s@*i@DID81V6ZZN=+?V#Q(T#%<e|bCE4u>bK^Bk(C)tG#f%6K4@*eM6OvNC zWlr!t==#T0iXC*KfQK3;=YUoy>m#CHDr<}38oOsY@eGq#kX-Ew7JDjZcaKZW=xnU3 z#jF?Q$&rj2ivYH3bQvE^fko1ajm*qfz&F|Tn{B}qpFJ6Bob3;tUtzc@{m~PQDJ@bL zPF-T+Z9k1uS$K|3#-+&>KfC5IogRp+rRct7c%2)Uk$1;pqL<-WOT)EiSo)JDP=g|* zD}}QSVJ_VdR=N*#_wHi2ooNtIlpG$jw?^df`M-W?7P7SPOn2I-iFh-2>~@J_4)=Tc zm^XZ1ziVbwFq{o}`!po{`~VoqXu%{E@3iCq#i*4{&!dH<ZmsTh+VHPmKO-*MqsID5 zfke;Uj=YC-6CutO@`3J-rmycxMi?!Uq1=9xrX>V>m(}6+V5aNU1u~>1_lrgx_ydU2 zzB@<x#L9QK2dKtHH`!!<o5>@sSJDf?YZ0_jdc9LE3sXHK_@ej&8YWG@e}8QWU_{%= zisE;^h#WjCd#N9UZ<iD2uEGeAWjcK`Uh(@=`lh`b>)h$;0rywH3+jFKP`hfB1~ws* zuBDDQ(RHZ}i!m`w;d^HFht|@igdy?W;I|t*4bWCY7JIA4kx;u~0;-^RZ#4xa#2L?n zu;`_+B>C$YjX++zH6pnVMj`?G@WTes=MRX+(g_}K2(+)>rih{mThT82F-#pLdiWZ< zZ1rnFYLKA99jCT!f%B@M;IV?)N47@a1lmlGd<qU5qnSz#f;evw?uLimN&Et^$opyL z4ck<>@5-3D^JK%NS2N^$AfVJ?^9Tdb&ciEFKVflM+6<qv18FjL&bJ^L>o^Tm-*+-B z1k*69el#Wzi&iHI1UXPFb2#PUAvF0w%TX+Y7_*3|(zN-3X`bMUk$n_~VZT`NK!Og( zKqPq^HI-`%>NRJ=szsy6wHJtJ%Leb@LpzRO_ZRq~K|d)(?_c9HoxC*l>WJw}s{I_1 z)oUH?vQI-~c9YBBJ-MLu<(2Dcdogfh*2}#u>dX)cBp!mFM1+b2^aRy_B(Ra;O!tuZ z-*AdUndeC!@+-)~Jd@Ml#=3>rsTA8|oakR-iY7)l%=Tvhh1%KRX~Z}KXme+y|FKM* ziym-)1X<^!elqu;O2=dMG^FGUvz~60Eau)$ZwDbM8k2^DSiJpo(UfJ7Zgkcx21jcY zdJy5*lQ!_y{`K|TzpOcopR0Anc2&)51qFN<18!yA4`et2k*3`rz|DFrTPuRdPh141 z0X5ed!axjGqbaOm%VC0f8tLXJ25!eL)R*xb@`Tr3)g635G)6~|>qOrna~XUvF&|LD z6r4FV;s0>KWGI>pmbFjm6tMVD;oB${6)+TW8Y#chj@V`P^a#B51EOeHjb|PWTG;GM zUw+J#mK+-Wj$U>mY=79y%JIJq;|-Wmj84ewnV@sGI&j(rlYRs5;%JkvZkf?QYkeZ) zqmUce(|tj=Z|#1vaxa4~-sh>KJgGGi989fp2?Y;=`Qg5UhFeI6(8n@hGYx&O7BJyn z{(1P(FBOl?HLrD(!@yv9+kt-hMKF9fK|YpFjurc!B6=@-jl1{eq=yiqvLoVWLcM$r zdm`jFC_V8I^WecrWqk$u&4bP7L~X$+2!}QWKgA<x(3^kX8!ECHbEn_lm}X$ePz5B4 zabN38WMpz4+wN{MtLv~xM(f8%E#rLJ5Gm6&aSFr}E-3Z<m^6Hl(X~QUCpZ{Tc#z7( zYd^{7zoWKx1(ve+fCF;cA=IjF#pK!ejgees8p&C3?%l)4RW6N7`Isl@lnLc<E}e!# z@QQui8E|p<H#@9(^#(2DfQ1mctWjqhZta<pWdI$uDxF>em&yCny~Xxj7|_)btZlCU z;(BJ`WUV}YNBvJ%EX9+P1E;?~b}vNn()15%y*~LeVj#&bmMEf5SKE*V#GFMqMS&QX z&tWTF?)t5FfZuqOtg@9&n9Y)U2R`<n!}ZEMpPj*s4TVZs8I{=WS&tO6V;IC|Ma4g1 zKVTwWB|JWuXOh|#UHIv`(=MUpjh-F_D42b=K@1iLa0<htw?>KT`>#Q(@~xxvZcj&h z`wQ@Hhy^FnI-}I`e|^X*m%yK1ywCplf2#@zXsT3gDVNtrEnBZ{iA#LC2hsqTyVmka zg8lY->VH?6=U^1d+h1j0qI;$d=@@!ReTo?am1X4d;BE*y@Z$v+)^}hN8EV@9W?Uu6 zq99%%XM`|vR9vbr@~!T*HiDMt$6>kDAkUG5tP2<&+h*;F$5xdrq*dmahlhuc-{g{s zo7<Pwmrz)|?@PbU&OwliS#!@oXZ%6GHloUu$!FTq+3No;g!3=BvDFzSOH08u{U(b} zeN*<I(v@+Srwl&n75#t$OjMXk^n%tDF|O5Y)2(dts;s|4Mk+c9;$j{l77QV`#XKCK z2v9XR@w`9%SeM?}tDw~j`29zwbbz2_rK`ZZG;(H<r#s7R=x=aSvAq@#{4CzxEwR`C zUv)=`8w>4!>rPNi`ycJ%n^Gb1PfhP+?Z1NWr7p9__jTNDc$(0EH2?gmneMRGMPvM# zi!RRXrH0?T?eVx37oeRHMM6Y`mY2H0iO?%{Cbm}tRQDhDmx!ZhE^0rvR)wd6kru}T zkNX2JLryI^XfK<$z>e>9yp@P`(~$O7kDZpM#q*VtO%TB0aXgiJa(vB)gjlP86aZ31 z2<CUzp${jcQ)iF;ukzCbWMp}m=jsYwq$wF-)p7q*eTv-(Rh}OcJ{2M_MQC8SEXSKr zZTnv`4`nkSIylway7XHBfP2r>bYrCz9^Kom3+jbBiTN|CJr0@J$clW0yZ=#yo{l)& zD&d2R$QO`=-VHn2*9m}{pC+46&>l63zPqbqwe!Hmp#=0rfZ0WtHuz$!h1bA%z!0gJ zf>f(HApn<o?_jRws!Zl6=Ldp=?oazb1QOd9&6urAg>+|S2uo-}n9QLkkN!K-sKWxe zBw_nGfwT;uk2M)hy9IJie}9XDP#WsFtB>N|58X=mO7@ST@h1g?k;q8`#7_Z2Mivu` zj}WO*wEoljK)lD#gV<QpeIUlt?P@I$Vp+Wwe+o(gVuvk3UHmmjFlhZcAl%{+i3C$Q zKZBMkv}F<8yLl!A(g<&^-+fZt!v+wS%mMa|h)G2H11P{$?ePN`v@1O0>a?@BNH|sH z6n{4X(Qxj>vgl|-oksE^th~{VbtN8{bQe&eSB#8m_uqAU&||s<s>c0qVbe7>Mgv0` z+t?Wf-VGpAhV!(sGhvkN#YybSf#mo-(8VI&FpyH}W3d4_n*F$akpnOmMRjE=pA>u& zU#u59|2C3-dFHmn-{q;4Wsjk<z%>E+KlH(gckhID;3B*gyya$T@5dD#udgT}ee_q_ zYUhjiR<<ZTSj&kuM?Uen?BPm^Meg~eX5ut5hzdX*LBjViaGyM;|NC2k-!Y6{V7{%g zTQBe~Ht+YG(HvPt=P)ouS{bN+Y`-}!x8Mn;f_bnLSXt3FvmHSBnU@KQ(prryE@n0A z*%4}ER&SjrZ*E1%6s_#-Z?duNESY~2a_)7q$znK|2WZU^H>%o92ddmr%JjSa+n_9A z)LHtN<mMY{R%^fA2JPyfznaj&Oj5$MpSLVJHiNnNLp1c7x!U!pIVvBX1cbwpo+g|% zL#v+l%>Ck+6rU8niabW9k+d5^-<5LjsN1?@o!ureul+HQ%DA`OhXRyu6n_uq1l*GP zRg!5D31?6BY)5}1Agj^ax6@3*DDtM)YZB%;&V|O#k^xU{4aS$nc?)=By5V~7%5X99 z#(VPz*u)=e9Y{kP^p4{Bp?boCP5o$0xG`blX{SY-7LfCllhfyzkp-P#54V~Nyh|LW znxvrZYzFD(?#h5Zf){#mGI_(<ITIaJ=3+6un;-t@8et`XFZ56E^!bj-I65-wf;hNu zA>g5O%^V<?Hyo;gKg9#u`~f`iT5J$pne=!zHx!ZONNF<ZywH~{*D<u#+;5WC@J~y3 zWAhNd=T!8uM-YiGG}aGlY_4C@7E<D1XvDLD=h9ELaQ4xJfJYM>pe1o43K<v^_8tU? z3_b7D(x)cvCPI}E;n1{-#}KBLBD)!vmL9eKj%YYnHJ-l~&=hbd30<Dq$pdr+c9A<! z%ZA2%Z_5mneYnM_{WDnd9ROJV*e6N{Yr<ngD3@8;goB<1qmR&oj@NJbwn`yE%sbu; zdwqX~iw6=!5LJB{0%Yi>rdF4*-diseOzg?=QWxXj<ECQshlUaCBLCgwVKZyqMNF&S zs186f;61k6WJLmz(MRENHbiBB$A%hz>zY8|wb{T0#zREY2f<=r1??zeLtbP)js|L> zs<sxv!NR;~9)KVuwm{@;LLKT9in&&>j#JFcxI!dZN@_cO^zzo(pT8}+zbp=qbL<d) zw;bi%z%<dkUBK3=Y>ow`j;yU{KN`t!4m~fExK(~g3QjpM$QLaxu!Fj>v~)ozh`>j9 z8cZhtnsnxa4mt07AG|sO&KN?|yqt)Hhrk0{&1(CIk%o8549&1Mb4j$;w=W?_tl9>* z!*#mC4Od9007hhY7L}I2T&Sfb;v?yH&UC4i&9iyKMrW>({s3--8ykN5um0;s_;^5- z3bcgH6Uq&Fp+}%1DzZD5eSdc<Q+I=q&*+&MN-jUp`$cKepmrArcW0Hga_MJZrTW%l ziof7zZHX<#Euzt-yc(~LDK}v=I(RyIAB&7#^I9lbJ<kl`X$H*cce%^+*gP=HDx#!p zeBQXa1et?gVk78^`*c2i;kwUdHgOlGe81J=v**WyD)@GOi7Yw=AyMPHQy>J|P?35i zY!Hs16?Xir74f~l<)=W2qU1CS3RsoS0jRupCyG&StaHsnM<DViQPA!tj6G*oQ=Ofe zR(r_f*?roH#Y_`ONVk%b8L}%GkGMp79+|{EaE<9P&S1WW=Hin=>;h?Y_eWh^4p-93 zx$quUp&MeXp=HgE;`T8rq&)*)4-(nXD_d|O-Oif~gg>s<>I>h1ergDJ`LT5>2sQFp zDa`tSZ2*S$YySa&_G%@Rq$WeZ`JMJ?cYeTDLNs@dG(vMK$nf-1L5;AW2?Y$Ie$*=8 zqCt*{(Io?DWG5?br>GUDy)loVf50GhE0z!sgo3J7y&Nm!;}Zz~eN%;jDz7rgD-ofu z@6KT=_QR?Vgg3d(jhPm}*{W9S%#(nxKw{8t-YeVI7SpSWV3Kq*X7xt5+@O9VA{gLq zWQDM&zWfRJ`}$~sCn#-P?V#EH36e>yG-eQn7zKqudXEB3d<~lD_JOFW5(*6jgahdb zFhT%J8Z8SQI!NZ!d_e`@9A$>$mH3Tm=_j*r%X~Za`=R$?f5Lnjq7do;*fLNkhdEjf zC13w=;ss=Ug$FiAGsUGzEg#h#nn-b(jw>q2=I9g#clM#BddH)I6R)cV2Mi<t2DKJU zpLg7}TU9*znkI6Lys{E2Egkoi00J3G)+WlAkw(pbdn3M#L&Opi+&@WIANo_wArHE3 z#;?hovU+;6`f%w(9Z)d&@lS=L2}N*eM~DiC2JO;a&1-I6dlLpVi&HkzoQIXCx)v7q zXQ}tqt;gW#E{`7Yu9!~7>5QiHajUINgXo$WHsHB`S5PBWRJ1sDeMi*_`Up$0G~tC{ zOA8|D0&+hv0EK(RX9jDJ)7`HEAwE{gF-F=sc%RSlH>JQ%z-_?eO$|BIiXKx_zhk4I zu1TH99pD9jS2!`5@gtnPzzgZa20(tI13kB-9WVLHe|3!$h^}$ZWCR@wpxPK5(_#m& zoKWh)HU!g#&Q2m;m}zzZDsfYTyU?)15zaS?mE`V2mCVPg@c4co_K5{?8|9Q1tgom= z7ZM;HoWG1Q?@Q#v9nIHj`YQk|H^McNH(7)X7cqUFQ}74tZPM#}{c5uG=9>(`_xx-5 zS``dr7t3{(o+!Z>kW=UHicaE)Ygin@TVl_W)6=Sj4AbHdY-7mK72UnYp6dNoGdv67 zbUt=B-19IBN=|E>&B?ktR4IyoK(&Fqu0&;&|7;tn{<*uJY!bQo*bh8~cs(PuW=&c^ z9>Ep!^ute+a6L&9nC2t$=d3Y`Anm=mKRFy>KE%XOM&`x}b>3C>3=d<$B-K_JckPr; z2omc1aBdG2T4KtkD?vPd5uFt_!{xolGVvV0QZKJlY*+Kn;|?q>Fs|>Z(%({U^Wv|X zkXb+Hl&MZJZA5wjz(}$2vXKe_1rlm6T3lH^#EjjYs7Q*L1Mjxp!sn*nHBK1s&8vbs z<9JQ(W{9tiX53=-N%#Tb6#cozs)(~25gh`dioeVCDZyQcq)*BFjRj5;wbjPk5OHUK z&trhdICJm9rDwdbX#xkuOO3I&AizhxP6u~ncY@%(dgqd%p7`b7eEE=qrCju!K}Ngl z@{+x>rHD*@c_jkj2(EjFUYXl-Y1{<I<-Trc-(_n}uAYngl>k@JPDqT<-d>GYKswVs z2AZ-nZS>8)C@I%(k0G>;(T@vO7=1?O5GO`Bq9E;PG=xUrAVNDq`HOgqPW#q;!~+D& z&{QJAN1+P-7{@_Em;pu$w0jk~dK|Ct&8r_E-8tG0q7GO}`8IVYQWgDH1kJphI%!;7 zoZi{+J++2zzj8;05QMRFHp$$|j;_!uBs1?jy-E8ZQvXCckNx}Elow;3(&FXixo+64 zfwA~}r>IPb0FthJFv`Qnp#6?!x3%yk@g*U2{n)+dJ@H&L`dRRN(6Jtl6v`&XJ+pHq zg$|zaBp*S#faB;{kpo{>KOH7~%4fE^C~vIahg;d$wfZ7?fQ8_#R$mW!TlPoI>h3?a z!zf_MQNrT`aTohc`b=G_Xj>WiGQ-Clx10Sjmhg!^eFSInK&6AeGK;pq-0NBVA^QGL z>b9YT`LzR|oRrk-Y*d7>`P2+-$w_Uix-6jb{Z-`k^|?chVjI4BI}Ln>JdgaGgm2)8 zv+yLI<SrT%VH+qBReC>NcL$jfjW$0ZI*ATpP|K9T4}pZ<U4koODA_X!rr<)7lIO~7 z(f3Ko*+2xrp%aE<lP^Hd*)vxvhPZ^(4u3scWSX)Tsn@1DfX69sv13e#nYj;?p&-Sw zbp@I}{_yv=wlp61BZ!j}2Zvxklw!t%Sf7Zt<J7me=44WHgrYq3!ClZGRf4k$ekQ%_ zZAoj{p{<+!rRPJ@g#kEB-Y|KH0=5}CDHjshg!{`Rgc1LH#enm6IXI}UPA=VEo&ZJY zQl8Ai9Y%@c*L*R`*8d+ZfZgg3by?W&a8d`7aDJL!W$aJ7wI<}QPzvm*Wb!~p0m_Q1 zMP@4D;F&5?V)<=y!EDQ!!qscYT@-TRuc_hHH<l+ucy}}^;nIQdXhXRR2(I|<FLOVo zuM2&ECgYvXchoputkCTFO^}G^3!EgLL0)d)rp8!my|G#EIYPqeXL&p5L(3<437GQH zxz32-Nx^_sY`0GkL}_-*79jbv%apDPT>94!pw!HPF)T|!N+k;-Xnt3@Q={UP4St_y z`_8+~8Ot|uf(fvhH%fEy7`X4S8TO1#bt!5G9(Zn@q?rZ``39AO^%YUg<2aV=i$GlW z>uaO$TX6DepCN=ZsHoUwKS4G<b4>{y^2?9BcPDB{U_702m7L9HI9#FeO?Lb?mi!{- zx!W+}oOSK}2Kt7}(3R1Q4GeH(<oaL&>>b4+_c^WiOTkXu;ubgl$O!|UuBZR}Pjj0b zjF9?dHz!n7UOq?t^`~71Vy>s@>MHG<UvXnRqQtHjSbmUW^%q>ISS%I+K+|PsBwQWq zP=EtHD1>xgzT^`zob}leukwApH!d#e=;$0F%@Hgt>1qRMuZfxrPOdId;8dL-%6g{u zH9p;BfC3CZFd@LG)4$>&K7I@8zQ?i3=M`Q6KOX|;46hmbB;+<6nv5A)koNdX;=^P# zQm-gIjiASsHw3aFZUR_kCBr5PN@MfNgotZyKh5UfW{87xJm(^sd$_G@u5}kQsp;~m z-fuj%x9^w_rWp5Kw?IBKk^%iRSQf~R)6(>I&U!Q!dZW;|Dq7^HdQ})qNt6+BjX$*; z#3UtACC6h#V9+!tN%KTXF-Sdr05=!P;vtB|@aEIvr%ZDMivY3&A=e9I3O-0_7Af0L zuOL^6zQblJ{n{2C@@f^zK9`HlCM2%D1{t)T-t#~6ej%^=+95}A6dG-1^=gE(6W~Y% zDdXs*B-z$^_!n*<A)~$dS!4A!l2KjL9G?*camB^g`r8fjIXTzQf*Wt#5EZrZtU~c8 ztTZ*Pb?3?(9vn`nK5pl*F^ewcV0SQWj&k|7I73Bm0kN+B5p+A}w*<V<@o~2n_nZYu z1nZ35`j)3$p3S=mE}z#I^!LkGS1&5{Ch$l<S}vWc`k-{YHLGf&sv5C{mdPIsgD=ix zlNRTi{c5ZaYZ7dh<bjt|Dl3dTvz!{9ZHYL4ejR_KGj4=cX8SrVEzS0D!cME!Ud!Iz z-Wnu@$f%BA53gt`C=?H8P2ZQ1@wiQVd&Xq=wR3aQ3tlhor%>}k0)w%CFCS~{UqSZF z_^TT=_M0^pv-cwdq?i{S98|9^Ea>RRu$F%ZwhjgtFY#JP;-5@B#b{(#x^m0#!)6$J zH>^5OEpfOuGVrN5y_+a(HMV5tc|AJ*QPk+=X(d&*PO`;^8Y@mtrA-tV@mJ%zm~(Y` zTvlS#lk>O5zrC5#qh_WwE`Vq2u-ooJZnOTaGwWjMZ7IHE4Fa1ash>Z8+HFqQO~X@p z+0@h-!yPg;JsrtynZ%)<T)noySS;H)JnNIaol3&*_}y%*aJ?17Ln6G^MG)S)T;*9( z;18^GWogzv%nEz^J^Ia9nlX(&=Yn|6%qx;d`fI-dL$%vH!#F)hSpk6E+OCJ%!GXKF zc2O$ge6NiEPTZcuXD6oVY?vT!b}muU)&9Bdfzp;vrn{`k+WKhi@z(0v$a;;_kPb6* z_3N5QV}I=>xxVw`ug4ipO-=ObB~_@73v#11(oQn()@oXReO<c<eYkJMC}T8x70GK& zUxU3$fvjm@86(QY#Z^)sG;<wZN*cZrF9wf)_!JFyQ7hYf<oQ=5#uk}tq{QbQtWA}d z$-k>ibMLsaYAV`tCwed@#Vi$5a}VGmg%<sK<aXo7quY082H-}yu-S7-rnr1|NVtbt zm4Uk0_2#{`s!^#~Wr*_;2^n3@h#!Qi8~Fc9|Mbb%cddU;9}>)^#uF2|iSHvl=CeMi zvR-OWO%p|X!aG~F8&Pi3VJ$HzPU@c0cV;gavcs0&qfwD-)bp;7e~as^C<6w!F-n{n zbw91&v#!U=54l7dZ4XbTR*Mg`M*rgPKUk~}c@^Od%1pjSG*g8)i&Wr#IkJ9z{sT|D zVgVPM{#P|Qr)&~`MxJ`9;Jz~wQeIT{BR8hf>K=3p(4d`d?30J5#iQz!{dqFei9Gmw zmax)fVdVoVD(dKP$Nb;T=okL(wF`cxr9pF$tDC9%83_rg{kHw)L~fGX9Z7%Ln-}`K zb*~-ze7a3LNErgR+UpsV`@2_XcXx)nVasqBZ?UxQoNqTqWJkCHb(2cdGeJ*Fs}_DR z$-=JO8R7E&2LZqH!7H1ktF+kC<qjqt?VdPDKqcAQ?RD8(prd4!3irol2-kjV#Ovkd za4<6VxE$`J0y<gI4Oj0>yvJezDc}lsrEXcJ;i3DDshjT@9V*B+!TL?3?`m&%H;U?T zZ9u&z-t8oinvHu)^@dt0C@l$+8C+DUI=G|m+$TtF<hBT-f;ISs*Um(L=`#}9d}o~; z<zWBc=PG!~g_`x50xnmq`W&8z5dS;&dp9D;FF?!1H8Xq2X!WO$l>g_?p;%hkWo~U2 z<=eyTD%8i~L9^Ua-SC)-WIY&l3|$*mNmI0H-MaBG*h+NVwG3R3_-sX<kQ_hoK3Lo) zO^J9Sw>rGaPQdyu@8Ui&YbNK#A1!t<BX>ySGMVy|8eHQfgujZU#OraDX4D&OQNEYy z;TgwenF~XNR$GJO#R@&(^cqg1?ixw8DOBrfIBm^cC9yOrhR0++ULzb{W;3SEdHwC< z(Z+NZY%BczsjAgNy4k+|uZ2$t=5v$}qqB^^7!)EF)@S2;t4}D2g?p3uEU8W<2mAIt z<i-w-MG)(XhMb(77Zz`Ca^v?|cb&X(n<c`biL!S_t?g`r9@j{e9jf6*eX)fw$d+B~ zHWEG|(^;lhP835+4fz6-4w*U6v)}8r5<0nt>$0s?$?jJ&&o3|HsX9hRMB#h=%Q%*) zY@?jNmT2+eCKA$*Gbh!&6!S@Y{N^%?FOfOwrEw5X#3W&D-I+<@gBHh=*1Z~|gS%RZ zEcG{Vd#X5pZ^52ZSR^`KF=MaTw<~6!O^FIgx@V~LQv+VVxQ>7<4hF2}c7=H=(c}ms zV&eIHGs5#jtHthEN-g~!=^2l0bK(QOyz=#{a4M}jTlHy|qZll$YkUF%f^}qcx|+78 ztK>uJfiqZNL9o8u*#=p^$v1fyyPxMMpX4X|oGT-Z!V@e!J0vACc0GKj{JPd&hF!!! z065!xZ)6A|dS@GR2sB$*BJrle%@>m67$j`AYSy^U7ik$3=@fRy?w_eTnB-(5?nH-0 zG0kUOoKC;~W<`FuGNX{8xKqLJxzGXS`RaHncMld%rNwkGCleJF)o4+K5|<3ob(Emv zb)s#6<?7yunC5olamCc$qD-aTEzk1ZW6b_NY%?ker~RdlgZ$MSMU2|oNqg<v1rU&# zqY-mNuap^CEi7~gQ4ck>G#3^Zv$X|yyP7E*tA#rw8}QHb0qlNYrkU=GF`RF9E<MYc z?<el=6m=9C5D*aOHl<eBum_h;C$(E@0g(HfD^$%kQQ;QzvzZiszPXvSCEIL&k3IuD z(oZb6QCEqLGWGQJ({a}Y3iE=4_fCyH@=Re}6}vx?$hmGD<M?o4Qe9h};h4CAQY03A z#n=>Q5UKw;5d?_C;9cjjS@T&=R;uM<0-SZ!HiVLL&K=v6^VF@06h?H-s?B#s9S(lG zr_(VoFd(g<j-sJKIFhX-)yrd(V-%FLHe4K3V(h@?poSE>Wib=%-WtkatO5X1Cm@@S z4WS9k=v;5-9x6yAo=T|FL#UL$zrUj6FG{UCf=hdSA4L)gZ91fHQ84XvbJF1jMELXr z(Q3E*m)fu|Nee7H@~eYM^a^!f0p3j5Vq#%B)%UTOMvbJZzrLEZcIb*JSVuuJg9V|* zq**2%9{D6Bmw?;3ulwN*BqTGehYwS~L}ae*Mdd=fp>R4qeK=vplC9@sy>uS~X;8+* z<U5zeM5f2l=Gb`YGWG*2sov@YWk7VCq8SUqsRMG2g5Fu%+CFvo9^08e>Gh^^i-lOg zUdXsNK}k*RtM#IFbc`yUlXJ8@UEiY|#p>{m(KdG^GlT5DM|lt19w2#AYm^yOA8nk9 zb5(G4#y<&p_qs4GMkhzSs}u<-f(K4h!~Oqzno`4|_@6&d8I-8c_E1s(^S4O4Uat<2 z|Mfe@2VWZg^(#+givQ0m7QLW4gHrGxKRBO7AYJW0etz5xgMg6#{81x=<N7~;g@h)O z#`3RU{r~ai3|SqJ@JE6ZU2G56I3*O5_^S`s7+B(XDE{?c)E+-_Qz9e#6YYF_`4ewz z$21o`YQ^PX<wH+`0LzSNR6RqEU9J%w^LhM-+0}{i^<CNZf%<ewESBiMCI9-UY>1co zljYP%m@FV5^^KmDi_U)YXrNU_gIdC};mZHrXkK*AUT;!u3V>>@d`vF(St2phHRf3r z=Cjli&dZzJ${E%fYC~>rm}^s~XuHglnRfeFBL8~Gp*&$L@zSaV+Cx7@rGn<>gi$(Y zW&~x%oVKQr^EJz5!x2r%$d?8=2F0q--D+L0oA-Jh)(-Fw*Ps8!E7;Itl})ou6+(uE z{}x@R&UXA$*uTDP0}`q;nxVY${lLCN-ZF(%Md}_rnKirhLGAoE?ibysuCA_!i~R$A z36_6Pe($3b?v{_{O^5zH`PYMGV|e5iF$V|rn|h;qs*bMQ*Wr&0*h|=rdslxn3GYpB zXTkZ;>hSDee=QdEOG5|Dov6iO`pO{DnK-GeUZQq9#%;KUzByGsHud&jf8IcHG%@=u zvcLZ+4=?XGM<;P{6l~_#@`&EEv{Xu&@!`XV;gM_B-&QuQt%_oTf@E^KB&9z(tgknH zM42daa)~QI`PVC|B(1n?&$uz^REq&IKLRZ)HWn6RrK^*2hJR&e)c)Y);jDatX788i zhd4L|F!+6aTSmj~Y6^M!05g=Tx~As)kqzg;7T>kf2>nb+dAXYrKj;qz(^|Uh!1}0F z?JN`idb~D`UYW5FLLb+v-;6}mne*9i4Z!zlx3Z&vjEpQ5UdNy;pZ{j$P+~tMlGALI zDkdtlHE2eu-noyVu{ORlh9zCIx0gV`NGPZ4U)%ggsk(XEcEPmZ+PKS$gkA2-TV?Le zV)?U03XNAauO7FBKt;-S?1BMSSz;lvDL;PjeaJ+H{(8dB!*sKzad_vW180gy;cbm! zjQjToVuZy_Co8l*WFn5~kM4e)+cC)RW;TTFwkPId^Dit;%u4TIkl-8F&8AW!PDr!S zys=Na=};kyMY^1#ag#ilmAha9>i_*ATTGfpH@{P6x?kZK;o22-7_QM!*SZ7OfpU`( zg<AXbU$Mt9g>G%k!zzzTM^zP9xll!PCW^kjgD#%ceYHe6PH;cVQU4wWhH@5j{XEra z&0-hflctlgS)5#rkSk~mUs+AU&ifLzpi!r$fX$-9G0KnFFrUL_Y1!D=nymltyMh1L z9nUKeoz<wcFgt0t41D_}>pisnRwLiFTTJMVVX>ZB@6i79<zDX0zXzxOkQxmYl}Ius z5l-$@VIx6KjCLLaU+v1&ir>qZanDS1Ku+>RB2K`#LGay0gY~j~Q2A6svinH!{F9)$ z%2{V&$np=*&6Tp{!6bdx+MRqj=}jH}&8-2Y%wby)&P|4yO+L4?JgRIk*S{M(dQ3U@ z?CDN$1O9O$97XgJy!IF0u4bx4E$gl%!yEbj^;y*J=b8;TENwW!MIst&`sTK`&hiSZ zu^=iP3B&;;cAwM$J(=H0vQ6&73?1dpj53^_tvhgdua2l{b3j8+R~r!_c%2u6inH^y zb@TZjT!v^+D4Fz5=>*QnO;!vSk>3i07wb$CsD=29ytR=Wy!mKGt=JVVup7RC%<a!3 zIYqg-0b(H+Y%1#wpg)i*Bl`EdWX_d5z`(>Dt9gFS2KuA-449b5j?1v(HIggLv)?J# zE9d7_7HHL4Nbm1hje)+Q>_ao^CBH+Qw&PW`W0#dxkt*QfL2s`;HHtGWXKI>HHlkSy z-&DTCvE+fhf2Q|>loCe*mO`L|HmsoXvxRxbtnu;j)d(D!z&WWH<~Bakf4wJ09UL1J zT}gnX0!HGt`79e_S1yS8%4BV8N^NALY>p(YoS_>)T=Q8kcIKMZhALZM9heW*R6}3; zh%wh{&iicFPvT1}rNm;Vb4OE?VACp$Rb~~`sj^y)UHsQs@q<lWIc>Xqojb4(5_O{M z-G1IH?s!N*kQoreygF5lR^zx@0v|s$0GDMwWp+*^hR<cod$(FTc97;vhDq4ZFR~6D zQC%lQBqSE$cK<5iWS8*TmM?xV&D%hsSJFy?z4@m4T_P;Ym<>Zp3JPpI$2Pp9_U)uK zM=H92dgV)le?5v<p2~(nzAYwATvE})<`e!=W}IueyZ2-r?Ccb(OSC~P8fbBb@++1E zAOE4*v+~`4{dF>%;+%~k{%WnDKGi~PsSiBve!;&a_JIEPLew=lQKDv>wcuh-B~iN6 zJ#>KoyoIiLW=309b{q>ztwfFcr7yHjvLB@X^}_9%dGrH-lkm4Lmm2qFRT0fzy0<Pv zpU<&aTTHK6rCYZ@(|AnQWQ~fo)4w`oOf3QQ(f?!bt-q>XzqV0K3_?Y^R7zTqkXED? z-5t{1-6kk0-Jo=Lr-*b(OLxbjJI-9sd!BcU=X?HubH+Q){$=ms7S>vyb>DMd^SZ7% zX9&c*$E`R2=dXI-)tvpvlV0(;xko)bYRG9yB}Qd8m#3HAe~H~WWKa`S%5jqjJwL}H z-eWTxe9{Ofeynae>1M`IuJ(}FzE+`4mbUvr+RbHDl+0%L7MGI?O+6y2r4kiwy}A4! zIpw`$3A-~|dN@x-4y@bJ!|07ZD0%km*<8ZWTG{&AL|FkW&rF8-)GIxcH7%u@Rq<E! z14HbM2PY?_eN}t-kK!+PI~}j$j{ZK}94q5&bj`SUr7_<kGhBIBq12|2mFv|j%2x&K z)s8%}#`1mlUjD~NEi1|v(m|Mwlz-V7MgDzwu=Y~+XlpW<T?URbq=0uAJY0qfllW%D zO}#_eRvwqGQ^;y}q;~wlhQLgQ49}q$TckK{XU^EX@<*yH<D?IeHZ|f;P*v?T{-rJk zr)fVb-F}O-l)__F%fG4{5|fH6QyL*lqFuAiY5AXT1}#Pnb<514B<njv*5xhI4~zLp zCtFUWM!<&jbooRohoddNJnb57C{6<m)ypiX-QC^wE7b#(KfoZoA0tyPI_&1k3c&v0 zJ|<z9zCd@}UC1(S(K9#C`H*xZH&2}xU<;9%8Yzyuu&MQi%g$hAwy71x66jY$&31td zR8cq}HJ}V8<Le(JHzI1{=db5paaL8LQ(@It{Es)gWbF8@K6L-Ym=BkbFe@Tw7!i8? z2GZohCs4gXS3lmh#(DFHj5^yl_MS<`B#3wNpKb@UwwxRvceJ*04tv0P-tXu<D0S;T zy{S*DURt=+lb8(}GA-~h@(vPBsA~~Z;Zl?w%cffzpI}ezssHj7F)=Y98KUVxO0GX* z)wloWJ8H|d=q7!w-UgLN{dsZ{%*;u)Gpw6S$WT|ZmLd^QXB04{BPNb}H8AaR0WN74 zwPt_ZK<5(`9alM+o2RlfcO~U)WAoK{3dl3FKBWCnt|`Pte1@5yBACP`TN_BF!gn8D z4M3sJe53|!W^D3eC|#Ouvw^WO?6|H$WnjwHgo<g!lU+jvEvEnZ=3a{!<KU4!j2Mi8 z$<@Zt79p>w82+1rY;|skCp7h58gD<fAWo(2fDYJ){sL7?r<nO3fHXA^PYosW)lB2t z3-`5BtBGxukl(kIa#bHfdB-PQ^!fAWl@1^zZ7+N*Ha8ZO#uW1NnP}<g)0Fcr6(~dk zBPjoGXc}*{PQ)>1o~KsxCX~&*#lTf1`vKAeid?t-=Ym{zsT=P9fs_g#i%M&SQR33h zJaeyMC@v}r$+L85D&1k1jr-1E`Y7Rxt#c=hbA<=3Hos`lMz(tMIAxJRcdQc3LREm? zV@dhMGO_hx-~Wj0tg(_IEB>FmPge06HR{I*ycQST*81x7{W{l&jDG-$V}hYm<;JMA z^B+HFpiFscWcTJxBP4DPAM1(QnC#tr?K)|@|EQkc-~GN4cNgef)Rk@J$<rKV&7!Lj zIiQ2b33w0c$ldL>r0oA^aS~U!{WUYShXfaw&)mQu95}+qWIJN`1ydoEO3xQVI3E5- z8bKp$3sD%ML<rxjY@1^8x3I7<FgK?_z;i;_ah01sBK@D=KH7W5r~il6lK-DBbpQW1 z_aEo*{|x@(|J|=OwLf3W{Xpcx$1TO{Eh>yn%>M7E{7c*bxRw9)58<f58CE7>f|hL+ z9hvZyluuLHS3ZO(|2vetXa6CrgZAy--Mdg=5|<hy`M-Sr9L@7z^+4fs^b4#UiHiEr zR1nQNYUFPr`v1=Am^bOfbrTZ(*9*KCu7UO)XwQ0*<b6obz%Vf}8y(JWO^k*n=3TmS z|A`zhvcvE*#7&#yWs1IsdEEpL<;^+<31K084rO~!kF>z$3pr?zV7FIn%S}HzxcF}` z04jTwEO&AG_+p)C{#WuBf>&&J1_`DN`A<RKAr!f98U}Qy^1-HnDu4tcHkVWql8u9Y zf97Z|c{DNd^~-aO0pl)qA9T+?8TM=y7JVVwdFPd{kxUwCg17Fke8D%%2~eROh0ZP> zhF@kNNoBvy(5`krN(45fQ(-!Q&}u0YjS{?F)8?%~lc6q4Xp~D+b!S98Ud2GGE5Uko zr82(?c+GCo$mUA7gV-I0F-X8;73OJp-2$xkis`!D;{Xu)lO|`LzV)SY{+XG%az*i9 zthU4bBr8|DShg3x9vzc%Cj+Cuwo-({?RK8ZD-kIh$>6kvMXv=oqob!s8IYC(u%l4w zWk9znE$|CfZ{M<NR@xu{&h%fLVLM!1-Y7dy%>pjibgS??0vL)MnT9vjps#?ioGHDj zZg#ojyMzTy)e|+yD}y<`uZ4w$+e-{=Jq28IHMO+DsU+~~PVM*-_&t?jmdf`6<QsOE zBgWD3y$9HBZ2*N!7lLv79EDn?pEK}klATP#M;5+&_pV&;)Qtf5x>)vXD2AyCS>GJO zIWQlNKSA+FhMg+rd&8t|n-TaCfC=q=Z>xS0_Kz|hS`!GY?f@qoy-eZ+yeq`7lLsu& z3og0mt(7@mal`RwitmfB@A?UMSr=)f(pS*(fT?#l-j+jAw;^(JKpGow6*Ba<hh+ds z!GZcynk&9Mkl~;OyqKH4-u2~c9Z$YDzQH5|P{8(o{NkO7;(;kxv_lsb7AO(BK>h>3 z8Cx%rDX2S5h6m6^qPC{CSAGrceQJ&C*#}Bmm7ZMKU>E_LisX!A<Es^NEc%XC`sQP~ z+_h^5=-gEl!PzFSdB{0mKTu{qGM_M<;w~ETT$`cUuxWR}&ItwmFNq)GrUmn#|MIv- z^%kI35D8zthwI*RZ#ud$s7VKR!_qrKUiwmdo_(TR?TE+`aV{++0g+Nk)~1lMol1p? zi_7q3I&c~c^LrA^^(Z8ZI6D4b1@qWtospAKl!m=qsX#NeluqL_$i15(Mf5RFV-o!v zVPN@v3N8#4P`>RP9oxUR-&}G6)PC#cL?}vM@7e5d{wg^S)E``XsJ>|JeXk>a{?v6l z-u_8a!cBKJ@B1_oxPOs`D^~g`Q?(MKAy|hv!1ZkJ4kqTnEQP32xuhuy{Iz!)gijN? z{Dx}`a}$OE1yUja{Ha%MR7gf0pS*b9X7b@BuoZTTr$}w<zPZJgI_;3(U)Wq^8!+6Z z)bewqfDlNRiYs58OY7tYN@eMCKgaE8O>gTjYe0BB`8%zA5JuZt^I9rvs@i*)xL4QU z{sFs0qhGK4_I9R2R;bapK1J4nORMhXrtjY$z`>{2D7WZ{WHcSu&t879q%A65Ra0X+ z!AUU$u3|(#h=B*T11%_I%hDTm%8ep0hZt;)gi!n*L`XKD3~55^783>)A)!>Cz;lrd znWPBHp<Fd7^4hDQm=r&H6((cHwZ9@~9@u6{$ZPO|=Eq;HOHCRljG5!_zJfw+e3)@z zX66TBaKXcT%_=;4<g=9FX)42Uh+d%`bU2>S%lO~?^5GxyCzg}t3ghL-P|CW!!#LaO zhero|nXsDRPmM*~aJRw(%QdM44v7kDbn(!Q&CLU~>8;`t3ALP(I1cNP9xeBPS!#0j zuI&hmEI9z=2V0|RVfAs;w5K&*XPcZ-mrv{<)K=RsTV;3H*tVx_Y4M2p<sX}#nR1eH zxoL*7ZSPH)9XHl|W4h|Czj12S5!_OkBf*48&MjMIUz6R4-W`C>9;%q)Hl)}btNou` zxzW<s{+|EEW4>q6EPU^q?!l@2<v#x4EJZ6^ODFyF@62b$|IjVl2zuiA3VO882wE|L zyNhMJqz6GW5BR+GR)WdOpfe+(Q2L&MF{q^XI}7|N5xDf>15kV>%+#X3mL<mVFr~|x zH%WY8&4|ixbG~|WLdyM&oLmRd7ZC=$W2X902Z~%M9*$90$=4hLE-!-8)it6Y1ZPlb zX<Cu@um1i)C{PLOH0*CqM(9r}fJZ)+%ig>16f@4@>W#yFbH-TDOjbj2iO{943*iPv z)n|yYV$-r_O6>$5?>D48N0F2$W!(qsaw59iWQVmo_N7kfV3oc`iOPa;Y6GFYdd(K| z$(F$L_VW=Ffu87`(cq(>oYO8!DIyr+PJ}EKG*k^|6=4~xmlrFXuHzNvrncBt0|S#a zM}t}B<fy0%wJ4kY=>mqMKsAI~Q0;UO@|WjZX4Cm;F%*8&eJQPF4ku=aKIXR#XFXT) znvo6O?}<1~(|-I|!N*#@+E207Mu>@ACFpXSdY+T)byM<zc>pM!!4lDo$0HHV@NXK+ z=_(CKCXWeRME$Q+f6BxfC*qs-f@}>n?<$DrELLmbJK1U}+0ZbXGitv~Jl`5f8e-IL z1&$!9RD<@pwXqY0p-g3AEq9^mPEsDP{)Kf!R`m26k79%N<XYFgHgGApE;y@1&_(o@ z8J@ruPCPvOEfA2J0K{atujo>ph~H}0=$?9w(<e9+8Sr&JpBZKZWi!hr<l`>gVwUrC zmh~Z$j+Iq@S|%auq=AX8rS5P|f{4T5J%r5tz4Pfn&lI_)+iquhoL#uth-f`;&WOPY zb2t&n5jn|W&Yh98dBDU=*i4o3leh4;EVd<T@l`uZ4!e3Zca(8E9A~DcdShQ+UNf66 z%E;HOqXza7Rfr4U!xwjm3Fq}i<nODB+Wq0>sIcf$6!ync?j}+iD%;D5<z_skYKtlH z9^U@h$Co6TbP{IU%ZR`fa8ZFBC@<O_W2#b{*_Q?&S+Xyl5w>i@=~L+@O7~>KCnL*; zBLuXB6u0|ft<^+r7RhJ{ijd4!sR#n?+MMtii~D>!V+%hmLI<m~3%?u4hHR~InZZ(1 zin@Jqhl@qH8;|kun9zL#M$dX1GI~sAlhZ;|frmX%zA#Set*{y=%qik<KJp;qaCvXH z)b-Pixxp~N*{%aGr;%1+aGI|@1FUxn%R!b>Q^{816_}Cp5K2Yzg~Wq)SoZk1ORW=_ z@(R!3DLQ&z=23_SulJ{Qf^Zrx>g5b;m4vMu4n&F{bwFccS?|&NAQG<h3-oh`^FIxA z8tJ9k$~($m?ky_TsYe))7D#GM)wv%n)?EDvBEM2W<zOJz`wwaj*F4BlgR+j$6)qVO z{eAj0rFKKyD8(4I8%IKktD_8!+lndJQ{6VqdB2KP4U>@rdQ$=T46;uePoxw0Q@k$F ziJL(1YeDQYLI8&c9WYDd9gbkP+ka&_T{KRR$Zv`A#Kh*ZCLWIH#5pdmvFlg%*t5e2 zNHB=P0g9+y!7D&%xRZIPEF0ZQE?DEi_t2?*$FN``(}AT;ls*FWy?Uih7PN%w_E%n> z?;%yO5%RwQ)!FLWY#bv}=0roiE-Y=6BLpBc$sy}?{t!;r>&sjmH+frQaJppFLyu0r zhtZZebymYXSfT<t5cpA=%5f_-Mw_=WiFX`xZ9(Z!@K+|?ZwlXm(3}sG!59!`+g6?^ z)5UNtOM?upYxi#&N-A&jLM#*jH%4A-X~IMR?V#MsRL5?#{{WXk_18c0qyhyAIG-FU znMJ%V+p<a61V*)8I1izhF}WZ(xWLu}k<Hv7RvT&y`q0|=Rp+aDl>)T_7-=C9N*zEN zk!*iH5PHh#w!Fos&r^5FXIX^smx#(^1%<&B4i|j)V*Qx*M%>zgBz)55BNv7k1)x#E z$VNr5afDNdI-xu?@($*_k)aFph#r6;{x@<)a#j3|$g?0+pg3Z$vx^42-}mt(kGTcv z48kEy@^~yn3u~qb3kkKj%~XQ!1tuhv0|TMV#Zn=fGn{3xqnE9mXBQf!Q|?h_J7uve z*CZLY;tl}UadRhT=RFfpbDKPee_?5mQt{`-3cE*-9wpN%82_oh?RK=u$+&w|>vZ8$ z)ab1K~%D=1a;E%&n7*KwpQ+E*H0O48>AC!szif5la)QoQ?YxQ$a!*2AWH*`ve@ zDnyA<@4y-66bE87vIoV)!pPp-23N$|SY47xAOTcC{;L<a`;KH`#<Tz4gFoRTlc>nJ zFq}7zsy;l9&Isp0`qSS%NLB2D7TWmu;w;;gqkY|!qyEK-@QJ;*9*0|##%xPFyAqDw ziM3`{%e^{-pApmMy;GjH>8Mn*+@tfi+_Hwv{*bqB=d^QevP7b|z+CDn1A``TX+x)& z#QK3(?(=xJZr?ToR1-1Tj(}kck)KjN@mre5FpE(6(jGc1AiC>@hjK;&Q6MeJB-vU$ z2|J0uWznH0B-gWfnOw&bWWm&xsBeh}d=u5AnbKOP1idZ5oUROD@v%7{D&jKCgv{8r zdt!w>S}h7%a5?>Vo@!OGNF#-dhnN0dqrwoZDl;<=0+U`*^;DUG;)ep%Dk--$6zTuA zS4kuM&AT!zCrX<$Gn~K<s#R0UX?g-T>(pcB@2lnTA3xrq)H<Y>fD{B#qweTj`NYVx zfaAUt(No<q3w@XEAH58xZn`VmEI{d#>;D@l5%Q6OMU`=!7l92sfExr}_Bq2>%Vx5j zsXCAH@byfdnyoF^wp0S#eht$+LO>Eiq~|pF$H?@71wD-VG~HqRotog=xB3Ycq3!{} zG02^z^@3E>WNQHCUhym{;In&V?jb8%h<XfQW{c(Y{vd*JCU|glH1@L7o#1im<qaPq z%m;k4HPgM7H2L7XYVqWIrX2ixRcQ(W+)z&MFICI|gl(@ziLqn|ILC}5qaLOAEWhc9 zvGaa$FfFgDTA3~#mj)Iw663LulvYP5WubIe4<xS3Ae-b?m((|DQ~fXcczrmn?oySv z_jn}DzQ$#FZ)ZnoWUJT86a@Xgq7I3k@g)eE!yQWN0TuB#fbX6<zlG4|&%(PZ;uY@P z+~XslZyy;0UN+NcQzg(FVQ6fe^YqghannG0FH80FQbj61e1Atd5V`d}?pcl1GAf56 zL0=?{aDiW|d=|ua(7>s!bd*mzm_5{5RISO14p?iRbE9v4&zSk$;?nuPc`oHN)~3dK z-f4k^Up<=XWPT2`s}9wu;2&%a2}3OztkAL_BS1KvMH_^mz0i2uQUQPv>h=Mb${pp4 zk)fZS=K80<-cUIFMHUtbsEhAjq)Dg@mbo|F)Yu5_U8GkDt4sVt_e~}5^5qoebjHEv z6^c%NIl3OyK6WVrf2^QiA47@AJ`=QLcd4kSG=)bXqN4f@1#RbRws{;VrS#b|UK;nd zith%VJe%O3z9AA?@Obi>KUI6!xDs>S@kf@4Qdge3>B6ch&nx};u`;n)!QFhtDb1(P zK7lh~$i6I_xarn?m*~_`@3z8%06gjtHtbIy2UA9txm|a|DYI09d!V?IgA>E;yqR(z zpDBjxxAAzDxpn+P1x@>{;oN?O)~Vga+DGvtL|(?Jc>#9k9{I|SDfl1Y{9jyFirzFY zw;X5k9Q)~O8}B}U5H$pFQvWpSt%!L+FaNwYbgHNqMfQF@dIC46DAa@4Yun04S_}jH zdbKC_2UFF?U2ue@7`c|wdB;&CkJ5M#;&PMYyi6@`%wafdz_|Za@jsM7Ik66%08x*^ zmu7#SP{{Q=HzbXfA@iN5PLiP3O3qIZh)79!Tip_k$GU!*n7G`u`qB%Pp8HcbV5Ll! zeH6b)3cshDa|FmUU__Af4dQd0Z|S}nCDmge9WEa182vFXFAoqz9`o&eIb>o2yUDf~ zg<1zB&D;A(!wGBa=^_nq)JQqzxTNcuj?l``6a<m*KSv;B5sqNwaNL|??%`Tob-a1& z);a_rhvPPuu)Og><pMS9LCoPSt(Q{Tm#k@%U^Wd6U8|SXND<*ZbA6vST5DLNoUfe$ zc2Cot(5u~tFblvu0J!@ECY_**bA!b-N0Dc_C{1bm;wFXe+CsYm3iI(>^@~l`ILX2+ zr-iL8BZfHT1LyS6Sj!vo04U_=X(YdeMH3`FZL04N6;P(+?nPnrH1p|Kh$<P>MO@DJ zOpKw?U)x0yRPdyO!UhSaU30X2x43sIE7(<O6t=L_FEzj-*AMmNSI+h$Q;AE}pMCn& zy!QN0_+yfVr$2*VPZ}&Ip%4Kt>TD%q3y=us8J0Zl678gN^OzNl#`ZEG;<TzAs75E< zTRraM7U9xriX|Ov=7R<)=4VCw!f03B%#+770NjMlJeH8IMf7^;nMagzBD?1jdTGbK zX$mYxi_Ka}t;=SS-FA+)ETM^s<xZ12MBE;d`@5ifO{Nwofy*TkKtz=tm-%7*3Cfv& zIZ?=h&{BGOAtWSZGMAdA{&-&G6j7lCOhQM@%Zxrl>0bUD?8lwGgEI-oM>l>wMk$K6 z^EAXwQv7C_{B_lB!^6t1b~QxbqH$=XBCfj8U|WWEdHIt2blbGR>#Gf(A1STUCVg{; z?b`fC!b9LyP^@*C%iE(F=3aZ#(1bGkvS@-S#1T3C23Wt)z`)Y0Ur(h@ynI5w^6Cw$ zLUZ<CJ^I6e0iOmA!fCBKH%B(3LD|u9V>x9}QAYJ*O}O)6b)V|Me`~cQ){X3nxvDNC zX4m^Z<uR`Wn<livG9*X9@fB#Ar@=nZDn%Sa@ka<a6O|+6G-oKIUVXeW*h>R1j6OrT z(Tz*STKH7wa0Ei_{)*gZaJ+O=YFSO~WB)z=roiU0@)}3T<U&wTa4_fSbxK4wk~&B( zfxAqxz>2hN{jV03T7&fpGTjLWb;6|+3E$bxIsXt==q;+3o&PD;PJB`3hudKaA$_dG zISJfG86(=Bv{NU!i_Rir9b&D$kQ2<7d-zZ+9vHy0Ov6N!$LR+87jxK`*00>$%|NZ^ zUmt(#<W$}f#~dsY<Y)EMY&U%M-gZM8*(48etJPzXFPu47d*{G;(Go~XXg&d)7q|1} z$DTyKf*a^qgd@EWTGpmYykkdjs1DBG8;>u$zt*Zg2xQL}JSjFCOZ^FC<aeNqfH~^l z!MQTKWWFD0&<yPwX2Z#KkqqZtT5bxE`elQG1ynxM($YeK+TDGIpD;W>dwd@60woFK zG4hy<4SrJ|i1jv_njYBmcxAAna_V@A5mtU3W#mEuJGo_!`BrPN*HM9&NG-`}<tMzz z+P|s_Bk3!qDQ&E<Qxa<Setpt(l=^(Iwm0qA02jME`Y^AyRy+#`&b0~l>cs`9TXM9{ zwqnmGIjKGQ%`j2DAhuJNl?VzT94z~H&-RHQ=R~Y{c~)m#UTH@GNciI8V}{h$kvezE zhGH-sLUY+gY22k|iID5=0*5I{*1<|2#l^P1gJ3DVpeIYAwa;qaW|@jkKX_icNJaei z$zQNFn#ye5r!?(ac`DK*$C5<a%u5Z;q<L`7&ETY?o;Y-rut5`y3y$tU@@3Cs$s)_w zcHN0DnU%d>H(^gHjSqJ(Zf&K1{dxx^)`0pe-SiNXv+hcy;x7vCcznAgg6(D-RJl!X zS!yW(^{_vkc5P-)LPKW5)l{;Y{Sv~@3gP$*zlq(_?Dt*2bcSB!-w@Sa8Ppd7+BoW- z?=H0GLC+7ANgDdCGRi;}rudFJ=0rvBQxUfBpYV$DD<DyEOTFy0SGD(!w%g7v&xzC! zu+xQp`UKr?4Vh3n4FcN}nyisou%Y#|FH!ORvB8?qG=Ogct*+EEV$O>)ixV^bW00TO zs%I}ZE1FMpb+E(ot(&vU)*=J)HBpun@!i*&fkgEg;H(o51?v^N>F75{Pn?qV5Fjjb zG)Gg*?#wJIiEC@8J&Gp-H!rx&R=PQpr)91BHr}R4uz>oGqTj4ecFnFnybVq5j;qK~ z>I@DmwMwl6Uzt*tJVGg3F_aRfV5k5!B<APkUJt!M*?XFpw{D46l+Ul}aamXV<_4C6 zlP)8^*wEiGWE?DYO2r1YCjwjje;TLG^U5p$AJ-@FG75K!2n#oxT~vq!X50B^6boeG zF=(23pg^rcMu7jp_K&UmWlAkM;p!EedJgwX-p%$)Can<T;-+<LIAy~BTMU`j;&XT4 zsODZDsi*<Z%rHz3beQ|ofD(~Uq&!9Dm8!#iFbRKvdAe?2PYWS`E%^NOH0NivGqN6# zD0C_{G&|uh&xJ}1q)QKKlk31rSn(0-3B^R-e3YkpZ745=L5=mm5>x)EPJJ!PjusYG z1A!hzEogf#3Wr5mT4J4&%0Z`>;?b8evx&kFwwQ92HgCEUS%jyhW70F*o<kDKX`Tw6 zsCLvCcisqkd5NN9-8MdVM3uznPYnoykeve`1}C8vg=B&O$#jKK)GS@_YJpEBEH5x` zi26jl@94SA)&Z)+YI%K-HS{@At%44?8`#x(N-HY5%-h4;lBT8n@wy@&dp4N2YueYe zXy_dO-s?s9d8wT*yEd4Q?Q^x1hNQG)$$#0UQ_dBOZH@@vyYcAg#dEQ@zJcG^t@hiP z4_ej>{t!jc$XEftCy%m;R!m2&)X)kL4TuDhWvmX=OYPk}FD!gfW<KznfJrAmx6jip zaUwsKWm9AG;H2O{%-wyx+P5?J%-t;!n_0U$7y3P3td^8cx_c}@n1uF#AsWWmO!38) z>O(NQu!B!Q>Wt;IvI@F0JpaAAMBnap!_vRET7;zl9R#v)dD*qUXKiTpnS{4BHEG!! zd6KVJS%9@%ZLZV++S6F_-#{}Q$KBKI5d9)Iwm5FXS~GsHEm}lSP*Ao?K@goXLk4vI z5aliAsg_AwYG^3Gy{A@e&=+7jO(!k~9zOT%wdH}%T*5G1sO+;6N3`lalzg#B*%O7m z#}0AkPX|CCLLr0eWG9a2w*LMwv=7C51}jLb4^5}}WR+uz1wpBHL6lPV_i$6a#Vj65 zb!qUl4ToDd$R&Aw3b5Zg*THX&i+4HQSA*i=9ftGPAk*+py}>s<y3wCy8>AcTn>(Gj zz<95K>l31T$kJl>#j47DNrv%VsRUjo<;0+rloW7VQGx0HCw82OH#X#zF=!cU*Kn2b z_aLJTrUlmLiV-xYRrscfn}AL7xs83wFzinYW{rX4B8s6>HJ<rflh6hPcJ$EhYBL4- ztj3yygPFz~mSeS(3x-#RXWo-|o`c7pWu}u8VDJK8K5#8$>o>ov`$sXTz>M_JiG!i+ zR;?9PKe$amF{lpSxX#0)fy*4};vXpQaDAzCwFDQBC|$4FKYMn5D~CY}W(xx-{_$!a zOn1-$Q>&-krkaAXD!=+?99`j|50>QM3dgU}4LX9>IEIhmv`3|+=!XXBgKHTO9;;fi zii=C-#>R&H(42*k(C6PxO;TeWe@Z@o`4Y#7V6OKiWbuxo`L>b;&cRqCMki%3$^wB! zWF11iv}$Frn>x1`3?Akdw?3oam2x}f4?<zMlN14`cv9&WB?9#XttKi>4>^D7liByj zfjK%p5*w&%N{E8sm5eD}^i*JJ<_D7@6YUA&F_1yhg}5}v%kg*l14>fYiQupCspM2A z<|s|3wtgz*E$8i4^nR(UJKGUT<+z*`ZK!7U(OF!rgMI3&oW4?)-ib@_dinz*qHG56 zbW74x(;h4!xzh^^ZBY1X_V+Dz-HlAe2<x@=KgWM~qf~O%@_v80Z+ha#9-0a>rqj9m zIQhz-QY&cQ7w9JPTBcbKv5=2oz=dcCzaq>*iEM9-rmTO?SthHL-%GsjKsuOAICYIA znx-Ph&Y;)Iak(#p4}lj*yHu}IB*>+dE8Bw+Le=&7tfa24?jAm!NpVBbK7V8@%Ij2a zsh$a)fGA?-<Huy3d*s|60bt&WT|m+Thz|*gRM0W^TX#_)3mZu0cLxt|Aifus=_z*D zBg@e~fT)bI-jqQ60wGtHx}qEml5oVk(B!Pg460A2luwe*rMc{v#FQi|R!?f5@D-E{ z?0K=}r7oY?^o1^FYg9<buXlvI?FFg?-pr#(Jf}|Ml`sPwN39mjm3G9Q2(`Zpj$@)n z0f;E++&e9yS5}g?fiaz<YE|(GNnF#H7hYq<j=q#xqpg7v0(Y6IFG`RN3ps8FYmgoT zQH@`d)#aS(CVY=6xc(^$zHO5CykrD-T6@oYub$tYth}3)l(beZEfPIxu^n0F*{QBS z0gV)FHh=FR`W&B5OP?bbQ)#9Zz+5`#iAP#uRpMHLJ@D!@6=6l1MP)G_=7wuO@_}DB z+uYndYfth%Xs3n~y&yJ96fUZ2XlNX)P7aAlPXHDK*l(MU4(4G~k9?H^>5t5grIwSL zqQRsiz)=M(LV1U4%&!oM4`1;ObZo*VprWJ;S?Xc_S>`M{l87%l>6L58!ngWWDqdbq zXr)C|<9(MrWB3!gM<H1!5PfQGdgUcR;X2Zp6AqKx$gMAm;HyRzrBj|VV=Bu3?FDG~ z{&>>eRPfu@Ye81WWb1hmWR`Z_a>Vqc6r_1MCS&73vM`&Md$i!26>VsCA)c8}4~*cn zhDP~+uf2KsM;TR1+0+=f`6ZxOFSnQ^%LskO4>wpnI>4&47o@45O)1R7b@Y)k`<QFd zdwBHflvDSoXqdFBlfU>!wYRp8n9%k?%N(jB0DO6Cz<Ok?e6&Kj7}n>_DV2Hql9fc~ z?G2HBYa<zPEWBQGM<~Z)D4WIh@;5S7{hsj(kVKd^O>6UZdd96|8J|*fjoZx3JY`g` z)ocw;VynK1!pyANY5RS?<e3}ukzNWli5U$!G}di2!eF6?<+|U=CcNJTjF&j;<W3i< z4YauBT&{nMEYV*kgQh7(@NlzBPobnR<-E1i)DzLW+78irJowCNKXG%Ctv~wX(WdrM zpwkeUo0vp%JFez!i}p>v#yGEau0>p@J-J}gsn5Rl$wwj-Y8%d$tJ5>Ri!xh(7G95) zUzE-%QLzo|JQ^B-7jBgnmX_@1JsuZTmq^uyUWnU^(9EJ-b%uQmB{*(T`8Wtb5wsfW zf&3;vmd%u8wguUiidLJe9S1K5l(}u^bh@t`e_oC{|8h~N(^O*~%9K;GRA*N>+!#$d zA&nRCmb;I~IF!hDMZf|S<j=7(^K9_g?{3=!mvm<#20ivyLO3j^(hWODR=P&7N}Pw~ z<ScbauCC*KYW(-!@A=mc&pu}UW4z;(tmlkQjaUA>{BpwuIZFED$-jhuybNQn(dB#| z9bd5Y#JE#$4JPPrpQ!nlZPnRtEw*r-ZItx#yElA#{T+j>_p!9&`me^Hx7Eu{(znl6 zvp3E5v_5`(TXglqM7IlOxxrWqiqAULK24%Q^Hdac=G{a?edSX39kvGL^lAKkFg0IT zcDxE_*1;-QvV^@--)8pkmAF+%^2E<A#t4X|6GI7FEG%=rx2^4FYS$5={*x`5M&_38 z!kwW6HFndKT^AVWcsT`A9Id9FS_)6-V3V@G*4@9kbhJ5M!^7=Xs&Fh2ZOG$R`W6NU zEk<^Bb^WgTalewl>lSiaIP9)0|1=4VEc1;rMjy1d3(vCGomDAxM|z>XHZXY1#Si1y z9y2OGMti4c5l~k%<bRs$&mA8Z=YNJxHoqN$^VMZHAXG*wmhGA6$gjqfkc6;L@>D0P z6-Hc+n4W9wGD&s6{N6hncz3o8JwIGepwk=mV|Tfn!$temRL59*w*Q@WZ)wwgL%`-{ z$W?uMeN0^)DeuI1vS-cky@ag;T8)LDrg6HV5fNXYL3wsC=ADpm-P4gQ#iHx+3G2zm z!9BV39Wf>Y&IEMV->_nla(w^`%hR<3;^eogYU)26*O#_!tTVP_21BH>|JG}nYu0$- z2<j4j{>{dqU475|MwG3d3F>(?7fQUc-6gpUbdyRf(Y=9RYCe8XJCSr@?UiKZ$`wA7 z`iD#%&k#{xj_s{Zep47m@kLld<r>;Oyyx#3<CHsBCj8dY5-gQqTp=mQdwPz?VUZt_ z1ZZY|HR@MBcqDRqJFa6mQz?hr2aD`=zo=dFHy!CZw3*o{tjNg4Zz;&Emv0CJtUmX* z|El%!$sDn^Isc=^3nQxA)Zph#hPyE9+?)&}l;+$y8Rc&hkDxz~|Jxos&Be)y{}Z2i zzHgppu%@WE^ffeG^!3(6iOX^8>CM~huh34^+b8|wap6@^EGhW{-!FVDd8!+g>DAaj zYFHkqtjK%$J-icYJ2S%qJ@yLo?C$Ow`^XUuDq|(fQxe0^pS6G2H(+0Xu$r8s%q0Jh zdTYw_{XtxL$OW#%G7dV=+y0s=qEDG0IqW0@I4m*R+|}|ieAU@s*q%RU&?vh7{<+lJ zfHAWw{?b&vJ$Y+TQp<P+vON_y*w_zdKsI)k+=yj&RCwN?xJj-^#lu6~Dihxf4`P9M z?_{a4!07%FmgVf!&p>h3PxLVuD?N#rUr9)!?eFp5IL(Z&uS*f-(X4a&bd!zCWhFWw zr6Awpd|F=K=2Y?plXh*uQ6Gzt^w^m48=$!Umf4F&+(=y6y<nXc>{TwSH-A~qPU$d8 zF0OB`aSPb(rcb^P(cZh>kDP03<a;hB$i9qjXrf^}M5u3iZ~W?oA}O=LKikTF1-2oU zvWTXNt%;@&Z(GsO;5$*;Eqxa4WNG+;EBl|=n2q3X^oaak5%CV^cwSE|U0oG14SJ1q zHdqENSCY=hU0tD&rDZ=FOiwY_{u16i4zspU=$#0Udai8cqBjMJT7Pp*^{X6ZRLWH? z9hDp(90W$$&Mm0*bMBrj+2pI>!(^$?zV1A0eE78TpAYKH&BqtUywJZobOK2>yLI7P z>3#LkRpiX9d}XxmJ`tx?W~jw%zg12EY8xFtPQWs=_Uvd$l#oD0mPH^8Q)?Qpq3MWV zq_8K8a!cAL$$%|}umL+TjHWk)gEkRoV<3lTt>zW2ClixH(bc^!u8ZoRGPPD!+*G_- zDjM$;5()+RdK?`pw3Us;#?uBKch?846TlYecV+%mL?g^Eh>D51h2(!!V-MV^T7j_^ zqBwePUFDkjXsw90C)Qoe)~&j;c9Iux91yVeK4&mKp2N+>>o9nxn%`zL5^b!#&KkLu zdm$Rug2`g~+vNN><R01!_930Wl>+Bv=NY6>uBQIIB^s1SISzI~YLN*qPxsIsD`fqR z?bT_~^+AzD((y2{M)(Wz?R`frnBNAj1smU6c5_@zC&dkeK`NMCqq1ohR#r?-$P-_2 za+)R75WS02#-OBEpMK29!cs(hk9s#+DSnUR=SO7Gt>RI1hzmS?d>OB+?H!!;Cjn|4 z>`GrVGdUM3b{BV<%97}MVeJ=I!-+r4gAqF40`CrLOZU6Mwx@Qaj-{?DYfm_4#G1~7 z=G=0>e*Y^G{n9z4Yv(IX?}HtfC7n?7ekdohP06d$rDttuv(QfIaTSs!#ka9T-gYg` z{fK;SbT7)FLGKp*nzLoSj*)WugwxXplnO`|K0dA43q*>ghX1!f(U~zRp%1t?IK=2L zUy_aD-y3-0-1w-f_hQxl5x=MO@1Yz{xsf7{>&nNSukQFKNt}C2MA3c2XQp7W**1x> zW7Za#Ywi?79hb5XovJiDM;DF{hzW4=^yY9L+3x?Ny?M*`-TW!qT1;5I$I!n%P9~;n zurrGChARt%Rq!f&f@#3-*30>}bzTr}k&d--C5@MNHakO<p*na<jfIK=yAkGwm%SJ0 z!8TWo6!81>9DnHrVw@@EjQucEA};H_@jjTGs>3@?e3v3MyJM5*sI6S3^-#Ri-O(bL zeZBm<{gCbcP->v~-lZpo4+c36MR3f;!EV~#V!FDK*K`GPs^pT~X!Le|k6ou`mD>%8 z$h=7Uvs)hx;H92DfAx5>+D&(9A2IkDSrLx3oBra0mQAZUG7FcaOQ%xOs{C$|2XNcB zVF;NYJQm!kDE@<3Gbg2o#KfX&ZDs2fs`#^%G~N_BX4l@qNgqUJWo4<B>oGEY{@l(d zz{+|LI^Llhlhes^`gw)cx<a{Fid5V~9Ae^Ngo06foBQiQ(Uw0gvwzx4Rwi?ZsbxsI zx%=`gr**$>{42xOsMriS)9?^{b_kFC?2<e4e`PM{PbEBNjt(>(5WZh+HC63DPt)@Q z#%`)>aX#I-(IOMgR6z!zp1cA%(b^>XaHYSBB5hu*N%+cIUtg*v{$s)Q{mp?-Ls`_6 z`;V%myNM22aRe+5<a0BS0xpm16<Sl=D|+k#4I~MV8L4iiv`B_jP1PLrxg7Bm8TV@a z;%!)s7j}G5Va(DU$0;KB^5yo)(t|spPamhx4sW`f3=ak#aJ!yh0L?@#cXQ#Qq3#R| zRuQ}2OW9^Y^1W2>QcOQTPEhzF$e>+(51;V<)8;=kl+XB|K79H!>V?JEV8H|i$YVTC z7hf#L4Hv^@qkUQ*%Iv(Fqve3%0+{A1h3N*vB1hL8Uf!O2q}49N0wbrQSuKMCu%2H= z&PL@o8owqFAm<UBWiQ>d5AXZejhl0w^SgDe?Vb}uynsZyrm`}g^37a|g9f0)6(38X zk`@6Zt#Uhzzx9FFT<JTN(!!#6;DLV+@chlJ6}G;zcR1<Jpic67H0{rwFQ!6Qg%uS| z!`&b3Xs#4j$p>|nW<+4Kf*&{a1IjRWE_{-Y5uNzI16sq}`J-6XMh-2|U>fVSG6DE# z>dP_&oS^|!`g-#Q$v15+=g}Wm2*2Ldh7R%nS_>b9bFkypY?Ee8pM%s4u*AHjb>!QR z8e@Ms5wkL2eFtF5oty2d^>%rZku*{>$vxRGTlycDU+J1~YkL*X+x*NhNzpf>_f6sp z+wX(DjOj9%q^xKV46mc9(ifR~8wrIot4I&q%95fE&9^Y)4w9>VuDkexzipmUVqBfu z6MV>te7@mbwb2?80+6oZlAqGKUi66=wPOK*pj`DTG3wu?Ocq6&E7{q*vrVD_q)7S! z&U-i8D+!zk@tc?+k=e6ZrK&5-F<HcEjw9g>OCB6hJS2*_5}ml>8L|J<v3QwVPpmm+ z837k4c(r7yv+L*eP?i=LnO($W6C>H8!gRoIlyDKhe`}r7N?2@#DjUOIx)2U`^em5@ zZo+~%{#n7_R9gy*$!F@7YT1-$?qbrHBAXINVFlV366LPE3Tzg#Ne6D2#DnO;#^Oud z+I6S+`4~LcM@Hy1E5EDT|JVr-rZrrARZIM+|5Ri9#6P;?9j%hcb4i#3wy#HNd9Z!H zLEh--IaADdaU3GP(aM`hi!z$-Ut&<jUXbt7xF!W7IhR|570;VgU8j@!-q9<U3f7b} zw%3>bl*g%dSQ9I!NaTGxxX#ItCQQObZ7Z}jRFX5Lf|09Mqt;?VqaJ9EP1YMuQgb!) z(9IpY5n57*s_O#-*}<Y|aNBWC|M1X>E=@x2i~XCYlo6O{Y*x8rPiUCi+S-0)vV<AN z?;d;D#~j%nuOJw-iQd=#$+9B-H$E=sc>PBMMV#ExQeI7XSb>zG`9H<-^bWXNzrFkJ zfp6KyeXqeLQ|Xi424;gpM45*etSGP=sJ_J>J$QH)1GAxxFx_LE8kge~kctTry<_EN zrUMt5*Rqc_oY&WcpZ!S7$k6|@f?(~nG}jPby5bLV@q6>OWky5%-nyr#a9v|6ZD{*| zI4*q~f%eUh23-jiHwC<fRU(bfdOTUhb0gAjr5)e<VoJc-h+kB+lY5kM4>sMdEWgw= znlV=xRbL|Q)hK*C?z}Z{>RtTPANj~*_L<?Yva-Bq^91CO4mqx@Ga{V}_{sSZ&&XBP zBSqcZxUHtEf^YZ+>297f9<L|8t#mkv6%X2#Y?bH4#nA6!UE@wO8yC^npMPQ6!N9u0 z1XeT6Pv9TC9}>PVoae3(1&wNYWBXO%x?#PXzOc}MWc`(_XY&q@aiLNN8biJF>RAEQ z6<k}gIX=oqnU<tLeKsy+*&D=rq@5MCwLK4g7HH1aXMPW#2?N_1A#_U^her=&pf}|w z9`=OjVbD<6sR@m*SXP0WS*LW5({=YNv&0XCJUj51#=0P&!m5RvRLEwxVh4AStzQ|P zoltOcs%({E<RNE14j6wl#L$SKQ-0lan~4?aHuW(L7Mta3Z{@g_w5%*FN*}@&DgTuf zSdw#eV*ltiCLzV%CY+$mmCvXk-6A#4ekqXMUvEiYjLP-j+8Bd3Hb~;RoD(;kw}eFP zWEGj|m2#h?jHBmHz1OFaeoHvuu^hU-bFyTI8FJ~b@{Eb;&1#wAEbm*9GLxyB0E>NL z<8LjuI7tQ6vP0GB{7Fyg*75@E-=gvd(tDW1JB?NA;mHmU3=h=X{$9i?U5`~}_A4)h zKFu6*S+I~zq|svb0V__QawHz=AXfXl{vH5ZAm(6!u3bS&-WCNWzWx)fUuEY8tnNVq zF|yx{?XL@k;c%u=yEU(*^s>O<?+LDY0|7|d5AFIX$@%R<&17CKq;@Xcvs_Q)x3JS} zW62*U_;Gb9rgZP|^Vh-+_xPE|Melww-A>>Sw%c9Yk(^a+y_TQfGgt%ti@!@(_r6C& zqz#-+)$21G@<a`PLX%5f2d99X3ue9n>koH#4m8cGXN2@s&L%14-BYm1Alq3*?Yg_o z8!?kgNsWcQZuos~mNdF`DlvQs8|6~_TF-9n=NQ}bm3Pzcnqe5}%3;0qpt_iBF6^W; zUXs5V<v1++;wID&qqdcQ6-tL#*k=badR41=zY9e>nlEJU@=A}grpfiTKRkdMLHt|F z1i+$pr!up0qG{{nv>dwx5A)%|jIptdUId(;RKco7LxKDN*bdUsb)=ZBdaXOQO6~x8 zm~f_AY7o(KB}yb*uBx???RUJpNbhkwSb2<-Ou+WGMtM6^TZoUuICT_*PF1AcZUhZ8 zId8x(a83Yc_w<P9)PrN^D%5G$^53spJ@SO))Y36&q271!bFn7G;ys#snfS1HoX*(< znYBZms~bmo_ijLt44EGu-nh^4r|<W*KAs3CwyU<UCS#@Fi0|R*^@=FN>_s-qXLk*@ z)y$+nt*>V_!AE%2S@>q$yw7?y4p3s-s}sM)Y8P9qUv*@O<QEi*!V#xGa>^Ix=7jc( zVY&V6;Odie>v1cKiCR)94dq<>n#nJJwRm$U7x2IG+Qo>Ofd2JJL_6OP9qVMY&5Lz3 zSZ&Yr@{Xc!v0*1_sjmSmm^kcnSMl}q=WQV>6;F?L-q0vt>opbMAfRf2i|UWpLyg5S zI?8qD9@dAexd=3&g!T~q3{{F;v6mKKv3)Ri-ay!iE&ndba8>6_FDmo&1J~Vu)k^kx z37;L>p?t{_yYcC^TN5xDbQ&rjLqZ<Pe-X5ps{KSz2uR}XahkcwP$(ZpeZDI3b8!lr zqpceO2~T2=&EP2$59cYadhE=!W_Xihkg~onefi-DA^r8?rwr%!(E9GB`RhjY1<n5Y zg)1T=g2HngmZR5Rvzc<jhpjUF@|&$gm6mi>VH~NFZ$TIudg(pxq`#csfcEuSAol)h zPT!vC`0$_Ne&?~9E)FLC$->>=V`J}8P_)N}1D=+<_r3Q$Kf%JhR5ES`Y>xW%Q~zJB zFl8%1{D+lBVH3~A^!}^{LbLY0=`0*Ex^mbQ^TcM8`cV-RH3wFPG<v&GxL-g(GKM51 zu4o>2BDw66k`mkXL%yz<nmbSi=zT8Ekso@>!-MW0c~iFUX@(@3e|`ebqh=OBeG*aV zb6W)~%+ST~rgtl0QKWD2x|Rq2&Vdj1LE~$3>qmE~xViE6@Whg%P)8SrYYZbwF@z~! zkXRIGHGDB2v2NEw^v=iV0r&<49XGKK48OuMBID#cdPx98n2imK2$c`^eIoFb*qqGY z6V`{l(|zjq9IpPCI&ab+x1%BJG=W5>RGnW9i?j4wa&HY5ElMn>2=Ap+p6X=Fe*MKB zhawWt-oYdNn<I+9dkNEZ#aMYT$hadV-}T1vXqk?2EA^FQkqg-R5NuqNQ~vsGUNm&S z8+M|==4DC_iwO}-)+!-|y7aea!v>EoAx9sdD*Y(*dP#b}mX}BN;6zjQ&LYW3vMY{c z9CxC)z~Q#;O=_7qspM0VR}Lg$G#&Y`@ls?)lP%-GnbGp`ODC<XK(94-MB?GVGG*>` zVT5Gz7hn`$F88E_Wz-CoVH6<$MndVM-}k6}K{U+|cc#IH!)z#5I;gpo=3V*pvt2Dt zi?Q1kBKdAr4YXk`Gl!e*LcJ&?<YYDd{`##!@{a}DCEwPVTY^bHX!F&4w>~<^LA#d2 zIivT_Frobh^<qcFmz<oJS@b|S(T8I{lu497>Iu+J2&2$oUOtf$g`_1kjC!pPSNC=` zujLG<n9hr&^0m*~{!#chrrZdD{7+_dLc%8))gF?0j8<sciItb~9?XVe^|#S*X@6SA z;r%;0dV}^_^%&Pf0`cbCT()p@|MJVP19U)t+)<qk9>Zcs#P&iVtlRk8FqMp1i|h`5 zl$%*vSWm(9iJ%yPE9acM)l@Evnnw&QR}_{|4zXQWy4n<iKEkZKhkz~>q)j0;vsiYx zDCU|7Pj#ntj?6T;P`L`&FEchaUhrhC+x$EeOW7n4i?X2=h!Ns-^#OeIE<cHRjeD57 zwTW4)`L{5A8>ecO8J{%CS)3n7YA=5VlojDx%<m3vZ%meb@mNnyWmc`xmTxugj(^6< zPLFRR2aevb0p+08<iKmE5sPbj#xw|0h6j`|*YlH~5PqQ>ANwf3-tm+D_3^NO{lz8r zHoJprb1sfh9D~G;-5pybS}@`RrD!7@`n7P|?R^uO`ke+j>lsdGmMnDlBhuF+Oo^=0 z?=;&DUJF3^@ii!f!9g~X@byEmwo=*AYWqqrCh^ngwigc>On3BO-#brFA#2)MfI6Q+ zi%hJ=0KToJ<|?KLBC@~Jkk2xV*Yzyo@D~mUx*)Kjc2evYK*sr%Wn~%8T;QcF%(R~S zG-L!ykdpr{LHyv}0SzFYsGsTfa9U}$d;I8?$HL9g0;If5%DTtNF7AE&yeDUnG?W=M zzMe8k|0zFM*}*yP){<O9!gmxNLacc>-|;mlD6Kg7WFPqnEJ<NIrcO>+m!sa%uQ;^s z+--XARaffwgh3>cQCX!r``K{rxZpwHd<%vsQd_It{d`yH{d=YLhj?DXRt9R+nqwSQ zA`BY9FaIk1$#1|!PqoNXzWL7|PT!3O-Hb>WrbO+RTAyUuJ9VM>;@g+|Mn9!3(dWbn z$&=pS4Wm>GhZ4>IJ#O_~tltYjyUgrJvKS95q86#QRl>+Ry$@G*@=?mStb~BuLdepv z_!#Y-Cy2?&w4P#yUgj3XSv<f`*U!s#x@E+bZlA)GpMe^Lr&{WOJ0$Y2_=JECFiA9< z?&Iu#|4>^;fGK{+lghNeeZEBglTLF4U1_Wz_OG@(ofI2}BqT82GqTn6dU3y%8*5wV z6>%iqB71#-z<I?9?AP#x<;4${xzGsyH3Un>fRPGDZ{wpqGe%qLxGuFi)$MOV&hPdp zOYp>W_}a{1%#-5De|gvF6bltqBhBsX?Tb8`iHfHSKiqe+&=M8Sddb4#12nPt2Y$DW z@ZUrBJ}596&E@$B7RAPmR3v|gye#Kv4<pD4c-#mq=rnMsCIVVNAxrNPG=AMJ@>nD? zFk0gf^kpJs@p#Y@O#Fsx0LWa`;<n&yXPHE^`hFF{O#=D??FO%$7tLMW8le%Xa3&(M z=bSISYMd;D3dpo%OEaG@roi&)6YaTh9KEqJ%WpgSqTjE*LVHXrfAbUi;V0)LvISLH zo9E`@K&Du!FldN{tD-$u&V9ag(kJb`n@r21BI*xAt)Hg^0fL3d{dJOulh)Hq>CXKI z!O7P2gKH}wix?Ib7nlBe<Sme$kKX>Rzv))>Ig`F9cGK6{PnizB!^5}_E8S=hEG$B9 zI=<0MrkwPB{heW?9sj|>I`9j60u;ppVFfz32Ko0AXa%bS_Sqc*?fFD+=Bo>GO@S`_ zpvmX>hv-qy!arCMxRB6u_j)5Io!_6>A&EYK4|L5Hgu%X$m@?ZZeS@DlILY|^EyXf6 zG}N6pYNz`b%f7+lz2z|X;1*hXy70_E12$eyRN&V}s@N5FN3)USsS87qL2YWd)3c3l z+nr(UGy8!%jP9<I)@mJ7EjGyy_>ig1Cn}l18nmHPWv8`zv8qsRGGHVq$Sh}PH{3<b z+VdAI9WCco16f|ijx!=~hU7<BOY1+~zo`?}PDuomEatk3ybt5+$IV^dA1DO}U}RL* zU|98^t}YCJ{F9Ii2uDRA5tS9}?G7~<JR^P}_4*iN<*jE;C}=<Mb^CqHGUw%^^#A*@ z*Y_E?Dy*ssU$oa%SPjLCo8x+|(kU@>=4#w!?!^kvEh#SkbH#x!--j5sJSJbS+i^)p ztv<lz`mcRFp6+^WGnWel3e&^k=-6ZmZfFB8>UD1HbRQ*LUb%B%Q=fX=e$7UG>ORf! zYS{KkkOG?Qbn{&a!X9Hm-B`gok%uP-JTFsJu?Q!~LC?v=pf@ryihgNM2YWX#LAe9n zE5pDVC}8EhsVA-?689OjSc4^nZoG$WQ9uGnGkW>Uh^10TT$^0w9}D>4a93qlfe3z% zr#vr%<OSLfrA{No$CJmOg*+nqkq48@k_o(#`>k--!}DZoZ3rH$ifW}kOS4CK_1Bbz z=vTW*Yqe$ln0XM-PaH5{{K<Bu@XrY~E2|&uBjr#vrL?$Dn^9SyL*>X1atJS3@Zg)I zYp`QC6FZF}HktrfI%!3sGY#jhtaFmsV(xb=+^*FM)0MGWO1WAk0d)9;C$VG8^3>}C ziQQeNKfh5>Jn0Y=%0Cizj&UwW{*&OUzL~q9K|+14uhMC8_sby5YMaHWN5ko0i6eVC z*wWgbLt~KYqJUx6Urb#L4*OHeN3^m)lR(a6@91e&N?;e-m2W*G-FUT@92k^^31!{N zP|AHQ(tlqdHFMQ4p`D+f;P?~v2tk%@=Pj?cfO@@@9n?kitI;nYb3PxBRG8#eEw#ZK z4Tf?|Lgdt$>C9Hi1()_@8cN4^=amn`wR#~Qg2eOvmNfj9kZ#>bSyPQ%e#c!<#WKH6 zfacQtI;mc9S~Z)JTmrBAONOG&Gglka@xfaZKG?q(5c-*1^&d$h{@V)>1x+~M<t_@R z7zxrkGhkI*I~$EIpRe*7n4Q}Y5|$`~!}rWvjt63aEKx$J#BhPy2PaDnx%-3@L{;*q z?;)>!{)|27>SMNNV28Y<D09eS;4>1EZ-J6aOj#CA!bP2Xd${hJiG^BN%!^LMx{Icc z%)_e<fse586P0pdJLL6KY!Za<h)%UZV!z36ACUp-z(U(e@qeSrRJ#eLJVOy=iAm=a zkAJS8{t(yD3!3!DW%hy9M|2Lmw}g=PUH`I(cq*=DvAv(2u6@6L>z-b>nOw9Zz=xO* ziP7*$9^%v7Q_?Q_7%{=RHlta<M5mPdTG{f8kG5b`52;~?p@G579g4{Z1Ea6Wg+xT; zOj~KBNK$MJ(`2sdzxug-vYr<5+i#UgDwE#KxIdh$E&l8#5o;7-3l4xq#SVT`ux$jw zX1!Seo<K%^^$+G;QCjz#+3RMpd4Dce2J1Tr{x)!ayZMkfrv_ITlGChaZ^$c-FJE+o zBYqYm_XNdWjc!eq;o#P-IA3^a)wmQBr7`J5@^U6wOQ)HK8Fj7vtc0Dm-&P*sISE_E zO0tAe2Zgv#w6)#2ae5^3$06i8J)hbk%q`H=Pvwv2X;q;%3y7xUh?t$sKtCks&EDo$ zgl&F*{`P~s+i^GkTb1kGt|T5D-{7yxWd4gZBP(k)Kv=IVPbzF#gQn1zrXae@q(8qO zwRHn+E)C-migM|Ul#<JmzjddcdLF)5Map5&8Q!<fx9>M20&u-N>Z`;bk_H3>{92B~ z$w*FR*2!v2%#YzP<Ymw5_){Z;{YdR8R7OxohBt=5Sc?u_pueNp^;zfUa2^l;6#Q~8 z+3UjX>s5rfMqH^t><=kYuk9BfV{OzokTfM@S^@69<-lh(iBmi``3MV{pp4{p{J*&R z3aF~G_V25xC@CckDkUx5AxM{Wi*$EMT)+U7?(XK&-6h@K0@5vAm-_a7W8VMzX02H> z<G?vL&ffcZe)Sx;#^{;jeETLkS`?ToTh||35^k+MPghz|Bz?PBRDfUaa@5gs-|Xir z=H~nD2tE{%_gZ#Ai3}dYI9ExSqu&Io(k(iPROI&|?J_sFBbhal<j+yY?GEllcjgJT zmf9W<4LO%VcX=r(y@bz)t$Yhoi;Czotm4OveBt;4eR8?=&TmI@na}_7L4<LsW{biL zg0Mo+a~4ejWojsn8L2%qGeZFE$~hVRI}sa$M3L5@e+AWnZ-t{SOcr47Lr-*HUXu#U zDYhW%g&CEA5ieQ4eu{#j-Li?SWYFutl-num^GZXIV3|R}8V`)tqzx|j=)x0fO3KRm zCMI3(0-QsS{loU<KmKK1)l?Whr_5~IW@`g)>P4Su>M#WI4f!lmN`axPECdORXL+9y zmMY|p1?oX{9&A;w+oA34Z6iLZFBrh-u1IoeN;5DpVC0kn&aHew^YD9;xTDVwCF7v~ zayoXP+2`825&L`*eX3eN24yEj+D2kp%Vh^MbUtv8PJr`Tx?5gSGV68oPQx&*Zar>} zEKy*mjF`C((zFd?$TwhjBwoWHK1+M%C}(I)J<RT0X~`txla4zg@&GE*S+*Tu9|l!- zh5TQ9dNo{7@en$C;ywL=6bR}Q&)ksitY?{rH=Xno`MNU8&P1Gf3a`1m;Dz(gU{gg2 z?VYnye{B)VYPL+koZSAXl599zb}CkYkBci7F64<`VRd+gtr-({shDZ`hJuX^^;J4H z-v+p(ahHn$17n}z@{ML(%ZIfjD8NlUuVX}BeA{+x7EX1qX6mYjAwY=;-*2dB`e-IL zA0MJ_47GOXnfn1^==(SSQ02DAQEkTm-^Nc1+J4?%4LTE`<e2!?4Z2ASr{uyy2D-@U zt#DCX6YG5SVJuMp{24VIZPYYaL7upbeihsArGqy%PK7G*p73mKzBcwU@C6Nwm?aL~ zty%-Rvld$-`IQ48*j<-p?dvh14(-}f6wNRD$zNM(?SKvnk_Wd&$yJc>#-v>?(gpWZ z8u)QAv1^`~4cx1mJU`z^Tk$X!)J^tBzoeSZ6|J>ud@?g{(0-y5*S6-AbHrl?g({?V zy+Lf_tcFvbP4@~+0Q1Ry$S#-2`q3sW9Xz?=`w>*CjswOqhAAb1yR-)LAp#RO@dU#m z`z+4K+}N@VLM+g^M{3#y#h^}KBTs*-JB6$|kL{?)$fiLKULaTm;JbQ8F68y=jJSr1 z&=nh-#bJVSZ>BoMq4KVsTxD6|y&kE7fkBYFd`RBr+EcK^a8Wiv*mtCZ4go*dUPc;f zDCI6+iM!)b1FSb!B!<gELvQ!K2xHoIk$N6DP$VYl0+KON@#ucw^}ks0PMrP&{wBzZ zwDnrSZZ8wp%!9uc3rLfS6gLv$RJ-rOX3EoSPjRl22hDp=bukTV6M?zrP%q)r+$_)B zC)}h2v_4;!F0N^{-G)4AfNVvHTmK0JL^5;<lm9g2a#YRZw<1{5O91n+k2j!BXlIG1 zD4Zs|7H(z@X|DwYNWpx0%Ij~QYkVbv=9A^L;fa|N7^6Gh^djm@o#|@mz9GSo1(Vg) zs??hg{#TB<6rX&Bz{4)_2S&y1V20ThOc)}c@|R$19ABHWsOyNrTTy(Gs$Z?2+rY#` zTFvG}RxX`xpnSk`3yC<!_u+u#JILYLuKHuDy7bRS289?mgoK2b7kW~Zxhj4vvgBsU z{s#-*lGWPmwjyGAVO>DeTl9<(I+}vjb_XDcI`IU@ci6~0Vnen7Py>XXVKig-y}07F zkfz$uu6DKAoXObuxczDlW&Ql0cefho0-yuPmn53Dl{~c)-Q%n67|Y<dB)+;l!eOy` z5N3HgN(E+aWhnU%CALI4yi|EoLFTmoJ3QbMrCdB~wrW7$ug74SpS6fEeT<-W1ck$K zGhnLv+SowT4~u0?;LyMIuC7-7Q3eVuQHNtLU*m%N1hgoBaCp(JjQfWs@KI&w<S3b& zgYXAN<s9qX7^7>@hpG@cah{%`8SuKfe7bG2H2oQL2lzY|7MOs9*WFNb5!EeXkBrhW zR%-mrQWx3GWh+Gzy+Bk)N4kqfHWO+k0nUGiz^j(piGOW#sMhPb>>L`4$>7M@BUCKM zm1Ekj7(P1Q6MpyvFrPE^P|SyFMKmp;fM2y$OhD5;cv2f~s3Vliw1#^^!m098O}W-i zznoFQn@OYeB>+j(wq#S1lSQ|e^M#zQ7ovL=O*+)g{neO^%bWLRd3fq3yxK$poP{~# zH1TCo;!2|?l4ulC6_1NC4L^#2Sryi_9=)V~6fnU})YGDWq3SZn?r0kuQ$Et9jVAjh zjc)y9!Ew(3s{Xv!l9ah+-hRRtm2^C8rs;ybFW%<3W0Yt&Ng=g4E#rzVGLu3A?KNu? zsL<DHnYz@h-p)$_V%=r`ida*#Jf1ZWm-bhFWC`nOdZeByx3%;3Soql$qAPICuaiOG z2hQ)j4?Y$StAj!_g_O!Lh|l#Pa=-C&bpi)v;Kv&4rOeW$@e7eCQ2J_kn~G=Ny`(}y zpWKLFay$IPqM7yx0-*WcM|#gA+v4;XJ_uL+$Q^JXR62<S<)JPJ4fo-3#3!s|{>~4` zy=b;tyCVNh{QIYJBh`X=<1rC}{Y=I7g{wX%n;~u9ZC2on>ORy*Ds#PfaXFYGjv)CW z#O}N=zww&kk8-KIg$u2rlg?F9<3PY@kWQevGI}BeWG}Dhfte(IOlk{hBdtM=aWJ#| z<{fmgIgomOIHjc{mU(YTV>D>!`u3WD?yI_2TRnCI%df`ol&pS@@AzWhF6n`f>ti!K zwov|waFI`WRnb=q7pM1Mmd>teWmd6BDePO-sOVUX*JLE$%gcxSentnhYK4knan7Pz zuS~=*912&{*vmD2QDUSI5`(iS;o22EVcV#>P<&&ozwu{cOE}~%)v9>n@aM{98F+U! zJkP)Rhftku4Ah~<@!PZ0Do0>xN+e4%{%a2)LR=fmT~1au?+u=icb~%Q5C<V){Ewf( zoei#|;2)v}D-s<Y9m`;?H{E!Pf$czul^ULX4RKQ`vdG+6*e0WwLFN5=n_Unk>R@HX zAH66W{|fRv+s6Gu@X0}@;dAoTAK$;fZ~S~D&G@ZJ&^VCOT3l<9jdTcCUt4trEjsSa zPkx&pP=BV&BMQ8OMTymg2D6S%s+T~2vDgUBjWnCyL5!OMDviencNuTqu$0-)l-d(} z=E{B8_B6?PrrMlL+D<D!{kgV=VpMxbul9$za+e}bX*$~G5>v83{!$i2)<?7!G>Xz) zMOjh-Ug{ScD6i*f1I%9L=**T=COjR#64NbyOQHd|MsAsG_~ZBWsiH+hltg2`VRmTb zJDI0*aQ7#|QSri>xV<3SN-3N?GNL(;eKs+*#j&Bf2uvVlDi?Cwu|miq<q}`ysn=kT zkXV%SGE=@i<<Q2P%l4f(@dSzH`c6trPUO~I!f+AoE85_Up4SFoYL`@XMfr>~1PV+y zU0sKX0>SUScn35(Y(X`+2t8{V>HlzMQ@l=~KAexrgNN<;u&yp+Vgx|Nkpn8AP2{fi zrlD1r{HbgPP>Rua56<n40kj9Q7>@oz*%u|c!N4npAAt(3t3PtxqcQvTXsz7&ftEt= z+zJQB(4sIb=|)b!rS-`;b>16zdiC4x5(HyD$TCr=uaLwi=o!Urvg_FVlKIREQPF&| zwM90i(Ii#HvR!KG26RU>{*BnjkTx)+^(PP@ViCtLHFnN4SO!X?lGYYh`1z%8f4&+F z$$X}>6XzxeaHU>Jq#xzSdBo_kQY*+(+WCr2L<Q}f#PuZFz3t#!qeI!Q-uF1X5b{R| zN^7~NeGN&Gqv+Mu)_3iLnVcOqxRi~HyN8PDzzDLaYvR~yIo%Icu;cm;9lNNow3#Vb zsOj!pHbw7i!ql)If{UVm07W^NP~SE>`e1Uupp3U~2Zf&Ag*2J4^Cov9t~<;+#lYR^ zAV|cbhe=nAK{Xn|Vh0?Ml-nxL65XAc(oUeqm9tzWu5_Nu#;s==(@#$;chqzAzmmm! zeWi_pjU)7Dd6kATuyat`b=3RMQ>$6ro_g+IVQ;jngXT8v()~AS?w@ixDUwfE%fu@+ zi-C_;qr#n5R?Zkd%IWXg7h76d#DfeO&F}{>M>g*|xffgIY1L%U=yXrd4+6aVPjR@+ zAJKGqT|0X9XnBElPLu~O-sB}(RC%a`eI<hbmd{7%tBf~LBz)+)0m7v`=VsVwB3kgn z$5q<XtyE%x32gvo{t0nm*<)Sb@<<6^tOj}<=fB=(*T$yf!-LhoWMz%>r5d7uT8s2C ziaE=raZXQ}avR|=Xc0m4_JJoMkzJ2qlnl_@tvkXwm`+!^X!(N{(s+q|U?@17)UG|y z^!1IZ^WuTy?+Ko&6v(+IoM;vtcQYGTb9&biY03?y=2lSR%>T;i99QSl-qn?mo%K|X z+Vkv7Y%ZVuDLSYWNuU7!r<w<wI<2g39N-r!HktmcZNHSKMg=0}N^>?@x8cpiemP`H z^oruQnQ@37i;9Pb=V^-*p6O6Z?(0SZBCy>dgp7r{Esr5~K+eH#y(2DG8!h4D!fE_I z@~`N6`fzU!C=NRwhymE8$pdqFV+!K)rv4e5Z>EO_@7%t+-yOs!K~}~0^70Y)RCp@U z2R&2`U`bG@9+Zh{EnCf9kC8DwT>$B7og;0xn!$NKcPS4(ER1Mnx^ui9Z+Rn$Ln{aB z1Ux#8U*J?3&@NSR5PJ4=rr`jB=<^_U_AXx=Jcyl~Y?&#v<Igdw&AuDR$_6P`_z7q} zqF~0OiLDP!-*yfdQSs^%o#&0jhlW%+iv<y}5ZupKC-OFb`iqA9CQT^0YXoctYXsAX z&7d=>(NvxQk5Nsf=!XNj;K*p@8e?OKf@DX&@;h!fI0?t!Vfsq9RGmH}=v+mA45R2` zQwHu}-{;#6(pe@|X)aXX_=Aqcp_uHfM|=&i4)bHwc1>};11{!MtK#lz*huRnA)-&K z^8~^kX;LV<F<KX(NkD^#M#zcbW5(*$Jp?6SbI%)dtV68zS6iR2X2DvAW29x#+blMU ziWNCJJ9q8HD_7N1R}`s!SSc;qajqrOE>kT1^p4@<n!i1cr<4!_(7FM|9*~GLK*FJ5 zAQH%k+V7}`M9DZ6MVbQskvCNuN)hNt^sm)kUFhJ!%Vsuc+V#*E6b!(91j4}yF~|j^ zLd5vp#IM{dZKsKn8-FirwWQ2VPvgoNr=`#HcLou1sAM0|Zve(^2;U}O8XUh}L8;<m zN=v0Sk9RXPa=w|D2N(*P@R%d37MJ8cwLhm|5q-e#iTeeBMc902W9wgLYCHm!h^@T7 zS_<$BT}hMzS<^@sBOaslJ*P#-C$(7wW@3N(*az51?v7%w6(Ue6C<cw9=1gy&tt5JX z$`Kay`1`OKD)Z_ZJVO)+S#6G5^iJTZQ}1`v2RQ9yh4=Di#QH1(q9-cx-eG?h(-~(4 zLH3M;!}~y*X3r~WLY4Vyn|H|<dbeIYJg1KMEUGERO70Od)8PrIFz!*9+(cDskm|kP zr`kcxC8`p8n6|%_4CW_Uxxf$k>a%0Y{q*gt@qN1JmwJBy`;SJ<@-7`A){!u*dGcfz zQh)&?=yz~LR~EG$)xmxz2!K-yq|L7)JuVWiSLQW9g%m`>_87qPbV($jTzOsbX2aEo z_8<^Xbug|cXe7E<($UxqimVO@V?%(<#c_1&rR(<tMhv{qnCrym?ePXayd!6zyqUO^ z#Y2-Li;E*rHXK4tUp7k2AD&aGj*-%1YO)j49b>DMS<hko`IB6V5)XpVNdl&{=hm>V zL?JcONGWlhW5xalYusq8N^n&4QcH!0KPNZ>@#~%bzPY#nz6t%&6^Lv+CowJUQvOoh zdB|(AsNEi)9z}(q%8(nqF=*DZh?j-T$8#R4bq2pNQ{JhY4;QszhF8lxb(EYT^18GF zv}XV>_<TX`x8QNFxV5$m&Jc{M8Rat~l>e-x=tx;7p_}!rVx|Gy#W5_5y03&yJyE%H z*T!=qtS4KytfN&aw+%pZXpN>epH3akXn3*c{TwS@XL_T2=<dsgYyR#%$LkdS_72*L zo@QXmP-D_gQ~GYj8D}k)C}yD(TBMQ=fM*h(T4d1b_vk*y!y)zuHs)WZBX1hru0QVY z76b}9shTHi&HMTys_8Fux4e!wt%VY9M^>N(J51($u=_AJ{isCjd`t(>doxGlh#JMn zbhE?<3h1-}ThCj%)*1Wpo|)iow$7N~f@ofeSp7%XO3sQx6*`3Z!tX&TO}Ya{Nq3e% zHbN+GG0Dw2{aD|l$zhsiVBSA<9<3BKn~MpM=6N8)M=qnBCj5Zz2T<SnC9<qx)=NY# z$}uv^;r4Rj3o|)*@87rC<%4cntLifo_oGFq`%4avXsx5kqJrEE88f+^P!-=6mdxiw z4)qkqMr%iFnf17IDq+&<wI*ju8k+gdBHwM9`0`ZopbA~<crbobC_WAL1G$%yUE{gT zf3~)K`qhggS%H8*;^$O+>=H9GtwxyF-<cV1-%;{TP)B~a4j8+$KynO!ujBbpMhXjH ziImw%)NyP<(r{U^;yiic9ak1gI#rnPK9E}}DaOTZYw0xxsqkuizS_~-`Mnf<AmsJt zh7lMGfUzZjcdAL72Jj)m91XBHwu&JHLoR!B{zdcWTc;nL-^H_H&z4Bjm0*$!(K2Sz z>FjU-Qe<muG=%%i&sVSQ&zIZ7jX^%81JJShcJ%^Z#A~q9_U7m3({&SL@>D_Qr%I*B zwo>*dfMo#CjmYXdkDPwrb=(ZMk+CtYoIL?4j!bp`TeNGpN!P6e?{o6>X1-M05T<0_ z443_cJS*L20Fa=HRFaaCqWr4&Q6F5!&CxW?QQa1j@oWT8%?1EJW!Q}SaJ%Opn!3j8 z$s+aVZB;rQuQjmkmRepcLEeWqm=4AT0kq?f$d8Wg8W~f}_>(N>v36wF{wV$S3{Re_ zK1aE&P8p(9V$ZwRRnOm)NWn9--j_@IWrmfzzoBmNHWkKYu^1}MkK=V?0EUqcV0$<M zlyqO7*U6MF5PH0jz&xOGVcp>VD?nk*ORT79+rxRXaEtFm&dDC0suQUW9f~b^h&>qB z3-s(|oOba^Y!jQVBMnv2hF9x6b!#Kbt47-HuisKoAbs--N)O?%+;~#sSB!9Q0Z<Od zKh__U;;qAg(ZW(`j2&&{nfb8IpPjD->b4IdA|mbU;&h<uc*UCgAzg$($mNl}q^z7A z)yYH1Na;Ih@PY4O*Kj3Llm7eXCabp|y{@0CC7?}u(B0XV{+X%g-Jbw9+CI5k({r7? zzZu%@KeNsr>wJ#M-Xf#R_1+1OVHNQ6ac|9^%p&xTfbtk3s*+cYvu1o3$b$tK8Rs{O z8QcI<{jM(xJp|)9ffMOrC`HQh+*xAQ{SO7n_v8n!xZU<_H8jm*Vszpe)%5CNr#cF< zvPolBU#&FB0c5xHQ1xr^TVtUU-L>_Kx;hS@L~SIXnr{caDZ=akl$;8^i@FW>U7-g; zfB3Awir;^eJ6H{9taiJT&&tU$__Y>4@%yCf>;XvY6yL5JsK4AA#fiQnuSjyz-GICA ztf<srtP`IB2Y^mea%Fu^`X@8@+U8pd_IC^LG&yYp@yv~rLE{(7{p}H0ZCo6xd6hTh zUd#Yv^WwSOc=%Rn{z7eaT|@jWeEsh=vS^O_aIwap77|dE9X>nVo<x6@9wF5Wv>$l_ zy=K3jnlpVUC)&glEsOH2D}T$&tEOMq*qY^Iv_5lj5I`fq%2tslDS!1i$1uJu9LtK1 zUIDfEsq^Aw#U?Y5WV)eG51Shpd<8f*<-TQ4r;MGGlQ1Y&vScMfT^xqjkFVEh7#JCU zd>aFethBl)ORyk+O8(fFYU;P@_=2A=HM)K(C%7I|YA@(&(ZS)H!%{?;p0%)Xze`;w zDWFbU!Fm70_aQZPsak~67Nen<P^c-Lve4chEbQF#?w44l)o9e2`zG^u#mx<xAVS)r z?94@}lcek+7UVq8naz~iP|>MHrQYp(1gz9s_q;{+4J8xubzMp+T&K`HWqfISMih!+ z4J>N275HyIe-irctM{tK!@V+=o{No@HUCFirUZIt>jS8<QYKO>rT_u?S#V`zXrRJ} zxg|E5H}Qc_YWMiieu9{R@ckEqi9py+h=Tq`uVn*TZw@J~d=u(>Vrp<FGJ3fOsvdUh zu^(qieN)jtSatx|g#a(BZUXVc3tJqE#?{L5WeEp>jvaLxJ_O|F@lodUIoShlV_nx^ z)O3LngzXW~GuZDqJ)ga>vn`k~yMdo+?*V@U#143<WaHVzi*R@A*MP<6^6G@fvN8qq z6BCcf^g4aDuCDlGl(QtUfcx>i0F4A1(N^&H4$PSfS0SkdB5<q$>QQlDy`I-Z?@rD4 zsX}k>Ql9God)z(P3yjTP3)NAUz>`2)PvlR94a%+HL{}iLm(|aTxldRuDkAA;9`3~h zlc3U0_c)6Zm0Q^GV;{EWpcmlg+#5UMa#7Ys^};JnYpfO@0T~X`a~^CkQVeM@kt3%M zyqpeToqR9&6nH0+m;?F<YF*e=r}CMsOP2e(^y;HJIL}ws>8EyoxLqkJ4aZe;K%4c7 z&#c65<PEh&Nxp&H$LB!dC|)A??ZFRLvq#0V9qt&2eE{1lx4xKpBD`H8g@5zro`%}1 zW2;PAl3WP{HCrv#2C$jBm}o0!->W`~y{)ANMG!*N4EjPuHwD-k`(u^oRWA>^iW&g@ z8@NV-VO<8FP>pvC1+Yja8AU|^zkva6?x)SM>U>lKRY~&uzq;(RCR3uKpE(^*u+8SO zuo5`UzuO!7tpXviMvFc@nFRl1ND_Lz4{c<3gk+u0HdH5rS$EHsnt}pn+>|kG!=JMV zQ`p)+fi8JCiVEC?0vJ32d#b7-2>#_YMb_|i=NTwJ1J?Auya`A+QnBERrkB~7%vF$* z?%%`*^}uwE_oK9Vc$&4gK_4?9s-&d!qL^azdFx`Cijs?u{cj|g9P}RzBJK8tlt$f4 ze8md-WWWI56gtsF@wrC<$U8;B<ti{h-QQ8rCD<+rE=-<dn4)BZYOm+z2Qt^c0v|4k z9eofzT{c!GkW1TL_B<mIba;qRz8kB4VdVF86OVddjhDf!x1o?--W+K38s0U?C*AKY zBc*uRe0;2Xdz0Vt{J#G45Jr$xUB%`Q1t(`p7DB;1nq@Cqw`qTMn>8vn_o%pdd*^k$ z21*MktrB7mWz>7CGhFi-LxQBR)8C?ReihY_M)JOOlq|Sc&v<X&_X%MnojL|!)O#D& z<emqAcPd|b;p-kBt(u-5k$nZ|!${_Za5i*0vs<Cp#duemwZ#=gNjxU?+9uk4?+J{I zeeWXNiaEFFbx|CDg)qYMPCI<q!3;jvxh4-9Uq3k?vK!b}n7OwzI-7AnIJq^ITaAH? z<s!vfqa-#KS_RlZ>?3+Wj^2wmy#v_FRg<Vcr^E0y*A7S3Qi-iXU8E@FaI4Isp#21A z>^Oz+NRJE<ceTKOHEX&vt8-53Cjz=-4lGu{MF#522os{65Mf@pm`y5`=NXE%YE2!f z;P_F@ha_Kz#piPeC^$JWOe*w<;vcsHd+BWRb0;AU=l^N}u>FX+Y$Kt7)^;H62QZon z?9ESi@9Pi;w_DZDDBJoCAc*UDOZ^?le!l<_)Kp72#S`V}TCdgWQ{$7ULz!s}?^rU& znHd$e?Rv0fAY}-iujURrcvpaJ3}|`Y+;05U{dxOsTNaG#mh+U+pC&8;+Bt+dK)Pi# z`)_3G2X!w8v5#jwT;4n<0h(0~EaIUN?@x5<`9J7;^kTYmO&dP9UYqgG4+aW$jdnZf z<s;erGGqw98=XC+15k^P^x{K6MBl)z+ztdl>Vo^T#(hyaFK`$&tF^jJz|3_X25p9) zc4W9D0SLl=?o3;yBNrGD)9jXiP1NbkURv@@yqpID-Pf;E%J`$r#!_kNcPH}2s?V;x z>ZU62ju8ET8=8soY(jw6XCQzrXdX09zWw%nDZ3a6UJ>m;<<IdBl(e<anpG@z2I;bL z)R2+I5w63`E}7$6U~dWE#v~jn0#ZI$L}FsW+v7B#<AS?gyr)rcb=b>^D(=nR7fY?D zs~~UoT<6`@QLwO}13dAEOFl&33=(q*r|NtL1{ij{fHfm*ztO#VVnW3?{D&pqM8{XR zh^^n?wSQ!Jak!q{sQA6vscb14SR5D*_2he}5FV__NzHXj6>v^WTAP##yM6bQe#nO? zg7IjtUrtZ+K{?|Fx<g2cw5a2~39%MrVy^^Vm=b1?72DoF6?Q%Q5?HMQGyp4+$Pi5O zG6|JCAfZ1?rqjqTDY$uc|LQ!SgM~9A*^}c(NkL4etqs%5<7XUSXSga`OH|Fx3G1bZ zkCFG^C}lkb%sk~aP&q4!dx?z-&4hit{TvqlH@Fv&f||%S=vm(>5`9{nu8206bwYe5 ziJzCcBL(2n7M2#i&LU079`9x=E06dtEd*T6zrSPxHymlhc|MffPuNntGNfHXVdV<7 zlYSZpM<_!%w%Kg58fSx1gN{uq>%z73G6Ys!yZKO;Kexyl4~TAGZNiy9N_m~w+0q#L z;J2?|AiY=o(wUb4|AFp2m%v+TF&SjF1Z;y6p~-3*oIrTKE=kQCL4pss@hB4A8ZXr7 z7vWOCg)kvtjxtVb(_IX`%y=ocJ)A1UGH;6&o;ap>_1{9o7sUysxLpFwd$<NgG;s5O z->b2mmd*(Zbkyy8fMAMyVk$n<0ZBN}xJTTA(yFzyu2}1WNnG7ph496T_1<$(F0B)t zIRZ_h<?vGBG%ct>XPJ7{N%R4D5-*LUbp&(q5kUDOhyV?^yC1f$P(5%U<pJTFWk5>o z2_I-?<zYS}0s;dkeeP`JLM;Wf^?w^rME|;hWGRYyAmjKo*$R?yRE!3fo?%{88+n|> zBo~G!asj!voUo(>d<Ay!7B?t3IG@wtqlmrJsIn<qiPu1qVEpeER+_4*ATKrW^n*d- zM<<&K@eZJSFS8O$8@n$;bsMRVe$NGbR_Mr>QeFPCG@s1loIQd2rBE@sc&Rq{oNQrq zv;ZFnMva1hWLh%4&DfnT)Gry!dIc<N0td5>0W|H$U!mUQQQ9StKdape!1ITWsAFW5 z+VVxbZib%yB!6pvEL+QAjX5megeQN9(1S_i^-{h!$)Q}Q8@HDSh++A<W!jJ0+D8mp z*uv)v^EK(GIK|GXH$l9|k@UwI!&oTerAD(B<p;})FV1w6MwS}z3Hboc$2!W}NszHv zw9E2?(_yb=tP8aL-(2tYqjb%Hbbu9WLk8Eh5i{n8mtM1Hr<)&J{i}8$K&TP$=v!kk z(gvSM+|hVg)TuAsDu62i7!Y;~Xk5d-N*<N?bkQe0I*Ihe-uV%p7T8YJsX|K1>lYXC z@tSe_H9z*|fn$yO^#ATYP_(H`Z5kL^`SvrNsaYY(o?&N!602;TUVUdNJQNmS>?-$( z25`W6(QdR!v2rYs8%}(Uw&pvhbIOpHyzv<|%*BpRxsh8L=mAC<l#>?>Vu4dBTVqA! z1%|Iqpg;?y)M9V$F`8RE2ecpMP+$v*XcH&vR!C9hrCuGY?&SbyWv%DB->;<_n|V3L zW1FdgV7PATunYJ}L|4eD<$<tup>zw3g}~!Av6qq?Be<-#MDVYVRa=SJJD>mAAya>B zlg0`gJV`8OH_YP)Q#GZlFZLEn>;(T@oy5*Gsbkyuxup~rcLzNoNe#<mw-W)9cZ)_# zQyEjS!QS4sz}Rs23L1OgS3ApY%Lr%U^L8<9R!&YoS8^$nDe&2XmhVcC3!Ia2Z0fAd zK%2b0Bh6eoRN{PwxtEn42w(r&;%OD%TqC`*)tlx8Mm=W;|AIJt5oxgzIh4zr&Av-> ztapjwhO^@J+UPcY00Nn+5`ZeaFY1~-Zb{~LIK|bxq6Ua3C<^2FojG@%!T$6Ws~tJ~ z7Gdojk0E8nkS7;{c0IgbH)>Js&mqbtX40vBYY%(mgOfW%rxR?Zt*V50AScYd))v+` zHdYp{&4S4Id^wJPzFO7D<vc^DQAlR2SiyZ>gmIe8g9)~E;2eFF+VWIc+5MsL(m`Ky z0^`|z@yDiKr35~wvm{+UnWR)QHnj~Gvyz!-sr?7YkjVmdih1?o#SvbEYF=wOQVYI` z?`($IyC8g1@{tiWAVRZ~a;)jJGt0D*itbxpi-$(NH^TvTc;Iv2n{6NmZO%Ku10o_V zfNq?{aO$D_o!;~iX}+qy;5YGJG!(>6<T$+)WuFev1sIyT^W2A)z~Z+oEbl;yO7C4Y zsYjXX(u2OZSYT>sxF9p=$dg(l009Faw&GPVkdMOO7P|sU<Dps!f_C7E2@n6$%0Zkz zSpvdw{maTsERu@n@>uEA(n!-y2DF65eBj`~iDAO*C|=mZK$cwvuMByONSa(QptUp{ z$0(%#8=>yXULEQa7CTlJmNvAdpGNnfOCoq{M=78BtgAr%9`P~jG&_*uP!D$qU5A$H zNWK5K%R$O331>Iao30AX{WX9MWDQd6ykA~w7VGoS)1x|WFsaejL%p&9<wA8}dd>LD zlt+G{ZIfAvkgwi#_q&pkJfY4RsgI;Q$Ztp0uKpWQ;Jt+ew1@203_sze(A=Be3;^)7 zZ7}kkxmnTyH>qLDl2ddaqFc-M2H8evU2=z=zz+BM<ovee&FrhKdD}P9LyB1SVaOo& zf`hPw{ZF~r!NKp|Zxb@0FkhvSkF|t&oSX}=ctPPw-?eN0DxGPj8kv|VK2aVH2_TKn zHeXUJ|Fa3IXI6P$Hz^QNlLLppQk9%{_PUYmyz%YNYYx{WSA8YqwFz=)RJ^Nn+C&OL znggt8W>yMqXzV<s^pKw04rGQ5o$YI*Yz*m%knYl+h15+!YhN?Nk(}3P)YrsPE3CW8 z%EJP|Rs-fALm*%-eFq>3B<oOL={wMHqA4Csoe{hz<}t~$menpVFMm!-8VIl(gTc8$ zgy7Q{|9o#IWv8X{Eq+vrfa?Qh!tmA(&%31WSeev{=4I%F2t~yHEP@aU2q%0Au**dx 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%0DJe6e~ri(hHiORo+8e$t9mMhHpbGKH| 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 literal 349976 zcmeFZcT`hr*FB0|5iCa$1i=O>AYh>g2q=gc5Tu1(RHTNY^bQuVa1aem=}1oqNDYLh zqSB;D2~s1{6FP(v1b%BPp7Z|R@9%HiJMOq=43C_BLUwu9v({X5&b6Pat0}QEb22kA zF|neqUD0G>VrDQg?HJj<6^`V58i4;e!i2hVS=&8ktjEJyo4&F(-5y&Lw?kiV<7Sp4 z(VO?EUwXkUp!X>IP}t-Ryx#Z^O-$Q7zPUa{z#v7htJ9#Qc>gETktaVM_}kWUJ{i0A z?XTPN;@B70Es87Teso)4Ys5RYddoJ9O1>_RFJ5q({PL|5)4Q;8wzjtR`Ubd$|NLh= zf8l)Ge;z=7_U}A3x8=VM%I^s%|F1)rw!dj&|F2`)FYjk;{I6q2pU9j3*P$buHAZ&+ z*Re-On0@~1^8EK)Nfi07kL`KzzkhK71)tSaTk==MS(3<3>*x3H+&Gv~K5W2MEWCb1 z)EF~N5;7RUM5P)DM=GnR47!#KIu>t#uznW_PgyF}-Q9~meE2YM_riW2o?e?R6$7O8 z-){0Igwr_9&CTo8Y<&_P?%m6QZ-|!RU;p3l{3H+U`cze=VpFWP=iguQG!SUFb4|<^ zVQHwZ53d`<^16&PUEcLr;p^A0xn1M+9Wv{`@7?cyktaMd5}%xWg^!O9n>;mj*JZR> zQFAuPr^e;a6`B|5WOZfAQ=+&JkGYnRTxhAUUcI{MwqyNE(uc-6@}yj-VHbHqe*E~+ zny9c1_5SgPe=mn*aIU>T%<@>^t?EHX{W_A%WN+*lj`iO*P``ftZ}`p=C;@(c4Y<?U z2#@3K>w)F3gFfHxQqpsIm~@$)5tYi{B1)M5Fg-o}?D_Luu5RmJ;V<>^<3~O2!w|Ze z-h~;}|6I78cB4yUoD7$97MF8k_AQPX&oal79&B<^QPEAeKe21&FY*vh0srr^i{Fud z&Rp1Echgu{x2f1(@65I=6OA#)VqTPnhQ|9bWX~f1G;M$R@+I~T+bF}a^YhlqfA6=@ zyEscE)XpYLP%J6Qp??0oxM5StpLiENayk>|@UWd0t}UHp$Kq)G`^%WDq|1%k`=_rl z3%A?pJmdPZ;ZKy;x5U^+82#BoohENPY}EtG%Ol>GH|$;iU4OV(i|E|af1@rx{-&dG z#zAf$)fU^C_v;^Hs<-60s@`+>-v{KgIhrPpZ;IsWUH?eJ_?GBKEN%T_FD-8uk7va- zwYSsnU;49PohD}v3jGt_aH8{_3DW;#J6p;8?{D!Bon9LW@B61mApV{O1z{#L@}JDi zI0_jRsY4ub%6R4v)ko`Mu4`z#{L$ZU&T&=x%b5#mX<EXOD!U#hm8CUj$uE@|mU%*W z8}Ucir<$%%b)SWVI85^Ye)iulDrR}vA8B71Iwd58zH=w}LuF-`m%yDim+!y#=T!Zk za{=Yq<qVvyc=YYtw?&<Xu6Nk7N^l8_h_vUL*WJnMKz2j@tFsCzDJh=c?{6D$EorOp z^Xu`NEF0Fo#`&acT*ue9yxX4m?Af!Qg|AaH0(P=fzvY-c`}^<K&>ONDBO@cOQP%zA z9eGNPvdfvg)(tU|QD@DrN;jsD?m8@+2?tN#tUk!iO~^7X5#Zxf>?v{Ey?D@;w$LD| zYJTUA6^%@g^8Hy9qn5^7bB4u*+KO6X&|9ADJ>Ht6w3{Xt5D*|BC>VN+!?D<iATIGc z3Sy$GU1(RcxTI!gXA8`#c9~mP;Bs>{vHK4kNNsJ^X62UB=I7^E?X}d=i69dUPqv7* z5gkl}d1Oc$+0w3KugKY^B9&)E?|#2z>{!F6D(h;fS7`gX*Kf_|U|?eW%9tg!i|A0& zkXD}ADXL1)%aI=(94s(lhi|X0zQ%Xrgn*=^env*dQH`QQPg+J>;S>d!cH!8I9-67v z%2-&0@R*p)`<u4eEKc>o!%Cuap7Z{7<>d$EQ=8o224~zao?}rk`~0^?np!NUcRj>G zf$O*dN>fu4n|dQY>&K7V#Xa_@<_xX00lKF-vCGh9f*^D{bAnhi?kaflq!LzJUq2%^ zH`nRdo`%}m+*MiMpYGBPyzYjDwqF@^8rLEAy?YZ49m>!Tx9y(yDkt<xw}{f;Z#!(Y zG&2Y%-%z!G|NfEh?;jczJEoAFN8dc=@k}Q#3>mH6T2DJdAx1>|0n&JOdiu4s#VR@H z@9*yWcezb;XPDPTWT-?6Gv4p^P1q@1l<;*~_|&N;$dJ5f^G}f`p4LgSd36y&Exl!4 zd}woGq8?IOo^wlEti;C0Qzin++uFY1R8&+7Y}#;Avy)L*gE>>U?29f#vLc)<JAqG6 zZ^H7a%q<Paw@aRokkCDN@F1hnZ#8Mhz7r$TlqEI7**lBBo@Pu1r+s$Q)vYWXM=}IN zJM*oz9`>uYv<9+rWmf4L-3zc4H!SNLU8=SxF1yrh5117Z5NPIh>rULV^FZstO!RJo z!mWn)Po6xnYAvd*RbJ`a?bn1u<A26E1R=pGLvPjcTplN`^aj0sdxr1iNx`E>6Lnrm z-hAip#83*Gn{)2*q!Adya%&yETEF+>g~^w+t&fd}bi2-c)B?q?0zD9o#lFF3mmA2f zPKUU(8@rAAtu6QwezbLW8_CRnGeb_mRkoI&FG};&*493C{(Rp1_OQrE8Y~SK_v{=* zM`vq`&0bdX^uSw-Y{7vHFYW^e$jQgrg$xTv5+C!}IN!R95r7+8TcNDA3Cy@$IHats ztO<La;8Zg5CaBZ#nb32V!^rdUPu=<2+2Y5?r)1-?XbA`Mm)GZMLgJ@Sol<voElkF# zJAZt#7n=;*lp5zX@wF!Oq?q^OloRP@&RIwvJnr8&jQ5rq`Y`4+<mKhPZlGXUAdu+7 z`^4<KFDPEQlK$q6JOs3LWk<ntE{9T${?EaoydD>M*bW?^&Nj-m*M<uc-rnuVHRqJ| zF2aU}@)gv3Ef6bKR84)CQt03M?v6wl+G`jXL{R{0$m2t6GxhTfym{=bXNT&sAJ3Wp zT5={ke<O(t10(_lzQ}WJWq}X1W5*8Ccwtv-iJL>kS!-+SsB`AeATQ97uU2|~=qoH~ zSZpjodZH-l{Ra)mq8dq8^^JYnvrQ>C+q+;H@lGzo4Y7pGB7)cng|fj2!+i6)1D`&9 z(x<dIT{bd`iF5z4qvFRvbF(J5q~n#zvV}PG3uATlgxzvK)pbog%)M06CfT|nGV`w> zQxS$e>C}{HhjM-65?4Bx*N=}od}eA+*4ET~{lsqCP1ds0SdU&&<Ldp4)RYwdbLTW6 z=Wp4v1%W7@b0ZqVi;y+1BdNr5VS=!@=#J@ncYl-E-S6*o;+@h*Itws_rZgG59ugW0 zaLmM#!-ga9Y6wqHM2ii&udk0xaV;^9m2zo@1s1#a<BE{p+e_i$;pbGf4*Sf#v@h!0 zim}C%yTST(7TQJA-A9@dkq5YO^&0lot8@py<u1lNvBG$G)tf?8AEJ8}I8bC!tCQ<! z%3xcu{ZzG!p^~R32|eI7ni5I%qAbUmE(}CTxsIhTPga=XbqLK}4iyAQ^)v#px4FC6 ziR&VHFw)eXjWN+(tR>NXS0T1I**c1>hl)CLOTKK@Mku&moqN~g)a$RCby{rB-X|?f z9omKDafQdb+9+$QZgw5Hikj$YTQ38Wa|YBHGnu&amd`D|yxM!$77&z6i>gFhiQIac zZ7@BmHNwTilcgeD{L!G-4iYYDf<)W+oN(|7dUy2omeyx%g4!k~S>-;<RIG|{2Au)t z8Ev^C*Op^e1(}t<^349jhqIAd!X<uv(^i(Z8w;t+G)U#CYOw~E)x{pO7Tj{aMtk?} zjgs+lefOZYCG7^L>N$63iCZ@8zX8W$SedMbSZNHTCDz{Q!_|-<!$L!okk!nPMs-&B zRk)6Kw%ydb%@Jr(ABDy&5mFlpii-4*_$rvwyLBtE*S((=Q(;du%(JN1bau{%3Ov{M z_;9VLYB0C7j*Qnl%LNHy7eNd|wrWXL6%Y|24n;>r;qX}`T*F~j@8w9`hqIMu@^4jc zMM4GQ3nBo*gY(>-Cs1N079Ps0I9@nJ8cmI!`><2w8nz)$hDI#QTF8=W5iPjaf0bZJ zR6{T~u3Y5dR@P>~Fl=00TvK8q6+d(7MY`E0!BlyT`1JHs;Smv3zye>{O}!JJJ!3{` z+S+CcSNwE@%Pj1@Ny^XH9vvO+Bs#=9IyntGOA#h}Ar`V=8*Yh-pX8)Z^cW^x4c4@_ z&d|x!OI%rA5EK{JQB+inlJhISZDvL%8#>gCIxAz#7k}&&GA-|>zSz5OpVqJ#(uguK zUAkNCQsc78I@_q7MyDQLTYSuGJvZ`|1pAm5&DLjOZq6?xR8Ji<gdGca1gTOPGE>Xn z2hZ<^3Ynr3NlgloZH5c#y?Jzg3%gMQtPmSJd)=tB4W-<NQ_9)uT@EAz1fwM5?B5+% zdd_meer<Jy@%`a$XV~3%tAa!tne!kO>U~&ToV`!Oo1~;oJS9*zCo9&<&z(Dm6mX6} z$jGgDT@fUnkdnMS0rh>nr$krUZ9-d3?K#pKn3;M{e<J;OCK%QBwaZP|<@JSoZ_p!# zkvH>fDPloSpMHf64c{cYx@d+J7-*N4mX=6AXX?ZN*0Hg%SwozYF_sN6`j#&p%wG0w zLY~jvRp!_7rWw=;H`61fKFhAgUgHG?^2#XWh5(cDp<QlpLqrr1V3}a!VypT!0PvX} zF@o)ZU_B^axPrz94>khGvKj9zfaq?9CniwRGeN9?#aE5HD0#E`PE;yj)Qr;7i-4e} z`>XI;X=-HG$hwr1@!q)&(jRZcUCfA;cB3|{h_o$KtgT#Szr!GX92y+thxMQ^$iz%L zL!x~fly1&$rTV3<=i3pS42g>;q{_h_ubVyZH6F&VwI6U~X69*(Aza0~OYX=rR32X4 zbLN#GAQ0GXVisRG>f_}qbf&a?*0`mdo1o~dL{!Y^BN#f{gb-~{LYY-PCrqB(Qr~x1 z&#wyFGQakP-lZ@I;pwWwy1u@?1iRwmVgsUmZ28*CBn>W@-W3rZZtkPRQrYBIvD{<9 zw!|5jh{o%T_J_#r`o{LX`sH!Y6?!|p&U97NnB+X&Wf7HX;yta1k<5y6baVvZw4rQy zqJ**3=r_U6p<8hkfqjmSxd()e^f0^h_4Se8UWpSF5^6(gWR;7t8M1IpOrpDsg^TT7 z#$VIQ7ka%MrD7oiH2++h<wJE9+U0ScEroCO{PFZ80^wz5s*mgJoq2g&$$7S30y8sE z)0t!Tco(-+vRki*60z44^A0m=#u0czEhc@iE>Z<2;GB(bas!-3c2QGRC7_dSqf(*n zOG1$^X`qR_P_^r$C9=shgX0Q4<vt|{jIKPBxlnP!lzrgRtc=G@vbgQHgeo4dFO0wK zAsR)><}_ntEzh4nU*NsuC^PkLld`HR>xEP?v6FQXt6ud|&LatcDQJLMa--Z97iBlW zf)}hlfA$RLR#5i&NaZ%<mcRczph^5RKiZ-MtM`I8JS+?#(fRKeOs!6%Dg#-yu3ULU zFJk0g7polLQ;Ap%cn>(AQ_LoeF+Yw6Y))GOkf@jFKwoKdsUqE=d$h7RSAO{LGvem6 zCr_IEH*6C1oU^JhbLc8mg+3sC;erb{(c<xA$n!4aooE@)xv6E-$=))IaWr+7)gtTG zty^#t=nx*6pY!OIBB*D?Ap;rh-L0>W$;cQ7v5U;_eAv?5EDBLq!Q>1$#US76WvNLv zg@&J88z)i<KYSN9CRsr`Dj?~U!bXMcgA)shP+#$E9UC!h_d1F8*)~zJ=38-$vbwU2 zfp&qsYzfih-nRvMqs21U_AFyEh27}x<-ACyInOf2NK(kp2=pQ794WrBYH0^VOvV<H z{Iy+H#VU4}OE2TstgzA1_;wR70y)R0-3l(r^XGIGLGoi&l^{PqN<3P%rlzJKLQ0fH zq0DQcP}UDp28Jw#JbFl_HwQ=qBw2{JsMHJuf?!4cR=sHkuoTst4uIhg%L%8ojOtzj zsv(o+(c{t%9UG*CI?r<1NMqO6F5~lK9a@5$=DCTU3uIXAWn%{@C3pMe;r_zH_6KvE zmFJdr&5uJ`+6ZA|1I!xXWg>Z@>;<koQY^^Z3(!uSjF&;bG{nlsk5?*ubVQg`)zrvS zeU&bK0qh2i9%UvggCc$z;pZiE5~5jf_+E4=qafTsxK7q-=x<*}OT2+%ITU4OHMIy{ zWJy!48Rm<Si|p?9vL5|6#JGLz#G?T+5kh1c*Rc6efDP8(F2M8sIon963O#wlzO`IX zP%u0$P8fxBx(~MOY$X^<RGgKRl<a(a>){F2sQq^jvkEO~ABH~Cvf&U?VV#B>(8|is z3hH$;iy_gXnup{4c<x%0QUT*UIC1@zI?V%mu#fw0jEsCu!Y1GA|Gc!t;Qbe|ix-WM zUI9>vgYPUC5Cag?sEWl;B2lGZH0gtF$+(-#C*_u&LM<c=le3KRx~4v8tn=d3Eu;!S zF~d8>!#y)<ZutIS-#k1#OhYmmlv9XA=xJA^BH3)8-;iDU$SARh3}hg2NVd#^t7UXF z`ldd5v>8=UB7Isv_ajy3SPk{>V@QUy(~+Q1p&50CmPLQ|Me^T&v#gBX@WWb12|%WW z&TfU2bFF!9v?Uy%bw{2hrYYgF?<|sLT~4mS8V*dmQ;nnQ?TNIkl8I(OuPbqfFS@@4 zfb7yJvrs+mia~1h(onSFkNn@gllpE)V_<|<oO%FgL(c$Pr8XNs(Uhq0t1(7*{0Lw- zNr!?1kc3}E<ObI7z2(A0Pa7<Yxuqp6mP(l?9k);#ip92;dAY%3tm&UVb^N$Ol2XV# z*KC`vseTo%quv0Eq%F8Z6pkU=<J2farBqZDlz9$!Lkn*MV6EVpHXbw1LLaCJ_1%&O zIj3czd_e~Py+u@Yyo-24Ji1<l#(nnoBjM61`QU@+uOfkOnzQ&dNr~P?S=HeQQ3A@M zwytg`?tVbmcvhP#dEAxu@##K;a_{2#i5|fWDyOl>V0eKE1*>1k3pw_NR_gT(^tW+A zbqN*)075o19^`=aj%`-!8XH3y-IwfOod}%@T1SV`Bk4Q!{W3<9P*ik*KH8F|vFsuh ztK;Sm51q{XFa;-_kzG6#b>KqKyU%|gOgd}!xz)4x3=47|0AbLuNjVN&OWOG6W*Izu z9gdh+uQ=Wo6-YYK1FVE2@eO=M)I8{ZBxBVuz7Ujt1k73MX5Nl**Rq*fL2NR#{?=b! zo!yZA`W6Sm7X5r+mmyGEHvO544t=mb)<!6?ZU6m=LbsA0gPhv|bcILB1{)lV5#$Qp z&ovzLrvs<;zOz5!3QU9s!5FGqHasdcKr?`|R?vu?Q*FssQ8Y3#dYd*_wV<F}ug0wq z$nq5kCj^l~pdL^`QwY$&Z|<H1JTM20MtV`vH|Bo4+m7@G2sep}CDquYg_BOlGc<a{ zf9JKPa|lH2l5VG)=K}!tRjh?J(Q~oyvCI6JzRTFRueJJqbi64)#1M2&K<xNdjkn<= zbMx{bx_fRS#B9_>k6ahEcwdG!;gCB71zC(6!Wl4Krd_Hv_2F*Ww>*@4RouRc<ycX( z&n!rzSmHXK`z+d_s4vie);fr#fZ+}07zelA<4|&ogHzN>ozUK4E8gQq@!7D@0npIc zwZpu#=w1>e0_Z{>2+Rrb^M4KTolEkpN={B5neTE~@H*^mAW#>PJn1v(wIRseCp#RM zg-)3G_Wqyp*_LlO({%~Zg_PUGX%x9<vJGw8Yco*&GI*D&86=Rq{g6z7w;(=X7Bp1x z_AX^RBkuMzm2pVc`x`a$7Du4(&;G*_lJ53aS@oklK-|D~xhYdl#o?(j6r_a{D$$kU zz-K_Nra~HcX9vxZ)k|6#Bs@E)s?p+h&D1tLJxy)}1;8UshhShHTs)Rr$H@}l<2v^3 zmQXy>l2#luJse#>)V`Gb=FJC23B&6}XlTp8?2bFYPPlA+UO#%_CPyIfI^P$HgrWPv z5w#RCzUyqdx&$POp7{os5N_!c(ErH#Fo5By8+5e(`bN=n>isqV4asnDkx+Et;K2;| zDIJgoV>-ky6F2|_GGp%;r+qf*zf~EiKP%}t@PzUVBUYl{K6Wt{k{L8|0FExf^4@)C zc0FFUhfz|#v4-5BZY&%L9UET;_568Y!7RqJNl{xG2z+8<VmDtpC`4h+7a%`0beA%` zzSBKnr;-PXH_Hd^Mndr2lHkCqq8&%z=a9qM5)^MOO*GS(;Y22ImL+bJg`eAq$-1gg zn_>6oMuZ}r1(YOC)p%Ls{;H6Lor?yBzz{?A%>rTs+6K@=>S%NWm1;3d{$fUvk?;!K zTt3fQ<J!*~1pDoYXLL=|p-&Jdjl7YnT8h|gRN_j2paNLFsaLT#&$7`XpfxxLRt(co zatR7k0xi3u{Oj`UmJ)2f-<mJMq>QBFjv;mxc+zcX_be<@*~sX_hNepQQ%4}x=PiK9 zkO&thC?{uX*%*h&H+6%W_V)G<v+YLtzO3&#$Mro2_y7;m5z;CF8HCo>9;p+l2y3UI zO-xK;+cV$3ZK~CJD0D0&D5wQV@SC>ns;0qd$%H6zyQpN`2g-TNhHKb2Z{FCj<sD#S z)32%rDy8bMpRL&asU16a<~_ssECVv~jSWgEtWg&f5Xf8t$qE0if*;hL@O_ct;n0<U zu!UEQ(%}e9Jb2z>k<GdUdM`=^h5Dq-y5)q=e23+)WJZ$IZI3x^h-0WG2m=WocxyA- z`Ox-*vcK+VIQxa*TsUsxv<Xnf@YTC`E~e+^p8NFqvkf3dTxMn%uggTY<o9!S^kU!| z2Arkn9hUJZ9P=w(=xW&nb<*7?d!wY?vVfg!|1sR3=QOMa-K<eZM+d?6Z^loW=~`|? zm5Qor8?>g>LtSx@l8M1P?%^r1Cb}1TG>__Qefs#(3U+dotdD1z+uLoLG70q!4P;on z-tQQ1<6|JxLB~q?PDq(}vEb6N{WBo20_Rap2<0;)KHqE$4;X%6`Mo*_x$E+RCjLD8 zZHsO`7aLm&P@ItTg-lBIcFQg%fJ*k$L`z#cIW5jpIn`P~SXk}p)2F~6z_t%hJ~2qz zcj9^zG`zehNQoK1+8hI34K}~N+12NV^aZmCCNHSd?sK2H97NqSXJ%&n6>IEXChEld zY2^(=c`sX;?}AKchIbiKyMDbDm<0^m<>lvV?G>wS0@bTMlfG$+K?jy%l~nF@Xs*PY zKCVmzI0z&>;LUZ4rzzpZ>AB#LkanbH|MKNJ#MU@aOMr&*NaEL;p<ry<Dn>ucq5#`1 zFROG$8Tiuc&}-)xLLW;VO^YWdTz=?09P1|T(UBKeI`v^ELWWVCps9u)P6PT3h?#PL zN(W>tT%dB2r^j7OCQ4@;q&BtB$Kh{iZOS6aX99mz*cwK4t`}>!`tWE65(OZb0Fj#~ zUl4U@*JHZbwIjljb=kB42W!a;8+|#`g|M3)wuK2L8@w5#X$)wE#}|y?WB|4HL$Z4E zWIH}d#Rn%MwEfpY`8O$Kb<I?}aESmVa`x<5M1cgd00Cz7HeJkUa|#^!+UPrf9^n;$ zf60L$0AjAWrG?OL3Y|WPsR%K|d}iOieOx|26BQl{96KftY+!ADJ=)$r3#k7e3vr^U z(Jr>OwuH7G8)|EY*1N{bhL-7Yy5I>?On7(-G<lgi#2-8|o_do#6FnsuI|qTtI<)29 zoXWnYo|1PZwST+-ZWKbvWVs>GnLtN$mU$7c{>^bTV=#B@^T25N1HJ5a{JxWFr+`O4 zo7SFb_7BWyV#fxQ2i~%3PDa&!`4XmG@TDtVBPmn*DWG&fG5h9Lp_t;j>`PSPn~@SD zJy~kza^)M4ZE=399z9Tb>*Zc%+x3=qh<u5ba={_|7BMrXs{gC8TTh#SN-ETZ5lAm@ zdHfbiC}=3e@{U=}evwM}@-QP~+_ul<&kMy0$QSXnro@NGjvr?`c(CKgayf8F&@hgi zC`<Ju`a^hI1AAFdWxg3@p}qkFEQyKNxEO632_y)BR)Z6hPfy0ZEuVC;KGnTWPAwm6 zx6>aWsYa(|H{AoC(sOAr(gkR1q(KL|^i>-x$>LsiBj7^<i|eOnY!E@(fGR?ti5x$6 zOw@Tq9Vx1*);2&ba-O;AkEmqO9b~+h{{qzJ6}g{%ySaS6M0H9j$N&YDBsJ>^4btjD z1@YVv;QAit7FDPLK|h%TC?3PyWdOGb;y?vCode|y^0G>^U$(xAMMrQ=3!eR>FVNJ$ z4PFavIR46P>z~S1oM=th*VzQ<%{IUX)QINK!CZu!B4T1~A_*)yAUU465tsQXh@A$! zV{Tkyb+tN_D&Dm-If?Q$B&jT*-}L=%Kp}%p6fd^MAQgx|wvO^#T^c6L7A^h=60>Pd zm#QKT8~J#D%1yP#y?y((;U3&CFgsYB@0Af~x$zD7GH-}>Ro{Bp)r1K?B(!qPRa9=^ zH6XQQ-aQMdqFaxPF2TP^v|eXz-5io&_kvc);@I>3OT3&Zz`ED3Uw4*z<h8Lf8l)$+ zp>x0l-+<QghVRTiW4{$T7MIlzT-7lYX_Y~X?mp`Ib8(tXfv{@^=7Ug$2pf0(06PQ= z#Ms?vt1yJZSHS$5*6%C@rT#<)?mRu)Zw153DVqMZ$KMe8Bq^_XTf%VHxw`qD{e5{r zp~uSlkUExGxBjUofiHySf}cOv0mUO3w<n#!{R!zizcN(=T8|P_fyO+KN9oFyU$rlD zicnfw+VEn0ak?J>GoD^*9i>ynj3S@4k%G0vJ8SCYSp);y!<#`h@|}8kxK*++Wtj8& zHhpMMA&O|zj}QCm4SxgGiCf0A)ibuT&uV5`z713+LWM5Dplv|9Z{J^kiQat2M4J}O zE`0+nbHTTtoOSHqRGNV{+34#K6cqGOz{38C!|3_nH6)+gu_xkk7FP^Jn(FIwir6{e z%Jh4@9<v;Lv+c0AIwA+h0bmv~$iLQjarSQ>kAc1Le6DGtD+8c@8$nqC?3BI>4~(xa z(A&JD&=woOZ6xDn4@tY)zH3iTO*Lr$2}fb4=!J%GW!^le{ks&P(8h1v0Jwk0AiAQ@ zJbb{)IEm_Q{KC*sQ8B>O(ttvBw~I9o;W+yt`vPo;HJ|8AHNAcR`Rv1S5p~!*TXq7; z16lI2$SvoY0hC8suYcF|7Ht&jX)?|{+1t(eaX>%@w2N5W#stW*t)7H-S{po}zwTCu zN&giCZ2|e!n>WW+Rwn%%I%`DbAuIgi?Rgfuoo<x9N2%1eu}879v29_g;nFPQ8V7kT z-?}B$zzoU@LbuWMDj)B5cxitm@r~cwD*2o@G?4JLuE*BdzfL_kWxs~WD*nvq0uKRD z|GV6U@R-pfIgAkIDnOD2J)){B5O;Pt{W=s#E?%8{9KY4u#nj{Nc07(fL$3jFklZGP zfp|a~wCsvi5`F3E-+ya^t_AhUG-njlBsu`jT9B1Nh=OLsO<i#m!J^PMdo_R}KiS*E zxJX8rR|GJJAX+dkAt9l`ECvEv-`FoYI*~K*7MqqzGpM#drIfc}vDn*e=h@lWw|yZ+ z3K^!x#KfGa=X)_VH6=wUfoCPNGS@<u>>779cJB+ocFNWjcG!{_R6L;yh*uIMsg-9h zHvJ)MqBBN`L&QX2$B@f|^bbr2B*|7JA@$tq*$<!qVYomchg5P3se+)pg=@2!WEvGW zGrxo`C^I>k7llqlSNN`g4k(23gj|BK763yL{f049Cqf67o6L1}ky$(i_qMiw+Ul1Q z3Tgp$Wr5-_Jy-<j`NyXq!n@OF&uW0y=QTgJ<3hP<g)gv*RxgWnDt4|Qh@xJCavI_j zk%B-he-<1}SfGPC33!dv>oqBZY7P=9PlrZ#<e6ZWIuv~b(Su%ILmGnT4SbB<N3^8d zH(PO^VQI?O__d#wsOG-P$1V#!ZWwZ=J}{Btzug$XvLyi_6Y%&k4G8I2O0xshgeVDz zI1|4W7ZiH33ONr#`+_W_1=6O=(3gV<@P_mW-TxEl#`A%b<KyMcul87!-C6GBK2bc3 zSVI(*ln~+Bvp-k@)Un=URWsa;7I>0hBDk-B?Iahpn+R5(0eF*qR3T8W>o;-JBvtM5 zP${d+JMh*B0JwrUkD-GAu1$foCj-_6dFr&W=V%JKKmZ7CSVx2&9vmK4!I63^eh!K} zWMne_J}hT~Y0oMcx*e4YU{ceeZwgL@2f+XqBOOk@^T6pQsF7l~KW?WLgZ`umhzvnK zAVlEQVx_i-RYX*)BU=Ip3ebw+w?<wn@q7g&Eo#+t1Tr)NYY>13%3%`1Sx>%#Pzt#? z^JJ(oUIf+*8Y_el*|4+qp@yDbx<s#gW%l`ku5mITCL6ZghA6Q*&+IO#x(FO8W)f&1 zXxk#RUF;BP7}2kw8zQbs8^CWusu%^j3l_f(E{?ijc**I-x)5W(eN>(T{x#%jAbmcN zVSK326RONMrsY#_p%>&5x845j{rh1CEqh_-UqfGBCk1m!7%c0776C;_cXAr{I2G|V z$TCKb3$o|~!2*I=pM>m*6IX%O0FZ9q`Lyjq#0{YSn0M|ZRDtB@2}PaOT@@_Rn+|-V zm{%4oQWPfZtJVz}z6^nM4`_Wb+-XOlC)9yHZ+^V%Bno*<g?3#BrrhO#@}rFf?x9k5 zwm)X&N`+3tL?z<%OKp0G4~Pt#o)hp%Rq$XDx65#xR|Df-LV9{Nb-O0mbzD}9_I?RD zz;5E6xRsSN8OUa39CaWER@tEHItrEZpgXF{y7nG|a_l-qX;qIP4PyE}1d#7V?eqU7 zTrnlw1K^9eDIASWPYwV*M}?rs%WWggpfdzi%7&saQO0*(fxiNTA3<OQQ>|<5i3o>I zFF$eg=w;Y8@o}EijIDCn_n89?r4<OpYw+|}ey~?G9S^y9yWXu0hc+m%38#SD?gH(V z)6kc%%_%A%h-Lc#HpkQxK;o1Fz2M=nx|3|%c{`x8LEGQD0Gt{NLgA77BdT+0(Pl^B znJURKUiSJd7*|YUEG#TyV|{3X94G(q&1^HoPmBnUP@FuH$0QaxP4|F1=a$Uy-3y|i zvs9FXV!$-nf&_DrFsXWSX=KDoW@#YQMOdgkMTH$<h)A;y(u96pky4i3yW5cuZrHSS zv-b*=<~d*;$;{z6k%KxE$)&}H48~bJh0x1UKKRw(c9zfbe48Dy=fK@v<<o7%Eu5Ad zffMD+_6Ra`5$*wQ=L}Mw;ZuYHLgI?9E~S8QgYJ~=Fj~sk>^X^x1_hGGcd^e?ZUMTY zuQ8HN)Y6B3Q{UfvLg0v5Hz#{e&g|Z~vjrgVPbsIxA+WHOZMbdR-gSlr)B$5(mEyLT zW$^AetxP?Z3%kWpP%f=m*`A(?FvbAv3*sbLl4>aH7TV3Q))P)MN89aIjNG6VU_edH zM!YjUBo};v45VHp_~X21P>3?6DD@O%I7IFV*~Y@rbW`F^2Cmu#C?NU)ZRtb10IjP+ z%j(-myc*c4E)F#)(=yH@wRdS3$C-DYh?WSCKw^uxDMX-iC9A~9>hdH}79-Y}Qoi&k zAV7>-=5*mul&CfK*ZE$buW~SiW;D3I1w#TZZ0?&`2*}EW-g`MYIh=C7rIcdq?_EAs ze={sRTx{upX^ZF}-4ndDz}B2Z1vA?yD8jx3-4ZdWfw&1QaR%i4VCJL1bURa9`GK{7 zj|!eW`;{bEmQ&SGSC?l(ff|$$bj8rnY1k$zRW0U1B7_FCy5OkY#`1zI3H$<}O*8M_ ztqZ7!<T}ndSKfdYqlCbxBo945Vfr{G<`9V4ApO)ZepY?@BsS`Fhy^$^K$-&3Q38lX zLobQvX&H4Ekd`(C-zqS~%Ga)K@0jHLh4L<$0ehg1Z7p`P#1|2AwwNOdQSjxgu2rxE z0znFO*F3M|PLu`yPLWV}A|saqEi9-sz!-y-FQdU{=`*y$)qQtQLDy28*8HYZsxHf8 zY;4RH3Q{_tOvqXhm3`Z(ME{%5Re!T(muOaMS%N+aJOB8ozZ=b|3jeWk`#Whk?evMR z*v0l6hW_(!{{u?@kGQP=Uu^;Z|1a*J`1t+9|2Lfd|NG0zjQL~uVq%(7)zs(<>#>jQ z>eq1AzVonOh9^Y8*dCSoCh3iV--GohEWh=i(F%WuO!G;<%*xkQt=Vq4)!|y}%j0Hr zM!j<5w>0Lo7Ek+2lwOhrnWf?$Uy8ZsO6)>ds8^?_aKm1Fv97AFGI79v*>|}tB!A)E zEm}^GeS7{6Gndh~?=RP{@A-Gd0sqWmypvG#Pz+ej8Bk?oi+>4@fmpj4S!LzAxdp#9 zC3DL<!tj`D^hKU*ftYY#vz<ZD=s#h?VcOkhyx%mtEQL1QpgFnIQ?D^PHKU?*F^ZWv z=;vpzi#$GWEy^0g!fa|6>!L1NuHWJCfqzFkD5oAjKh(x0DEp$FRuFeSswhM`QpIm| z_^;w_u<brcw2nGsk$l_i4H}+Yz5OiL+UIAxGmlXOPXxDA_bG(MhT<blOizSVCACvL zOc#26^FCDKZZEgR+ZR6bZrM8DGB&C;km)=+*dEC*QgJDoINtis*Qd1%6L}<i-TUtE zbf3_7^iO!l96lEk+e(`(6#<g1`pNd-VrM<|<)u3-mO3vd3-YpC!?jMH5<g*p-Ot9B z@nq^Q#`cy*&dkhCUQ}pRFc~h17u8eZ`c-vJS_!5gK%b@Duf*a=OB0fJuVGv9md~=v z9izYp`X=cZeT6Fvt$in%cXW2V<Uy45?@RD^+V&so|F;Qya=KF*?<cn>EjR4TP%>I1 z36H}->`b-?6j^U#;MM}lsN8<v@1|aF0bD>D`0?Jii^S)qGyEKdO@65KTp6o2%#Itg zE#|fUQr+j<4@}@z(^gZg^V~;NMb^jl+isA%H7@hJ4S^$_&u(!r`hwRmGOoqOs=ZZx zU(5uu?<!+Y{C$ugC6Jx|f;ZrCfZ*vb6B4q^cq5c1oa@=&Ptpr2?2V-b7o5u-9dCfH zB5-mtA1<oL9tlK)el0KO_QE-qaNP@NO@q|MUH4RFe>qj)e8XG+jR&iZkzGQlXHFlf z_)_nc6^cW8GoA9FZ>J_{G^*qLer`5C6mwn|VfudZ{I#!HBJ=nUqd!USh&E@-tDoEr z=)hDh!sCBgZxIS}7kRn4ijAzlZ}E~<PQk+F_1k5-5XljE6y{KbS_}o{v{UL*rl!tx zR0xmA#JMO3t<8vp#|kZY8Jlw}7MFi8DXBkEvpDG<X^1^|v$Q8l$(>{6;_ol=pFOza z$gdw4Kl2Olw?2-~ZjID`>_T;pP_9!6i)lsoNTpg0B%I}xanH2fx}da)X`}SLnJ_vL zHsf0Kd95<f)N9znv2H>L***;TJU_aW@p(+37+HT5SCCEh-cl+HJcdb2SlRRGX1}24 zn?Po}R#vq$8K^*2-`}@pceGJIG4lLwYd4Mi=Tua*2XL)h&gM|ZM-oPRJV$EnW$xgI zDK$)Yv;K@{d7JHzkt9@<(lg1nYuAK{emQL~Gb^#lM6xiNsK!s4c(xQJ<7=;8Rnyqm zzEh+Wkp*bQV89sx9YPxz#fNemm@ZudfD);VzO#%(aa!^fOjmlJLb#WdX-WCF?4*;q z;9SVGyZ8K?=Yrv=V}|E8%1C;(r^Cgws<X8AUytnWYHh};b{}cEc3M?P^(dWT*JZ4I z1jVR)FGJnOmA1T<wT<8-V$(bA=!mFz;Nw9$SfJd2EKs+#%|!gcpzqoMiq7q@I<O(Z zPJMldtbA|tZoBs5e#^zo4FeJv=37Tkuh`efkAJH`FZ3)5e!9|T`U>3xlmLCM<wl+8 zN~A$!eSO;-#UN)ekYPYNRgIHlI^xXx(e3T(#Gc{wf-;9}?QzEKiZStMUWJM5AfGxx zfsGTBi|yPGeEMbLaEFBijqN>3c{;{d<qla4d-G+tLw`>d+H9}v2FA^`Uzw(<lROyL zyw<h&)KQ?8>yTG+<`tq{PkNhV2V>cM-+uN3y~$?9M#3^{KWA&JtJ4bz(8<Ex3Y<RO z3XPcya0xcuMfX%Y{nBAbr42FZ-KpM#kPi#aOrjf!zf-#ZY%jSiezf-!Q36*@Bo#=@ zl6!(2&?zOk8vQED%K7foxAE0(wPF08b6=Ijz?FoNoCgCKGQprKjjZbQiiC`mfTnA7 z8QFD~mQ~7=t&7dDuZiVD6{qbSa4f+D%hAzUycsHK&vU!%sGY^3yf8^Y!*{n7e71~b zC~KlE`#wI}RZ#fbG%34yW;i+3cg7^?nKyp9@#%HdRriz_lN*%}E5O|cEzvEoG?|on zj*@6uEu|i_hzE%E&;@l(wD6hRAD^74=MS?5b53^Y%rmg92F=GY`(J&N^m_>KLiQk= zZ;H~|w2FtSL*>Iw7u>xo;*1$#zVorBq8H}DN&9k{wlPc6X~+tCBy2J~GCUylUo=-# zD#9)z#z;^n#ZEF^>cZWX0uau|qr;Yw=ByG?Z_&~*!)!-c3AoC7m?|M_=FrB<UB0Vq z)AIb+DAxG8-<h2=O1z2FD>YeL(v*F6o|N#IH$$uHisWrGZ39=GE?1w#IR2i@X>c|K ztvu#M8B3keSFHLK{4qDw;)Gh<#0f9cKG#|Y7nDuqPjnXQH-^|4wf7*tBo7Y{EH8+G zpwMW6%fi<TEZT`cFW{h60Y&L@z2N?_Z#fEB;1hcq&TnYaTc5)6pY43Zw-aro)0*j1 zTGD5ydPo+1e4DY(Fh`5%FB=x(J0+IWg(}9u4tF21F(QlrxOAkz`32Kc(PAP@muOvX zBPwO|iO1OFgIb?y*r08K{6|e>NPIMRGQUr$eJCIn(SbLs*kpRVT}$F|B|a1sqZ)f6 z|JkD^vC=2_p$hb_SP`(;zgm+Fbs_1~e>4-Jk3;12RT9&;Gc2rQZi$5{mR6JZE0rg@ zHO!QBT$nv)dv<Gkr(VH|+D<9j`AGhHR95?7n<TWTS?0}8w~H)bCbpD0E4K5{pDzR3 zI0t+o5F+H|CWYO|FwKUl&mTXw>JLQ6$7h2+OoRJ^t}c=nAvD2q99D0E7xRS_hRAj{ zHaJZ!EsULnsup4%hOV-?xfv`YN*KedR|A3F69u{)CbhthfB``me4{XG1SESqhzBe7 zdtAYr11$S<9zv~<>twG`izxb+;awE?Q~Og}<@c|b@$aSK;coKrJ~@es^Yo#pcB;@E zAw6B)-oCAw1}nQ^(^tqu7?6>mWkl@k$OOVMr%g=xaoOb)g&2-NM)G`qTm_?x((JVM zlh|z^5|M2{7{u$;*%NE}GpI)nA3T^?)4#U7#^qGLLRf3;jeV?yj$b*v7W0~S&$Vmv z2R3fl$U#2x$bY-e<vmn`@Ce+gBJ#LKhR(8}c8Pi`nXJUDW80SYBdf^a^zHXsHnY9t zd$C9UfV_OQT4Bwdh}mVc>T6NlTTkqmY<Ib5KIC07EbI33;rANLi6l!?6Mkre*-iX( z6OYQE_0i+T@uIS*qcVPrihUuCYcJ=`Eoj#iQ^ak58kqVK6<l^bj!|ngQ`$BcWOwG^ zuR%lqtYb;J^7t7iA5Bb0Zx3OskAy?->DiHi@9{qePSyu{N1OfjM8k4Q7=U3n+Qeg! z4H^COSr+%c-H1#e=;)*ZnKS|xIU8qtG&&p+1R#|nW-Z{;vKG2wyhIV4Y>-!*fRfYJ z)ouUYJz2i2=1@8v2u>=*s}2hdTDiyMEtTd7p<kmblgpsU0F_Imd2PFEBf6UYD;$|F zu}{BecUaCOx0gs{B+RMj(bUpfmOTfmQ%|1${OJ?__YpG+tzsjSRN&AF@&LQL?*_7< z=#{;Fa@TL~W*yB~BK9VHdv(}%gU;a@Zqc_D6D2EGxA4rm`DovHWFPAl?z!15GI{G! z%IL6a^V}?_@2igp2Q=$KrAX*twaxJKKyRg8G79acGPI%!-Cvg^mFs7oTsx;hXj>|- z&B(HG1w8{1@v+0b??BdXn!uDo?qroON8ARA?8eF9{zG8_f<VdBR#$KOUdpI>M{n_4 zGrV-kpQX~u@y1Fq%)e<E8^=C)@BpFK5QTwx*RBX&aLpi$nq%?Bg?)$#=X}G3O2gw) zQU+j$1+%CQjNQRhQ|C(ArVC<=!GHa_yph~y$N9y~2<s^2Mikn1vRpOm@P)hYxaMWV z=e#n_D$5|(A>2<RV-wS%c#X=xL~ZosLouLYCcM3d6`lB^5lntq;?^S6UazzCk{R9p z?G8uau@7GSMP3UhXo`wgN6Mw`HE-Q}N<Fme;JH@f4d>91$*_yJC|p^uQ)Z5{;cyu* zc@-Z8WLSoL?_bjS1#?ICmkSBa=nD~(CzXTPD0!oM@YYedbOhQ0X|;U$`_RDP;3$x0 zSl)oZKq}bdv_WX#wFdpb09-)5AOl0d_^mBd42te1N|e$BLD~EYLvelMKFDWaxCU|y z8jVf?p$5Dy)LOypu)0CSbq<po2$w&hu_<=*<=>O=P3GJJ4GVT<*dbaQ<%$@K0!hU4 z)gLbakVynGaQ<|CQzrk=q@v{Og$5<yp?{S8wSHpfZd%IJTNAr1u6=ABS+bpmzbDih zPUCUSL^>`yTi4iFD7yXxiW7WTB@fGCG9qAs4ov7c>k_#H+!_UbYrf-9NVe@dqz+=8 zTXVLE9zh40$YW)QvnU|0Ot=yAs8n#^@8_a<+*XIEa5Ht<B*^4^Q8i?Jm}z8Vt)LHA zsu0Gk%<SZX_(@UGxho)R#M}YhSxb9zJ6{M&o0xFKkN67}yt7VxTS%^=+uC)qb8vji zB7uYnK5*=??<5ehQQZ;{ag)ICE)Z#)1Qbl+sqb4j4OW^?=XlOb!<W|IGT^MQ(Ra3- zz<!`-EDD)?pM3O)+$y(g7gN){fWW!daS5ZOpw#%`Nu6Ioc){)?eWb6&bLByFc6*-X z4f+MoGEi}gdnR1l;6AaUcdB1lq;1$o+H&{J_TNL!{=$Odx!E^p^k8cHm;rbxOL%Az zuU?G=Mf^?#ObIFnTU&@X6u1sGd&^XwDZOC|GnX%{qpDn3A6I@IgV~3k((H#1ABNy% z{ad*HS?gf#sIfeQ4P>TZPH&4mnhw5Ay6mWkNOp}3Yy_w>*nyQlljn=?!(Qpdw=w7H ziSp+To~!^R0)+*=qX0Zmu5H=7x3;&oigNuW4ACLGx4|N>058jQZS!xw?-ILfM{(Yr zg2kbiR$5iY2~V1O>$4s|dUOhmE7&kBws}Cc2fVPTIR3p5VzQ%uUcf-Y8a8qyzDrVI zQ)_M9%A#|9VJK|`C}MDYxl<}&iU=m_?QmeigZW%Qg~i47YIIoU>;>O@TKjyWxtQ<S zUgCH+8l3POrH$kst9;}9UY|YgE;oqi%MT<86R@UO-ob$Z0J4PlB!F5`Vi;Zz`S&?F z<<ZK2+E8Of%6Fcq^QZbA(e!wGq`jT-%P{R&wxJt_V~`wVx9eLRSkAD#FdYLBM%(}~ z%Yt#5w^6GP>@t1E_}y!%$;qMz|5}}@+#MbJmv`xNR<^X%R7SqIf9T^sm)AUGx`Lqx zQT^n_>`UjwgAcVbSo=U(uCXal#)7#X2lu9e1+zc_VCRnU`K!z8tIxzL#3iS1`RGxc zdazu~>&&MwzY-?$^iDHAiTL*UR9H6hAj98?EQ;39I0{e>G66FA=}<<GKnyPqOm5I> zP`@TU<{bqkq8VmZ$`X5!`8gQv&;%Zu*BY2#W@cvWz`;W=U%fh2v+pkxFhApPIM89y zXa<OcDKHwf`lx&@b#APqrE3yu8!{y`DYn7csNBPq@7I-H+Q#<Rp*M0p^RI^F?nT?! z;JbWQB`xF9JR-ZBQ_Emj7*RYy06Pl0jBUrcEt@xszQVqE@gf1#&!Qfm^}BsHdhGO> zYYwr}3R-e2*Vr09x7Zubh8ErTJax|~dI2Uo3_z$4i4ZXbn^p>mBvl5MFT|w7HI59z zWRa)>`UD;Q(+7}&7K2jv98iM&R%Z{dfSRtMuKt2brIrq}fU5x@uD!Y?;B|uv-!jnl z5semRAuGOm)JyiFDh>oGqEINtk06md#4dXE@eucR`;u|-;KOpOMbwQKieIg_fTYq# z8!G8vK17Q0X8DA8mCS$ODp-78Wq!8Pcc(dchDd-5_V4+=<W0{xO5xW^MP!S}PalL1 zuHUW|O7lu`p^2!9*#|G;(jkTB2O4Jd36JyUXa9CJb^y;kGB4!ZAURxZHPr3z&je%5 z5_*XD5)`pFpznKxv^{oVt!zRD^uT2;>RD?Dum0fip1KTxLPAPJR8$+$)rb}=D?^_5 z@88E>+~;YiRYB}U^xA=e0iDK8P4_t3+S<mSFGQyT#u7?v$$$Vt*-Wwj?({Ax-EnKB z2D^yR9*R(O?s;hBEq@Mqm5vdCiD9Md7bh@KpCG}(aw4h$NSp89zppah&BV)(q*}y= z0GF+QI>N$ldX7?*9TaiL!a^Av$a3(<u-dPOU{yWjI6B=L%h0`wo3RyBojA*D+>{o7 zfcM1c1KAa|#VB~Y0u)Oe9<K!p$ji^mdnGY3Q7F!m*o8JQp!!hKZp4eT`d$E~+{Wf2 z#Sn}YZJ=fE8!5Mg3<kE<EU>@{^71}fZhwbzKDOY(_u%&{Wxk6JI7%1rnTO6F?oNAv zRlsFtsN3E#{d9G{ML+3;_09OptM+@DqOLTtpWOL7sa{eVhW889$|b}OrqpKPH1%VR zr)3mG(=F45$GS`_y#kg>6q&4=pKkTpWI*{%`!yBl32k6}eU*XyS+!pu)@N$kx*;&J zuK$ONhf!&T;Rb KHDadQANDmzw1ImHu;t>C!g1oPYoG*H0t<>xJY$j&tu>F9ZJ` zOW1Vmf4uz0`O<n4|Mz45yPmA4tbdO+ZP>C{0{ODZ11%jRkVVk4CK#i4rQu?Q(ULK7 z?Q~Q4fh?&#?u_f~)6Y(K%3tE-%DPzbetC8>rfEV}C{Xd%(LUy#th(;k9u40}AI9ii zD_U@IPapPyA2JVMO0s_|$m?fZ{0q7GrYAjvn)mEtm2F)c+YK7qe;AY~+t9Ra^YBGv z;gY)XNu92bb|kcpJ}$SmSv<Z4Zz&SM&APGb%ACgaE18VB=jiK`dY|CG;(K$bZRf{$ zUDqkPUuW@e;YLoPrXZ%4#*D+D)wS>&4GFv2zsY2WtXemI?8(BtA<46~vDM1Nw2Z~Q z^FQ+G>SuuyANDa#?AwbUNjmynwoE3wWSfgzfboA`e1hOnc*>X9BTVhIbQBBD3E~PS zuZ1()*b1a)p;IbHC&{GEkMq=uAMZZ3Fm>Nz;fm5nt7{dTS)ZyjeNQs&H`~U4=E%r? z*FS|BxmN#%Un^pK$=WU!zAp@|LCCD-G>4fex8jwaPV4OSOm#)`0EXv+Zm$_6t`)Pb zHpo{_xCI7&^w{{$C+WwXv!{K>4y-@kUw?7$KyF{^C1;wJJ{$dVFQ>VVw)NUeffIAC z=U{|+8*{Ep!V$xGyX97|i>J<9d&uBnUFF%g@i|M-j2ZDizi5gb2~ubE)a343&T(Ox zH(|}p$X_wFoPNZB(DVk4w7E?g%5pC{zq?<tatKCUYks{0#p!bu8@P)@82^cyCj6%o zBVT(Lw+EENgokfSx;qVZ?uoV<CK~e%UZ)1|W@P4S$NN>7Ab+ryGn3Vqlf;IsrX=oF zzh>UCi|!Qpe_fRra#f3{ocgS==Hs0{qTixTO!y<M86`r_8(p4DjejGmO3&Mc^1}G* zV);X{A(k6cZgU6C+C&5z8jUwHHRW{Ro`tRUs0c{rtFWc$<MP4<dA$=n6?c*S`{c;) z_OjQVIlXGX@1Jv~{o1QB$Hdek3)#a*yWX6$6FS}YULd-{P@er(RBG<*`S95IjNRql zN<ir!Amk~<C*@sL)tQ-kN^Q%Fj4#>Dlwg*gak^<J#5d{halt{?HZeUxI5{>S(=XSG zU%1Jqx?J$rNy<bhO$Uu01?TDu05pin2Fyk$7E)m11Uy!)Fi=`r6}bCw7V=61aG8vk zPXOr2w`mgqi5C^OdwZ-?gCsIsf2Y78`eGU|orv!bUQAM21wK|$hu(`oVPtk-mPl^@ z+}pLQE-o%5O55OdN&itGrrF`8PchHCQ!~m2!x{5;Gs*=8w3Mv_y04Gf5m|NPDBo9> z+|;JDPR2%ldTZtW^IEK!P40>3QJF6vD%IIoOMTnKbV)a&V$I2CX68_bz;5DF%=yn> z$ocqqt((NA{_-r~smF4vO5b<DAOx+j%N~<I2@||z@G3UlVTD0?@I-;GPF#utJ_bk@ zn@}3q!;qT4anmNQLtt%ff{zR5z4jvl3@V6%w>6-~xi8g$*P0In@2z6qzWv3g+b?f% z*hxh$ldMqSr{T4(esR=yVx7JpF;E*Q&-!=;_K7$3t}3A%7L@#JU9}2eBS$b5s}eQy z+yuqEh$cq#m<J{Frp1^0#O@8;LGF}sl|Jhh1W(Ah*h}tfRim*$i!+f{x*|={RJ2aD z=qb}6``cH!jKkv=ef7L63~X>74|Bnqf-scuIvwPFDj0B5^uC>f+sFblcfMzRyQyCf z*9_~99bbir-EV*yF9Y{0cu}<U^<S^TOCYSlk<-hC0y@_q_s&y^0cjtGGcuL}_AAf9 za9w!K!5olTI0s5O>x28{6WsqSvD^{JTJLtG-y`LhecMOvG0;ox#=!>OoL_5^{q^&B zymkM4BQNUS*G<mkbd(gP^-eIC_+=T=zIPj#oQ2RzyQnR?!-diVhS?+E#qGQ&Bcr62 z<HuzeV0a1MSYsaK1vm^$q^E24g&DuSc^@oByeN1RL*cPw$MPKqm4QUD`}X!S@-mtr zI;d9S_T8sY%&e@4CkxDrM^MdRhQ`AjGzRQ(@NNzbcmvAT-8`pJ2zmpiXImSLgr<NQ z=NfjnWe`T3n&1}&z(fh}BJkMs;Xm(`RsUxX+;*&LN@a%FHs<`hb;8CuHc33)*f(zH zXSXlCX{i;gZS#t+$k-OY8ZPX2lXT!BU4^hp-GtWGT`UoUVE7S4oY1y&soBx?EpJeN zaAGCdc=%On2H26|eL?~-9tsnJ){dq?5Wx!+ep$w5wwlwBb%3zLCc|Vy^|-y{+nCp{ zM_I=jz^lSF6MpelH)7Y?upzF|*P%1Nri%vVE<P0au#oq@aJ3$~a5n+oWg&o)a-T{7 z2a1~V<UfmN^{YPEsp}6nQDYPs^+T~y1va5PT@k55TlgGFs(!?+i(xH;tr20Wo?|I; zqqS=i3KhOH_CER3#^Ji*OUO+<uY37}WiUBw21PLDinncFB~pCBnyZLSMuxBeaH&qz z)z!^zbqWm)<s!g5AmY;01n+olt-)$>OjMKrD%XGjRurpzp1=Nj17nIPO&G2PWNm}N zp!M`lp_H#*4{NirbM7s=*UyUrPzR*s$&`PyjOhOFli<Q1Nq^odIcM(svb<V^?51e$ z82!lep69)i9)@e<0iP1fpg8yOMrBSZ6Rl8@CJ$6gYl&`hMb{>#1l4(4-_Mo>j?Fsw z+|x>ld#4E#^^gOQ_Z)eocEb3N9t8|vp<eLX65g8IIj4k$vub33t8Il(+~K$ydbB&0 zN~gA|96fq8m<*8m?XAkN`1nZ~ox@~8g^m{R0{i#uIRf+4vD?RJz5mp#re8?wxrTjq zOXSig#!vN^<st$nyLTP}D^Y>nB(bw_!Ej}TUgbP=5G5t&5t#aSbZYt(haYhp)1^FS zrwY39*%s}u?<Wmd8Sn}fWa<TryyyZPSHz+U-;LSuew^r~1xuexFqevd`&J!tdVRhX z!eeMwPEGjjWMK*81#b?F)X~7l*t=36t9y7N{9>p#*efSn{^L41py0o=Zk%wW;T1kH zco*K5^PlGH-kJXaNW3qLCer82+d~~>voszywzl45x3ZbpLT!;IQ^q$iHC<A)Ci7=6 zjO8_gW3LW)LTES%YB>dZr?JV<!HEalgn3>=BbbN%#c$|j+eM`!oz^l;w|INg_65P) zqi+0nz<$raquhx$%DS<Ohs<~wkSl4tYQJM73=+k}m)OqOVy!xg$(tO7P?wI7tk$rB zovlJ|qmhNaREU$OknyK&?)kvf8S>TyUTf&yo(0=c9^a%Ykc4*Z+GVd>PtMYn>ml~$ zgnC8q<K*nTLm)5a{u6BeEgOD4jlrAYsx&x%RE&Z^e#c7BuBO4U-^ieaLRrKM$2eyQ z$9We6Qkj@6WMWFoiMw?VcdBOYR#|y{7GhI{Bpt~M;uxa*s7@?T-Xv7^z2HUb>f&LD z4SHUo`I~ti21eQ0k<rnDk#%i9w83YFHZ+8v2Yuq<{W35ieIOeK^zLbT{*kGfE-4_W z+}OlCR)K5g*&NFLzH6k;VhQ*6e04i~vou$46Y}Rp(dLzb?s%J_4t7D_qUkv~K(nb$ zPcF-{GUll=MK%2(2W6ziVOvJSc#+%#FRp-rFf1|`&n@e%hXqS{CcN1M@nC}c8D5-{ zF1tK-9%XYjOwc2BXctUIe4>M!7Dhapyv8HIW5*AfO$Uz#9*JwwPWATfH@r*v|2$D9 z(W}syH1SFHq?XGXy}9AI8{>5O=^=Y!h2cgu!`B`M4H%zI3x1AQ(0&f=bRLBz{gzl` z=UFPj#B>rzIXKKOVpev;MnCgDb)Q^DO#u!kFgP^iNs*iVa=xBi1N#{K+<YjB9_LVb z1)0N-ARmAeO~>8cJ?a0j_8w48rQhCg)KO<pa7G1`Y5@@tPyy*pL<~sp-9{HsBp@Y# z4M!2s&;)5p@6x4&poj=a?;r%F*U&=}0^dI9l>2}0ch`H@db8HJT#km5ljl6o-oLi* ztdfW%?0~6%iE0QJPFBwYj9+AW-ni|J8<%hrFK-r^;uT&kEiQ`ruCHChz;7yO(}Z2S zchmlT@i!Jcpo(A9ebJcXmuh3b8lAh`(#=mjM)>o&NQ;tW491k)=rB+|;%-5v39i&f zj~loq^$?x5p~~Lr*b)T-Yb4_DaGf2qWng+@?<#a;Xf5ZDg9jlNQj#S06%^!ReLyY% zzRBx(Vh0!$ii|};@QQ=u7<L$<-2gPsh(o>ug8Trzc=Rvq?8XrZq>Z*c>jKta9!kZ( z?l)4HC`P`;zcVLUk4`qMUn`B;zsv0|rN+~1m7cmhL(`i4nzXdizLX0^X2JRZ3o2pH zRBLAL{!fiMR1c9@<D=CrJxjj5Gp@I8y#*=)ytxA-9aQMn@gVL;k`=^(mm2UKj|Hrd z0k#?YXi!N*KOG0ab0VO0VlO|GBd9LOt8rnFL{(L#h>rUmaZErcAu|U@7Vu5#IHVSZ z_XM*dBG@*4dqwF%9H^sH0lPuB0c{rI>m2|NghJ;5=^sd)2JFepan}oa5jGyJd+E}j z5TwA12HQt%=TGeloP2!&PbyLVnhj%alk_ZEi_J-iGM8a@Y@E@B&#V&<&pB^iCQxay z(d63r$;2R1{oGqxIWM$jcLuYPr<kQi9y-LV3=;)yhCZ^80f*kXYnQ;0BMGhCb)tBq z#fQF()$;+Ca0c*3njfnZedGZ$RXB5TJP^8QUx(uzbo>${)lNf_lC<Pj!VuSt9Kcc# zd5DvJJv=gU1FZ`M3V>8|jH|wgZx9R{74%?si6%2R+wBJ@E1+cU1XzL>4SoouWSw#M zPQ=#s{~w=^uO#Cl$#&Ec({!{`5;n-){vjh=O|8SZvTyt<%P&X9ll3g5Rs^8UUGOkN z`3oOO^L{B@@l69y?x48#2=-%r*V7urd_O7ky)NLs{PMICI1dn872u33Ey_W;9=+C) z_MmJSBm?9-*bVCT#Q+yxh?sJ217IA)rf-lGAmF*|^<6gBDTDKQJSrD2It*5LB6$I@ zS3@XeMd-b0*a9a2ER+BCuLI}YW$5JG7@XTXQsBT@F_OX1Q;8F^^xeNvwp-{MXe3)& z(C+7WPViBy3ka<_&t_r&N44y{u%h19OrjaSz&79P_8d;xyvRyi3*I~Y(dBiA)@pYA z2#x4mv2c+-!lz*G_7%)mu`(sCec<e@n1;)Dcx#hqybOTd#1~O^KLQ-))L9q5%s-A_ z6oY=pGasB2TrRn_0Y0ghquwClXDsT&n=G@l|CGW`*MYYyp&cFvefq3B<VtyQ*Ghu$ zI$i=!?AV6vqTLM3^_4rM&Gn{9?nAr(20DgPHHWm6zwdYJd{$a^<wFSbq2D{Gz*~q_ zPrkLM*@ieakJ;*5ydch0ZYYbiyqhHGY`$iV`7kF75x9W9LcSvp7#k45IYT$(xq$28 zGHlsTAw~-5v*^7;YPz1DrNJCh#~|zM(4jQM%G&q9J{n<|fldQ+5cF>cIXGrQ2e-w% zL;!argKYcu?Kkp_p}cw3G+HTaii?WkM<an^@gTz3dX+^SD9sf_Z{y261Lwzup!RgK z=u(lZUrzlj6VNDC&1aX+E=RI%r1{~?FB>(#%oI%dVtA{BYr}aDs^zzxzwC1S@P)`v zx&KJ|d6^pTWA}_VVyf<DQRk0;?-V>{xg)?TZT{sq-|0NC^dm{Aw?nGGX~P!6V^3Y4 z6bi7fuC8W=gyI}7Aex|j>Bj_j6#r`pxg!T5r&<(V(}mRB?j7ZsAwPEJJ?aSBnmL&| zF4M5Q7(FiT-N!+9>k~)XXhQ#Xl-qe0b^l$wmN`mKB5CE}!@9thKdwHS*_lz$EZ<L@ z{kv=);z6LAiQkzF`j;<$Qp&EE;(6RZOL9lK-7*jlH(gi|^`f^&y48gBmU(?LUzuZ` zL}~y@Yw(*E-Kg6S$N@aTwDNyeP7DunxxPi4m%=UkBQqI2AGy9tA@px+sq5%-^142t z?qyreUN#cbAU<B(4V+Ira=AlczcMkcdi=$Tzz?WH;Jo!?nQu&+Q>~{P){ps>Y){y8 zOLBU7gVklSI*4R9_AwAM@JPb`$_!9lKOn^xXEXJ{FkQ>BrLyswk5kW{TgvDDcu!4X zfI|HBrmh$S877U|(cf2J^A$l^-2oP(eDpeYaYaA_9i1{QTxL?eD|jAuk*$|gar(qt z%li6x&w&Z&_dij>iHFFgX+F6hZHj*<q3XEr;Af}(3p;PQ0tVbnu*yaLyA#^foo)0r zd9CL?vPS-SC0K0z<BV&sEJRYdTWX~!u4TWiZI@g@HfyWdwezf+m6s(f+{>>Wqprbb z{m;w)9P&j;^4HH|yf9WdgAHFot7lg|WKf!SoZGWIt*{AN1e0u&ajWD~)`2WbxoYIF z1Kg}#-znPyDi+O1_4fniMP<ZM*Yu`uVK)ST&<!OX`SAn%nH~V%S(Pd<&Ea)?IAL(m zPrFDM7ScBVT^yQ^4SlIk<@?rh#=cZ2DG-KCF(j55WEDWI(CVG3U~theIDjd*o0+v) z^0jF?ZFQR7x%mQYNGk2kdW$bV?wSra=rpBl2rwUH@eV=g!e-%e?c3N_zSPg<nO*kH zgL_Hdurd$pHMIiI%GV+I^P-yGe@B`jiwEsaQ;pBe8%@YXmgwfABYP5*Gt;wMH?eDl zuyeZNX}xMv7Mjqf!@nCkSkT!umF`D)Ghk1<QPQ2BUpDq|8c(1qz`+EiABIWw!Akz( zajz+2uGp^>wYYiG({7?p*S!af!62tiHLB=3G6J<9EoWdpxy!F~^da>pT-_ptfO0W! za~Ymu+NmyuvetwQ&WEEYH?C0wYoxFfC+}0}EORkz5QAp($F=lCMr9K=r+0>Pr_XbV zYQ7y~C*|NWAMKMTtb8*iQA3&)jP?zBq&i10i9*eTZmTC7HGEtDR$1>?*^||l?~2y_ z{^x7cwTAwcOc@tLw;L|#wy|uYAR%G?m+~KGZB$F^7A&ne9&VwNO(1<u<*XS+Aa>15 zO6W>1&kYYREIe~VeME<mD_r-GwdiJGBDK3{k=}_*a#m7O;}TVSRpPAhI{H<KZ*Il? z>c*VNaBdwPbUKfHU#abM)@@rg9JS`tL_ntPB&B;WqJ2_-YH)85ngijmyh-xtwuEiB z%ND<b=xb<hU^%c<p&RFyqn$mFlS}A-Z4%ie`x-Vg#s2WVSpkn8tffSX_uKQ^w_`0? z;aU{C5r(<NS#^rT^hHGWzWl{e8!E5A@Quy)ZUdBV_LboRk=EIQF~PH^>WM<gc0He` zv}5=nXQvqk!!+PqEnYAG+~d3wv2F1<^=7*SE{R*?vZ0qv@zba3>@&TuUhuYyfeh+X zh|}8p50%(A%$&Vuk7{_;n!j|t{P>4}FuxuqNCPKE$-2$BYIcex=(pu}l)tn9TvC_K zN=Ulyb4nn@FgYb#u@82TZ^<)QFMh%5aSUs$lx5^6#(7T*xGI#z4(O#6UqR(R*eILE zY~P!4``qS9HPpn6JjE-#vZqo>!rV2}Mk_v1F~xrC9|VAc*lDnHkj#`i{0<?Ix(6wj z0Cj$Wuf}YIG<D74gQ^uMkM{sh_X6K3bTX~gi`Zkw%o3TF@YWdq-cFSoSkLfe-^S9! z`nZXN_+n=wuUWPQJZ%iq%wAuKKOuSlV1yn{(5MtR*`-&$DoE%X1D<{;EUl=2IoBg{ zvRZ`LMemkNTR47#`eV!C{L;tBZs41A9^ws}vKn|iKM*#BsvN>Wp0Rv0U(;t(a`qBh zFMGgOY-l>FrC;cz_O`B1B@48gPoJ;lfeyRD(r7%>1!?6{UpS;Hi`<x9@*GHW9>8=~ z9o^cIZ%H4A&CE{cbz@F#ak9OcP89GzD8grvrgpmerfO)jtdU3KMmV*0@3MzFa<`=Y zzg8$yomHRmOn$H*_ez~&3uv8@!Zbc~oqm8f3{+{`H{LB3gJawMI9v5Wb->k=r~Uia z;osR2*izLu2jl0K%Bs&-Z&5^RhdfZ*P#UmZ4}SUFxdh+T9bgccP-_EY7VImtaYAJd zpD@uL3qlNYUDZF=+yT&Cg_Ck4co^A!PhGgKS~4l?9h+FQLPfdAMK<u3*w^=c@l7AS z0_6kp@^1=3?)Zzsd<MB<r`&wOO!@!=%I&0Pq+V_gRw<J})!tkx@D{)Ry=GmP6D6IV z|5OdTJbEH|d_*Ak?WJ&W@hNuZbl+ATY1^47X^*eQCTlWWsFr6X^5&VQ<rbj+!Zc>7 zzxsOM(C<AH#&(yQS*E+BIHcY0yWAo>=O2o&0UFbDIVJ^CLyGUp{kSF+CpWB6f1~i~ zbX)R`sp_ot6I=|xq0)?iJ5n`Vx8!#AG1}w2mPl2pp&(rXJ98v=E6&KWo9`9jMfK#( zx5XsI9G=OQqIdz}6Q&XtzUem2FWt?%0iy{)!ad<<Wq|h(WIf2-1;|xNf$r$@HGAp8 zaBw?9%7+f*8ZU6M%lo`@uB6z254fZ}1YmnRFf@Xd9eP&oW~p%wh`zuCrCjU+_g5>F zDwz<RNy-Bt4Uv~Ygq7o}DS~54XJo}Z=!=XJLTBW4PBrf9`s}%E`&7ItBg3J2cPfG6 zo7%QIYh+H8cP%r=@t8R|g^KUvkR6dCUVCxlGiG^G4a1ab?i`ub6`&xoxQ7V@rVXc` zu{@~yd8?!q5aI;g7VzMaX|ZE`{j89}`TeN*2eF5V(*Y_9-9nMX*O|gE`)}Go{deZ( zKxhi_ltm8i`u()VI>A$I)y>(^H<z!}_WQk#dq2?c#t1tlWZERBq<DpZT}~YbX!Qz2 zV@)FgwDB9ud@GO_@V=DWZ#_?bZRo*8aY%Z|1SZ=KkZdRz73SopLZD|tgN3^lAOPk= zJ-7O9fNYY>Z~b<ZO?Aiy5?Ad98QqxKqHZJ&B`9aSVQ^bQVrEAALZy4Dd0#v>p$?mD zJt`n17+F2pG5_$rng%iV!*^Y&7|or##45!7CT_jv;XfguYnZ8$*Q$f#0SdhOQ4QPg z-6iigDwH4dqLq~HJ^hu`c{3NX&Fq)RHOoK=Ag_e$$DY80UV8qO1=*$VwSv=t@@H05 z@PlfTRKLoC%O!N{99M>XQ;@L_vA*(1nJBLDv)B7fHl8l_$+TLZY!;Gdp&LU-Hh9Yk zsO_z;20;8y5N{!w{%Bom>tt|eN9`I%LL1q`K(GZ4#Lnt{3RzL2wrY#NxN&>Woay8^ zAnaHN;PKq-ap1-gkM>Hf!iLWAi_ajCGdz6K#gAt8K+y%>EaH^Oce!)G3COL_S0lk0 z_;x=l?218hYHEB3+_d8vMg92DA=;-4j_W<G(UQ)W6BR;F@OU;K7CWMOAhh-*<%<s6 zi_;gtaRLTJjLXFbeazto0w+(c#)!5o6&w>dd;X}L9QUuiWyh1>`+^V{SFD9Qc%Zku z_qV^w?y_AcsN1XT>nG0@ojq<OGSg@{&|0gs9TjYK(Yego^KS5%`P~OOgf&)%y}#b1 z^PsBuZ@){@-xKd+I=30E+i#d|((84zrhz(;Em2e^!CQ0S6Tr?$HXN)2*u)@ObYp#7 z0ZH87y^jl&aJWu~aQkTL+HeT3=ly)dmk!=n9yDU02B94?rvY>%z`;yF7=}~cZjjG_ zhg%JIURiksvO6I>@e<ArBAy)}hQF`$PAaI=kZ|(%4|c2LU@8F#ySxsu=WeYktY{qM z2#Z4?ha7}{!s&#_Zy+)DWc6vEK^c_W1*ABP4UvDrV<ASD4dRwDWz|r~?WNPs7JyGB z=MUxPmbJVmgTrv(85o<t3F*S74C1Rh2`*VTi`?<^pUOcEg-jqgAjb`XBg)4E;$CO> zdmshm$`b(0ZF$vkgBy0)!TS1YINZe$Srg*9A8XW~={_JOx7g})(z>$aojMD=&qDw0 zzYoereBsolTl@FSA_?0ND0opEEAw|CX4?dFUVLz)*|x7jG`U6&P(&o#UUpkHAicY$ z;e0uBCa={Kgh9}GhVy7di`B7*WlO-K0>z0suJ~r}v6AvpziL|>8?PPZVA5U)@R|00 z2aApQ*7A!5NCR42h2GU2tqU<+`1ZTghzuW$rQtk?a}}~;5Kds?PbThIM3Wrwai1NA z&_0Rdk&0nVecxPmBjprJAm9#ratWE%&6R0<aT_H9!5hz_#pLT`YK(BcJ{utiy9D)d zg;$5WO&6QTS9(I5?OX!J(Z_aBYaG6`UOD~qzT^bLK^1cm-fNo1G||;uEKvTY586Y; zNX*-L|GB#}yW~n2Z+G@N0qTO%bllCrG~Gb*SWD{4%v7+yJ#cz2$<4f741cxXYbzNA zvfU4@RgaKCHAWf)WzC7{6TF^WJFOsm0oYX*S{fms)4>2ltBEVmpZ^ZgV3!szAA$WT zBRksw!ozv^;kMS*R)w%jXl?<65fSbPB<$xf1$Ab<$ox9JXG`9DRbx)duq2WD?b}0) zE(BFjrFNAXrK{fZfbF7lAK4})UIN|T{Ho&$0g9~YvFQ$2LOki845u0Y2;uMw$RT(c znpFz@xCf|MbAJLmaFlF2#fzxzCEj7ChTo6^sqhLI7Y66c&dsfv@5$MG@QE>g2nf%i z!sV`1b{|8>;nmoB5dlNOM4Anm2heZeDWS*MGJx;qx~m8@SKMR}IC`>9H6Q#0lIgoU zteGC$eow5qrUUxMPz;=h>6q!Ry3@~W9@wo+K@fOnW~=_yx&s`Lsqhk}0pM$c8F@oE zdY7*c4gUx6QpJ6dQN1PYYLLRAqn;ZUR@%lqXf}_rv~!*1m_dWaoc~6sTX-rW#nu(l z<o+9_?zxqp{=9@Gq%cdpM=n@gcB}X8wU9l*iqb5qPJZl0B$8Uf_55;V{M>WPcDgS? zVRp;37q8H6TLjrN4u<Z5N<`qp5NaKu(_AE}9_Djg0vWV6994j|@uHDjd;=r;@7puu zt01NEa{JAE=l{a#tiD9TYlBWOaA*3yxdpO3fQ6ViB!>owUp-g8S=Ncxc|gRGJOEYF zZ@%Ns_BzbMc5nc9k(T9rS^q})>f^^Nx_6C5;w`v;e7B0@O3+@Ey~UZ9a}7pk%>HbR zyh+%Nl;RZMY!K=hF+OqhGChQ<A}<DOUX=}BL1qm=#3dF2uW(6VW%ugdzkmO7)sB5) zJyr@eXLxv$G>-N_@;OU4WA$?$#=~cmI)4LEZAMN`Q+f00y$BoMr)+OOiJpY3j0SXs zKf~kU_uU`U&9t8*8_d@07Mlar^9o?Mr1r0H2(`QXO4+Ws+ZCQUXWEiEzH+X{CY5VD z$|tk%L&^KLw&Tp%a}>C#g%Emhq8sAbm%j%#ZgQmUn=Iy$?C}V3l-OG>^M4XOlFa9o zy{1;#b6TMlU-J0bSEDrb0F?9>PRVb2U0X@a)Oh?9DNhrAgYtCK$2RI5sV_}o{d@D& zKqfY1W+$pp>oVzAPFeGb0<Tv5aZ__5K&MF9Ga8PSPN>(C5laQsW?nEB1hmWNocfYr zG6@o;fCDh^C>rjJA)t20j+<@t{;!Cjs`P@he0rY64)NW1`_H!?iSGOXGsPoFh{fmb z$Lh<GPWA#NGV93YGlP_+eI?Llx<ukso7D9b;EGTa`BW8Eir54@D<=q-0g`ac#h*Y= zb!ERof}Kbs{ZK+UfI<;5X#K=_1t5JF@^AhpD(J07`!ED_!>|P5%ua#K&MC(A;uDbc zfb;1?uxrh1Er!KHeAdTtjNiE{r=jXbUOu0<zzn`7;2xiFPMW^;WIbwynz)eRAh6P( z>X%HYcz5ZXcMyWP2-~lJ{wANve5J_YON(f<1sLYS!N|;Gai>vy@VN^fw$1^FNQR}4 z+X@Fl%mO37F|e{q&~F5TlH1#=gk@+J(YiKw3{ZW8;Y)!f!-IzO7#v@c8PNz*EJOby zfvEq|xQHRTI_c7xrw#*US2N|m)RSS&_zxG_EIlq8{U)W>&^rtpV?qOEa(Rilr9P>* zIQsUg$rNW-X737+RitT1S3Fmm3KUenv24lpv!bHB=-an%58A&2_GiNc_R}Bq&rXE? z>9IY3{ytCLs4Kq$VPTU`l7q?RWeLPdK`F!V+iysiArC(<Z*rZYGh_quG~XCpTU!fl z`-dE0W0(iJ%72)wWLUY8C#cL+(of8WyRYqgJ8ok<S7K__WC^qKtQ0x9%AQU9dCOus z5lx*4)Zo*v1;89X@_~i?@zbYzhobsX*GW(c>3~&<eOBt$kUtRiJoe!D!X-h%Bp3=H zjZg~&Mo2VIg`OvG^M$YQ9HMdi4;)}VbO@xvZw87SBOzPj{(}eNKJRS37C`aAyv38J zBf+UqaLsE@hbO^ipPrMWi4*f&yg?#ILgFj@2|rY6AOc{Ma!n$0K;;E35gdvqf`fwO z5ZnZESR*S1g}M~lJZKejg)e=}d_QZ)Z_QKlU%m211d!fNrc_@t=4r&tCB6}OE@1jq zSG&um#XfnuU}s0y)?;wi_s+2S3hBU|^Wt+avB?+t_S)apf;$Y36CO0g+jK$zq98aI z>JHS?$6mP<LbHO7yD|$^Vnwb<>BxT2tycuH2q97j9*7XpfIyuE%j*#KGuVxc-~x(u z8Qh)IrQ>l+yZ!_bK7{L>Lf1pi=i+Ds{{5hq0$rcmXZ{`!=)4hM<)9aYJS}OCLp)2m zJ85+t2RU)(kku41;OtUJy6e3~0$WLcPixOvJR84RS71P+nQfsNP&X^uhU&Ur0QCu= z2XlzwfUhnk)@mX`HK)~T&NO2Sa@~!R#<y_EEw5ocrXy5BGWrbr=ay1=_$IsJEnBDL z18d$OQ>I{!KqybPNx?<<ZgoI0YoMoh9Eut5+;`s@Af>vN<_qzdYG`yT47x%jw8*$A z9eRUsISj+toWJurA)$)q1(`2{^VvK|I1OSb1IJ$>grp)N-9b|@)q%)<IU)%{{*nGw z&@c-O3#Jgo>T&iK9{f%gFgk;AibLy%ie+f|xrxE+qQ^|s3g>Ia4^uuauOQfxe=wqK zaXTiGVm(bMyy;i64JEmgiFtgwSap1=d&xKTu&u=i0QL#(>}O6|=E|2{+INcbc$M?B z(~_rz#qIRDO0VKm0j()?NR~mO{t-tP^g8Oej7-0mC}z+m!=`A6WO%#HA(2bqSHeOo z!59qs76?Mugt$@52g9`0*`*w<XtDJ7(KXjv5#cqGvI<dy4sTgN>Oxr>7nGN;)Y%6i zErxb>X$TuA725>XD$sk|L4Z}hF`L4X3_O18Tl8;NcE^NoxcHSdPjB3;I)ZfDLxspu zE&T+T7dQ*6>_5%Do&M&hkVGOocZ%e0_%Sf-b%0h#vEV!H(^T?fzg$)Y^XwA&frJnF z`8MP@IcXgUE6?;MuGpTrX?U!s5REz5;lXG~z6<mz^fG3$<opKVc2E)_+1((hg7BIZ z5|N<uu1ib<mN9zq;bYpW(|Vv#^=UT{j3ep=sL?<i2gL79S5h95z3&G})BhdYw6({> zFD(dLlMwpu+NGFt%wZG#AKJPkcA(0_LL~619Ww{%6u*redHi(*aB_1PcyQmXzd5I+ z(a16-h)B|>-rIpxlq#4as)|awm0MWTVegb(D>4gDPD63&D6ZfC)l);GUk<`&{+Ikw z!U0OPNupZ=HCy^-<_fZ_>zxu6QI=5f3G(%8NR*aY;6VIBv6lXw8B2W6+9?M<QT}Jz z=v(g-REv_eQ*>s<>>f6b>BEN-RQcl56}hlbKPEevh5IgrP`t+Qet-ue{E$C4!kGeZ zyfyp-#^n9<Cm}b^KlEYJA(Y!`P46ddhFbdeU4jCaJTDtOvN~tX-Ikf^8!G!%YhW8n z`o2+jPD^flg;{4&CxUSgse;ZP61~d_{eRtmR26#b5c}QC^Qo>;kRGP4WbnFocdSS% zzVLnJ9xAytc>$}1@kaSGjg%L<xb-LAG0?`5kbUIuR~7m^vK0SZ{7Mcl9=q9TFn-Sb z^ne;&5}h)6^VZs6UbWaM+2w=ozoI7W7N5Fe`s2s#J;s25_*q16y^-d2Sk*%wDNM8L ziK~9T$zPkIPk3~6jtERQWU_PYd3(sqt<7$QfkBp81MG`wPp6JYZxTuz1|+ty!oRNt zHGc+qA5~}DpjAJ4b&3pYQCZ1Mm5jh3Id@m>F>vaAfAS>%(5E_wKY)sS_f=SKah<gM z#ajy|F8%8c!~6L>gl%LEZGp*Y>x#*S&(`mw+0^ZkR(uTqKJSdqw=(;WN31}QHSrLk zq*;UsMn#ySf5iI86|JG5n3;c&@g_H{%pvCHDF3Xy#L8xY2XR5ClfqUT9~#B;%l=<^ zUmv&tAyfhr+xG|xJQX}?6v_PF)yYwbb)eyX*~zp9gRc7wPX(t8+-Bd1DLoHXJFxw? zqep+a^y{Qt)MY7h$nzIxetW$)CajsZvS_{DM4>kw*f?^=bIc=RHMG`XMD$gQklF)N zak7ytN>Qko*DG-@UJiY@bkb1uXKlT8?`)sI*%)JM@`PJpuKcR2)Y)b`e62wemPps6 zHYWDQv-K!Du{~Nlehifmp?(?NGSEDjfkk^~2mkv!Y}&43g^~=>_4QPH!p`?u%)+)v zOQ(y8b5Oe1mgQQ>Bt;3|S!E-WiQk68D7*Vca78Z>skfU?WF~H1!;fG5MK83nqMG*T zJ@&0oRrP3I?hm%7jR}ZYKWffWHdfYPZy9hQqfi~r$xXVTky9;nYrpm%Z=i_0!I}2q zj(eEluu8vsMDifPD=dcBUcTU{(=oAPJu?F2k!j0#UJltHZ^pHLa3K~-|64sTsc{gy zZHQy>9Yc}dN@u<Na*b5kgY=iYtPRVO*c89XP7{mj>ZVq?ZK$GFZ*`W5-bY#xM`+CX zllt2FATh_D0)!I$jw7m%Jn;KyYK~MY`8G?cz}4A9@lkSBEq5MxrQg;blEO=%65LHF z?PulW$x7j25&!Wn+mUx+3S;3ioLN*7sPDUNIT!h=LceykazfN`@QAUf$ZR^QT2che zK}FTYJ@Ly!fgS>>NBXBu{_CD5u)*i4YF2Z-&Ro8JR%&s$c^VsX)6ZO`R|ac?HGMc8 z#}(V;$b?dCWc8EOBsa$;T{lVpuM33lYKb)5bzT({nS&(`55Fc$MSN9oryQ}66;>{; z(k9JB2+tOYimICFiVD^Jf=Y`Dwn>_}w~1F4(e$<8G+Rpf9krr`)-3yOh)v4c(OR!A zm)3UQ{L#f?Bjf3lMcj9j`>b4xo}mW08UMa+M;#y#73#Ds64$tMB5MuoOm?-;wp21l zrq^Q1d561oKj`i7o*;DJG*G*mXWffJiE9BK$mO#jOm|#lpX&Q|EOQuD<*5@Ep25v3 z`}$!~e8cdm6;C0-Gp4x0@k|PXW2X+*g_0@EhV3>P5D^vCLy9h_NW@^+A>u0L!y|Fc z2!sbiw7@rnsEVP`QHA8lL@=gVj`ktyVhHGl5o<UeI0eB|HVx|G@J1V%*)LGWYJ=d- z0~t_ D(`JKNO)^cBbqQbed`3x`yDtjAzFq^2(6e)MYa;S+Mc*|EX4F{5l{w>gz5 zBt(f2Z0gNS;wG&`J?e4t^3`?`ABr47`4dl`tnaSgEK@E2?t!eDrqaanuIVM3aQB7* zx4}uuhN172Qnugd)$C{~rKUIQqGd!#(iH>L4Vg)Xm})OxyqMe#R9c9_hB1_w?T`~2 z4x@$I+VXwifbWAyK7^Qv_uD9KD?%p1K~}oDi%zjmCCuqS<bj&0OJSn5wY82Q%#i1` zLL&)>kRMnGGZfUig-r4<0Q9`VPf=?F@D8zR!&sNtrJ29KV9X!LexW`|W1XlfyM0zp ze4MrA@PdmVt%X&-faxluxRats;QnnWhy4Ajd0cUKO3tl=o@Ebe>i%&vqsji-T!Y)I zdF`eiR|X=fV|hBRGMt@OJ~4pYB9la+#A*<0bjU@FZ-|96Jk~}A6gdde3ULJ+DZX^7 zXRg`1TUQ?)n+275)|UDhN--qs8mO2wZ*o3~UQkf50(0|Xbc5H|eee)|Jm{$U?9gkI z0vmhqM-GN!ScOax#a=uH!a}=%Yrs?ZVAcZi{~^SGP$2~99`M~x#903=)J)4f31GH~ zB+F7h6a8*TQZzYme8;r2uKl;G@x9N_{XxxbnmwfkPtauCO9hoD{J$C2qEH0E%UWGi z<D{_3g_u_AGrCOSWKpf=WFL%dL+1K|bu9u0xU4#KyG?g#0BmFcGo@C*);$4tq5!gi zbM}Z-Xd|Y+4M_G?!$I!_sSvXkMj+<|9QzUuhBqvOcrO!LQRrohkZvDY=(sRwx<Kz~ z`06^KZHQDY2~usQkQtuP4dp=HuMsP45ODPp4v~SnP@phGzI9!bIuBq~5X}&1^^vD( zz-Os(aAwqc?9PjSt@Ag4OW2;2bB+tX>D@7Ph_A?FvS#reR*S1Vcl^;*YgV2LFeT!> zvx%h6ole4q(z}3kq#AJ<qAkZvX8$Ny=H%=x%jla1AygQmB}eS4HqCL_P^&t0BQ9}d zN+|T0f)(c=Q`Y6G<muBbG78YImb{dKNxJbg0Qa68;PdKs`uc7miTopKBa8<+$}iq* zE~SvPZP)YmDlQ4Mg&?(Trct=$%~y9-D?QkSgheywZv}TF*md(levv}KPx=@(No(Zv z*qc<_*#0_x;~M6fLn&u(-zNQ1?A`CT{I5>*Hh87m-&(N-Su*|1?GB4FdRcjPFo=L6 zBV!Vj6@<wRmaSHenXAz-SY>jqoYVz5`A828D4R=ZClMrDJjjqQ5ZUF-d%=nYZPAuF z1<-zjIRuu0Nwa8OXwV?FQNX-C*Gd6xox1et(<ear!KD0X0Q6!;#xN%i2C507)wHyX zKzK;}&+8Yn{z%XhRI40iXzLOjjpW1He0#4HjWH3~$>Fywj7spOwHqA3jB}H6Pb(ap zj=#n+`PvCq>Jb$Bf|5SU*q(&*qdDa&D`acG&r|NSlz<3x7^U>dg**U5B1<lt`POIi zfWQ;23*#J^+1O04#$G)%)mJplKal9-hejgp1@I}5j6X<=+$@(>2Duu9)|yS0Ez<W^ z&$IkVkNRgJ2`3^T>`}o5WnL$WOXl^M;>7ZJ110K-c#{yDpcO^ZQ$E{msHw<T7uV6` zAZ(AVO*9vlFmX=ElO{bouvn~8hpJL&BRee-ZBo*g=`!mjME-%c4%>L_iS(J}{>8Q| zkg)~^hK`uE(X$c7sxGL}IG9w!yOF7B<yr=`SmU#rFpg|_x~>8gfMShm-Qkhmke~;l zE$eard7&qf3w4e@nZ9Uc+3iNFWEU{9FK(Xsr0FDHsPPb4^M>q8v{x%FesW_n;2qtt z!+kFn!SQ6%*X3vXSMTkdgv(vj+eh^vByJ4kN^kAYh(W2_{7w+txtkN%M#+tb!H}8k z*-&V3Mnezwa)V0CN*ECZ<_v>Z$Q&)*UUVhyARAi-oIMWR5Y<eR`x`1!w73Wbl%|q< zo2@mkRr_^Jn5b<Tb3qbJFPjyOJC{%{{ZKsX+8=OG0k{(6H4;HEc)2-0IWUOJ<*5@Z z8XJ~5NLUJ8ddY-ZPnDDzAkaqFJP4t^0D~gb8QP)0I2&3+>?iNT0pH|~mPqr(eKiY* zp#W+momk+D^y=sPv0CE)x*TP=oQxN-%TfC!*3;c1eL@6<WYaz}`mILo?7xYehmU%+ ze4m0=dG4K83nqGT+@5)Cy7I2#83m!N(-ImXhC<N^A188~Rb^50nHPon)-Z&CMl%|Q zkb%S$LDou6QhvKT!i$n7OGlCU3zL9I!Q;fdD)|DYp+T(a;>zL*P&V+pJ|9RzkUtFJ z%i*D+db4FP#hYOJ&+guU?C$6h4wEdnz>HfA&Q1}r%TLbkA6$qkvOoAHb=T_KlYgLw zeAwi#B&BFZ>s+mz3*233+rBQ)9mQ2r>Ah*gTXRY#asgFEI&Y>z!4N)WOH(m~`WeVf zSsIU|$8!Asdjir`JM^@W`8fivrhzONSO4^FCnWVgf!KpgA3QuY`MsL-Mn6!Ihw-@V zLU-nX%>t(KEqlBFb@=+1J%fs0|LFMVYn;a3da(kO2=zXnNDj(^e1TGS^mMa@jB(hn zs9W-TxlikA4XniMrO2CNhrbiz3P;SEhHu+b$|a^gZ;+Y|E}-ViyYRX5{g&HS6;)Q> zeRQE2*ns5<vF<13f1d#q5K;W9<qC;x!Z6UfZ@2XCLI_MvZ6uaRaxK;LvH~Qn`Xr6| zJSN6`QXIls2C?;<ocs45LqqBi5;x{%0nn$`3BUii&5FFPdJ)_rl&%4*lO&5aEiR9| z<{5%WnIdb+P|_(>T42t*yLKjZ-Sa|}jf!gl?%Cd>VdRB(>P5>$KmGc9n2q3HQR5#~ zx(CxyuLeZCEl%HfcK*Y0dcKjhui0X()E%2}C~2m?mKGo>VuFCJen8T6%=(<Va|X~_ zUl|!04WMY++Iqv|3fWm%`O;@@03ehfiqn$)?JiK2%w1sd+A1tSE)PB4ck;iApTki6 ztOb1y8&zBT79ef07|s)tsd$^n7`i+yG7mcPFY4YIDi5wq-`|E>pUby2vg^X%5eV}s z$&Jg-7PO69^>sFS5>bJT4d!)PFuH(}v}HTzlDtRttIsO?;Q%k<+E6b^@6iGEN)W*# z1I*I_m5X=NfZUH8C6VDT6(FFWVf1Ubpiu@W(s5#U=dX||5)u?4#Hby@$ne&t)u%g3 zT&%XH)q|KGy9(Y31fS#$55I3#<iLw|fb~Wmh6)%8oX@t%R|KXC5%g4VK`NLjn+5)P zfU(E}tf~DnFF9*un!iZ8-c#o#r6BmG-xpgJmV;^IyH;>=RcY6lQ3>ZtN8Y@rj$2vg zXfF;F%`wy8x%C|;O$!LMNw`>KFCXu3I(G~ebH_+_{ta76<xtk@p<Df8D(>79sTV52 z&oe9pwI=t*{BGV8Cy?<{;Ttf!gBJ~gZe#)=&*abC`-;&X80~7m@Vy3Cuep1!J2&2A z6VjCN;QafUH}NfYAGiEhZ`V0wP6j+hmvBJhBkB2&xXjQEDqaKw)a{+D0I0Tb%Nz<B z(Gd9_SwRcokZPkXMA`haCAh3F&8VT$cEGdMN1*n3=`9L*+$0e?-Zh>Scg7@pbn(hw z-bbE%<2U=P;PheC(9M-uX~hC=ujKP}9?dC~zISW6ws=CjPJ+u|g{g$bVActtvX~WL zNKO1j+~LiO%{A@7O|POD6-p|;vN}O$%5S<uw5+7TfF61t3h~h;BFHs5(YbyQ=M6!E zd(dqV1@s!=RFEJ!K%M9XBjyFnHz9`v2JC*O5drrc41ob3-|6o>m&TB(;mc5j06v0P zJV1IRAFm8gH!_JKo(@e!8r(S;%3}gkGZCmt;Km_voeICJD!GY0(fc>VFvYG3%^X@- zHQ>9U1;2-Vai`9yJikr@KpK2(x;<_t3icNjA{*mP45>$XGg?+_TL7tK9d_`JG7&B~ z5IAajsbkrW`noT5=ryP-ug6#|v)G9}2{x?D(%Bg7rkIM60-gKtHrv(X2g?U?{D&Q9 zSL=x`1K`Nh8x%Qmq-vazW81cENTzuw)ane~0RaKXC`bej^MJU&t+ngWl5h{kj7${R zAo1sLUn)$rPEnu`)CYIwg0DPZ84R_;KoFzROF(-emt3FPH~Ft`Iz+OSRS`dao7HiX zY?N7ex^C(u%h@7we_*HgP24koD}va1wx0y&XTg?x73cR9Y(r@pr54AoP>1&j9?ZMu z>!YgR<5fZ=MaE;a)i<#CPwUn}H&=K061h?9$>{zjHc|5KS?aR&EPa(IP%mpbTI57y zG$JnObrcil3(9N(w;gMW^=@-SIN5<))r_`2`>IbbgONl4SQALY0SXNAJfOnIJaUA| zvRex`(%kh4Jg<W0?J%AYzuM<0?X&h4cw{&Rks(R@_q(=nz?_gSn1CD(lgAMpI93xf zZF1VK%}3q%XO)M*!Iwt79Kw{vp86(h){rkRra)3<cNZ~f&tvRt?9N@kOi<qAG2>I& z0&a$zpRc0)SEP$(vr0BL?%mvWF5dI&stWa6fp=3cww;Nd#7rV)>3I0?Ru8>DigFP4 zzV#<nYpt9b>}USi&;0e5j|25uay+U^#UGBzoXj!^>tn3Y{We=}%DGYqN;yGU+4ZDu z7@(^Ul@EO8>c>VF*C0p<sx`^ky?}v2exCF!CiP!Ew><PB36?U;?euyLO9#v|w&UaT z*OF^0vp&y-+_imilyP~PS8io3#p;IXOGcD7ei4^DFh+Co{gBgKL`_8FJe@aBX!Vs} zm?rpKQg-p7#|-X9tskwjG3prY=AT-e&I)$51iSqu94xs+pnQ#Ee(I6oJnnoAKYLIu z(9>j+M$DJK7<A|EbRvVJ`1zyXuoVT{UTBD?d#mEvy<0xq0O<FLLvLO^j#R(zQ-he? zIB#v7#uD@3n?UMbY!Wqa8)|$2Hn~pNxWT%AIN&OV<F5lBrT@ToYI|CwYiQ)u{3^d; zZCc*7NQ)CC1y#1^^1M|U|Gep-a|~5gccEw|tt8%9|MiIXt!4=*07GaMW4&vQ*VX#U zM=Aynpl(fpAO+kcc9@@o=HMs9ATZTbEPU_MZ=GY@;xx}?1<B6suMsAE8E^jl9JzU& zXOr$>-lI^=g+X?iCGl&Q?yVk)_jFxn%f9RK)l-C`hP$jsq!WeIWGYtHiR^!0Hp*Z6 z;TsWuujInhXc~cF3a5Ohjzb0RD_)JdU>R?cs8}Ay{?+W>HXjPgKRUtbf|-!d;(?ug zSS{<z!B&a9E+G-M!}%wpMqF7O>-xL-MMU4{|8wEct+|U8p*q;-+HTflm+8U=1@9j8 zY^@~R`$k@KmfrA1YW&6k(vY8I?JZ1Zk*7Slzx@GrY?RlkB=h5&8w3IVFD)f|azYa& z|10L!p$1)G$DWi_eVUP#psH^Lyl?Cpx3jjrPJZ*uzFE_$5YB$2#QGiHb})XyGf0>c z(a_kFo9tpGQqpi0bMT*AfO6nO?(d_IK?n3-=G9CcDl+_nt2`^0EMM@L>Za2@e;QyC zMS5q}?K^md;XC5LIt+>CKH(+0rlVgKjfIwHL3atC^bjvElT@rQb7V{(`**+qo~m;Q z2&a1zNk3ax$&wkv-6;P%LYQWS@Yv<_&NB|;k;j$c`V(`Ed`0S>^Yrf6D<_c_IcJVH z@J!Zp+_7Czt`&YLcI`_fvs$I<0f~+toJ%RaUqQElDKec*;>zE`RfmQ%tuqhCzf2Nl zy)YS|V-(lbN9uO!0&Z2{l)!3Jw8Wn7G=;r-`sGixl<P%KcJNt=7&w>)c(AbaU6Kf@ zG<7m7$y(;J61GUk(|oaNfUmWOD~ohjRpK=T|8hU{JvjjP+uoC3Fs$Nwbmy6=hwB~U z(q+?!<4u-!y^r>^*V=g~KqVcOuwl2KEoWamMfd1?M(h||^F;s7L<hIJlCPg?^xRH8 zIj{;hOI!3{WZ1-thkQp|58YK#E!@i3t={oKXz&EZXs{!~Nd~J{i3^JgPXyZ7wBKWP zA<A}qWD5TNGQeHdqeKsdjq^_)2d{n6Xz!@-P*_C%G?kWPTws~my@UtvJo3`!)?VJJ zZ5uvP!+&)E*pg12sb^spqWUkt(bSXVg+5@kLNr-;xBF9HqwU_Y$Sq+W;YfMP3R7^s zBLZ?O=kJGK4l!$B2{yQD`Lt69dBf&eg<IMp1WKH%>rzEQyC?e{XWvQ~WXUs`zri~F zzWjt;-*K}24CXlV@7k-^$>EL?b(5~1-9D?03?SM^w;2#NV^b8o2y=)0LLpLtXEHQ5 zl48C|FKeu?Z+gMAGBc>+7w?n1;k6n2)Nb%HuF!LuDLE-6c7t!<)+a(G7$TdQrmM`- zK?0S{(|o6)YWkgP1omSd_BqW6Ml7CYa0gke11x=~^#kK5ra|Y~C|^Q2sXCyOG05fz zuv7R_d%lPB^V-=Tp!`(&$E4%bk!fq_1{jza+J^37wY)<r@xpCIMojHib87`T9PXvj zVoWfRW~#NQ;FE=4(Uwj^CUwU4WUo{yxEF9djGF`2Wl2^pXx&$aFQVNVj1LDK1r_JZ z;Z!mh=j3Rs>Nx3Qm&`MXIr;!KoM-!Gn!vXn$@U9qHhsUYHuTc3{`i2Xv<2j#^S&Ii zzbp7f;*r)V9!zL$@=NO-H=>>67XXn?(@6Y1@H~9NgYXHt8_msMkG%4|QC{h}Bp}6E zw8SVhsaotfYfCoaL>{{p{aPj`=GHe+@B!LKy!q0x{pV~8wFrZ99by&eN1poS#e;g- zhS@+Z@Y2FrwnKPsbjfr&;*UW+uVE&RFdpk0HkohJjB#RXIA8hh-M{>j)~#Z}i{8DD zdm--B&y6m@89CmXr1I&vfr!YHz8E|9S*zu}#sRF&QTJDI+#P0&!3xg%QMcUB-)Emn zj0$A#dYcCm$|jtJ;{2?$0f7#rQ!D@~iReTm``Y`U0`_(;SJ^ixu5=Gd1>sG3r(=_s z@?oWcd;b=axHW1V&BOo3Q<OAwA=^yl5>B`METnFSMaO{+25_m4VoU==w`!4~ARlX_ zWSEuqL^t9;Kwb_k$X*vVlca??HD(3p6l?x|R(`?TFaG9#-dsRwdx-t&kPu>vwXm-v zPkSEMH^n*XoZU3t9Icj)D1;pn-pJpI{&s;6+`td6JbDx%7hCPS9@ILzNjK90cp9h1 z5j?z;n9n`1d-u+I=K`a5l^U6skVG;u4JkEs`i9ij#h_4WQpoo$`ZV7|;C8zcT#nIx zi9rF?_exu6ZCU9ZZ)7>ovfkL&rdq&~iMG>=_jEVSs*IC3AN=N2AdV7WJKK@}=(>UV zbDOO_y-K9Zr8lGS*=2Mab0m|tqCY8QNImo9XauXb)3$B6XI8l$Wjs;g=2nIrP_x`y zeX4Th=cQnFD{T8kn-3_Zr&gk-Dg9S5VP3W*Tp(uQ-F1ey;`2>&v%Tn6lhVFd;kH-L zqSCP2XYWzhdR;oivZ9)0WrPf^2n#f6gGC`D^XDnnduknKc1+*+r6(&GS%@)t17~iV zmQZZbZI3u*CfYWz0_MXfF>!7oi`!kKAj2obe(DC1pFKcl)Dg;l$w~UptLpGU4!UhA zQ26oL>g0DSP4R|^YTeEZ$fR|?()ay-`3K}V+0<zkK0CDV0(DCO%1im^BI8Cj33Al9 z&By6!3E$lB_uT?<vEH?~V!LXi5WCMocYs_>;Hqo*+(OloZ+nezRg(!zdh?Y-+@;&{ z1?L;Lg?YhFa((8FU*?a1<U9R|`lXKVqeOKa@*w%qZ|f&_KYDaddQv`FGgVXey+o4I z+wIRX2wYJqo<2W0CjYXhP+6FYh*RV16;>a>nNjp%Sx9a0jDZuaakc5gg9l>M`IcUG zbSBR)PeWe*f?BU<xzerLe9AEJ#2@lYU!UE@u2A1X>n_BKpJXhWx?5Vd%<TeSGRC|q z@4D&o@`1kf6;@aJ*uv!F)wvfu*>`CgDi<*wEBoZ$2=WbJ49N{&zH~q~Q37O9gM?fY zCTU$Qas+6p2%PPJ;%L+cbB2N*9fTPGAi$t2esSlo?><ETO*_@cxn6_RYQnlJf_F1( zK9&vt-|<cY-4sz7l<`sFqdM`zmcnR<Lv4y=O)6~uMAw{#*$5uy$T0n~+N~7rVt*7m z03x1w(mN(`{lhtLt<<K@z@VbT0k_+Z-GaHHnv|uXzikdS-+{#{GF775@NO<X>^yUX zAJe><G1O!F1C+f&YC?{-zV~oPcWe2*{xju;{L*^X1M1YuRe^e~qLaOp5~y6lVCRHA zr{n6GSLf`e{%k1PXb%w#^YIfDnoQWB_Z;`4<UA1&{;ZHlLxN&qDqlAYEXP33Bt-J- zm)igafRF%{)G0wEzXI9;I7A??)&NF0s`-WXLsJV`kVp<DUZr=D0&`ErfgY368cwQ( z*kz!&22w`^(V#br7PSrT%CP|a84~I3U_>lJcl8014f#45Fu9$<aXpq3mGyh%troLI z#yw6+k4bT9irzI#;-)31y!EV1FGj=&8$Id{;ZhIfQ7N_)ekG)sea!R{4zzQ@$p-7x z7e31`dH7GB)YhmLtlWm!A>pMspaczN_NeQPsj9v_++?0KLvVkI>qGP4Q}Mk$TX^vW zW<kK>_x$>63vw5`0Nnht$2Fv*9I)6@3nn4&@m*3+^D_vCP@3&I;zY->p6Rex5$>kb zzUJ%6Ho>KaO$VN)bpl4bNon>IgUtP?)CIRdknuXazrS-(T+VA5Nkz&4LTfUwmaBcX zgqQ=AAT^5u<_P8k2aazAE<qxLILu3fDUue5!V)64?|ut&9T^{=PL8x(w3Gq%1(|jV zV}Y0BvdZmRkHI`EN>)FN4rURtJe58pHVCb>9VA3-srs6)1Cj&D3DUN`+lI^qZ%Yas zbZbznY~VqE(_ovvC&Q=jx!;rA6bnJiaPzLM*3c><BCQfShOGyKIs4E!Q!$r}mWzzM zXfwYjtEGct8Y;DOkvuBrTs}>X|Gcf7s&HF{tfzo=bdBIBkp9)@?!khj+{^7`R;%`1 zZbpya2C!If_m75A)DVhbYY^cB_tZG-i|Hdze$$OPjk9vjAUQ}=KC6dY>BD-|Eywh} z`sILMZ@NdSoUd9p%fW+4w#!!FYn^3XdT=;DU}qm5?coi_2EE(dpos&UgWN619-C@Q z4&1emYesJj!Pf#9*?ExE3S@Y0Cy0JvA23BG7y`d~9D-@p+Q3AT+4vS_wwDG+_IwKF z%rtW@Re`rD`~FlAVOXK6K~o`fr()C$OjO`FcbQAqOLc&VGMG%!0x3#vFw{>SApqfa z-)YL<QB``dKtbuw;9b>C8IOC#oFW5p#*1JY8qOh@mQpCv5pk1CTDQ?pc+&0f9#9c; zIf16SkM5IpEu7K7*6=dn$?+mEX$QUw;kn*{a$B-6s~T=~F0dO|W9(whI59`t*|OJu z3F~d)#<lTtS)+_WZQ^e_IWcGQW8c+&()OlW&D<}r`BaZh`_cn1!H-S9iK4XU22$k> zXc3$~HY${KWM`;v&LBQY3EMGUh#9?{c^$q2*aU8j+FHkTa%B>&(kvV+b63lN6-`cw z2rq%L&PXN_z*=d2m{$@ms}T_JO><s>^pQSsIK$?14kOXtSjZ88Ogy~GFzmr`ZX$5w zK$3{oEwE{<NL`3P#zn*TasrLa)r4Wh74alcaPy)c>|)e~{TbU8bm+|aKmM@RTI<QT z4wS8J=-T+ggc|S58%~{tXktyBS%8T12yxEN;E&iC(rYw(cge+X{z<b!E@A2Q*SUNG z?USX9E`U?u03u=6A>v}bazmWNIXcRE3Ac-JVp<M7Dmhd-vqPICl-yuo^RnMK-xx=W zSgqkx!}XQeC(G9cLTkPCni7Wc$srb+A2rG-f9CZep8S2-*U#unSQ}9AOr+nFLz-Ff zh7Ww3iD`zFDks${D~q$e452E8id2#Fxz`aT8N;0U2FnK4FaJLzWRXCMy_Xisxvy}N zKir3x9}-+~H=w91y)({``#2y#0LHi?F|I--<x}l#Fxw+6A_8>e@LeQ_+#><r3Ve&_ zbtIt$LHj>AgOXS<>&)J28YL+;RZvEzpVYgp%1VG%u7%UpZP@U=$-$D5@=b#WG1a9O z+G-Ewb{E+V>U(ItGhtL_yM$ZZ!+_5XI&}8Z@qoRHCSU>Ldbea)<T#*))7LjY7MVFi zstznOPkU1GOfLDa-ru1_&)b&=)$zNqYRZ0zXC>0RG?m&y$bw?7X>4MYqOUU0sAx>E zCGY!=J9T*%s*6fq4sla@wFhfcvvYE5EjIpHa?+sjI&g_(zu}eCT8}y#mn#6c6!nlv z_~8<~dk$6e@Z){yDl{fOyfc!QBzbFypJb-1`(3DN<J&$z2xHU(uLrCt<mSD-s!U3M z$A^S$C&57^C?;0;0jyJL0JVXrHvOEkr->0xxGZh4wyMOb-w?)KL!7a9pR;Fxzdx!7 zs)aTTtA*POgkyueZ(eCXo8A5eor#XND-)&*8oPCSU!BoyZ{tPNy*8<$!L7$1J1&3z zmWs_~X?!)+N}JO*y_ljFs|g|XW!4Y3Zx>Jqtv<b1gW7I9Ix?1?kOl*y3eg9|9S*tn zk$*y0+A<)}(az+_A*eLrt{c`?@%NP{<x&S@5>d3=kl2c)H^F_e;h9!vUAJza@#)ze z7CkwE%~|h`SU@G}tyUTSx#4n4N==C4&uWiFy{B}*#TyhUI|wsr#S`9TNXR5#*REZ= zrjVl~?xk6dPU6Kfc#1oU9F1He-o4AO{S<GE(6YmP=pXD-8bln2TY5~i93{yc%o<tF zh1Y8?a>8JB@(oMqJ)&)rr|TQ=FuDkib%evPDu7Ke>_t@e_x+ENM3GATda=umz_C;e z_HO7W2A8%T7xGV-Q`=kL_c8z}ij%jO!Xv5p&NH{zE{EvRDrvE9A4JywA#L`AZmXh5 z_)U3FwN;ikf6)m`&Lytl^FgU*{AfbM<s|RbY^18WW{=)YFDD+|RERys$5(5Hql162 zf)^PeyK^_tW9Bey78wx({?<VZBC~)zO8wE{u?Dz9KrIVciCDQD3V8G8O-5r(csMV5 z@W4rBWn~CQv79Xf!3yw_{&&)q9$YE1>(Zywmi3`C>%9GQpXg9V%65k2M`-DM`We_K z_8zpJZTaRDinY0_bkECKTLi$KKwbD8D^p=Rr?@)XZ4FIvnYrUZ2_xPNhQ4<*0g?x8 zinjWwbrQ{k;I=u(mwvt#Q{}%cTGVdQ3}Q}yXaQ`45m5#*HwH-xs$7LJ$(~x9a-0EI z?`nO{ZhFE;Hsn2ZDyz*~pO0r`nOodX8XkV)hx6={gJ{1t@#6u1E8-O8RFHD$`MYn1 zp5~8W!5vl$jLobF8<j5*{&v-C<a-WMQZ9|x)a7Psjr+<MwBgL5flWReGM96WSyMmE zL*H@ZPAYQebv4XN7D&F?rZkK~UCFvMcrXzSI>bk=G$G}*1*CuCl8}RhTZCN(WD3ZX z=1ieYzzQIEYU{>Fr{HiI3PqA24dGJ;Hy$uV8Hl20=08b3aZ74tx54wu)~Q31>NKMe zTmes`t-FQ3qeX8{GSK})UteK}fowhWv++^D^3*Kl>Qi6LvLt83?oR|JVO0gW%X?G` zNkiTAV~KCp%i{G72ZcPq8fM_tNb)7i0FN&89gZ3pgLO$j@PlD0OdN*EGP#Q@5V~$C zX|i_1YxR^&dZp|G{e>IfiGU*fH(ankTQ(r9s>KR6n7wOtgD$kspmntIn<i?+vPt9v zH4`JFMHDq7l&_KHMN<<M0j^=@C5jdTeGNAj<U1&bsK8xT-%9W|@7<e{9nvMtjt`I@ z-oHtC0`_E}VHi~U;22dCkg@0n3fLIJ&0wMrFN8W~_U%R1HfU1>@h7CDddsyaga)nS ztN$bUoA&-Puk$+tE{PDkY(aD0+OW6o&zeu2KBCyXZ!Y`dJ$G2S{+n``?mKK<q<!+D zM)ofd0ESa$IZ-9ufzXDN&8FVEkF12V$4?9%eKnv!bhLD*Gdk@5<69(N69(w<(iWb9 z9XM+_8uV12dvc*Rh~UA@eKo;BQW<#kb*~1sPcBEe_ZK;Ov>ot(=dQERUJnUSa!cl$ zg<&gb0huU?skORKd~v^2z)S=NNAUe!zWj`bUsBQ-EU*jzLB{*D2@1LAFtkaSa_;br z_@VI}5)IsIpO7jt$zT2EGHOVx-No<X@m*AT_kme~){;FJbrx41j6CEn^rmMbizHCY zsaGwMxMpRG54n1X4MW=Ddr4mh3Kh5aJE4|<YC8*t<T7-hvZ^%4K{90mgsQ3IAj@)0 z=vP0;9AmC86*S60rVa6I1$=qJc?(M@1*Aq^4TW$PK?p1kx*Z-c`A}yJV68X)4jK~B zDWRe5w*OAQ3zlan-4{(FA)_CxRq8me)tU6Fs;Yu|rl0!`N}GtFp2x#kPVjryZW?p$ z82|iY)=y7oRWrWV|8q*&@S8nIg|cx5^Ibt~G2anuvqf~vnF3U69F{THTQNeaZ@8Sc zaULZ(w>oa6eWSL3X1SD7yP4BO-%aIzAp)ZuV5Bn|S38W%z)lAK7OdyMTq(L#Qc}o; zUqKmz<Pzczf)fL@Q0f9Qzpa6lV?N@#QMPGvO(3f}4!}>CYd(&*LiCzm(?UP}DDzE^ z_i@k3Ns+^iEL-E`ym`<-dqzv$NdYy`qiHxjin=4Pvk;Ty1$T36q!ltGTwMe|GT?^@ z0z;a`{zZ#d-)Y;{p$OH-SAmf7k5fk^AFm3PU&d|->LH5So99bT(s5CVPWHVlCwBOY zF7;%$V;YC1u{K;D=@AujrgaOBr_>B2N-cP)bDN*0KRuS<KjOccyiFS)5cF!I)kD5T z)UV=V%}#_D-ZV&b8x9loKK`a*R62PYkp#j)YTui04cb+&mCmQBk^MK%Atprm0wlZ@ zEPeHWO+YT+GEA>BFed*$rH9EK-wW#gwIFUmJHR$>{G~zQ5)o*nnCo0x>DMByPDF8$ zzWkd!8rmx>?VE9N(>bg8%dl`KplT;6amS%@wePPt*?IunW(HK7vrSW(<h<g#$`s_+ zjWj$rkN;O%IFulD^~=jMkeOUAfX{)cYe;hs645cyeb7cDDH?zw7#TwXXa>yMNcSes z4My2VBW@)gI81j<_2eZsM?)hv4YM#7Z6xzXWZWjSHKNYe&?qqz5L3~;(rsmR)%j4s ziOVmwCmmB?{UZRA|Gp-O5`TJJL5W``70T^#G<wdGmwq?*%`Tz&Cbpe@D_@5O%Sex% zT)kxZOc+t()zuOTDeM8kOHrP(!a`<}7aw0U($8bqcnhZdsh%Y-l|uF_05}z0$lN32 zIJPKGU0pFMoWgsA#d;OiJ9;zH@y;)0Rqz2D8(DLQVYx$v9=EsxnaSzG_+?#Aph!Wl zc6u*Dnu1feUL3Ndk$FOzn!yl53`s!140po*z|buntGVTZ5(ax4Bp({SOM&zfFUZeu zTbsWMTqBUeU|5M0d!X;`K>EMpij`mkKP2*F;fI|4PBaWH?&hzcA0qulx`{bDK6_M$ zO7J2FV=qZCZHB^^e%rprdl<g--6@l;9-9)DeqKJ2H{CTKz!0qa=g+$hU)RG_9}lq~ z&tO*TJCMCx{aF8HXyTu%v&^mXYS@eGN>0)qMPlPo2SLA&gvj}}IR<mdWwf>F0-_Bk zypboOLTq_mZEp(+YcSQi!#-CgeCDsM3$=nMmc{=+&fWqls<n+D#STzD15pq-Do6>a zlr#n+AYGE9(lvw(NP~sS0dy$o?ii(pMny$HLTZGeq+tk&Vd%NfM$f0`{=a+IU3b=E z9Zzlc?ES{`KEL|(rjn|0XS7+T)^``60NS(6!CV=43}z8jk4Ick6~%GZ;1wNBmdorn zf1%AR1!=*yq0Z-&PZI-i_Aq0q!)9kKhX!kf7C#YkpvM{hrfZtXp%H`p=*WxVAg!BS z!LGYd9efYYsr<s`pq)LrwQgRTKN4DT4*;&)iLW@kI>ypWPi(u~*R`Wk!p7buZqR9- z4^Ar#y%$#Fo&$L=IgIV^^kEx6sp!$nHI9&@U7LrYb0Hfj3Va_p2kXKq;>n#`EdPb^ zX*%}42A==tMJ~sh`;l=P*&%PQ04BPGtGbSzi2VisG40u<&qzn(JydKn+nPd}nTw1} zlh2lkN_k`yZxFg)#?vYIW-t*d0yW-8;7fY`#q1k^)P8=fcfj%VTtpc~j=_A>7DLxg zvyy4!>`V}pE*L%VKzN}wZvQ~x1sdVE@wh4@S0kV5*%l!LVSi4n`Wywof*EUXDpb(0 zZTxdZ_-i%58*eo@N-w~XS0URZVYfn;@YTmB3_Sl4Hy|5|8M@Tz!OV$;1h^u(Cf!wY zKKGQj;Zlm?e!-vk=&uX<BKy;AmbT;%2Zqet6?0V{Fr8g0KjjoLy7~n@(P|808a&q_ z-&J(akGV2xnmo@JpXEjL$MwRN2iG$GZhMJS?w3UWfsND9tUm#&T|>&p%EY88R8Ejz z)aN0MFZpoX$2Tv-dAvPM{i$3cO}j3EzEqvQPcrqrXD=hY+I+6xlARaI%HO9Ln9sjI z-p~{D<>*Q6`gy)j*nMx9b9^A}nRLN_%9WexCv$g;L<7#*E{a@Eb5k;R>vERBBs#|a zK6Ckdh=-|rPX}u6?<>k4fPR=ShlY3LDTJAGL9ND&gI_~u@N~Q$bi$&5@d;IGJEtyv zSzar4_R~k7)M0~~pD$wJUytss9x!nSD((%}@=DEM;6;Sr=z(*>u03AnSG%u`k2X#7 zDeg>=-ePHrTU~#=60DSNMJUrfcjHkTc_^O~*gbdt_2ioN!+aa-{T|QRAmkP!qSD(3 z8k`~ixyW8(L5RDMjV(|XFkL^koe{>g(w(^IIVyv@uTRu%F6LrTiP(A->y2Aj&_7=` zh5?3OQ+7o%Z&-9b6s;L%l1-8ybD8+-7Mr%yU2Qh*R8oHUFo$+`LemLgXvUS1O80a0 zPiI@$km@bYDLxh~vL|^cN~{+^>G=C|$pp?)F`{V`om+%&x^|7n69xc7XEmRbymX_0 zpOi{dgYes8%6R!%^>yYq8vD6{GnvE|p;Exb(9}sE-*YC?oXq%#m`ZI29IhSufJ7d0 zMy3yL^rHr49k)LymmEp9?7T(4G_&>HKQb`VcjS1CY3a}R0#EE%>H`_m|1m>+1+RQ% zeCzhzWfZ8~=`aMvZ}-<9auUn;G&hkb>Sz%;1ScmoqEV}fS}I3BEEX_1&J>@E&BMN@ zgErgmk3%=0VV49z;-vwM33$UQKe)^lP?2d37UH1R!0ffLR6k2oq}|WILul=tF0|@R zy!A6MD9PLEJj>DWMjHD!ga7^P?2u=7FKGRK>Z}L6tc<IQ0S9><H~6FrZbxs8=l_&9 zCTY=FM^_o`9!CX#(e(Yk#^?A&l@^)Au-uF(PBqW+O#gu8`1gH+KK5JgL0|++tS^{G zrom#AVS@C*7E1^WU&(|cqC}znUlIAxtbq%x)v|Ui$(r%`SbJalI#KjmQa%=Er5{Q+ z)(USXIhtB#wA#3@iDoi=F~`trxlw;QNFw9I8LRq60j;%8zV<hEN=6tt86&|I)MMQ5 zc#pR$z@vUE7Ut@l3Pe??>M`w!@vK_68opb%r1-mv{Hwu~aF+BnGk8=*PtB^%l`J2^ zwbFSfQr?x@eL<33wk`l-tlNq0f7@<&HLa~WuUrokH<HFpOK(aIGY5oEK5*e9e~UG7 zrZnotFG+!|s}9aM7i{6VfawjG2axt)PkV@XMPWd#R9^&MEAHUe0a_nYENJSLUHjb9 z5$doZ-gCu?&!|l6p#N1Y($oC~ECHK%Hj^<jGEyIM7(m8fSpX94UKb=|x5y^2>31bZ za1c7+d+(D_ulV8-Ii?tc3l01)5fNfJ^n%Jt<T~WG(~xx|4)zMU)^G3H?x}QjU%514 zGWcwrkkm1bnw9y5=jkKPM`3aImFwK7kdNpQl4J8OD85oh!5<Dj*|wv(B6H5iOMT_> z$8^tN<!BKrFrz@+Q$YWLY~l)7h%p3H1+e=Nn0!bto#8x<<xmoGoiU70%3()Lr@=G` z6cQgr3!sA%f%4Wvd9S46xeTQHOB|EaRO9*6+uZ6`hK7a^7$_bv6nJ`8AjgJWMZ3Vp z-`|rFnVe0g9~vWmPR=38ywlTbGp^E{4sZ^Sj9AhN*!>QwcC|L=i5BIB%_U=)R$E)K zfokYcb4$W%1Sme<Zs!%9Y1ek$xLSMho{CNHSifECXNkDb<igeWR*sHuq}P93jjXK} zod!xRP%x$83oC>0eBK!Ez2OegWkic<@Jm6m-xSRHn^nN68Cuq@P<#PL7X@`~Zqn&~ z(NeGVxms`peu;!dBIX@Y7fhZ&{m;K;H~_k!fkx+xD=RBo>{UV#^s<qQApLMo62E@o z4KSn-=Kp<YF@hG%TQOuIS&87x4f1nO;<E8SXdgW#NK3oF9Yl?FthaB4?w3_=eS_g_ zTqAnq6Q`sX9(q)9^RBq}9OHP%;H|fYJ^3+RcX5YWIg3JL`v<C<0&8<*Wv0nm-wyZ1 zQhatLKX{V4_Bi^3EJ+A}CB%7b61v9F=n^vja$IV2d8p5Z08UyP-~JICsk{82f+H+D z*bsu6=RR1iG9r#ETmBSChBcxTf&|1|c~-Y;UaN~Q*+H0wkb^r$Q4rE+n3o?C1fBi= z16#S?Md^(9T8hMb8ffPKxBh6?Mi#Im+|`m>yw(e9!6_e`w2kYX;`JhaoR@NP)CGb- z2Df<OWClLn=N9nlxLh9VREP#)?WKmfn!XCyP|aY|8~eJW`HQZ(%BJ4*+>!-vk<(C< zHI5k)Jd8c(<NyaMdv61{S|acV&nV;*eKyJ<9W|lGpI!+d0;UuY_O0eHU%2}S1Xt_| z5Rf`|ESw&kfcQp(*kp_^U%uQ2rM)GhSzEJ3)J~<qOKOTWi%0!GfE?C0|8GixYGhOQ z>bKFUm6a;=A#;f-wE}ThuBbC?T3<hOuWv`UoJ&h}x(|CfUyFq|e8X_QlV^f!&D1a6 zvLmeO{@U5cF0Ush>ldS=QA_UAH5?X|@+;8thH%!UaN{+~ENUVOl!A&_Af|@J8ZD*O zBiwl`bjg8m%$q|CgnLud6n1WibVa*%*rUM(PhDTXi_(hd93VZ}LAly{1B8A}%*@ON zCV#vkM3A-I`#m@Kv(O61xtuo?qVz>6XgBn)x@x9>3WVzLEsvdkVcUC78J&b){BZQi z>NKFL^A~ZQu-*>6E{V>H+sG?=_dvC3foR-7u-Da4Ts?sk;NoflK^*%8wX1w#oU37N zV~8La!jS)lU3UA<Q#p6`?7F6<rgb!%D{Ph5(lN7GuDzJ&f&S6<)efCE`+4*u_TMV1 zKfU+v<!k>rdim;J8{bFlru}u|kz*A3sIM0yAIW|W8QBo`KjS%CHEa0&{@w;*${G7v zwrc6H2;I%i4)X%;)2EX@RYIR7LQ5|um*>0AH0}QV8nUvoMN-hLQH^i&crT}|M@eTR zjlsAu1bW{Fp8Gdv*Rl>ab4#_yCx~GYo=bScZ5H+F*tBInLV06_orsi_`HOCM54Uf- z5>h965(E0&r@Y)eR!SN}f^9py37neqkJ-6hhz&iHw1wNt?*<Ef(@V3mrc^Bp_EnoV zGU+C|fVw8ntz)`)OA^II(P1$CNje6D9pF^6*Hxyh-P3+N2%YM%@Njp-2*@uLuWfVF z9x=|GKii-72R)Yq>dJ)6u|4H)C-?f!V+q`RO&j5#&ilwnd3zUT$#9*JRcgDyu4PXh zxw>+{Ji=3zbxqL*6`!+T{+V1|OZ%nzfFhfrD^ST?stw{y6`pddvv4uCwar1)dkWA0 z{#y&g8b-J-+b|!gBhVHD6_R)}`1rlhawFve>#eIzJB|E7NI5Lb%{y7C!yDYxPn^)R zcrrCLbvESp>3-`j-yJoZ)$y)(hhGM*vR?Wut}zdM*VET7QC(C?SP3lYSgu|n&#VUz zlcq@`GHz46Uir?4IZ#>!vm{;ZP@h()SDO+Srz9Jim6Vk`kO&LyW7ZapQ6oHMn=$Dt zsw-=21c`@tj^{Buk>=Z?J*4*0(dEpUw2v76*2h>{A#e6PCq>!{v-54^J5~A2q>2_h zkxKiN>yL^G;P`TnoBefVUo7?Ix@Rx#HLGV5<hoV`r%(pHP&(zvf~1@M-b+B*pozJ9 zD7IU4-0gcJSwaA+2}IP4#D7l2dCVZ$n8c|0c_)Qdz?eg$qYcI)0og~dsl;6RF5Z6x zLQ6CTR}KhhuPL`_0cSY&1eml%|FN)yg9OQUx4MSItx`^DIOGg`nmE_yM^0vMn}|Ar zWtEZ9k6qtDYVmiEcNP=oIi>S-<{NKx=L+MDFV`^^iT`Mn(S8+z@Q}xDnBKqjFpiK+ znuw1G3rj_e@R1tEnUssq0+XbUPV!7Ik?d98YfOrSsR26Ii*z+b%|eah1v~fbf!@c5 zAtVV5<2@DsJSZr<UFi4fQD_RQhtSiI3&BcRYiyQ&pLDQ{>5pPvOB-Q!Ok`eoIBYl6 z@K?*>oka&);U0CEtBcVKf2Z{7Z`6<Q2=FbwK9Vu)EWX(IWCaRThoHZiPxRilaPx4p zY9FXdFA@<ICFBl!fEO4EgvL3Jxz#=+%-TS{2RA4i!y{~Lv#Z|PV#ToaV|nZed=N@o zTq~r^BIa}rYbYl9hKM-2VM9SVH53II5(F`As@?wIvJ3r-Oe!=@`dyhj&Dc<Iw0fKT z<qVFO@<9==*PKx7Zn-=WCPX7-v~AN*fAd3@HAjC=h)2<CScA3>)<XTFkf?vvTEzUt zU?|AmiaD&cKbxNy--x!hxmUxG%+PtNqzMC}0z@*C4NaO}SJDGo{vRcq>G%m~e`|Xn zN#Fg|DC{talszy|PX~!L*p%nb_X7`JiwLG#Gd$CvPbunTcHOakJG2@l6f|sYZ39K8 zS;d`iXpA&gKo*Yj+25sy5>ig<NtC)Knu<g9)XwAGa5RjewEw1y9zmsSvtlpIu1f}X z>)qBL-)rx;JTflQEMBUc9ey)mIKcgaa(Y$Q4@P7O*i-hXxDA)b>e@L53g9lmyxe=e zs!CPR`T`Ri0w5LEy+<I41XNI4ew{doHpLU5Cd5FeYbzk3qOy`h0W7V+n>K=d0;w}~ zntGvt1eZH@1<2ZVY^0^7MS`p+AS}W)%nES9mc*+Z3eZ#)2l+8k4`vAxLY7jm;h^33 z>399y(haQ#2c7x=RUY0=KDgI(GirC@#aJ_RfehVqjrbR`^b#~e+M89I?)KlUcNOn* ziXKa0Ysum`qNN{d2QSP*zKV)>YR&4uzAs_LWAnR2dx1fEf%wqZe$}>>hwg;3v!bH9 z!P2W4q_h2qjyWmm3V0GZtrbHeFuV#Sc%4`trD6c<ic;#C(crM_2t=wISm665jK%x( zkuRK8i5Xw5s;;hvj23<caqsmKKozEVYQ2H6@{{m_#+Qc$0=Q4^w!tC6C*7~_JhYJp z!8M_=6il&NVTU)2Cp_3itEI26Z)ark$EsylkppKoH>E%?{j`bK;=3L6Po_qSS4{Ab zOV_KhbPCvr#um-wJ(I=C<)J7Yw4E$X`p4#4Ro-KH>S_iQ`Sh)a@i9VU{$r$|^0XoK zRbCnSYIX>X<?VNVc8h%r^pp7pZ0hea2i<3@M_XS;c@Wyg2@sE4UY`Y)vqzGl+z2LF ze0i0)l?o^1G<*YzM+ci+9W*)*MDZ`JNt|F0u+SvYY$pP0FfcDf#IzSKTtG5=v!<gV zozBzK(@;j*W$G1aZRpd+eWIiPK^CNlMbu?L@DQk4PD1RvKAI_j3I*J-LVB9)zx?hn z<{l7*1GY&}>rJzh-W`+2Wh;-SpgZecarT(Ata}y>Jh1GdtAXRNN(3$#r*qCQ_l56& z@NUMVhjR5jGoRB6o>P1hKKQLKIP7I1(t&I8OWbH`3!=ogB}l&{cT?U@i;maG-7_ud z*wE#ws;VN3uZ`{M>|Y-hEd%LKcCH{DLZZXX34^s7l1&HLQPz?^Frq<Nlns^%rRL!6 z3gTESyNrws*f7`FHNU!G;@m7n`P`5_U-?~zZw2brkE?C*n_5H7awdNi8-XP-eNQO$ zQgUuu==IY2ojuE8UiIKTPKy|nY*g@$<?14Fn-sae>OO$y8G-l+yw15>xh{Uwy`#Ij zYK!Jal(<%s-g%aP7bsg@5=NHNgNs2^Nw{#C<m&1o4W)kSP40;}d%yVe?yp%ZhIT6- zms&1t4u)r(jf?AzK83tEQ2X-;3u{YDOM^unm?Ih4@G*gq3)pSkFfTyY3yW!AUmtL? zl!}TVWvBjg#(I<+jO+#?vAjD9PL>D_p%pGOJTj6BJ0D~W*Y)@JxBl_|kPfj$O42#q z6aL2xSaw`8*(1%Io~S8kM%m}mm`0vSn=NoEIs^P0QyS~Lcn_<O?>ns7+TYn312327 z22`B-Nsl&2q27ZAk1-PcVB^xX%}0i<v3%{Ulyhz1sx!&8+vEJ@ecTiEbuy_l-xDVf zv8FvU@z0udI}~oVNG3yxyn$v7hm5uVKqypu*(k8{Ak!Gg@k~H=ss$PWSX<1Hn;iIm zEB*_wBS)B*g*ya3PjG?Hg2QOc!D*`Vqa+_kwI_F61KF6xWL<6hQbRRA9(%ImhbDB5 z8{%(e2E9u}FTAf{&-Gk6%rMFUr2}6VJ!;+Ph(!)eUf+A48yfO#YTqizgD=icE&wXQ zrWSP@6M7v0)YA%pQR{;F`Nu7T|E=DQ8e?;_%1#>kn4l}EY`07?bOSkI$3BpjmkfH$ zH;rASq}*SuPr1;S(+Hg{Z_G1WkkLtBitQZ@^>obpSnK(jilWg^0qfZD$Bf1;V0nG6 z=KN1`^VY?E#gPWO{lp%Wj+|az#|7WrFTHF_^Mm<ZqcQZh$)#sj^+NZ`GDP2LlUSf8 zH?j2EGoRzR(NP~EpniGDF#ww=d|o;IZt>Pp;1cKh#>U9>v>g;5|9oP0BgFNOdg?ia zC1cPR70NIndgr!Yp}Zd``JvW(w4)J->wpmweOA;CB^n{O{q@zLOI6-{>vmY{e}D8Z zAQ$3T_@N=DC<r^9P)SMA)!`g2$LL;$Ud<idd*D7TE8$88!CndI*s}7*09wI9m?5DN zZXijrw5wO5J&Ip|2JG)^(rjH+CE7|nv}_g!)2C^lg<I7@FKJ`!L{t~uRn;J-43{eD z&Rsk76MdxT<4#LZ9HPUHnb~v<DsitQef?<bb~$YV@!<IHCm{^l?gNEpEN+@3AE6hp zEk-c?q6?Q>^GUqkQ(W+|ASSNpJJ1WTH0pbWzcTii;`H-^*nRa1GSCk!G=J=-@H}{> zWvfGLISBklZQ~g=M}-M7J(Rk7;viN7*vIXa2$vr|vH^o;7#f;JdFvjk9?P~%V;Yo= z_y;vO9ocjx!-8$o4~1;hLXH0xv%PaMVZ;N|RNbC!V~^L<Q;5^yi%fvRhEH*qR^KGE z@bKBK2QzR|Z)IXk-09rq%I1J}Ob9=Y(D&fIrn^svcxswOnYrIKJIv59FT>Z=Ha%QK zN-)7rtLGhCJo+x4h*|l_Xg%EGN3Q?n8kOKScpXKPKBD!>CG6Ob66eB$dqh=UBnuJk zL{cpt@gJlw;yTnaU%5CY+Af-3P0Yz*SItJ1#$W}`MTD1VX4c|irGT$^Ag3hdngI1) z<PyuJoYvNh3^6=egw2>9$;$O+Gjys^X8xD8P7k(;TX$Raa>1`esZamA&U_dTm}<Os z%NDWgRmW9qJu4cTC{7qdDoUTer|QVlFul}VBODB~67Na7C%>pkc`E|+R{cCVA5Y~S z9tRww!y=AZlX)X}&sgCBIdGM+b?ci%@BvF%|6o=EEv_oJr^1u)C1dOaTV7WJlyHc2 z!8pZ@LRAq2BT!flu#1~ns@gLSF>|X_@0Ftbdrm-l+;As-_n2*E^Kp&7B2gH@?p0|M ztfA3Hie&nEld|_f7%m$d6Li{)6In4@GU}hJjDPF2LJOkGjZ}kK*?k1c<uZN4$4a{d ztZvMHM+?g9z3i-T-^GCv;;y}`%OgVq@-kekg(irDePTm9zJ9{Fo=_`qa{XW~<%C$N zTm9!OPo|dTfa??Mcfi8^du)v}sgN6%c{m-cQC*qsy$BFv<FyCcDDKVyE#wgXh(_~} z>UiADt4*bql~qNoi#Mf4Z~f-4$7*>HQG;l9e#M*VghET#(pl^o8~0F41G?Zx@us`& zFbx!;d=2l*scA1a<jWgRn#rx2POztP%oK7ls0p??^O%zYwi?y4JI23CT}fmi@?PRn zqx502%j6yr*8YAdA5<r#3~1z`tGml8J5x0?NS(b`<%8qDu71fm8Oy^H&K@Y{^NQ#W z8?@iX+6`<_{0)d}%yISpb%%|6U<1Oex_v!lseHIPG8J2K3Ewr|#3EFwnj-hiH~jlt zzjSiI6T?A~Y=_YCkkk<8`ER<%Qny>X4n+H8y?+-S4;PA(0NpV0M4J$4X<~k9UZXU* zqR%2FB~=NFyhvQIY7wE_`Cu43OcZ$HogQA+*TJ4T6m$yLB2+p$<y~^mfvzVsE8&M$ z<-)H{nWZ%H=(N?BTzQ&$E#NGou_hyhQjvd2oGRXw5=t?73b!{p{YE0Lm7|9LUbOZl z#lj_W9W0V5VG*&d-=!L0i2)e&?Arz~_uaL-Fn5mpIqwiQ1>33-nWi^OcJUZN^{%bn zZ)lj&w)46_b{-6K5Taaue!-gQucsqq1v_0k&%zH9Op9}4&POK(EEvJ3FbbadF2-xw z$?>?yb-tq(efDuJj}GaUG{!KP>94Jta<FyTs`Csiew-elT!(8dt4I1{?X=Yi=mLd{ zO`cw*SFw6EtM!Ag?;M|B$}-;hYng0uf-Ps@rJj0Lj>#;XqAU+T&!>!kaHW(rZuhDn zw~zbH7tf6xy~J`4y%KOXsI1#=G>5A#-QHNWj<NB&{`-R?<|p&F*4(J4t@-o%C>+ml z+{7x(K(WS2x&HWzbjh8BU)ZXUeMJYGuY6Z+M8gCZ{7)^WDQwIB4{A8MxjeBpof7P7 z^ap0MAD1ry-eI{qQ|%U%$8;~3_+`R*yiF9RJLq=+MnTifsU?oG@v^aB&-$<P33j=- zh_DD!y6AkTYbDGK+b3h9$D`9$s-=V_fM%1+_DlLF+lHWs@+bTw^jWr9Ivunx(|?$r zR!0>0B3zzh!#Q2|xug402sFi`^49F*l1cn=lOlq#4BbDLv=pl>!w-6|6@M~Z(Cw=9 z1mVxXxnZ+Ws|J5+2WXoVRd2RsR$ReMF{P>WN?3hMJtH)g|1y7WcsGsjo*-C_G#nKa z0&$#YwKrM(dd)*j+daJG9&2K?bY|2Z7hG{EUn8W1whIA8;lvYln?wKXCku!QAW)Gu zXk2TQ0CO@br9^eN&5r||rr#=z3f7)1e*Io?g{7YF_4yMmi|cnLH-y7IMXNjtf@Td& zU@T09h7C_xe(`DdSf&<;@Anma5fYc|8h8IHQO7=P$Rb!(^_!0&ws0m;c(T2+ATM56 zTer^%Qz>&D=v9d6H*oN{BqR*X%*=oQtN|2HOw9q&3?Pc7dvyZ41c{*ruat2x+xiN| z!q$dJ(;tKxDga4fdDw=$zdvT2Bvfx=ifZ2yIN%h5#6v<e(y#zbm=RMjXl&1w2#AR2 z%vLM}!LKkZfRooGWTI<=Pe85L0WeTvQi@PX?DpX@o`~$?alJG=J+i4g&54kN@32Tf zI&g=F*H}vsVoRP_xOfv2Fg{o;y<!^0URPUdFn#5L<mgma!I+hgO3x+|lm#ClWf+69 zfvxmarkI@xbxxrv+};gjw4gwAV)}J@trx*~e<NAaf`2B36cMq}ZD$^(V&_RQ|5&?T zo1`UM^OU$!)&WdIKQAI>QZ=HnHJn~ln|Ec?Q2%b0vDXg{Dc3Pg9{zLU)4^{b4FX9N zhM@3NFv*5k-Lskb8JNX!btF_1X-24$a=@Ag@oWQQWgXD_Jb#`wb{-C36+a#z0X(|u z#nx4JL=lA9HBuzmx-kYhiAmsiQHn6yAwbn<jo4pk))3A_$u%n1p@MN*k7AXEnYtU` zL6BK}X$+C4@Nn~Km)3k=b*#>a`?agkvpO0?qtr6m7jG(P1kV^XTYA+VoIcu89LR1( zpnroVK{ss5uLi(~gVS!Bza$YY?-4F_AXH}z)HEnf&+-Yl#kLN{VWKfV7CIi#CYcE$ zWL)K17Q#l=C+ut*172fZF5t!CYPnrv9ZEJdQF*h~-*T&Odfh5LAx7@Tdo}91FFq0D z5y&lf&<C40_#&{cY_%_DKm!2*n7Tm6b;>1z$=}jUufdobu5u|Vn`^2Lo@)9Qbq{hN zw_;2n!xKSY*b(dPX6dyYUQIi&Ttocg$~zIziI$PS9irt2d0z4XuMm#APDH%xtZ}Y! zrM||9T?Hb_0_}^i<KQ)gu*ZcKac*h)>ZPX;)^#D(p<=UmIexX;=Uj&?mAAK;cAt)= z{}MJuRm3|nB_tD@0!3iu#%%D2vpBGko?N3yB$MF;gPJwQrj$ICFWeyZ=1EdlOdrnA z^Tu-tIp3z<+nD&Z;k-T$J7LH0Ngou$2-16ts@Q7BdIS?~9cus6I7O&Qx+dG^P>ZQ1 zEM}wcv4IzVZi%+Piva%YQHO&c&<3`coiyp(yd0X%)J-b%@R}{DUtgVZ_v*un6QB!g z1BTvUb=(foJHj4IwqT@p6FOE%L=G9^4@x=#vnlE<sM=h$fqqX%Sz1ZSEpTE9W9L49 zUJdb$*-dvm0VuoURckYC06zWf4?&+Kc16^#o4uBb&W-`?8sfm%(xMi~BB2ApC@<%# zMGFzX>Ad+|@Wuv9NoXQ<gXbdRvWEbC0E3l56f3&|q@qA*>w;JVXi+q}sc0gIdZf;j zmyT-Y#c_e-5(M2Zd9aZ_rp}JfDs5)2Ke(dMI)3P?5q>_dZk3mxC3_%27UJ`8E|ZAj zU66WTc~7ubUs)etMZs<=?)a}`Pr?YIEROneMkzOlMu>S2Ay`MwEfHL~`fmiz^t?;D z=39i0boL13=ogSK3Bd~J$L#2@;;`5i9J(j!p)TvX|Ni{una01F`;BlgevQV;UY?Pk z1YdN`2!5li%1*E(0cx5OVt6hY_Y$lreKtraYzor40(?_A4>q8T>{lM3X=(r)N^%s$ zmyCoP7_wP_jZx94h_YtC54Dm#6MA)d#QWLKAh|;9PS^oBQdn6DlZl7(ySU@vBX+CB z@voC#Yc`bak^Bwt)MK{-05C5fa}`7sPc$$dE6pHtSHeEnzN4L={hRRYx5U_)81Ino z<uwKD{{5<@#?j}|g=ha}o_103B0x()rf10pGu^7UB|z~{z5+STt^&Om?dnf>#ci#W zP-8KI9&%@bHjhMD#)Cou<iN<RVi9>Thb?uy&Vys9meMRK;^aH?twM=A{W;&wJwka_ zN76~fsP(+=^#J;r_D%b~!oLnVpu=M7+uwL)x7+;CLR4uV>rA*;XBO<4hjWT>xYiaW z|M-p*+W0~DyHRP!z^)RC2jJ^%AfZu$&61i!-N<CmI+uoc!+A*k^_MK@&p>dZ4)6%+ zOB6Uja!FO@e?G>-Vl-3+(u#=yfhq(7Kw5%8A>{_bw)Qs`>5A3nKxi>QBDe^;C*$wG z=^&Un1DMkXqF88}I(?<pnOf3UadH|XxQ5IL$UeODaJQC6rHQ{w8FeNS6#5!^Zl!c5 zCR@3+L<|~TZQETd;a!q-HAAB#aPN~&D`=Dt+%B>k@;MvN^Yi)nnm=Xs+E!9`>BE@} zzg3>P0L}MJ<-fZGTxSx(UWquCdArtl0j%r2xCe@iuY)cXXqeQP<*8WA0hi7h>Ws#x zXN!V;C=gm8u8CMY-Zjt$iJA@#J*v<OEnGf(duY3t$Uwi^E&Dzo9<VBARRXyaBzgDr zyRz!bkO*!n6XDvmYbEHe+*Nz+-B6l8efpG%q8)2-{7H5W@ddI|)PJd0cT~uPQ~T${ z9a4F;q;Hpv%AIwfUS?G)w<wTizjOondjfwf_sTCGP%a%TVCaiO+$P&BPA_~W)hn-m zw(FF79XJ{^ZlQiUVeV$>a2k_R6;X$(zE)g)_cHt=c9u;;xm}sC+^Gee>1RW~E&$fK z=a<NM{C_dI4rA3DH(DS)heH7|_Cc1O4o}+GR#D>4<1g4L*qLT+hUW_l3*dM=>1YHN zwxpA)W7=UJ9PqC7T7&WXqtm$Cglu|rwP!HmvEUzR|6_{Afgd;oSte^POwyP1tE8oM zYJZibE&E|-8yIws(MaF)!TLNMBP!6`KSmu1gmFJC!pz8;#Vuu1)kSByFU`;?WM-oS zP<Z4ET|n{Y|8=P4^G!{pr`^F#(|(%o&7Fp2t7ldgg-BTgAooioSUL+zCNvH-8pvLc zO#y#KsD6^01he<Q1zgxU%t{L6tx#pLqHx`ymH|^E()zcqt}g6w+2e~a+`%0TGXoky z%dKw#=ZX#^{HCI=@^Op*TCn6Eg%`muf-9apxskB@W?%NU5K7j)#jEp6^my@OEjd#t z(VI>CDa23a2cEb3E?ovP6|_rhjde}xT*t~v;Rus;vJ1|-mi6-&@A1h9Ko1g$Z_v`q zh!wWcDKc=Ul5sxVGBPN@=s}l>#*c~YtT}HeI@~$pEbVgp_U%BnWd6-fvQLkv*B`)? z5OS9JEMuB*`pJg&L;IUL{k&CLwHXqol!L`^Tf@*j!k8{}K)#jjo5u5t!x?_oV-07d zzd9L8Es0B=-*{=gU=%Nv*c%=9=C4DyV+%jT@_bQ1T0HdKt~1}>juqhus}Ly2ck8t* z>?YV0kC{^W%a>>Dw+8^JeQBBqj*~{Nv7oY4AJUT%7zjtA`u@QFGzRC$SsUP*c<NMQ zX8}8Wzka@&Eu_%EbzfOYNy)oEI*<s+*3SKxZOmzTfsPlbv}^(gTecB}+3cHFZqP0v zy<M5n&KF1b{kOA3wCZu%Erf|cIfSvk+I&h^N~KnKv<a>*71TnX=N9Ql90Q#21}@*i zzkVWx^B8M0j{YCGAQ}<dlYu~_m{l>22X%uuY$zlH81va$(Jx*Mte#b<^q|0tdX%dK z3VZ-DC97Bu9XeIs>)jo10NMb9Ct2%77hq>~Uwm=rII`IN`Xq4Jd>fP9Zdn}XzRVC9 zd)_dapXsy=HA<=CNu&I!-aOqKc#^hyTzbqSD%aZbMTQiwQ;|*ARp^B5xGyX)9QA(O z?Q(J`>VPF%N_mopwSsL097_uXy@#(gt~EXYpzf6bqZJG-II`uq4zE#!ZQox-=KRC) z3l9q^*=$V1=LGBp$ShxH3p+<gN6W%I?W;Fjj2zzW>ga^r^^BaHn;IjzWzCX9E9UD^ zxmW@{2I^NR<+Olx%&y&+X8^N*)sdl12s8Zokb=|5j}K^k!*YLgE9i8D?|yh{Z3BNW z8q?Y!^!EeC=PVu;8L4M-N>qBYwx6oQ;K6+H59IDsU=>YhNLYGvr)O$)4>c)Ioa(Z% z(o}8TEb8cVNm53-V}>OsNFATqJVNal;C}Y}_-0ObA#?ZBOuw|*w-$`qN#~mFTr{;r zjZU(HP1V4Zp``5t*79j?-F+GLRns_2;-ri|bQ+m1YF6nQkKTa>U&gx+6S{RXm{rk^ zPV>d#H~VL9Q5y6Ag;x@8f$1Wue^rL><9Rwa4-Z}*9z_ka%a_3FvAYbq`+y9AI>u#M zpA=XQ@?0>>i)H5)5h?x@?LyBYKD@dN<sP=jetS?rKsJKPB50?^$QaYfljjuvH57)R zIk;-uD1rwxS6rvODhP2f8X*{FM5AL<jJ?VlUY`)2p`ec>HtpEVL4F1+E{&WtNXs#y zYIJ2D2|UDRS@uUqe$M2=otdZJ;>He&&vwZ{M}BfF=~Tq{oJ4%)o8h$)d7sx@3@wEx z`wFg{;gkkB7mZ9?o~B1&v{Po)@<6o(CJ46Hr6v-|kkW?5!JiR1B`$u<z&AN5X%V~- zJUn~Rc+yvSHf>O+n*V~spkW3%NRvc74vMj1hf9l~6F`zm(5P%tbkBGh-~BJI*y4rM zVJ8L0=z26B1gu&Bsl%v3a?C){8U~u69eWOD03M$w^#=qB<Q@(MB$)!NHepN^!8zB+ zdu0TTU-(p8OZxG>Ui8W}d3k_f46sd?eh(^}8W>cC6KyQQO+YJ=HdqLoc_pr@8|zbU z>@&9`_NF3^e2zM>Z9m&;%5G%^wSL}Wp2Ftd{Ix;}#y5WEiG_a|*W&vJMHY&P<i+vJ z^Y#hRBfj_S783#r2lB?U!aONH3uie{1DprF@IBBCl`I*mEAQaWZ_taqFx_0OGyC1k z#wY|zQh7En=pN6)8C?sS*5LA9>P3W*SAe!tdwL83vy6zSwZ{$*4V_WQ!`gQAz;prH zRs=hXj5iYE;}T{fLtVeOby_mhyAO`jc`=BYBuFa?LBDVJ?e#lhHb8Djqdjr~$E^CR zyz-iDz?=bGEOLvR&eIuzxg$^m#t@oc*vprv6cC6x&S%q&umXk)&R*1;f2^`1J>#^6 zP7|4W;w7_|u_Q&MhQ%41Y~<%?55F3|PfBixGf<~|=`yR!@%?+tZ*056m`VK17#5Ll z+*RABZQN=t#;eG*6haeKGG)>L%T$qg48?|Ut|GUZ6)+<D*>5(`eMi@<86~9qP&|K@ z{cUixZv$xJmL8``dt$?FC{mXrMK0Ts2bk}XKa=S*OI~lPY9Dv|$faCK)y3o~si?Sw zX>X~@0a;}w==Qc4Ft!OvRs9dhH8&C<*X(oW6rfzc=j8)oNqMs%{k<$`{-p&niy+RL z3|!DMbZ_oq28LA7MV7|O{0~_71mgM*u<mTm|M9Sx3AWjkxQdwVmCK6~QBHHS!W&UC zHf`ys?D5dC`Mf&|IyVS59rt>wh3{LJx&Q5^blK>v;_m95iR4RFc4dmR!R3wDU1t)k z)DaW8cDwu4w2M7c5iq{!r;UyE=5te>cNXf%FRc@iF?PxRwty6+>$Kd`tUAt1v}Zx7 z(QQG!%N9dj`A8t(jV<EQenpdK`{R9-!`c78LA2jD7cKy45>dD289emSpRZgV3?Qe= zY-E0l5BM+e+Xx(m#fdf>&)lj%*du4qi@Wqol}WBK9h)hSw4~<VHegduomsW|)Jw4X z{CRVJDQ_i$vD`I5e6dWM#l1IceozaDCW%u+4O*e(UcC{TsD}Vu37J|)*}BLOrt-$) z#9tUBut5=YbGMdg20=|qbd96SdnxVjtK|_kZO;v$_GLZUU0|4;=Zz4dB*$9?uQca) z81qJ~%g0wPWaeuYNanFfqBGF1yh3&dGrM<>$;-)2bm*e&o@Vev`2^N1n7l|~n{d!C z0Y8JY=KS#VbS@mTwG0d(lL`(d3au++@v}UKsO@k4c90>$bppt)NDB@^_keIZJUffB z391X>v;nrHqOx*WaBwiBF?N9ErM^-t`L}GXg$W8<{WrrOgg&y}w0*tcy*%UVU9#Y7 zD{?i$@PcA>lv|)XC3tZ;xU6q8wj-0eG1*S_4jX3ET6$wvFTNU7ufid8>udtIWB3@U zWo)QpwtgDsu?ZmXwERyy?V??{3sTy<ecw{)CWW;EHkb8_u=bu`d<v~T=3Z1zm#gzl z!=2|;pLo{Km9qvmYug6=f~#@p)gfwIU_tssIn_J+5wuQaUZ!c5KHfjgl=d1OE9AVs zSMD07NZh&-uwgDxe02%~F0Q4g7YXN*<+&lLJoxp!<*qo_-6#|aitA2~{)s;^d}!h4 zej6>QXe1m-Z)+bVOBA|+JJQ;HoBGBh<bde2TuB}l9Y0d^6tE~Y)MI+LE8nlisonWR zs28ic*;T9iSv|^2<>Gc7v9LE+>pVue?tT-@(@O}($1zE%Ra2etCsoi2k0H(Jx^B3q z&(hhzp|wuSp>k2p`CTeCU%!PN_3|@+J7Y%Jr5n@<KgHsT$#7ByX7iTkXV0L}Kh+nQ zKaW{(ZnvDP>R#*>qaGhI8*!&jW1_qp<1y2ZT_^hOb2W9YqjNpBU#ZO?t_WEDXcv+T zL}f2Yp~D-E*UsGa8)e7zQ#1dvD<I~$-bmOyf4&}?MXA!gYow7qn|e^!*AO+$#Cgvt z?iLc*=NNyBWgCqolc4$ENYW$1SH37&dE~bgKzX+uDj}@CnXldNTXNv)1zK7atGas) zn4x98)eZ*AM1e5TIqUVeA@`ae8V(;i#AlO6nC2Ut$;a0OcKM??YF>-pwI1lXR5&+p zEvkd+7rYYTI&G?cy3nPvY^f8wr$4lJX4A$NTKGseT`cxs0CroWs>`G_g31H3C^=7| zMBwrGKZF+!OvtNj4-f3WwK}J%d6C>+qvYH;E`cEw$`{=u(F0|GQqnidkZ^EJS-1U> zs_^osqZsDW8+H=&H*AG0RHji9T4@u;ah?wMQDi!68}+k=IsoyuX5ZW7DDQ2si@SgO zp|sb6yJFSb6PK#&i=eFwAB)+&-2ZR^e!VL`8syQeTDQ6C$UBIY%)Vk>?JX#C`e5fi z+&9L+c<)-%{`6Y1vG<+*BvFHnyzWdt0*g+>yM+<v;~h_*`8`qBalTSpta2~f4Z2S5 zU;Zj0FU`NEwY=3UL1}6A?++t1D^}IXi@<>5tw-LL{XRz<=vDpxSZ+g}#EZ6x_8FEn zC_)1vKxDGIe}Y1_ugW`qK{FuE(_o*xrfF1KtyGnt`hK=`#sd{IuUCzVH1BMfH#Fc) z&ZO;bQc)R{ufMdIPdxXfUo|+MjSmFdmQrO;Fa+iW9Uww%eC>t1u$d->z!GP1YUQ&z z;9FZD%RhHwIf~qe+EiQ(kAQu5@EzAnJd1PB1Ix&a^w#sQ`mMWKJL+#V<Y82aL5vy1 z&vHzX!rGObIlBIFf~E`B#2e521S6Ik&oPXZM$F1TDr#G-dU=fFip_ue-emWAE=svk zbA~+t>O;^h_|@<z3h5YvG-59;M*cA@0AD`|?}K60#pCaeLz5#~cix2ayQ8WrY>Uxl zp2eMBg>t*x(j~!9z8s<M1k?6^eUUkVjMx1^CD)&PA919=U9=<K_^<Tj&vqgOR5zwW zolQyCEbHEPyS5qxSHhu$4ezEusPdEan&8L&A-72U58YEjBv5?|uk_mzZ7`1n!{efI zsUEhOc`P0gNOec7`j*>zxH&i+?^dL~#wyBdz0S!bNlqz?rRKv_7P@<PVDS=*ocMB= z9M-DL{7Fh}bFdDlj|}NS;>Ue<j9IRm^K2{kbp=-P+{pXI>Yqza?NmcOTa)=8w{S6i ze}J=PKR9CuJw3DMu#kOcKW5}JQE1Gy*=ly?Y8JTI8_tdp)$e%u;Hq@dgtw$225D2j z^#`kP7YQzMT^`PZ<sQA}c9oTj?XNBa&d0%Qf%9^Z-yjLF)iu{vLPN9Az{a@p%1G+t zV;np5(|}21mgZ^y2cv{WR`9ybUQ06<bl}UC5az1}&shwr2~v2;MBeK?X=9_+i6;Ib z)*F&uJKVDx66B9=1U#ISv5F8USEFFU1im_+p||Si!zJ@^WB2DcD7adFRKbu?`pW;h zGF)mCsJ|P%qbC%~5ymHs%CQ?)dN|?G{QDyWx;8(ZQQ|ZNeL1LTYiW&#(2LrPhKfZw zzhiN?nX6Tlh}0v+iLhMHAU&-H7Z=Wswfw-zZzR!tw_QRScN5BLq9M#yp^P|{pBL+_ zY|0pLII)!W;NGwKoYLXd_RM&<&brDiqAYJ+0oRF^d5#ac1^*fjCy?QA5#{ryc5-iE zT1ttQJ>O<<nsSAzsNqGW?0zb4-icPy{=Dt}NvG1&wH2ACs&DExJ5r%2Lw$bjCTeUs z;4>(F;#`~Fj7Yit4L0(=ePA;lmHk%a9WY)Mi{@-dzgeQRF(y`=RqBp+p8R`8K=&ts zL5wv%rzgfU+vL`130_?vpFw3K*RQjS(InQ^2<B>S1;@-<vPgM#w_IO}aYSD00JCO? zS356KL}S0+PyCuCrr3J4dc++c`IE!Q^Vxr1Ohwh#Cjn?~nZ=tk_|Sh*ITIKzD08rE z_Dud^1MF)KeuXX1J<It%P3~2GKeucu<w8AegxQ>49b!=>t=Ur=zGwU>>1)7OUh(Kp zt<tsaNZ_tLig?oQqS$}<V41r`ouARe>+O+2@s<3gFY>Te%$m@N%LOK3s;|flUUtlk z^=lSFq1?r!uDBlY@8O_{42NN&9Snz-;i<kis+2}g4P82F;HLPjHjCJczuK(a4QJa# zG>mpj=ZxD7wNs;JJKWyJk4*QM9y*d-q|m*Q004MN<8D{FuV1{uiR#hl+kOHH2%I{% zqyPHJV?@YgjOMpO=`3S42CHBHYcxax+E92HcJuCqX>XXBdMfFe<m}?fpv(p5krn&| znNg;tE@e@lQfMW5?NCj8#{e_7V{Be|@;Ih^s?V=zW?R#TcjRPkb>nf7=sr=6WC>S@ z<A}N_gObU;RdW5Z-NXN~4YjmhSgT)5AlEluO2H<b`xlog>XbnC4jRjoGM=t#a5Fl! zmdEN98_540rA{8sFz}I)8^ST=x=cT`?z{c%=r^~D?GnMdlm(!z&U4mF7vFTNvoRBI zU=o$oXHPG<xu-K&V{y0=J2&LvjGUzYVcVr$)f^m}&Ss$1;bs5pgPlqp<7?yA#AXIz zXHbCCtY1R|XA4fggY>cRy`3439nI8?I5>IuP})N6!OjfFtEL4fbZY;xU89lZ1<2cy zqpJ6q3FeVGw*X#NK$;w6>^aGTneNlWH^*hE4?W3JHmGJIFuS0NNZ!fam}+$fv(kEn zbv5Jwc)2?Q`{mPt;A5%m0xJ6?W;KS#Q}ZILBM`DqN_o|?3I_wjF}UXeGfL+?r%sm9 zZ4bQL9b>FcmFKhl3s~56WU(59cpybYJ)QbuSUHaekjgu~zJUdeW07*cf?fPN-`t*R zlYy?X%lCF{Gb3*v2fQ0ZPa&WtNt~Lp4GRmaYiLk{8kKNBv?l?a8VDuLLdtes`Etyn zXf1Q|G>{~w$HbgObd7*;wmv;{M$-EWnMAMw+j}@Php_|I1Bt_`-X!D9@I+FW%>OU& zT(-^W+yw;$dYlr8-oB%IvY0BWEn-0S|6*o7VmVPh+c4p*h&Au?OnxunFYIFYYgM(x zW>Ir_e2-0REvhY392{wrb28N_+48-KU3mVMJe)~3!w&EInIlO->aH2h9|VLf6(5{_ zB6Wu9@{sw$1%1HUaJ-^(XYhJJ<BF0<ikExVqIJKkvheOZ9t_<+Of(eBQ9;AY04UMO zwo>|M2rQyaZ5B4g9jhL03gVHWiPbW5X`|FRIfjm*efx=cdqO3pFB^hD5NfQMS(xgI z!=;l*9~2}WVwGz%<sD0)pCkG0VQqQNz#AGF$*oXdSND=V_LAcj1TzLqX_)7oHZ<A) zC$v72PIZoe2rbLL3O6*85vQt3=-*rtg*TS^$qUTQI%GEI=<%SnWRbkD1`ww@bXkj} z4#cv^wrSqax{;b{#>2y}j`sGuSuiSk8E-W-yEOD+IP}xge@qJ+A$Br>;d5i1Ywyj+ zPYx~gUPfArlh3~kl0WPam>8%s>DYX?k?z^;qB%CcM|dELP3ZQ#F(%0ShO}L|@ZGzG zN9Ry|8Tm=3_%7gSDo>oaqkj5UBN}hhb%d9pyJ@31JL!Q|uCY_({`_ErP`bCOBWY|} z3hLm6?5i^kiy^s|7_Z@?W853yGZ@fZ_0>x-9!^xfkK2HM03zHk+NJ?PL7jjl<%0VL zIF2dgVGQu-j=stn`%i|zUjQ(jT><fMggzXiRc(wB(=;{?qc?@jDF~Q}?pcBt<gw*H z!VP!@{24de9FOzf;OVCe4+%+zoT^Tf(wX%C3Cfr0xq>GTg6t5hpp|V+o<zDuL$T6c zWykoz67LA7V%E7C>4h(X;M;>(ZVD+I8_V?7+u^&|PYCBNP!_^^n^4-nAaz;gWuj&R z!?%?YdL4PoH#ghb(^Or@^Q?j=>kr{4!m4xCH11|uuen-MU-&&gzNC8~3Y#E(1kY7S zu{Wa}L|3#}E-m3$c-r(vMWThd6n|1#b>4K@>WffKFxLHDcE*OU62k;gNflqtKvAR? zl2Sv3;;hBmEXCaB`&EI43CV)@<B26h?sJ*0lZIonvpC44=K(~0VXT<|bQEF8_=9un z<SGeA*g-EjpkIz5=@2NuxiB=0NrB)5z{CNt^MU`y8bIGw5{f#>v&Jgr-d=?Je+THp zRF5hEZZ<cBsa~;w_u_Pk$6h?{|3v8TXdPQbl)Jh}93Da)(J-rXg+?ipC^`mWm4(5= z4N1S=lEOf6%1Vsco|Zz>u~BY;YFV*TnX1yHoC-s*-mI^$!>l3Bra0GW$8syF&09$f z|M+MmC?Ff*cBqmKD5qnJ=AHceJnrSDp*AdxJif=S4os_tg+&@P9K7lm%dbOG$60?C zXzL(hgFE=0vgpd~lg+L#40AQMe^=I3SbdXmSCCFh%sQcaW%U*#U0}WWw?&YrwU?Td z5GzW~U(G&-QmkXNd;ptqA@U|Rrl0xn2;hI@G%XL;G_FEYy{#~`)DYgy7IB{7PM%Et z@uMEstNqbP0V1>1(ddzQ76{@q!jI|f+q+i{27mlsCxDG~FHj&pJv_KMxSCOj?kc{= zDS$L&3;AH3Js>jx@k|7Jk$rz3hS@$0gw7<a691M|7eUIfTF__)I)D6Mf<QvsQX=#} z+IIvZ&3F{L-<bH56u5xl1dDW5#w}b$(G`KpxjYe{qBddVSXFPpo8`5(BCfC>@<iX5 z{4=;iK-+A&%f)l0vg43`?E43IE7zwk_THa3w=wyAt<bSiB$nsgd`aKy6|NK_c~Wd< z$AQSGyw4Y?T54kr><>|C>IDzl8^up7JR+X^K#-@EKM>lOv7(+~DQ5db8IdMF_IJTV zNBrbehlO~*O#%r($YJW^jzhjW++r7U-)-Jpj5lL$TBS>V(w_}@Dv~pZO#%H8!LC#r znowa#PW=4Rl1n26iCO|(KWIp@T+pD;fX)@W0`!fuGBSR=%1%kSHZd`QO&K2_w>C3T zfKa$sDfL7*`jZ*!8`qtj^0Qw{crO27lIc&p>aU2sc=2LrNJ!fNOnyE9`h++2b=g?D z{e{$i@pNe{H!WXm<LiNGS9I*A<4kIr>13UM#CX)#>W<!O_nQ*<&4m1Xr(n`_-{r|~ zHfipt&C=cd4p)r)Wzt2a{b7j}VgytR!?R$6?*e$VjJGTucCF*kbBYeG#BDLyl>+jM ztm}3vR>>X-4=F}*$ms!`r61cdOU1uy>MkYkfnORoxB3446{rUkoCKzro_yyiXZ_Vf zXD|o|2q1qEY({`BtPmIu6RPIt>t%Fz?%D-wW<qx@^tFHxCzflgZDynZX;40aHvg5x z@;n5IG2r)sYgtW#bT!(4p+8U2L>;rY7wEFJFkZA9noUpKVY7+($1+9#%=0Q)TD&Xe za`qX(2R^WNT&?!d(WQ&eter7P*|;D-oZ|p>@HAVV%8t#HP2E|Y#UjVaiw=37-Pc9n zVPN)1m)~MAb3+$ICzVYM{!j}z{M`_65?r%U-sh&7;1B$~b!{N(3dQ8l)IQtsT4(-c zBNXELu{++#Gf$lZNY1kV&7Ue;G!9u&_8-Vymofy0Im9cVa_$o|qQXJk+7w!g2*%mK zDWtv{X*s1Z!_ga`&2w~YY%II5uzjfP!-s1GvACve9*Uw<?|DOvAkHeP1ARJA<4=4) z>X?s=jFfY;y)d~u`)KEz8mrj?;xtoxb+CCq2)6Lg|CvNKBifY1G>u(}8@148p|4tB zH}G0n!NXWB+tiI9F}Cq*QWnbYdsd{P9DE+rdue>X%9wTDq#Se@noDyOE%orW&vjo@ zF0ph|C-%xw2NURqYJK*`LZK7H7^87_o2WaU9VfM(=Z=}47U31(YoFBRPamcgI>Ieq zoIw~sm=F44AqpoBco@$|#xgQ9XTu(R0}HT!M>&3t;0$~Y1kk4R`&1*TzB)Q-;0pJN zyjp10CUochPP~-1kIOhX)yAe?0s$-hYv5|OFT4K~{pwMoX(1DqL%R=b!2uH7zi(gW zJrv06A6o1ISD`?0RWEmP%L1+<6L@Q&Cz@!kt`0mb@T>M~KLXk=m`0bLS1B6-g=VwB z_91%X<HIuZ#aR8hPfTVhW`z72HQDi7nCjbap4?Q{#3|`!dj(tNcWp572}XstKDf`) z?;Sw=LO>JRlK0g02l&X^afeGThP%6xNLx=MN*AYgy%h~y!3<pcBOJVfLh;hBl>_d^ zO($X^z$OE+x63-$-V`OA-OaoXJ2+(X!QN;%bYixeT2*Y{Z%lnlg>X>Plb*8m#ZhBb zumH1JKaQEBP-JrHWMnAL1v@PDVd@s?8mF}!obC|JCt7WY|6+U4I3OpCcaW0C@qrUs zk7PCHtZO)Fs{O`%epi(Eonq;YWhI8;cw`xM<4qwILF<Sjgdit|%f%1M4Cg>eKl>wN z(ldByR*)~!wAI6J=ibJa=-b;atE-*k%Bv(z8oleqU~qZHl~2n?Cd<mQ$0xgW)ZRQe z@Nrj8MnF>ge-yW~hlVO#RJalO<;%tyb5oJW;ilLhZc_BYb@tw4Uo7qmsbHH|SkEtx zY}^|9VsOK%?}2YoyMqMfZ!!KG&r+l|rk8xqU%GeWt^U;w?>@Il=cVa&@f(@fhHqS= z<kgZK_eebXe1SunJI$*(!r@0|(H=Ndm_c!SUy_vu7=c$!O-&2DAUuN(tRha(fabHu zhq@sNE#a8^gU@754lRQ?>Gnu{*rrL(%qJWt=r8BvtA(ZGgS)%Cb=d61`^FZ4#vAmo z3haFuUL=;4fy8?LAuB=46x}>^y0wTr8~v^sSMij#IdU|9J3p*qzdrsdGI|UX?}}~f zYf0o?5>HMhVo!7WtjAa1TiPe;w2@POi(JPvX-zWdwJ*N@9|A>jHGcI}O_Kn-*W#H+ zwSf~KJ{-1PK^dwTX%8HoovU*+4DH}W9*CqnssBW)>;0b(#LK-*vFdd13&K#EGll+L z&?%>z3M$H$goV@;PS*K8aABD#9b;u;VxlRT%*sA4dEcSHYuBz_ImVStzF@X^uiuOE z^2H0^n(qUUPdp5Ec@)(yqe9C=WHR~qlgr=)?f2>Q)VphPa)(%Y-4(?6_zo1Tw9M{) z85=v@OdP&l%lzcBxw(0{1>?(^#QdzNm|S946h668hB)u4G28iA{hz0C`n2*vZ-MKF zCW@UzN7+0>oM{d2xj2k9((gEbr}YMZ<)&>Ab0@9?m0~bm$9`awLE)i~T&|6v*$ORp z@22Wx*1Wi2@y>UjC{F}EJEd=qs!_WGyS(bSal`)DhpM+i@<v{w8ZGWq)wkKiJ<;#; zau@fQm!{X?IV7epx2qr9qQp4#)H(dS$?myc0(19>;jw_op(kc6t$pw^eX+A(v{+l> zIHcbLuU|jm&0Y_3hpuS!{m8Jek0TMNriEsiU;-(%q~sN_(qL=%{WMXA!C*F<qnACU zi_yLN2b#Y!6?FZ5=Qz#LW5+H61;^Y2m@FG(R;%f~=sj;qWH6Cyy?e?Pc#zv7eO(&) zPa8!Od*5c;SJwtT==JyflF6xhd;QfRmRE|f@%{XythHQ2y=1j*ILqMWk)$1;bEk=c zase~kvA$9@_L->PGI}(p<+EQ3U39~Xg<?U=Zl1$?nm!#q42glMf^NP1PBL+H>x;9G z?i~NZ9HHF*`NzPnkea0dpN+_uJ8F05xG`C~%|@Q!S$Xb!@8hoiT@nvIUoiWWQ}>F` zUpljxFGPh+{-)vZWeT8n_kdTlLYpPp>#Uj0f${~$BF)XSM?gQ$H}mXoTTkQoX5b-h zYq>?U`^SCBslMI{*)f-L?sMmM{v{<<+4!vdp#MXV^3rtTQ2m3H<G}fl9a?Ju=<hFw z!#{wC5X~~Qu=1_Y>Ie;RzcvYkxGuRA()<d5Yu?}Qgn4c|FMc){2z)<3H(XPaa5w0~ z%hlTqJTBr0wOH7cq84UucYh<@zq4s@beh|4;nk1jxkaWm-6yD9H#<Y=pEg$P4C(4q zc$QkA#pv^KhHd8Ht$^2hD;tjz9~lULsg`)Pwjks9{`IqMHpZ$_vr>W&-{<l^2vxk+ ztu&X{@h<2ur<>1|o{qK)a-Jl+(be4UWN15BHv1MKYpkyls?EVl)Q&YIGIF0#xG{Z< zw?_hOam)7>Nd$Ud(5T*hBUDul{>6l-uzL}F2G_m3q-c(uU0-xn)7Jio@Aqziy>C{a zjp@m|r-uUD1YM`TU54=Dx24wB*0;)>xm#}ShriwZ7Y|Q8bq<uUU2s}@>j(pB!J@gT z>63L4tG3Ib31bnvuIpynnAax%JgBEnoo#qlpD(Hz<ASG4%O9{@6<08_lWLaQ+$|Hm zs${NG7U_yIxGd+U9bJ1ZRVBGuf%b&=oeN$np3gE0CyqZ!GbJDO=#;uKQuX$VWs+2A zsY!wG@yvj7Qk2_GCb9pEuD6bga{a=F0To4Qq)S0UknUDV>5%RaB&3@mq#F^W8>CB+ zZfTH^?ixb6W2pJ=@w~_Ld)NBjS?f6-{bSZVckH<KwXaQMFtGh$$!}v&rB^*C$aZhm zXA+9(j2>;=$K;~-#-gkvo4<R!g*UxT^s1^Zudy)&4oin0Djb2CfAkblLE}a0_pd>p zF9sNup4-?+<^zDEtD!?6w|xZEI-#fT$oWM@#$X~S<e=^T%cWJ_hWSA-b{nZ@XlNsZ zF6|)RSOoM8#J$i&@tL;5q$e%YZ%J!`-|YWP7fHtwxgKs21|uEdt8;)15)0^57y6SR z&jep-Sv|yxJ}7uBoAE7Q5ajkC<UsD}?Ol$Rq&Q6X24wBqs3^{cU`H11n*I0HrtFCi zDub#oyN$kK<Ky7?fB(;z>Be+jhMXwQI=GAsFQGZ3qxn{hJfujv!a_XkS6?0GQ#8Yc z?C3MkJ`tQJzgX@#s|%kJj{l{o?au*MO@TeiXNJ|s#K?H`>pGLPv%CQJc3Yn`m8hM| z@9JQOR_=N)bg$l&LZw>{OXJv`^x_~ubLS_l{7bf2PQ#)5T<qTMM}IwIUvlx)gyrA| z&}K=mUMBVVq1&ybcHvup6$$&!hz)W_eV~KgQv9$S7&S00Wp?Y9v9#7VMxH+em@$B4 zbb;e^=-woFwNr_Bc*!se3%%-nz!F*4Z_;}A5-cTImKuVi2Id7+fbRhAbacnfx^9gC z=<&jj8ynLX9;HE!dT*nkD=W2N<b^Bf%|3)d1ka|7HC_;S+YvuuWDMIJy|Y*brVa-J z(67>BoB<?Gbys_>4KheT^%WE)FYgwUzX3;hfmWWVzZZH+A@#2X6kD}@kGSkrZhq1b z6xi&;i*)^)0CVFqXmvU~dLQ0YFo04^!x`Q2%7KV;moYG<At2V!0WG9wtD|G2xzWnq z=B}{5XzSM69S)*YBD@^gk)&DXmIg3`c;ob7`B7!h;(`1p<q#>!=L{FzQ#fLge42jj z7gt$sC*;H1<&h01^_7X|zsuMXF}?KtKYfa0DYYE<cy9tA9PFUM0LW$ESl*9=fXNj- z;B@u$J%o5$vnRSPeY{V^@A$s*Sbz-E>%3u+?fvi*c+${@aeo{Wl7C>}=fp%}+n*pg zPT(-ZB#?ntErTzilTYcf@j51z&0QCfuLl}xd|*S8OGpFTfd5%oF%C-B6|1LAAKHNP z{-o#&flAzCi}-ufrOtCgnyG}|?&V$^NPc2AJ&oVixLM<urS%&f5)OG(mLk7++r+B% z{Dr@mNi_csg>ulmsMBW4^M37@=C}QvV+2n2_IxC#S1!@#)8Z$o7lGabNPDF50~n0W z@6K^#zsH=p%&xg`Ks#EWe-thYddH%h^%-o7YBAUx#T>I|9Nx=1dY-pJaWAyw-zaGo zc}PYLt&eOE8J=A1hzfhFsSzj$osQvbkb=t($Y);*3q$+*q~Y$4j-1X7P2*5tQo)Rw z*!XxAC8dvsL>eV(z+EQoIyKBcCM3MW>b#>-tY%p$BpQgmY~y`J3Vierqi;*j4R2&+ ztvK#*%I~J~J28MR`cBizW$>?n0sV~#@(g&9tIgE3zRQ%Zut!_-)+B-yRv#d8*Z|u5 z=M%mD_5^=3v)bzIFLkZ;(@Tx|3ywJETXgN<FJYy^F&t)Tuch5z7j=VRj7HG<g?Tn* zuKj+C?Rt~g^dQe6_gfbudp_lN0*g7k=XSWLb36KvDm4;ZuCcAPU`*C!Ji(i*abear zdPk>jnr9<4R@zq*jFKTzF6xak;`-4BXlPY-YjPZQJC_a@Ta}bk)oyeiE`%zZg|vKJ zX{%#*yV7{W7d(B{Ih}aPc*!E$g_-&JlK_CgeGXu?pvy~luxda)u4In`-49q#O6Ncz zF#w<g%&S__US_KKq1NJNNbQP)AO#i%28EvM8WS_`6}nM&wlBHd-wT#AtN2Sj=l+qq z=PKc2oWp;)0M<VrIiqi)Zf(z99~X2Y9x-u&+RODvyldgmkdO!~yB5QQ5Lv#|p4ib% zp}jYKkK&eo>iZPgJ_q+LtXpcb{5W}9LsTVXPiVAdf`>f?PQmr*O5Nt6QHAj=6XE<I zEKlcg`TDV&=IxOxh(Jzkzj{opoYt}>CM%3Qjvh3uPT;dUqL)vBSj|g#fnGeMoZQ^c zNl7HDoKz#D0n?&<c60Q?x~Dcsq0-Wc@VVDk+>C}LvS{b-O(|?J6V#LbouB#tW31ys z!Sxu9+zsI5bOnyEJ~8x&fx>g?9^!F-muq{&M999EV>s3RT6@l>!XGEujqO_^A+&%c zn{)qN-w~m*>a{o>UA$=3?&vYGyBBhGIVXIkVDn8ei_@XAo*{M&d9pP>JkFFx9|G#A z5FmoXgf35yv&ku(9zQZK@@d#owmdtyht2edKUz2u8%kKGuOU%eBsG=LT-RL5?dScE zTif$vlMUKJgPM8^(ck{=k61mvO8K2&sjJxvHjycuoaEUrEkPbOp5dF&(v7&H^}}6t zQriaY^eM~g&QH7tgy@1$hrpDY)UoArJQBVPJiPwQnUjSFkcCU1s^lP3wkP~lQX!FY zJSiR=gbGa+)0cgd){4FAt3=B6W*^F_!A}HCQR6C$tlGcEB{*2hB?DoFV;kOx>zj*M zw#@&uDTNE=Mb!towRon?MZjE}7SzszcrQP(pD<SpP5)ftXrVDbDACyMO-<048BtXK z5w|vql<qxX#O`W)jZO7|!NW1o(sZup-Ds(K_3dUdPvvIvhVLgSG2gGn?;XJJ03S#C zsJzp3%J01{2TcEMW%omwKkLyypFp_tVB`)AB7A##%Yb-Z5O5Ic@ud=1(#Fg%hD_{T zkP--lmQN|=L|uyLT&XF>o#TSb+6pb*nLEJEu-|`pR@@X7Yj}P+x$;^xfrmL+AMjN5 z(m|0;iCGA0QOds^Xu6%=?8ZUb3}Jr|BK9nyFVx<b{1w=o9MRMLm^Mung*F$WMKch& zWfV96U!l8)65?9TH0p`#Z)zZ}pVyf#;vvIX);ZPZ;5+?!*wH0f1MxAWVu!t@ic$DF zSqppnxY3Wp8yP=fA9`Fbz|)9S?y(EUO>{?HJ_MeoeI>hYxwcub%1|3S=2Ry>&5lb% z#KyVulqGJi@N-!YTcM7)J}_*X%K+6TVl%P*zeB-XgZtRgXR77KEKW|RAWiK4RM=-h z0Uwn~@$R!?=7UZ`t{39ps_)u3we*rn%XS5vB%g4%Gf&CvL(@B=UD=2GGz>Ob`6yGv z^O~s)c2{njh|<XjbHs!ui=W3=YaQucZDzlcdPb%Du|F|rXd8q?2qTN;J2S&Sw})zB zv5jfo(hbebt&U8ZnZcB&{kx^Q5wsvmWvwGU_9K54Y3T7VtPb9ij<i&pd4sSxL~Pcq z+{sm)H*udda4#37Uc*TX$`(R6Y@U8~V^P-rR={CQ+0ck#b!osky<yeG`tx?pql>Kj zlu@m+p`JE)**#KIh56lCKn=Gx{PJe8V3pB6{Mbz>me7WlcC*$%67efHvA?K}Lr!<k z6Xe$YY;L2ww+(+DJnayZbTX(oi)mm=UrR5^`d&;{IqlyK?W7>-t5s^}-MsiUaHg)N zTKWF)YKMv8uuPoyN1Z_zan9FgRTpG7O)cRO$u*ZEJjnwo+=q9&!ih$1S^kS`>dEju z#oZI;<QOicC(G^TxxG9_(~%N5oyZ9FJqYeZZTt1k9kIG;yV`sXntOHhNnlF<><&nV z>F1k~Tn6?A!##f%6wOK8#;cEPblkh;YUupA-;K4_^<`0c`&UkHw%uSa;dhNA-KHJk zX6@VVC(m%BOLL3qCI2}h-;P}Hj|N;Uv94-a8&dJQBes0RcDF0b)Q&d`y{|;hT^o_c z#wLz>;}^??yy?{SI7i{Gnr`<Lnl2d9;1_xgAkp8@cZ-o>;Y}898ok*DXbGLZ>pe3~ zw^pyH?)D%?;dWKc&e)i4mkt>`#0n!m(ad7N?@^fccQqPFVw<nWyjwizt*~KDluhx5 zZKilEKOW&wVMWjGyfI{JM++mCp9vOG)I51U*ceYgd&p1W0!*+7H}5e4?iXi*Z;A1j zlkSrKhYi2{YB!QGUdc{0r8=#+&AD%;4opmXUDCsEZLP6!L!{K->c!&iJV2Z`@~*kQ z&Sr8a9kV0%reduoR3u4PBEq4RSIV!+xT>le5BDT@rc`@M=RKyC%9F!S-XiIFZ-{#L zo}Z}58}0OD?ks3`goQ11K@ZE{AKst4)Son{;=G-@)lV-yiicF*Kix>-$W>I|Ur!HP z$gLggEgZKb8f#%G=nZ*wLHalDh#nj{^)_Ol3VLU@kcL=^FO%DAr-bqLozpFAKkax9 zjw<(+mETTWA_s;9=cx1$!O`2zcC+_8Kt$mw9N0VImKlZPmaZ=WfFZGi7!|x)R>r0; z)HzIM;puI=@r(0Tp1XNbN1dP7@w~)Wr&QIx^MTkFeE4NY{b$?XRcg)hy}2qXT-f*a zBuwK-&GF|&+R4n+ac-OT51K}%pQ|K%pR%s4vvt?t=uJ0=^Qt0}atvPGR#qYaghWN} zBy-!`BgunVPc`22`Kf1~!gIq3(15dH?9!I&*RMriBVAn1Qu1%&hyCk9q{{PuGmiMV z3Z_-d#8Bx<$;mM(+`#Zn<r3Qi@)mxKbfzn97Fs*C7-BxnJ%@q#6BWEKwej_+*t1lW z?}GRmn2P}Sfu4?`7SG4dM?sCK{bKVy_&>}!?$vHBm~I36tW2YiW1cIE=P3@1^L?4% zu%}#n(cvd!1n>?q9=O+WEMAn^SozMAoDU-4tX{hFAU&<_3j4xiGtj<qY)FKf9fXB8 zmHs*Q<!hZ6NOiNMEI*i@GiAGbV<6#mMWRpHuqP6+yCNaM8Xg|FM-?mn=aA<8Xr_?G za&8{)GlFjdC|{2u<HE)&mW$B6m+&@X9f6J45)lHCpN8Y;&XYd;>M+w)fJ~f@?X$Ed zp0k7dJf)xeoLjPe+d2B`&;&L0kVfvFMU3G=>!E0^Gt8oIYs-(coHRkul)**Uld{YE z@h}er_6#^B2SnbYu2z~=23GmRpf?0f$D#M$hdnzU&Vw!i$_gfLI;3<63<FGHJ5%V` zEu<n__Ma*Sm-=wxs=xMZ<WYH0AWFH(W{WKkC(<xWB@a@=IX?0yY{G38I0Zco-^Z-a z%4Y;$mQLNLwRL=lHrlPYW8yxKS$RviGZeMxOUiv92R2hoT*7fo2BgOSe4?L>A`mN+ z#l6qqT=Q9IbMGz<>I-%d8<(yPCR3W;B<ToJC=^|NFx-4*wm7&{*}PFpye&mxf4}-b zFEydotbqA8^aq#A-D2^esap8O(*$%m1?&C}r9AtgDlDVx?#0nun>2tph-s~r7G=#; z2~4pe4z_QX#kYe>hdkqN2_L)6YquTj{Zh7;(A$^3zoA1>)LUK|I!=eqzhiX0p1x-_ z)rjwdW-NhAKF(V;Wn>NU#ECp07>bWhLw)%{cRuRgVi)Cn&{VO;&w&l699lXf_QV4i zWNdu<htA*EOp`?zGLyx$5ybUXFA~;l-(lP{-s&lGTfN=rT~r%hAG7c{!5)#gPRrzQ zVLdoec=Owv+EiPXj&_gu%=!ZF%at&ih5$47XMOZd;6!y7-?Y=QonML|Og3x=<CQcG z)qFtiB^VOf^9?kWfLnE)J~=UQk8L26)Oqfud^+Sa{FriL1H2r{Qiol3g8k8jY4=!- za^DArvm`lM-X&(X(>>G-*wE{rA_PGg?X4ESBCZf?_2=Wxesfnb=l=7V?2zUW4!0&@ zf|et;Fnw6UCq+i}>uW)Ik&S1#F;FeOAFaUkM|Q+)a-Fd;JQQh7Z1FkrrMVEChsFoA z#Wh$x{1>`t$k6AvlwrJZbg{#ZaS{T<16cRFf|9;K99p!eG>$%Gr!Z5YD5}MZYE8r% zbR%pbTIftYe_YA6Z{gO>ZIy1rIV#()%-PDagfIG#UHF_8_wu1D^2JK>esH)gtA&Ph zE1T2l9{14n+ocaHhpq>gkOb{%EY2&hlb3)qV{;7q_ua&Dwp9?p*Do=BK7z6Fdbjm& zldj+ijtE<s;Ui=}{LUsOA)qy9lVBxw&L96<Z)3%-fqoH23;c}jt~Ro;4PD;8{2%Z@ z)YQ70)yuu%063YRvSL%SwOj5;A?I)k!AOz0>-UxVh1S|vsQvoQ(!l)iJuAii!UBFp zj@e9wP`Y@SNUI6^@+mi*;=0vn=i{Ymj*CQNwz7(LKM-&V=!UjgaXTEknSGuXNZp^X zUTVir2e21xNk1Kz9RJN?xZW)k+}RIlH4D4zt!T}_yvj;!^Q<4kAR-jhe}gBXFNn-W zDmt{;KHM%&?O+%#+%5{gLQlLIsk@CQWH<eR{d)H)(;kmDb;!00m)%Wimu@Ag*)1b* zqveY*T{^mbimmf~s{P8a-vWmiaIN6!KXJq*eo=w>!Cf}pg9swlBzW?1jcJSReDxVd zT$3Z3Fn+K2Dz>WX<GTpVxFEAMVPqGclWWD~r0V9n)&DKvoVMdvP|p}guyiWshsQ-? zVyjDY7#K)QagdJ$GR;W8qNB;<3Ys8CYb`f4i+q#%uUr$zeU#cOh=Gk&XgYXU+Q%Ra zx8U;RaR0SreoaxITV36Gy!&G6j?c6S3OamIuBibzYSM3->;j%M?{U6->duCqJwRm( znz688T;`VuoA~D=HTefDuCP&f1Colna<|ned(CS&ND>i4>xIdtpM|nS2xR(sYQE2? zydi-wzVWm9T5W_kczrL{+B@WOi#(OMp`URUM%!5z6~nq@3fHozO+`ePsrn_4j4GB$ zlDK?D;PzgX`nl^iu6f^9w}q-@hN<jb3;R_8vLL&c)bto~uHEPS;>SkGBiG_w2w>MI z!$Svt#joywq6ECF-76B5(1l^EcmNz%c=wJ5lwAOF2HNiU00oFx2#8>H12N{K<sizV zoAX5#6%|ncA9E*1fX;tA0Jh-~5>9S8fOeW#03xT?*LO{t5TVkg*rLSiI%`(Wwo=NP zn?DEQ7M!5?d0Pc4%cZp|4}s9d@Rr^7WZ6b1p+2B9{Al5}U3yvCbf%S+oh?8E;7{+6 zLpw4aR>mnd%);ho3ZLIS54?M8LIy0}?F46DZ&#{5{=$FgDwy+(ru?}JsW^>1*j^2$ zk0MEnm1Pg!LvBnfLstD=kwDdHO8xEYvhT4zHvt}JT*C1K(z1?|EE0c1gP!O=cXe7t zkqm@rx<6d>KP)wraT^e!nx%<^9J2_eHs5#{CWI552T5SiI$hl4V78<euCP4s*Z1Lo z<CAQqq^2}l&cFt&s6OXnlW<M7a0~NA%G^IOHQXC~Li;FkN4VYfWKzM9or?wLb@AiH z7l`<3xj9H@HwtFX(Po7k5&~zM?$2xMSEZ)vFN&?Dc}MdtQzjJS+!q3;E)I6Q5d)|g zJKq8WQ30Rp;%X5t58$kt1^1$sj;&*uE2tA`elrq3CObU^CAB1gYdhSWPI3Ttq))e} zFeT7-r3VeX7S*?4smtx466*uWLE{!e@4bA0cF+-+<+XeaLzxH*4Rr+~B6Xl+K9SR0 zxe^M7G6FPBbHvK?czs~buA6+$Z6g&_G9BLopwwL}d1^MvaN3V|`}?}SaeY>9SxkxU zr(w>4TJzWYAQdgXxVA*B{dYIU_KN$k^LmD&DeW;=WN*`bN2C>~k*$A_l4?`>xJWS; z{pBS@cw)l}`3W1d8lm{V7bp0{7EwFERxQ058y^QHR;l<E@V5IAUmDN5q^-Cg5$d~e zj}9eENoxUsj2BnFHQE+sGaK$}32=a8Ld9lFHa!J7I@*1AZco<0<;qYt%^%m6lURH0 zsCi+O(tUmj#SR#QKi9v_rgfP-yr$V2Ou>QyjN7#d_&!>y`Dw37iUU~ddzkNI9CON2 zA<A#>V2MitjbZkE&dn0K<IbpZS19d|N7fg>sCMt(Nmg_qgxdpDebKP6=;-KzToyeE zK_UW_BVeGWkRa^Ij|9q2x1ViB?ZCu_9~M;=R@3aDwf{~l=)>#wLB10l8hRwM!C2O~ z!qUf2hFRLM$8Th0<hu4n9h3($i;KhIS1oWT=t%6~?U_sj=p~S!#qoCg&=>n$HjzC5 zbe0ml(D3Po8ZQ3`0346IvS+$A)~PM4mPDxFDiQ<T)|D6qVM8$B4O9$ofp`&O?{Nsu zMz4C$eu8S?=y2N|Dd}LSNGbXIF4iZ)+_}^DzUXScHG$rHB2M%5#ntMgTzURq@Tsl= zZP-rHI1;#fM%>B4A(2#1nd3mPwxC=6d1~tYh|1@Jf)Z$e`r?o6QzIhOcJCKR07M4E z*)?u%__?hYq(QDj7fyb!m2}@rDxe702MF8!k3UI9_>+!iAsSHi8u>at$#bxBUE^wZ zt1Z?kX1lxd2$7-w`o^@lFv6-CBAx!~?In66hHC6C<dNBeOzoK$dUJcS)EJ&C=~*Q# zJBCQ`M%x=_fE9f`qJMp6t>}3{i9io=eG78a{o|V1^v*djN#vgzl2~NI<ZSD0Uz5Lh zE*YdUm<;Fq7Uf8|Wv5)GS?)}r<=sY$%~R+_-ppKlTG}9@CJWTF68IcUTm3u1|Jj3X zTd<So!^6X^V02sp_Xm<dLsnqb5XS<bqo6I7`{`2={Lm{fMKC>X`_NUR#+sZi)e#qo zi;D{aEGZK3+y_g3SVoo8NEhQ}UY&Rff^C4iJpIl1KA?VqX3V^S>;8C_yyb4RSPrv6 z6F`DSdiLzuFwn%IfE>Jn2ve4|+}5{1wh{NF>D;I5JP6FpxDTeZApK0@3IhdDz{~~s zfnjGTeu~qCCi!Q8=$Cd}01V<cHXdF0+SO@t{(^ox&tl2D)AQ|+kjR|+`oNj`uKj3? zc7vJNn49jOf({G{E#DuMO@bJrQQV(8rLWKe4uwiawc^~4-owdDx2Mvs-cVUCH0j*X zKR&GyQQUVP9UcaPXnF;`$T1&5cJ$9D$81ZO8doew?&>TSRlrxOMoCGnm-;wuqcNmq z>8R2g8WYu=Y3lu<=t_>@zMW@T2E2fheaCk`Ckpmx+0Iydeo<xDrPOe;rUe~QNp%CL z-izEcAwwoc&nL&;S2~rSZI&nSBWU!aXbZ!7eianbKXASqP4S_7lINGAizA_AoE1y} zTx)X2#a_DfpT(M$T8$CzR#q?Gym^Ck``Id{pSd9%(G81Cvq-CwE8Avd-l#TfQFS>9 zR3Y|Q*7fXrX>PNuMqy=*N78UReK3<FxenM{gual-##n*M9g6+=1|C2-N6E;@K#K3b z_fl0A9~2Hy46ZK@5rFG79xlm#{vqg81>wW25O8{w;GPv<uUP7Nn>|OsH}Q+^@lk4! z!G)|914#iZ+L(~!vW67o8<Lhiw<bO5)HPsEEbOTqN?Uw?=chBXMn;7#2ljhQBnUlz zlCdhVwt6Vb=LTtYAPQ_7nADSSmu5%0va|pZPutCv-I_Ruz}`I&-~aQGiqAw;aKu0$ zM<tnK(5<)EbjpSl7(vm2D57R&qZ(9IU$;nEzQ=vz=k;bJLtlBj@9PV1<gc^vH@d2N zW?h&`St%{JU)%|z3(PJiFC`^y`^$k)*wx$<+HGD><*UP0aux&b`?mt$==L2JJWK<n zo2f>a3;Q2sOn!6036V0(FPf7UU%uM4FU?Bn4wmJ+$sbhGU%XgoTeH9S*fXjFlnaqq zlLt)Rz2owjTekg_kkA7-pqedSLKIPXoha-tKYU;Ul0`@+W@a_DHlQM2tW$>@)h#M7 zkJ(M>EeMpIZh!275^fT?F%c@YM7RMkg`m2lqNXMR*iH?mgwdsCIp4$830oB00*a=M zXQw+`K%NP)LMKcY@ymZ8iH%D^T-5m^U_-VWdZ?(SCJ&8wqGbD}G=*8q3VnHK$98?0 zYe~=W{OiJQSL+j+=g2VyYl&omhPLCK9M8*am8!f&kl2)z0K_5iTQ%hG!mEQ62x0M> zBzaP$#SC_9_~zW_{bb4AxUd#r&$PMMpr_S(%?~2TUiOvOq4U`Y_~m+vuVnCPyj~Gt zv$M6*6iyACX)WV3Gt0Hta##L@>y#26D=g@_A)}#14{N?UaTLTTQSc?e;Uh}|D2QEX zjo>{p-OTDY;>-8P)c1K;po_rQhlY{nsexfXE1$xOl6h>-;?0wD=TK_rt&spx&W<;U z5K$uoqnv|I$mBNeBUn6P9$@11_0ZzUP%b(+n%}>FCy27-Pd6mGot#4uC@dY~)DKQ% z!n9t%DDpcryP$B_5TUF3MMwS0X;~u(*&8&wXEYr(T1P^P;BTAHdl9%L;%|;`pCSI1 z_pE4@@!vedJ{*B(2O;<<XQ#ge(jD3ZTpTX*i(psOWy-Y<lpip39z}_y=^0ZPPZbN9 z$a$rMTDM_^zl+|I{F*V;qy5m06h+Njz~YG~wa1{Pe1yVA;v!Rr5!&^=-R4yN<Gs;Q z^ZZ51922S$Jk>9R2#XY@s(ZBWESMaB^L3G8WDvM{z=azGb9F9&&>g5BH-Lc11?d3> z##)NQAYaZgaI1RWH%=Mfq$b`box&ii>)Z=U%dMaHyen=sxE<<r#%^2%U~xNhb)(*C z6N4@Wy|v}#hudnSCV;*&x#ho-YhMN^KKc3i^Oa#zlWWH?jf*Y;P}vY&fOj=eQXF~x zoBrcO8^7v5ry-2CHcJQBl{_o6t^J30BjWL+rb@B2PU~GY#|w^#vH(>wjbQ0y`L{EU zjTqyx`&!`~a2lNkkslk!j`o+4(9-FFGX<86#phu+mTEB}iwZ=2RsHHJyVgzRzsR3; ze?7Vu3M;QxJo4Nq7*##Ok9Jls0f&`5x0#_#cSzmk!3M|%5llAT)IrlIVA~IZM6RD^ zaL&f@EV#Cd+;ask%0D0gM#+JG#|Jn`3P=9(p^fb3X5poaJ6z;8M5x5X#P<irPiB&G z6+zGgqJJ!R9U#qwU~`o+dYe7PFYWW;s+<<He~p4ENd(d|014gIp;ufkd}h|~97&om zK5h5cr-;=*Ltxs$o*vSmN|MuER9L)T=It8Na=T3P8K9KQ>LSKJI&l2?w3^@L_TtK0 zrOSluIy}dy>g0844CSyv9;eZFvOkJc(ku4|#_SXCZ}r<MF%No&Zc~S=c#-d;7!?Bg z%ChV%b5|tXMN9@wwMzmBKH!{_Dk5eS(nRFK<XyVjk7JL)oPZTae$dD;HaU4U35EhB z3b-(XsGSigSbRt`9xqgVp<Rvc185LHPsOgI4x{}*p+_h|^!ZasF|qF#WcQ70C~tSy zvFLzbVA|&XfO!GYID0ZE>}g-=876X(aLT8BovyB??&8Y*-?7+xjevz(H;$Dm%3c6u zD)Kof=yL4WMBQO^eJ@g)%n=6oXNFZ(IxoxpX+QDWa);b8Q&F#r7-_u6dwlywcWq)Y ze16Zl<dzHPO`bs%@$w%+h^imEn=qY7aBrmSYgrVQ+x=~S4N;IXJZd)XjmZP`3@XWI z9Taj_M|NVJ=XC7VSdj?}{^B{fBoqqoUCFA4AG}bLD|oy~4{DZMh1FG1m@-y<H(+=G z{UP{<bxkrD_X9>o{ETDLre|PSiSoXt#u7YuSu|=jS*+O(h;LY&^0Q65)w9>54p@RL ztzZN(AbEX|?*eyhY+?eJf?{C>N)grFVgn>UI=Z`SU?jTC>MsMgwk!bABP1-$^0+oB zDam;Vl%z$af+IK-QpZ+|&C=Nd2DFa>__#oxJEpmi`0L-uL`<xn6LE}uvYG~cw8=uH zHfFwClh)i^M<L1bdy>WL2>2oUaj+%IG3{Z6{FdA*_mCoY#v1=x1X9A6<_oV$X540U z%z8EXKQ0r-8B|=qZLGCdq}@)zhiH#^GQSRv3f)LQZ+;WZ#A(pvIK&?(=tgo{g^xHu zx=I>i?1u&IA>sRyCOVX4N}E&EpT7ms8B|IdW7rvd^EYC*MENRJK24Umt9{~h!nb2w zti}k``Zj=wD-^Ium-<;+azLs8k^xjKia9Gd$jOI5)Q{%VYqA0|I+_<R4t$Z?S${9K zhyYg^baG?x_U&UZ{I5hfEiNu_+UktZ3yW4jfD}Q@th8T~_TlcYmrLZ};6TJDCxTbr zjr1@7TPFm00Vnh<7N9V}*S|r)whSJCD%rKInc1ENs7MV-S)X!ufpG0X6shP;eo+40 z6-$cSBYFU6EClXx@J(zN(3owak-1Eeu#)r-pt8DHaZfVo4>Tu*T|ERX`Txuam{~#< zyvv63?b=~4*+1~^f^>Z`eNg9dUOu9d7A!*{?Ktu>Yvpn|cvH^xEy>wI2W8%#gke>H zakale!VGgoh}0x*G;efY6Wk)+ftZ#w^5Rg^DH4ZT;s8YPC?ay5Lc@r40;-)KyH<8U zYn2Qje}rvVFu?0|n76jJlD>Qdft_{@_rj~J<?iQ+C2Yw9x97zmpa`cBs-I2+_zB!C z>DIi4r`a2nb$~$Pca5I;>fO97CzWqCLI`92u5$XCa&mn9xNN9-71VMps`mlhc9jQ1 zIgysxjD`H`=BTLVKLQ&f)VeSavR_9oil}&T7D#Irq41MA!;Mf<Gy54$ykLcJ^Z%tk zcwWZ<%l=yP7KOo?rE|l{#s0EgU8Olr7v7wx2VK9K{82(ck-{3AtOl6k+Zaam)d92Q zjhyFlJ5N8ZeXhtNBM`BB=ya8eID(S>B)G41`mnQB?qd@tzY?>eUB-Ft&yS0S7S=|9 z8`5doZBlJW#H3&d*tRUqaEu*I7ZKsbUoCl|o1VyV!+>-r`TqU;qNp3QUKc=t?&$2S zst4_qVL)vbps7<$9z2?wn#fTN^VWc!iYx_)G7c-H?aNPSX#+uX9DtyPrp?mlcZ{mQ z5zeq<w~>%Q#pXqGg?2>@umcARsP}hYN=ZEc%+K94MD`M{R{*(ccZYAl^(rGNxmQ0$ zrv;vO@8h{VempXa%_}GPl(|~P;ct{1?D!6WDj<n_NP}9h*o>mCYI_V8%W7{B;pYUh zey5u2a6AR#5Nh_u&Kugw)Ty6gfVmkQSg(vg&=PBW0Pw@l2U~vL=lMA}mLqu2Db2gY z#)KCxWbx#@Y~gW-Nr}T0wd?6emj^WhC=-m*)fE>ZD)|Krn9A%p=7`hzt#?|i(+r1r zHs~Oq^9R*uGz^6&9TX8<9UnU_z|s!$>Ni^Emlm{XF8|oHSJGPkp}Cxu)972#C!Ml} zAFHl<xTvl#uU2+qAc?<eSA6!^=t}4H<{4qskt{9lefU=X;1UQM{%|(q<P_kWEwDQ> z&A>m*fz(t?LZaHO`41gb1MJZfXaRvn3hX_g-(c3R4hM7|Bru+QNx!VH&<H?22?M6M zxVTa>GVQGB65&K`pebMqB%)xtJvxQpl((#$T!csi*f>5uVxRncdVm)Kx~&NqCYs_r zV~#xPR`X%D3s`idp8sKpqMmL0332)-&G5suJe!i4W{<UnXc^djK@BezN8zts$<h8p z37X0SAX$yl_sQOU@AGF!cOv^&XQnHOoFLrQ*p^{eOi%5ep<l4zqFxi8s={K|nLs^@ zs;YDj6sCKsJ=tRn33u8o6wb<0lhQh7K0l0G-N!VlSSLGspx5ke7e=#KLz$ifIAnBe zvZhA3s5q&dpYm(H#5zuB1sTX2sG~oX^S<6u()fV+GY%VFWioO7_o=&GJ%e4n4sSoB z7sEk4iA<y1J3TY;do*kKoUVfRg*KX%^AP?&XL71LpW)KCzVL%2By!B~9G8NpbU+BK z-1QoZw;^cv3?~<e1CAfCBmnmj%*68pI$qK7@sqC2V{es}No?d=4BJt?dkL4uR1|1f zSg>ju)}D6&iLh>qDllt;n9JhvBIFnYU;=`N9e8uL?HE&5+z1701RIr8{yqhteGdEr za2=1qwj<jjfC<3;MPUVm)HoLX$ZqH|P;z?*8W2II1o}z`({E4cfSJ3#N}>f#RBef7 zX}zNgA`t*60NP1&V5lnq89v3twClq!)#1nTsr=*c!)TB$?RA>4+no`sXneo$69r0| zsD$Y*1hg@G)ldGKvyndq_f}OsVgRn%-vz{bhi(=MlqLUOY6R_!h%<-M)S<s+_&Xo_ z8)A3D=c4;YEdZ9g2H^<7Qt9+;;x{Y{XhS=(a~m^y%s>mbnTEH0A7k$>m44Ze*X^#b z+fFh6d-A<Sj_b!~(3mOx>8e|K@p{nVlQI>XDMp9>guN6i^7n$jWG?oW)HBW(1lm&1 z2$IQTrUMNfQ*kBbbag8W8U{ljrj$xcd%rm5{^H75SO}_ZyO-CcTQ|Gz!Z@&yX%g|4 zH)S!$zn(Q(Pa0BEesSgozf<_Pa8$P+;8cRf4UlM7jC&#yJymsBm=$PY#&Esfty#1_ zcB61zLIyNV<l6Nl%c<%Qq@Y)=ShpdL&taW&*1Mmn#-Q@%WTCjg3f=aom+ndg2nRw# z8B3RdAXWFq@!^zl6fAF#ySJ~;2&l^<Z%}fWq65_23`CEBtLSh(KL9TU;p3}xVNaBa z$Y&r_6uG%FwO<<=gbthwXB9@A3*bcBdO7bUc64_-8u0_73A*=Ul3&!>4aJOgwe7p~ z+g*40f8xjJQfWl+m{DCV42t!u^qzG_82Y6eejsv~3sZnLhRJ_*Sse43C8VT(;rz_- z8}%DX7~LOMQ;knWY8lk-ev8zsqI$=~7qe0CKIIIymQIs{rHiLJ4G^x<%Q(7Gr?~QA zR=u>E9L?UE!mO7x`qA9HSspksyutYwFQ}lG*c4ynLHv`seCR)ATpq|<uCbf&lOXAK z7K<Cu`^8nq74V#~QmU`gV_X?^#>U3UuXD(IRCUS6HV8L2ci5<T_kNCBU6~MYtyyA$ z*%zq2({Q<&;Hzb9X4#&e9)sV*nZ^1o&7EP$R@|fjmRSK=8ybCCU_b!*RzE0|-D{NO zOq3NoXuTr{#>p0I*DxEDfu0ngw*Qoxy1fO|y{0POJwnRN%rr4IMJ3|^tzqDpCy00p zV_;wakO(wR14t<TJFodMkPoF57ES|0l<5rSS<#srb}D>c|8r%E)U_VAT*FkY7LvLH z2ed(VqIF}>IIC26*t-KCFAxl%Im?1wdNO1+A6}Ch*8GbbfrtM2*#G=v7V{DHitYpV zrpBrR>IJO}oXj(9W;m=a#p^8O8Etpf|HbH{%cplGGy{Rb!^Q3mjD<<m$-StlhTHRJ zSg=%YCT325H)sV6Xk;vX*m#~0#Lz*|*MA&`y%vnAVZ#7Z1NAkUcqvvQS`N05J0bE! zVkSEJRK^?+qNJ(EqQ%~8kUc%4FRr$gjZ>7Rbts2kjyI5A2h4YwH!w^0V<r6XSTe>h z&G2mE!$rh0jh}*V(UWfRuegQ9?DkY@Egx!6n`1{q7@mvnJ)we)i3+#0FC$pENN-hD zl{BYaapGoo0ZGd@At5gBEs!3lO94;NsTRrz32LR;5FqWRfIbj(P*|?|{CT926VdU( z%#3OP45~)SgsDd$I`I#Lt^m+o4Cpj!+jWjfNC=*{w&CaoRPcoV7he}-ltCXgJu#b= z{`w=aYeb-njQCHYh2@s(`Y&<8<KI+9(CoU~IL#EtEh4IHGEm`66b<Q35SQ(GA$a-@ zB$N_}fb858bytuLs`%K;n-Hfr50}Eb(ffl2gmV&OuYHuX#>Jf?dA#e#)q=I!(fs~Q z`%1S$=1Ah=W}+DXOl(*>%?tK>9<C@)4ZmrKQkBpAU`_l$6vUcXQTcYatPR8m%6jsN zMI$0kH9Or$)|*jZb@Teg-;vgM?Ct5OBGw!=W?H^)82;3)C-v>)W(B!vt*xRX^L&=} z^`0ls1Y<yf6u?TZZ-=0^ytcerUW*e-AOjDHjI?$bN)z(PFDnCS8W2L9+Y$yj!+gWJ zq1gj8G`_6ojX?<LI4FJ*5>I}wftbVS0bW=5Gr{8Bu)9e1HET*rn)hD56}x-q@*TzM zga6V~;~+$A`%*U*@keT9PKwC<F}ipC2JxjSXjfqI?)r^34e06LYZtA;o@T;_-u#9; zY!$hz{Pa!)oD4^Miyqj)T?w7v9adpSWxD(sJcy*Ks^<Hs{ZuixULBm=i24p4^?uo0 z|ExlaZ-3&Xxu#g;TQONwwh+HyL{0^w+5eMMb>kUDwUMl}8dVvyYa>B3HUJ4ED(_qQ zEa$tLg5vGM6NQ-%NgdkCN*}wSXch~lS#<FU;`LPR<=ClSn7=kR?g~if&46eYsi2?$ zFoRL~B7#piPfx9#AMXHi)&T&%4*<Ij*2xtQis{qqcKssoP-Qc|Vb{#I4?OxoB>^E& zDyp{Xvg$yt!83TGT3NYmMYeYHmEXUx;GdQHAg2qe#!_@M%~d`P>(|6SY<PjTYjPXW zLX9G(VRfB1)dvgD%-}p|cdWClHj-o4SURd)_%0gB0Wss<=!l(3ded_Q_uoRskx)=i zpVrkKUB-D~`smSm^LX*9wu<V{*(imqEECHhGi>vaUMm`Ib5<p^J0YRlGGNh`qYM1` zKR>{T>Lefu7$=CF#`QI{fVJ!oes8Is&>v)SsJm8iA?<I(=VfGgUXq{jb1mz-+uX|D zRc9RFj8x<{|3fvtd;S9(XVa~Eeg8piFe5GhRtD(edZp<J1MCVU;BR*r=0sb5wx=^N zQ;q!Mej96dJ~O`SweZOOT_O0Ye?BG32vS9UnZtdMZr<(PQr*^UvJgTt)8`FHjF<na zpynR-6{C_X^ulWrdvTv+j?2Sty#-`NuM1`1^O?lkI(0i5PE3h(g8TZF+CQ(ot`)6y zU`$oyyuG7V?3GK+HE)97Jk%&FU@$$zL*$mb%pDXmI?~)=MS_C|o>A2k8b&|&52V8e zCx?Ip1|8G2d<hdGY80l#|Dq}q=fZeB>eBD^;+S7oL~e!YIZNKcJoZ>)H;UW|e)J%S z+Ykwddw$8R%Uy`qkA&zTM;)WrO96?UU*!SX@YmRQ{oxB_0F({oV9>JPZKG-pgyN;O zhdQ~bJkhIT7X;^8|Me$+SR+VrV}bs>qI3E}t^#42zeR~I7zH`YRLg__Rrn%+?}Zkv zet+5kt__hsKkKBuUp%?T@(utuN@}sAPlp(V6dWPmMxRmfh$rKNr)0^L%)zdg2Xz|* z(BWGESDcHS?sm!Pf->D=@#4$q%9PMT25Cl}*w}cLy~2(^HV9`Y_=u9BkP}T4yoEbv zJ8RGHFYZzvD!6!nS?Sso;gVKRHYvXQf3^|)Ay=<P`bsQPN>|qtal8ouo5uAvgvSj$ zA(0Uv$|qzs-{Q?OqSBh9B>9yNLg-JRXXGs2E6kz0pZ8b~Fi0A79o9U((3TJJ9@v>& zOv=m4E%|zFHhwF~&`s|*VLx1HDvKdWCn(p`*KYd^%UhXiXx2?vs3)wXiLH%&Dn^6; zgn=7R5*%{yx?oF52qt-*CJ6$kadA%y8txa)=#N@mmR9}<sLaYbgx;Yjn$gGGskOh$ zaBlez-|dC7$M2`Rk3ci;g`l??GN_*I221_-hVzks?yqNRZc4CJe_tx|Eo9LF(KT6n zlzW`uwIHTEf~P%CNx+j-Ui&L2>KZ}EY6H}!3UUxg)eNl;$?Zp(Ox<f>OZ2{cx6cxI zVyu!F79p?RAQ;s9{sk<T4s~I@s=3;iMj=gNGtFuDNN}XeU;G(PvY<aAm@?)-i`o<a z6HKA`Pi21#kT9s8VM{JH0F?hnK9d{SbE=yxoBWInwrZRNt}=|^)W-1$t0}9=`*q{( z^o+FWj3b&3!TZ?1g$V1nc7GkTSB}w!Q+$6@Q2A42fbfYhbG7KvpBjeLkm|;%;v}+& zWKA-YhMcY$J;H>MB_rJB`j!RPfVvpwK$t=^;*m4S@w2o^?0lXVMa|D$u{HqsrK`PS z&lGacYeA?2p)|XF&G2xcZM#5d1wHMOy&57I@X-u{%o)cd7ua^E8*3R+!WHO4Tcd67 z5ZUvp1C3O=>YbnI6tZiV8nXFY94XpOX!#AFAmWwqZAmdJ8?xw41bl%JMb|+Q(D}!T z^^Q3$j7&6;l00g-AL}TSOuKi>>sez?VpCUyyN@jXAUbKL9?<H5-{NCfHZ(*|Z-FgH zUaus{u#vCEuTZ{#b1og%PW^Ts`iDX;G#jJMeK^!u0t{B2sHB6MR++O1f&kRB{F}ez z0S+IPlcZ)SUbJykziOxco_8A1I~Uv}?$v?!r`uh>X)h0|g2<@0n^4zJx&b~IR#e01 zqg0!fpZdX;``t^&)vmJIg`w(7wd?XD61QzF1ms50TWApLMkSY|4ulikFK=J#W%`&G z^7dXm0|Jfy0%<@>7D}4Rfd+@}D*zmk3PjliUqXchKVo~ls2-Mj!7V^riP8R>U%gv> zw+!~J_DbbVO~LnB&WM`LZ-qBpZIO)g389N%_ebV2hA29CEGI7MuGDH7VErmAwq3C? zy%Y)KR`9cHT}b)0N*^Q2{=w%Y$Ajms|DFHthrp)Q*VU7NKURD2cc%K`3ztMlqLLU( zh#a2X9!brz-v;OB#DkSfU2&b3BHPKm>=)j@;FT_mzm!xhNn6u7XgJ=`0x(YMbs57G zqdVU+g74wS_K!1$-aE~r3VoQK--Cbe?u!iHCl4Nu+<Q&9i7h3Ca`*LvO`$|tfkn!v zcY?5$6F{5)^+f&l`cCE0!hShY&}yPf_7hK>zT-1)i^Z_+ytZB&R?f7WpT^`m<cF`V zh)n6YZ$~G5pDZP#iBSDydChJ;tZHyN*AVSlYImyC{=gR<lli0VS@_2o4<a&MKg0di z``QsaV<ay5R;ih9`Ceu!iqfiQ<c3vNC5qvIV($7U>sNMc4?~OYG{V%KpaYCAd^3q7 zFR2P;zUX0nQ8wRYN8FX9j`n%{v_0#d!2ymaRg0<%&t2MLtrp_aL3zcZxA`NRii&U1 zp<D}=v(tsk+q>hR-~DB@<5XFoU*cBT?fjMzi?iP`c&O)L&49F&cHg?aJa1oI<E=re zWHH0I-a)t*aoR7I?81}B4@bOTwI!x!FugG!_M+p#c$sHdr<kuZU>p^AMg1*<XqIJ_ zyYOt<hUw*7gK(3d8AYw>$M@M*XQkNdFm#%XmUf6SBqy<XYf;-4ei2$k5RN&QmMaOo zDyZ<&DfN94qurpxk-DHrKGj5(ldL~#cdmRspJd$#7Gozxx+HGFz+gBYyz|WWWh~4e z#ruS9CZE%gjM)=EsVi#iAD_=V39KGXIQ+Q(U({H|_FHDG%e)G_X!P0#jVe4+wOxOm zr`^WcsL<vhn;?B3^;8T^RZPQ!kn{)X7a{rdy#7B<I(tMai7xvdIoVJpefnO_u|mO* z@v8PZZZ*~VmlO+Acil)R>Nvl{HKgNiw{%xHD${L>$OBC?XYThAXYwV7`I!6eVn5or zh)6bGPMJ4mIv@DVOnj~1E*&8N>u@*I$#MRkPeo{-Oxt|_)A^)fYdM~UB#(FaUnZF2 zd#FxO{i<XT=Cl53Bqm8X#EPDPSyz*BM>`$4=Jd6Rh7^aY#9xm;#{K67H;GPYvP?}l ziN0OTj%!@+TD&LQIoO$!WL;WVuyt}NJSG;HWG;8uMQJHb&*JnDcsNR!y|lwl<WwcV zv)RXCYuau6VD~)PO_nAe3U}{@>T928k0@RdO)?IUiBOWaH%N8KN{~-L1afqPAn(}k zk<Gte275_&&dOVR_ce4COB?Lv*<SfKC*Ki?J9Ww!iN&Xl^Bf^mpuuh6>AdfX(c{PJ z_g#<6wz`tlHSV@^MIO>v?1LXoMU{2dIysBS65;i5o7+ZoYqRon5bNZ)?Nh`3*3P;; zZ%f?2n>k;srEugIoFrCMQsImy<`_fISkkJVe(hf-3_}yXO(Qz)vpw0HMRO*Z<xj(2 zS{kRs)VskMhB7|Z*N6g}O5b;Jhc<gcu;^g!;p*2xKaY-<0psSg>V&bTI}5j08mXtU z-tQ*3M4Pw0TpuKwYuo&;((;Qa!AqH^1}}S0a?;?vj&FwDNq{sIxhj>^Y7A46e)p;R z)JtrwA+~D%rcC~F4{@m){_oma^B-z1?0FUdu_;09*9;9_l|`Vt@Dif>F{Z}*euwS4 zt&No=LQ22^b7N5d<r{NivEX4+bj8{HrTy&)Or_=WnxgH+FMoGgtRsU(iB$dTxOT%` zs(Q3{sY7i+HeMJ=zlYh#vh^tfBj>X+zt^2<KYC?)#|(adX$OuZ8_51RO*;hf+PyP( zl{i;+7B(^ux3H>=V_}I43)ZfJROJ&|%$TJKtVf=XVS6;hJc;NU=k21r@r`Z1W#2dN zzCsnaZ&T~;<P#%#mrTbm!w%D@#E-{nS16;xDNuP0DFE!U4%*9d=U&sbFJH!Wox_-e z93O=i2^>r~LQCq@)s)P4?L%hpo&VWo3Fdfe2En^Z%TFhm1HdKDA8<V$)+1vn^^{(S zxCBGuFJ@-6A-WZfN*>iu^ZJe!z4fQhne$ie!^&h33o#J(N<WLcG?d&kq^D1wOs@Tc z4a^orof~}=CFDX$W$gPjMz>+RST^&c_U}>KN1i08ADABw0z&>tCvP(Yi7o|8kgTCu z+7-m=eaXf~OXY*TL5k08F}*$*kAk>7delo5+oq{e1}T(m9UuAm$sp~dUK<u2`p+zo zb6e2Sf7p4dp8uprYlx>$HY*tHtAkWcMlI33&T-_0>!SL@b$o(00~1LlDoevZCJJGi zgC9EaufDH3Rj_*I7eZHBh3}?1V+s=*4t0-2#0N^$tO(nrYVI__{4u!4YCEuLs@{;r zgq=80gyVrI1vyg7OPdEy5U5n<nUC3+hO0zGK<Nu|8p4TozJulMJv*l!bxz`MhRduu zl=|~IN#kdGwuj-qF&@vz=6y5mF#S`r6@V~^fcjKEd4}T5E83cmij$ANq5NxLwaI6g zO7^O?A$6oSN^hRaQnh@P86zM<N1yr6Lm=+nuXlgEgcho2NIpJ$qO3-R0Y=;ljXNF@ z<Px_VPtnOBkLCnZwjo^-c<7{Zw%KPmauQaTFtj&4>a;4Y3)7U$dgMzx6qxtppG*l{ zwaY{ARW%8`tsYb?<ov{F^)#lYwC45y{{b?DQ8xtlT%Jh$IYR#h2vk}9TI%%y!6b6( zof#}RRn}|o@DpyPjeg!*u{A>G4$IUjI+<=7S{K^(0w*U_zhs?zre`ctJ7ko9^V7-n zebVznvFcsI|I5j?^~k4*@dz}11m`VIIcL-uS{KHvs~lN;BpthnaZsVsJ}V!QmR9<E zb2o6}xYYO0R{x*>SgZY6s~Ks;V(s<}_O-{NIUpgi*%`W?tw|2oNupa>#mZ?ZyxT_q z@?l=rH@Uy_8pR=R-uE-^>f^_mwZ-VLPMRJ@2KFG2<FGL8Ms6yLSzskCyzZ&;Lt<PX zq9yVTCyVtqjnb?k`FzRaST@e<!i)Y`D>7B{%L71*MnLUAN>)}3(54;v$sa$w*Vxp= z=6Yb@xIM93KLlon7+;<3^4cyTRa90QvJzz|(q||au$qrN<K^d{a5ufVJk@A$W-2T! zL_z|A41h0zs0a0v_<mAVZ!a%lpc5GdxPuAZf<i)vC!-3~?CceT8@PCQhtMdItc%d| zm!P!f3Iuz=M4fXFZkY-B|16l;*utOVPE3UQG>e<z`QhUQ_gfWSe)EIXmc8!z^Tmhi z=W$rOC@<aKy>nu%`K=s3zk=)VsV0}yW}vAeRJv$PN{r`z)5p}NkfhP*Mk+|{{@sTp zw(Qbs0R;MF@@*eeUN??&kvNB5-pSJ{Appvsuk7vZOFU5hkT-_XyMe+1HU&lGq`vn} z($fi0^@h&cv;@#gi}vuR4qmq~hGYe^v|Qr?{$5p=3&8xqu#=_iC}Cga>2fSJfV(dP zDnVJ5H=u*%Dx^o!r9*JRca)vZ0k&qj#dx6>6bwG-0HO#7K!S*xo<3jGlJ0-bt3?!I z6QPeE-m=kVRf~SDc;yJ8&w{?j!J`aJxL|dK)oVj2W9X9_wg_T%wi>l{?D@WH>x5rt zZIvBA3^QP5*N_w|xdRubvJk$qf5>Whu9QFmo2!0Q*Hf6^F?mz}`gx45i?yC!8s948 z1C-0t?VyVb*QwcAYEWSFzJ<|+OHc#46@tKxPQod5bPWphY~Ht!V<#|P(-!bfTL%U( zKuI46%liT4yVXP*nYaYM3X%v^FwreAEbI}e4f(FFngDU2mC7OEcCd69udqwCy}>a9 z6$C>}*aF~q*MfrJr_Y~#K|QMNJ*N>+KRGx&jCMQ|a^6Y!^SeML@Z;~_?|~vC1|XID z(uX2=uEJni4Va(CCA0fKXGLrmAJ13pLyB^*v1~}b)8}532O$SM_uaFhqByvFSein} ziCyeTvQuuqSqVyJO)$^b_3d;xag?;PmT*qR2B>N(9;%$taq+KeQwtvB<NwPA_?nN- z5tVBM*~s4>JU&0~R#6ZN03yKX<os_(zVUE!K5lY9{gLw~#(<T`_V@79IWW6)9mx{3 zHF#Yt-$xoZoF>$BMNSoP;TG9nUj7&y{Gith2nbKrInW`swzVOv<jDs_L|`B-0aj)w zP&u#znv^L*9t1!;5g?y+);D0r99udGhvRR>KVRK+2L*){=ywKZ1+VqTC%4yR(HjjU zajn<W$tL(LEg2xSmK(M&t*rQhLyIqwjRRy}J3Y_mCtp<kuYs;o|6_9OfsM>k`_VlF zRnFi+XFJRc{*8@NHIqAi{-xjK_hJd-3iXe}!|QueeDS|_JaBQi2*3IQ1Gj$Ax%~L? z_6g7TuJldK-y7Q>Dbh+OQxQB>{{6c8`XBxMj{paF{gaj4unWL-*FWthuo*vlx>%ng z>^XD&6VQweG5b))GiSjhR#Y(V(x=S;L9!_&jl&nm3Bsb}o^%89OK<k>qoQVkQB6`( zQmvpXK}lH|1rXh1zkGR0oqc(uzQ52k@N|&`!8itbRH2}Le+~LYh&bP4o3JN}|8tkJ zCW;i*12*8(=7&yxyW|Jv@o5D5h;#tN5?n^FKjlZLFu=MKg0<58vW55^AC_UBbp=rI z3qKxYj+E0IGU3c*&BHcRNRfE?7F+OIh_orND4V*ONCY#HuP%Ytg94K#kF$<~ipo;y zNK{9RAYM~1q^0thsbV5jCGiy1b31!<6A6iih6Y<4=cQARGeQmpiI6ZJH2{MA<oR<n zBw!|SC@A!{n<cV8=H<~b>(u&yjuoN^i8t}fjOJBZtE;O>NJhrSWqf5|xH4D>pI`6A z?Csfsz-hqGpRx`HHK6uam4<T{am2a+Vf9mTau}e8)YjE$es}(3O)Q$wX>s!UrJ0&b zUzhLn+Wm87N{GEfWyiXn$6mjp!{K5f{el}!{u<k%K*h!pLIg?1?kIU0O4S$EZ!64o zr`v^6^hd=&kE{R|64C8t%y0hkZjABmjm?jg!mfnR%{UGg6Dw_LIkp2QsHrU8JPe!) zeqnu@_=rH;(#Bc1g7G`>e>|HoF3X80JUoO*!*vd34z{XA<5}h9*hmP*de55u>e^Z+ z=pnGLBXf3kJ~%kYuS(O?pZ_}b>lY45MDB#=D{O3H;*dv#TX3#?v~84^va&z9HZEYW zSDA{f2COgbHvQ1JxOz<3!9VF9*8%3a)y#J^-zN$Bl{EjiRUP`rsv`1Nf@d*k4=|6* z_QpslLxD;47rR(gJpW!8%3zY-|GMv^$&T(h52p2k*`A)uS8d9jpzcNYLM2N&2tVrb zophi7kFK{2sB+udhL<2AjUe4EDM+VCDGkyfsFZYfN+SZ&(j@|m66x-e?(S}o?sqQt zIeTx<^L_J&@n_vLMqJkzV~*)nAz(Tif`-!gaWi$HG1#E?W|U+F50C4D3k$mp7pT^c z+Lh*qAqBK>yqYRgX=(d0qO+g_7|03Ek^BP7hjq>Au|q{cdBaI`4<eoQ5WE=m40J{{ z5OQ;Kt37B&4f^yczfb}<B2wAIrzwVVHt%taG-Q<2FAoZRV{Giy>jIuFds_5r-1Q^V zZP?GA9`Opx*`8z<38mUKH$lkSStMQ515gBD4Sw_epO*4JhmX5+DJd?uzPhbDo6A#J z{mM$k9C@T1N>^meN$@!}Cj4n|wvF|X@QzLuddzCfiST&36N&E4CHkh8B+iQM=Al`P zq2c$sjAiYP4&9DlUJii@9rYVG*DB89(%~U^5c_?s(9n{*z=A8xrP-qOj2}>FS5bIS zPE~OxTg0lN>U);zxi-Xn`j1pF|LEi6qjg3?LUI7A<6k^40j_23^A7N@@5r1S9VLN5 z1qee?S2qmYN?6W{(|zvlF6g~gSOLKzBGTGNDiK%mlh4k3%B+1<OM#4xf&x9`8mr}w z&%eA$0J>FDVprD>Zk1`({-qRu`Pq!qPcVKE2IxUf`VN<4&@OJ+#`%-h)<7zLR$Nv~ zc{yDLT#0DBXo}?(K9Xsd`wzOgsp+X}2Di`s&X<x?g}tvoHuQ@twT6&;`c_5hafZi# zlDs~hR1xHIfx7f?F(A$rdwh1VM^X#h4H@th8(f||TU;ThoD{>lKQov~?C2?i)Ie|E zF|zOJH)vqmoJU7xstY93z(qpUHKb5oBg<?+P+eUe7Z<m&y&aK%cGXx~Mur`fRn&qf zo~><c?s;p8j)O;@7r~zStqmb1IquJe`lI5*K|p8iAd}&5@$lv7w8%bHVwN7b=;t+^ zO-+jlZX+FIW96b;I(3#}f9i(S`749}YzJ$(qpAG{ZdlF)R;%O3#sc{2vAY2Wm00zq z=3H5t-IuMm4W~;RVbnZ2nVEUibSyUnju=CG=2o875d0rUwE9y&ILxmtg#$i$AoQi^ zt{vW5^|cKtfhUTxD~ej<lk>2I-qTbI-C*p@xYL*c{TJl0h6Ehfprfi6we9Gs&m5Rh zQ2n5RDUqO)Hn9#vg^s$Olfz9mIkJy8&%FDvd%^g2L`q5+=!pgoGGgGyQWI#O`o!=j zF8HyR=Vid}ou4(_v1slCKq_i!$qJf*h5Y!zv9h)Xb5E`w4ncg>)bNs-ht<h85=wq* zdH!{EH(dL~p^`_nAlchIJ9|@IRQ&a8>-7{Q4YX?m@@Q>mSF>jaym#a}vy#ByAqK$8 z+}dGWJKI1?kLtO@hKL|PGW+4%pfF4cS$6_B9}l7t)m<$#exY9+N1q*O9wBkx_|AIm zdCxV^9+;1Ce<@wjcSdlPX~)l>`4lfw(B7?p8Sx3<NYAfcIt1Jd{%9-`Z%O9#3)R;u zyS~yIyoL3QlQ5!m&F$;$3F=ZneNbO`Xke)1RFy`S%F;ZhND#K~UK75^ozFZsy~c4F zHa6EIfy;-QDHX{D62A3wr(2RDnJSE6`X4~eG(323vlZNG0FNdHfd_|MTU*oe^Lqr( zKm*_UHKK}HM`CcH%ot<I)y)lDnSul61WTfLjwmT9X<=taXWc_YL<DTO-9m*h====v z2Ka`CMx`OHT2})<2jdwM5)u&gkUuef%3*dVz-dW9>n!<wC>ljNiDA1Hj41(JPje<* zda22jO*^n%Z7veLiP2%1)0q0xKYAH@9+z5=Dg%nqyFVxKzQelfd{6A<`I%b@1QH=y zAL)j#kO~Jezc9H+=6u0bd2x}rf8wRj>giJLYfzsKeHa)gD>allpMJD#MRA&rpQiXS z{9}2A>T(@>|5BS2c{|ckJ!p9v$Z|>)9F*Xb&4s0@E5$=k(o@#sM(j_K<{R?r2B#>~ zZoLmyQ|R6O+NKDtbIiWBE+ILYbj6kr4bj&i-zXUhWjt~~SHg{mjYWh+t`|zM#wCi- z#Ky-512r8@038!ebhFp)%&M^yW$A#^d;RpY+t$eAmvXU%$^YSlzrl%+{y<z#sJ@h5 z#%X`sD0Xo&H5Mtp>E47{QE}c~6TeDyH1*Ml3(c-j*leC7#p=RKRJG|RnZoDz)#y8v zgxx)T9lHt*X7ypnv4|eSIN@**G=5Sw_ru5SvZ*HZ>kFj!?+Tq3uA5lOPN9rU&2v`t zOA|jeH-v4eGWJ}Ed}N8f+Sxfat6S9teA*$YJsKq;krD7{DT)Znc|0)~*ZC{p{?$@; zl<`~hXX_J}$45urAy9B<5t^<xzK2YLi+kVy`90qz@8e^8AW$O-c6&2?b_=7xmqTEL zN-mKbfc>Rre^g}5IL{#IqH*e{PjMg%`}<zAVKsn3u(Gmt_V!A=dq=g`aCfVfEe5U^ zLUL{g)D#u5ASUz+fM|_CMR6r)Xld_3R2UxtX=K*@AB9Y%!YQ*cEenN(MNxm0y^?{e z15$QyU~4g?mBElv`;{a<7d#8LPB5g9)YKO<&8%ayJS$*|yyxYaV~}53`*6@#H~NzV z;?>JSg}qt*TmH9$;m+qL6@^<{0!Se#pP+X0AFr9s@7^(oU0;eElL!$~RtRaB$$Q7q zdtRP<&?NJP-1Q~-+i6aQx>|^f^GG*Q5J$9C<yt%$n8zW0YPr*}4d)GVJv^lW3?DTb zJUvcaeIQ<UTW1`mWkjGUC}<hd235@)$W}<zO13deiRv-{)aV`rw55%QZw5fJ1u#dN z#Tl@fqS?duAfQ}JpNx%(sRg_nNEz3?xVU%^=q9k1eaQm);H>~&w^L?NGfDel8QkQw zLkGJ&H#Y}?06^^wR2%F+DD&z_cA9&<*#{FyP+|ZF1D@$Bj8-{+_{_x6o+$*Z!O%h8 zDOhCDl&VSxcnL+p<MZS%PgY%+&-IDMu7${-)_Wn{dG4|w*OW+QKChobVd<mIUM`X# zesYqFd5|-I<4kADJ4ePrCZeD@!1%m=7V)(4OYU97r_B>Yd#`f`mCfTd_L$Izw{w<} zE-!1G5*oM(L(fm{gd=Av&JLsw3dFVw($C!)x#c_`GIg9vj17{GC*j~c^b@H+$32=) zgpA9O9t8zy`DkUq0>8UMm0{QiWks_uE7&C^k*M3-7OU;RejGNVvMt2vd5UUj5rGHi z0O$q0S3XrZ6gbaC@G2t&0$w4sd!vqZAB|A?M!4O816EJT>v_$4>?-v0=g%jgqvnwv zsL@)(`d(1L0-owcfq)|84nXC47bhBSFH!T<3g8rP>PrBAU*pHY!C|+W6YPn9ibTw9 z{v;fe;7Q{Q-x;W)Z#`TF@09~Da}I9rf;OqDW+@cN;MUU<NFyM|pz9sb2(CL<&_A-J z_V%^Ytl@2S?jM|P)*NVNPUtZ2#HdJcke0vq8!PdSKuS7RK<wTkhhz8+eKU~~AwEW2 z(d%r9*Uz?o1CZUNzCh_CEmU=LO;PqH=c5`Y%1%}%Qyd9wr*KblV~#A+(~Rd|XWh|V zh0x-B$hjPuwSA=K+=){}o4`Hhc8}oW*IwK?DKpW&8bY_a_w5^Sge1L?&kp1xuY4fK zL7`20cE<0zMXuOw#suFNK|#baa>ruy^XtLh$ROqp-Q32N6dPy54oVe*PobXm;T6Ow zVHkx@DTD9*7(N2B^9;Phl6-Vuw6QaS8boSuuN^@9L_~BVKk%|nIuwcm;!61^Njj_@ z8-tm&`u)OJ%%E1(AKdOB5pu-^(9yPF9rW5oB2MhiZc5^_Yrl2??Gk$RYO1OhH?vdQ zeGpJ7K2jO=C7JA11JW-@0<J7a=Fiu;InmJ3y#vG*+zx35GGI3P#Gn()&(Ckh`VSb* zLkuEzQ@lv@Fe8&;X6<MrZoYo7^~TDb0K{n$NqTtVWf{8IBqe|GkxY7GO~+b^daBj? zGg;~u3R^ngjpu$>k`W_flfOl*!Jr#WAje)|s$ykh%;y4if#2=73~B|>kdD42=kYwh z68SVdt;Shd{^`bxa=FpSZ~m5{I@}dAtUf*RibJ$9xz2Urbno@y^qR$&@&)=YvfmJk z6vRgqi3B{oLvr~11x%ito$fi`rHUu9KDIirQ;@v>&OY!nB55#ymVO}a0~Y)ow@vHJ z!rXiSG~0z0C61#N2_FxL9h{ti8;Gd1i&~JN(9kwO<lmT?F%iaf8GPX|L^0}3@CTj3 zU+$T35`7}(!2o^e*VuvgOGrS0DCUhKW5gnUxjNp22S5NO^N7Bp%2ExUHwUda3NPS( za!G~~AvifXfi?nK9IVK2AlO6s0GFriPkV#yTMyuZEZsAUJfHF(Kc}*=W=luP8O1yN z)sS45Td;7*Q538yzOm53t!AxOT5kzPo|1K>j0)KNdIstzE#Ep~IDV-$XG{`GqFvTw zK8K%YnYZsXrV{%qI)9BCKb}<K)@CdCt9|+)G>9{N_Hqb66y*{QB93jM?bWuq%Y<b& zZ?|zdGX34*Fj`irbJclgPvBr+w_>qIWbDnHRRfPDCRK(jFDy{GbIn!$WwwDh_M73G zlX%$`lkL5+`Q8=;1xdt=yg(V>@$vVZ&YM|r5D2(&#=ydY00A}Lyu7@PZCSTvuBSV} zpazbLi3v4>;W^fQUIBq|lylveSodo|j|3o!&uwhj?~8gX=lX?*D-=|@){%kx{Sa^P zaLlvZe2->v9UYST+e<UhG6AH8pB0U_3=bbwb3sO5yX{wRv+C43V{>zJ4{V<toSiio zJ*j;Br}g**<HbmvprJ8H?_vR){yoQg>)C#mwbh#(a)Te=NXv9pHT{!5nSUh{4E7+t zZLgPed&^OpYFW%tg|>fveDAs$o@SZYiLBYLAAjs(W|Y)}?d!J@KBuneE@zJ>s-v=k z5+o`_;jocj8KT!kUGEzYRgbJ~m#OUCS7_}?Zi&oyNNDU-xVfDV2h$1oR&?D@m)~92 zJGf<@QBqaoA-Mrv)AEsKZF#CBN`Orm1i~yf)s-apOr;E?n~R3o0TszaLUlUWX;sA{ zQNX(q$qg&KF_9h^otz}>>+2g&j*5vvNR~$u#d-p6mGZAY@bPYJY?K@avFwBq{|d_g zpWW!}&h^L_!k*>5quAe)ud_*qp?Y!qC*~?;H7Q(vgKxx}+T4@)98m(x_d3EJO)Dy? zy<PmM9asERS0ZrECbGD+M3dlGv(&f;D~ATrv5?34n`FDQ0!{ytj&Mo_?m0on?vPZj z#~a!$X)GO062sQ-PTcK1m*iT7&jnYcV+_LT3Rr}lJvnuWZjt9wuSgw9g{M|-f`TA` z8kw5diZ&L^?NyFW&rW5P<^U)Ufw+5kEN*XW_nZGKluY%58)m8Qg=W?POJ#~rlFSvf zO%nX&Tv1#P<&2;6us@FBBd}EM7tv^d<`PWDT8KJImIF&Q8&LO)01>U>6^ELJazGzu zz4Cqu``aOmM&OZkoo<J6$(ITwx_ibMrPN!|2t&V$G?<CEm6^z(9GuNmL{z@Rs}6O= zjBpZqAo`h1Xm@YvlO|64viX<<fRsGEo|ir7yD!Cg*udm+XhFLHBoM?3c%JS}!MUq~ z^6&YZ^1-AMo(L)6c@U9ILAj`k4#B%6u{?p(_Q0m@j)Jaj)o3+}ZF{=NTfPr<W{!*J z^TBxe<-1iUO`gubb|WH-8I#G9$=nh6eHW|yt7~|ho95IwVm)^*XKgVpbi!XDVN&Fq z@f>OFv%j+B-O$ctJ`*hWI28<IzJaT|J;C<5oKZKE{~XSPCwBv(mrrf-YDfwN$T(z2 zPMil5$*n${IwSV2nVI$-%^%Z#^joRGAJxL~vH{<78et*?qdH=WUtmh*@MPG;p;IW; zx3uN)M1>98t!4uf;_OLF9#2%K<)HJ)HV=(HAVTmdF8KI%sM{XGR2r^+rG-C!h+eVY zG+-X~{SfIHmli;372&|>@JyUcTPM!gn0aabg_9&@P-x)F|IXLRJXOn%-!I_J=$&xe zTq}<AcDE+OW2TCUTk(;45QzB~jRpUF9SQ;>j?b1m6_E#H+~I3!l3l6a`J^dNa+<JY zHU%{&!6gaVAO@C`wVuwGr{(ALG(V~!7pAQLQh6@c88cKtpb(ZCb`xxZu0_r9g6No~ ztKV$EuH#|($kx`h$BK9eqKDZE&3+41eP8@dk=vl%aiBGNaLf$;{d;xG`Vmj8@VIwx zkoJ4yF_Y!34*7#}Jl+CI{l};#0`6efyS-^{iWW;VG_wS;IGGBIR2^pr-9Izx+e<T$ zl^JSQPEz0tT&@YHdON9Rkla;j-L@MC;uOLf+>a9SJi$wBC1_0CyCw(x5tKt|R(n+? z=$?*)Nc-=GpeJi)Sp`DXVPCv`LxfEZh(c{F_g#~&jNxInYcF%o*H``XO1&)ILW*$R zlkdh(%+sX^sW+7bbWypQrj!}w3N2yvun;Q`dO<k~2xlT@Vwan$)*XdPQro-2L%@F= zj`06!idlg8*K$6jV^#CzsBpu~3!uU8SP|Un+-DPObqzIXS-<Huc6q!!ciXijnYEel z8J*L?l}4arxga3BO^H0z8{chRDe^KI(ZW`DI2KAx8d)%oI^B7`bb7z_q-Iud>>`*a zk!1rFf+Ycq7|7EyO9ftaq-_V?J>R9d@yPw$eb`#(^mc>vhTW@;(f#adYb`G@Xo?vL zs3qW{Q~A9Drwa$gH1G4EJ^COOPvCf07wM8^xO#pPURL?V?&6pTDO8Az&=&LBy|%FG z^k-S3_0r1fD_g*d_ja66tDVA14)S2dDZfX?SP)FcyhZg)!$IEqIW>IGYghfH7A%rA zq<Gn}uP4W_K#85r)(gf{t4k!WqDh2gHRDC7mAntdo9mee$h!orgd$1yL<)5m5}D&6 zFoydI<9aw}Jx=xlLVhOmM2|_u^q7F_!4;nS#D*48i@^Z3&8m6Q%mFn&h8qHDV5skq z+SIIug}!ebIeCE68D@Jag2-||X-z^I2*7ER>|CUT!4d=ok6D;HoI+yLYcqxf>EgQI za3-V`M0(Drf6pPX^U^`d9MmuiMUYWj=#tu#dXd)PqJt~pUSj<K1to+AcHZ3PvmYXd zIA#VboSxP){&)RUrgFcnLegu}g4b|^=tn1K`FkU7k4K0HDG3;3<f6tn2;~@lvb0X( zZ1UFbQk377KLU}E6Ok8kzk1yI)5jOIY4j&ABq~>fD-ud|ozucsF3-#T_>FX@bA6Gl z&x=Ag+}CH<io?R|r*=f=i7r2Kkeu6~gx#^@zfMi?#t@Sf`}X-(*YSHrONahlsEq<z z%hkMlppX=f_E(TPp4A~C&3_FCGYeck@<km<<alCMPau$L$4?Rs!a{GXj8TDLb5tF- z{One@dJ^cqUw^}Wyzwv`72ob)xu~H9F#B<lvBi@+LDZ~_%jwg^ihcG#cl}K2gGM2z zH0kUPg@)U(nQOS6NiXC<?DT_^*px!Czw>yzsK50gFfI?~sc@y}(Lq*5%3jAIhlfrW zEvzr$lDrmC30Fy1CE&>9H-9f@oB#MJ+77Sq%NEC*^JM3PHYpnY)fg@NYA+Hr#8;W) zsHaDMKP64-@#N@mjr7cq`DKJ}pFKQ|na&xwy2w3u+Y<=Y&C4xqbD0p@Mkl%2WwIyd zd$0%}D2DY_WaY%(p)JX2t~DN2)7fo}geE)HqWCf>=j71dp%~CgFh-EI9j`4gE`%=| zDZ~R168CdQ8M|hhGv2MN;lpZ8#!!W-Tj3$@bwcdFiqp>*<K{uC@UuM!I;nmppqpW- zvIvm-Nau^`qD~-uHOhFsoh!w@oQN=>ruugO12uu`{OjIZt-rf>bh`eQ9>H3|<E$|m zkQG+ZK?ZDt&0z=KH#}7;YJ6DjeT2s;mHeJUvxwQ*!a=$3lXxO>hAiUoVm<s%$%jyb zp7)&T<C#_&X<zeSnn~Wjk}hQGPAKo2T<-X8wF@-Iy}^a~wCV26er+&TTkOq^vg;vp zxjb<wwM=&A`j>F*iK7%PyXWp6-&dkAZJ2j)>D>8{;;X7yw5YK)Q*~GaL*PNY5y(&3 zqYQ?n)+`E3bCpV(6*m_8;l5|M5+EdDnY=`E=3Xnfu(<Xysn-2#lDt&M#QT+1{EXU+ zhme76Df}*X;4dq`yx0+ON82P^f6Eb15%p3;<DZvec9DL|Nk|?wE((afWtPdLCjyQ@ zK||Fzlf?rPc$AB`a<^}zM6I69`3olTB?Q1Hp1nPTk`Ac7XVKx}l2DX=LdWc^V2hT^ z@X^^|hW^FNe)C_|*rLE4DB)CJjA{HjM2bu+(lPPXZubm(4U#r1Tvp<umk;v2&fYqA zoQm$_-(mtMYuX!(iP@6+RHP*(Gx*EFC`oj5jCQ&*)el5A$0JaxMrHbHs4qz(s~iO~ zP^56uu+LaFI$xs57_G>#5_y6D15|pDSr#fzPK;>vcTB_cxm;9!i9(9%@(ZbQ0a-)f zK|F<Z%hr%CuHM}(>gSB8rGu`_@?qBl1TYna4J9{F(4r(jfeZ&qY9f+jtag<*=$4n) zZ5|I0gGvEKaeL$sTCcAHRnfsVDkf?B*>xG)7+k$I*RCh@pF{wP!`w95fxdso|HxFJ z%-}lIWL|%_{D!C0Q6(sKh5xE&ldi~tk_*AjQ}2T?rjR*V2;nc1)1C`9SxJwm@j4~^ z@cpKJw)wCH?SQlnyQsy7xGYs{$Z(dMxZ!>-dit|_bzcPc1vc!*^5TND0<vKW4u(bW z+#3i4)U`z<Cx-9iu>{I{UCdj4@DwIEZLIsQs(v@ENg0>8t|#-kfjo?cPE1?X;qij@ zO_LUg38A>`S}k9>x;>|hYBJzRm(DKPF#EfqSH_q>%)d0xcE<o0qlOW7x-sy$mVbg6 zAC}|et>P@u{>1PxhvBi5(UeQlgd0hX`tGx-MO;*M*<MkL?DiGISBpD~%!H{W2150h zE>l9Qi~p?!=tVE`a*&!Y>A<miUq?&c5I%<~cz;n@-6UQoc)I-tbK3Y*UAhAcrN>z+ zZ;dev)jrt=OKSS(%ZqGPY*Ag-^A;Y~PWxmUKWv_UyQ`d#j(Mmga{$X3fPzMD39S2& zXC|6_YWb7M5JkpEPvT)|;H2)J=1*353o%~des#$O7ksZt(`ORi6zR~xQ|P1=@j$SO z*!3(6#c~%aF8($VQ%^mSKIbHZSZA5zgORX_oamq(ET1nj$)FaZWnp`Na^(cdnD^O^ zmH07IRIycy?#_HAK3!Co&!bl|pSujdd|wbc_eXls?nK7>L0ve-I6{cZCrflb>Tahh z{lvEKoBsN*tPO$d2S*w!LJDu!)r*=8zI%31D{(Ha1f+hhc6q!+=6WwV)fvZBYIA;F z+8<5<vmU7haW1SVmbqiefw(}01)GZ=6My}Z{<r+*Mc4>;UzdS6&a&9PnDw)h$6R+L z{2%2W)PV5Jn8jSc+p~GI6m8Z1U>2@>b3~x3flkS<HteEtb$}iA1HVU^0*oTykm>Hg zNy$<Fo!Hd_nN6DJhB3@oqMvCzX$$X!`$z=*eYG*(bbKuM%NA(1Ob`}j=r^!N7MH~H zRq6wnnqTxoiK=s4j3c&EXfa^?_3ft0%w?x_C+kg0Y}ccWvrA?gcmB12@p9ZK(ZI}Z zV=9x~vyJNs=T;FxJe0CyUUlsl6su5@59{PESg#uHu!$Y_%aqH+M@T@34u&i&ii?%t zaxf-ufvsQkY`dyTdCgBn&qglwFe)M?;z8!%`}*~?;-a##7<*Tt!kq=PJT+0e&aEW2 zk4ss`g}Z<%oz&s}11MHuE`c8WHqp=N{>*9_D;PU!!J4EbFx6I#8ha>5_3<bq!sZuq z*sh?DpJ8G|T)f%h$6PMw^HnK!;4>qOhki-hyILo;odzNQiqIiOM<m$d9V%sq9riSv zh<@WMYPNl@1NNPy3nH|sAH=%zk;jh=C(c?7Xl{j(W>Y+o27M((zbQ(u@tSac;og&| z<zBLpO%TGoBT@JP7H;q|rO=%X^qCPKiRBgGOK5Pk9~h}7CnNEr4(|HgZ2-AX!0PY8 zR5pJ5<hV+P)W>X%ICPYra`PCGKu)rAb?E!Pf5;@b+k<s~v0C)aKMTM5z3>?!LX7mO z-}ze-&s=RQSoCdiX-nhI*8!+`hyO7C=j(o(9o;(kt}B8kz;P0}qe|93mFD<1PCRh4 zIIfglcSvCw8uUi5%fUq{qHXMU_ef#D=^RIKVgdrWA5U`A(cirGn0nh~h@TPF?z`Pu z9&fcfo$IFrzwgt5_tZ(-wszM(y6np}ZXU%0el_``o7XDKG`REOe~&wt??IPZfsc;b zl?u(Fvbt_&*ZpUH;c-Zj%JP)-MG#ltd(!^L+DDp`d=Q9&6Hn(VhqGHHJOm99{)gQ! ztOfcTYjYztZttzWX4XCjuOfO*&eEo$;90M~RbGo8M(`hCS|NH^IZ6}LX7Jyq=C21C zeOY$~K;sf>Q{?l+<R!U>FtXmvx7SV7c=E_1Mj<eLE2sFO&Dq|c3|aj68F<1<x8p0` zsCbLPIw~I!AM?qV4Jk-Ybs^LC)D5ahCDtcH-939!-tSC!`SD@MuD%H^zP$d?h!St@ zG3qhV5&LxwdOjEZ$UJ7ZNTLt*<6P$>uaeKN6yN(x2X9EaRPw?S24I-p7a?Z@#TqIq zrZx-jsazd58LGT?#8JGvNnJBr#EKo(bqUZAX_95d04z9~0T^1RrwbmSq)T|n%&bmY zafKLY&3{V%GWx!Ugp&9>TSiFZaPKGy|6liGz!x%3gMT}LmJreT#9)967<!7pZopt9 zCr4VB$OJplCx#x@#`xA(ywTQJ(_S*qBwoh*=Y1=0r*Fl_!S_P;SH5&yym(nsyq&gM z!>2bpc=p^BDlx9d=RvgRY`XI3wTB_W!I+@=^@2^v-Z0581=2RK|Bc!DddHrgjDl1( zV+q5LIpBzmdK(K{qz+Hj=hI3vno)qwe|7PCYvOk`zJ+gI3C^`gtu^aYR4<EZbnP;t zL-q)WH>uaY)Yhgw<e9n3{S{k6ouuUdAf@Z7$M*^g`wq?yB>|v7jVtu)G645cHtZim zn33T!sGGmv9k3_y#v`&}^2`inUe5b8+*I9bqs@YN_t~(kIiJ8h@9!}Z`5)DJ4RC|F zQmNzP5j0Q+3*-9&evM=DvtP@^mBdX%AM_;)hAh{FQNF#vGf3_IVcj+|W|G8t{$^6; zeG+HnAsgQH2LvV_p6(Q-CeO(2VJQqP`<sj;bMtFYVZ??fV}f}0-B=UvlhT-&$~Sa- zX}32p@=2!gDLu%ahZ~D{+dcDJsi#1$ERdn6aTh=}bJ}TNxex&rJsP=MRHh6_ZUT;P zVV>R8myF0A-{|f;GNLbb-k4Q8^du2vx!!Q9r3QUfo_zCces1kT3~Ao~LgWqwfG2+$ zwPsQM@Sz{JM>lh`{9^i6#`X1Ar`i#&{G?zzCaUe&PRV%Tl65hCn~)*MfP~m1{;%*n zPygI9JB&~@i2#bvEkD<_V-zPhvmv;NVUyyc;PYhD6{%~geaL^R$y>F5|5mqzxWkdO zSf_Y|^>H+ctj;whs28JM-gY8s1p!g+>3VgiW4Woi?j^VUq{GL1u8y41(5*C3t5UhV zOaA?KHjt%W-HyLx+3D-PR_KOXs_1z3{D-=l<8gV`sKwjcip4o?H~qot(DV6>EH!9! z5K(h~OA82r0OzNK1G^qz+4F+=)`E+5Z3WJoZ-tm-BfNv0i234KTumZsyC4^d2+I}e zqZqB1oo8Y7b%WV%_+6KPQ194LA1n{e+X!z{F*25|xv^uvb$0HY?Y;N~OGE!2IWgb{ zO%CY;<kPnU6`@LukA9<x^Cuv?L<KmR=LcO-CZm@nWod*lgpvL3?pxitTQ4ht{m$A; zbb4esU|hUAEr-IMnHZNGG<peJmV1!ySS+sXP!I}uO#C4AxR;in2H9TgZGvZOFd{?U zu;Cf$BOAb5)pBoGqe=MmLhA}%`SudQM(obFFTCMiOuHtBRIcKiksIH`iCOr=(a2Se zTFcBBC~d~}gJa7}uPc~U?5qY<>Ju3|nnW8dLs5<&1+uk`qhG=06g_)YP1Qmfeu{*= zt}yVf_mK|{e|gK&)vURL(D1LrbOuINQB4U1NMl>qgHy-y-qVEt>;v%I4xmu~_fE7o z)pZoSMjREzx_{sQf)Z>4`|r@O*n0yA?#FMWqZS+qieFxNA1@nQ^Da_2=1+W#^m&M? zF2|FIz5nTXQB%c>_Fo~=gBMNe2@dlZi}xbUlGU_3dWg?D?u0vpGE)P87GCnIfEgVC z=~!zJOR(r)GZ-<kG1x?-DY(T;PIX7M!Ms62i8)59FK2u-N5luGA0X_lfOqYOUUQ}e zw5K|jg51h1?sxYrp3ccG>^}K0^pyS0y|Mi5ziUC2u9{%n;UU(J{_evKl$1Hkpx`2m z<M!4-N=EMc<&NWfYs%z+ZmR*hox5)B?nG67Q;q;K=YTa>I>HCc2M6kTs&J@f4QDRH zFQ+}_v@+i4g!xeuPtTHFRV8H~t`g&=MIO2@9oN+}7y>+2Dl2;C<sONNg&DYa?pI_F z)%zqXjOQdqgcQW+;_653Z0s9LZP=D#=mVDPCXcKsHowA7mI>kV`~Qhm62mAUvTyyE zeo=7&tccGD<FvY3fXhY5!UY7)j2Bm6C44o+fjAgi-?cKP_)oWeKwLiNQ@ku4n)BN0 z6+B#?tJ~j{&$4~eXx6GXsmOZ2LC-IFIm_~ekN1at*4C}@eUmW{?dKAnc#b{J52WHe zg30>p!$C2ZS?}SAb%)b_gKw!Fq4QC<Ch(hvz|rL({>6U(gG*uh`5I<xrLKJmADTRn z&Vs`x^~n?aok~FU_4<r|U-bQut7|gZ1->l^dJ$n<mtof2%{+K*7~`Ku2i5+IsA6(d z^$60zIon>_?<mNcMG#RHZfzvGa8zlY<uN>NN-e2xJ*b#}8h+6_j}jUv^3%4TXM2t% z3na*IFE<`Li#tl}uV*)B>(6W1HN(Syx4oq2jZX5Zs88~rX{KUQkroH&`JWm8YtnGF z6j5DoIO6kPOV>~$!}&b-U~||+hZQz~$X&W(XJTne*Zb!-y4ZbmS<4%zVlOnx5hSYo z@d^`i7D3AG@V4kxdig7vcKW_^LRiSPn4ik`hGsk$>6Gg##jN3i$TyW7H8gKK3;P~C z{cVtlZdK;wndQr>$4JGl*L4T`+*m?VAf+7CSGHy!9M;-CdDl|z8+h0U{OR+&vgcXi zJoEx(MDj$TW!-;=7-1NLDnsof3<9)^Oc1Zj>wR}5w1^FiGjqtElS!Wg^$HV{dD~tG zM8L_p*zj=-b679!FHh9D3dob1#P8*Zqk~B=-{@sGPqt`s+-_GVpYPN>V$qUWQ6=>V zx4g)kJj;jXG?G7UXbi#><_>pp*g&9fc!F!3VtRU`J#_(}Xmh)O=Xc_DUnnK{zSR7a zE>OX0?N-4$ad<<LKUa=J-hX!w(bL*5XVU-T3YM_{V_0gz$js9ZO~PoG+@F){h}cP6 z@_g%TMw@gi^5DWl(+dWu)@LNXlJEw5jqNryv0P2Qj@M#|*9mxlIwz(m``zGrA^4T^ zRxg`YX)MGF+!l>qGXrY;#iLl_bnakRN04{#gsJ)x4t`!U=#jpaS;UQY62p>8vu)Dk zp+E+bNJybV9lC%zTNiGXY(OC5am&K=<wCZ|_;OxWcYzA?U@zrBN8atr|DuV%{<a@} z2h3ygA?7IvjTJ;H=RR|`$I1X1TDx5BBCpRpzXct!?jC~X1+NDuIuiGOOQA@)n08a< zUhXb|z_P0S&bS0eY_gu8Hrbt3$oNA-s$HX87B;iux)W8cYwjDIPf5RWU3!Fmpw2vB z{_MqH+_v@Jgf8<Qy;{H2&-PU8yUy+n&TFoT2?6P~35FN~p<_=$_6^n^jZ)lhZi`|- zM0T}5hgZN#g8n@+)L><xj&z?z^+0f{5sMrYfKqNLXU~1ldBzYUcg55Xf($eb1cY7d z*7hBgG|bbVuJhf2F(0udb3epJBk;^N$gfonkv|JBk;dQp%_D3a9Ygl+#(nk=7MPY7 zcU-FS)^@EtLgsZhW-}Z#d|~xycwQfI^48M3gDSAD8jn6t=g`{ijF{F6xYFD{HD?gM zb-Y);Bk%_Bh^cG}fb0JhksQn45^}GJM^B>_pp?HV=)_=GMBa(LEh@H{dPk+Gs}+Wt z-A8S*Z?mIWheMA^qh0=nifN1M98d6Q&MuNYbI?yWygt|`GIsl`TUIB9$pDYQjcmxC z)xhS#boO1~VCr4J;2IttW_VCvr<~ACMwy0;swVbr$`!^#^&ZKJ2pnve@hB_<+b$Ay zdMS5yPZAD0TXvgMK@w^C-@A?azou~T1ePc713pu;#?Q#mESnq2)vUR0FNIZ3w+Q+J zWpbUBYF7~j7Wj7?-wk;GkVS)CX&ZZ(32%8_-kSm$R$Oq{S*h?jGR35<x^Qp9jdfEz zWc>T;I)d{?8PCGnx)mAmlSQ{{{%W(3@pp2DRqMsONBGvxUG~S<<AKOkCm*!zt_6h- zT9EdsPIM6GE^YDp42(3>l`~GMC*rc%VR-7Fp)?D#+{PryoYqIylAe|kWinN7K}hbc z(udIxb77<Db3j^Nz9?o#bA?Cw@yq6N;xWmTD?~ue+`s&}*&;Mpi#}CRPgduc5?6ZD z>vI0fsnD3^v=w*_R6=KTkjLR}4i5xRINwc{K6ZY)MsoDU?hUSBrW*yli(bgMzD3*m ztKv;x`UULCM|G*GD5+r{X1&44XpKKX!TFn^m)A~f<|}yRH+OqjWt>(#>N%?1W2}Go zbNS1lXtBeHVfsL)H#gz&3FfcDy)k0-*#aI=qRP!^2yzXu5)~%N_AWc#>Se5lu@;iQ zOH}AgiAi3Q9^MW;{ysV(-R`APOsIEL+b*s88jom!wo16(BT;p0qTZgJjO<R&84)3| z15x%ILq^J>R9dJ&)bgijKA9IAoa>B#N~VaPw#KerNFlq@1n-sCgyX`Kxr<9;mG>9- zP%;8OBBOo(D~$e+DH-_*yPk~U?}zkezEFRRb-5aruinM|@ZWqjzez%A>|Y_gHCQpS zTx*J|K!okaSAQlt)5K_QY1!*lYG>U?-)21+2>TTh46~rDArDUCbP_*Fszk?XWZ?}O zG#A~SVe4M52^@Wi(j#yeIBD~z7RXnAWfoCvg~M@r=YKFwE^(%`-!#ahVyg$rwdd+k z9o<Ec^2&ExqhSn%Lo-(^qnui>vEl!i!B?=_O;VIl^VhSBDvZR}B5r4-q=xaQHrG5) z<6k1v*gr?6OsB!p+ED)Lo0A5|tphNcganq(*Bns<T-1*Yy{d}%k3Zrv`Jg{$^g+q6 z&mDsI!&0Vux=+4C>_MO?9qAT%;n{bX<WX4l)N`4Pa!0r7Rh{GN-RzjQD%ZA}s<=N# z+_fiR_EUT7@p~4pD>Uc5s<q7G3L*miIT{0djfNMxT2xrr`#9#E4sxcB$xL#7GP0KY ztn#s}`lUxcRbz2hm<<%pK(RUGD;c{>`8HW+N|gT#N4KclgHJ&qwxP(c&k5?;zlg$O z_?p6LVs~q-JceIyQr60=R6J^}){Fs<fk5LJ0rK~_#=-OW@H|I4sY*hxX7=09(To_y zimmvzIet}@DlLi0-BTG?5vN#fsXN|`c^>oeYBsNdj|h59LZRfSm^wkanR|*QtSrnW zQQ7iLhXJAiAKjDdHr&kbJjG~@orTDH-HbjVHr%T9F*8$1#w6Ge?d``AFdvbpm{)MK zrWE$d%&8?4BQYMv2Cgs?S@JF0@{bmo;m<lcAl31j70$iB^iS7nY*5W>&0za`%Agvx zcmoypdCW2+cpkKC`Ec!GKF?i6lXfIGgQ%>Z`Lul;n*SMVoVG5mV|g%`x}(f(nAJk# zu%zDe%#L){i!(0dL*u}rUh>H9heVdAPLAb74&)ipBb;KY^-J&aL+Y=b%%7_K%HGFg z8vvbNH7rjoE(U0Nt66TXgc%PipUQ7{IHimhg=FV>_P>QX+z8oLK4&%tk798`^~ljH zs}kF5xnJq!YntWY9f*ix1VYt5aU|dSXZi<r%$IQfpN9#*ZcLy|mFeph)>{p}ONYj2 z$Z>6{2$jreXG5i9QSR0;1(Axz^Gc&%O;uPFdEQuNs<GTkPJ2#8=G8q*lQw^?cP7j; zz;Ps9y*I~x=`k<*RB0XCYb>;0VEoQJr*$ito@}_~E;;c?r&Kl?TDn(As@Guk{ilfG zSF-VnVM)^)x2Tcxu#QJwstS`k7~S#8i;D?QjzxC`>@~vWQwqs>4!4CAS*kO9NW#2? zk^h-L@_X3)RZg^u<H|O+?GYar8s$ISQt7>5f-1MtHt4x(Rb%W5r?HsvY+os;na$#h zbS@w2{JOfwTk$0!=A`pehk?@s%aIb!+|YX7jehWH5j5E$bH6B0ortkmt7b)icdAm9 zy=-fxM{DLxFr?m#dUwOq<E9yM!|CLcFmv*iv7&NrT~?*)M*_QRbotIyfs}4a{`}c4 zk0Q!>AW@9IEd4)|g`hxS0?x>q{zLd`p&4%tycPZqs?u4N%abmzsv2DMH7!l1#;`AW zbu2<8Y~$=?x^ypuywrBkHY+<zZ^-Rlr8Vu(7?q(Uc9aL`#Xa+18f5z$iU$-&FZ>^| zWc)Ie)-XzJcx{-|KE6XwK7LSzYMT-g{c%BU9@YBYz8VXuN8-<R9>rm|_QyXgWm2CW zvd0|XqV~U^wMyi?UVY5(zEk-@xiR1GXYn^s&-(X3fP~aPqkN=yblpu|Jjw`tmxVl< zuPyh$p?_wKSefQL@>ZBET#7y{X<$!I;N)mrWOMsWc)ZxRD=q<j;i11@0E0;%K@5ZX z5XYV84c=@b=cMB3d`J<Ap^Kxj5fLL_MQVe_x83bAsHtxNUkMXZeQU-(0)MSxvM_;b zSq8C_N|dJp)PA%&cHAP8h;C%SI7)9w-OOtwNB!GlmSigw(S;Wal6rqn7t)CEW)Pp@ zD|Eb&>ZL7$K#XEG)O0*teb?0n8bgqM@UV?_Q>ae2NIsc2%VYX<W88|zbQGz(>}K7f zDjrODg49unW0}2eB;P!KUnDwTtxl2%dTD&f{)oAsKKx>y=RuF>mW@#LLT1wX=cO#w zx>r^fy1&YspgxBE30YG|EgY(5b|pl!hhLhRREldYOD0FkmEb*&E)7_2UH#i{jla#1 zg{Ny#cuiPvkLD|1q+-JTGj}+$-+TRVX-Jz~Fi$#$>H28#=!JsJc++d7Qo~(3kFze* zo8wh27ma$j>pl-QH05{Om$90rQzoNZzr6MC1c<%HiWH<yci2^IJ&Dzs$F1_z8PhdG zk~B-)Qr`}qy>qFXI$agq)wr#H$UmQZDHO<5s^YgA)Uv2p;aD(QWoTD-(M0d+Fy}5- z{A@0dh%}2Lu*Dwnp9!WxV4K^@YScBJ9G^w)MKTx$q||YesNmMxe`xp|d&|3_=It}5 zvhBe^4m)GxytfsU(kDk=fy;f>gHH3Yaskq}bNPdroJL*heEo&*XjN*qAvZs)KZ5=1 zirO7(ZyPRi>6(VxEkC23`}J8zqJ_m+M?U+~sX<q$s7{)#FCot<&hu>!UZ(&$j_DWq ze`W^3#R8__-qv}#{?x_x{^iBC!{ucio5S@1`|wK$tMYIk%Lx4@Yj@A~3G_%vVe`xb z30?JdWu?Y;#(r4p7$M_@+w^$B=p~zoI%tt?XB4{c?jteZz0k*7KtAuH)&M*N*sk2M zle5l6l;WfZ=nn>SJUuuUzF86-rN&>r>(vq~d$woxS#j3>Uk94z4fYEevd3HziAgeA zsOMzb@-ema-J&g?+XuKpt#?Ue2^>Af!f%doJuY@#;U(~kj7Hyg9~Ch*u&ey)pL1Da z@6ISHd7(7AefZro;iwjD6C3qOWqmTYazm|%Cb|`Q)_I=mPa`LdzGz0W!UtmHBXhoi z#}m=x$IIVX0!%;5*h%ba{i)CQVKNpQ6Oo0aJ)7rSbDAiB?{mmc38{_2NrkRWTdlSJ zy835UJ$gntTT3bo>e5YKo8a~EsS3lAri_LPvt`7Bs~sG!%B_SXO<!GVjpJV0+`zM~ zZG6OybtgULD1lT(^N?-#K9x@l*@T%=CP#g*iG)o)dd_$3TQGciN7bF@T%7Uk>Ay}6 z!Ee?c;$6Fp<_L8+|GJ3=sbb({R(WaH!C0$OX;^PRsz7wIG#vnC)zvXa=(bzi<P@XD zx16iYX6_elqBNaYXBXr0A3mH-Jek}e)8hReieawf(f4#zUms@QHblb16(=KUe^p^s zx}!gYCjKEb6fpmx)BK1_jvmrUi(&j(vNq;xC*v6H<ZcaS&e5y_5wx1qhJCDmv30Q} zK$>-?FqHWCCNPA#q%{$V82Wey!$K>w%~xO}D&n<+{grDf%u0>sr}xt}d<CbW^8Uq( zTPe7>oVVzB9{=*Y_+b)yX`f}@D|g$&dFz0v0@kRhS_g-K4ToItxXAmQ4e<0U@I&dd zHE1z9Nma}FsH0%1)fsmLV5##dTryl<&+I(d3yYL*Cl-&YdyQVzw4<N&ZbzMH+|{G} zILczVCg%a=$$t-4#A&Q&l<Ju_J|v<T!-NplSK(e~%6WSh%q2a{6<ZFZUu7$%6-To| z!b5)u?$1>=DR#A8=x^f{xZVkM=Q~zh8I~N<s-_&emhE=CB#ak*P?L9kksVI@i*L!A z*IxgMTkB%Ye%8s(2|l9H|M9DgO2%jweSY}AzYkIL{vHE|YuooG4mwg`#1G$S_<po5 z)ROR$t-ELWFh{i?dkVnJbZ9q@6Mzlc<AuP49j=ABJ=YDVU!PpG&z<z>Ct^lHBXf#{ zp|#11@v#I#1%{`)U;E?VWWREnclK55`vNVr&?d~ee>?Z6?BXTrKVSC_X~|&2f;>$4 zt^$XvQkF0}*cdFv{IuvRnOMqrwO&PHaJ4K(&1=;RYUYyEI2JAyyF-lKsa&hI-trz( zU8lI6QwlMO4{gbw(jxUo`D@38xhMN|`8)Y&sZS+Ba0fTsE;o;I+42m1T@e{STs_D? z{BJFQ-T$=+Z($bUf%<oV8^t438Q-^RzqI8oK>eCYSDWSEUC*WBZ~+yU>U?{5B!d;+ zkvW`OUr};d;?n;qf?hyieR9uw>!&CiAv1~~c#P)KaSFM2_mz5LTrEox{q(x*=EF8F zlL@iQH%oTVR|OwGNH;<$L+by%5dgkoK}@*~fgOL}EaT5)vZvu6;IFl|?_R0%8&0V1 z1%(v6aS`_5XjAOU5~#K+s!uqHHB`IVnl{9=C1ga=`K|Bk`=d2C#AfS1G5cKT_%o8` z$fCaT^$X@oM_{iD!mpGqwS8nPe-2aUzsIwCzfYlAI)DkPB>|Jd&rGdZQpO@#wu58- ztq#N$+hL0ccViRh6Aax)#qd|?F*+${^ny%IMn-)ly?cszltn-W%sZT{#*8!F-Y+(C z^MAKF;p-m>3LVUN(7y#!_1uF4cUJK<Go8F|oA>|zH00Sm*up6u7A~mirBQsJG<Q8O zi-5)w7{`;#3#YGD2))Z;bo#AyA4sQR-_5)_-3qBN)-tl$wNh1l!7e88`Kwss*!#l; zj7tLpb<)}Txpjv`Ia8IAfLJ*<O*S+aMM_r7x01K-6{+X`@Bxr_;KZ>W$N{p0;v*nA zpCw6}s9|KXNeCS_OcMlX06OysU;p*-Y*mvJVM&^Xb(prtG+MIxcjP-OfGHA0(yHp6 ztBaIR@Ai(WXN_K6(V>^wwyT6z=Y{V$)-y}anf|ZWfxOGShm19|fqLGMx4)6Uy|-x; zUsX~vy7DbBCMnW1hw-cp26NZ;8@N<#FT%+AbNY2tE#p-!N9Fnkti>e09{@cMaY=A8 z_9$>S43Z}oSg~tewBA_5*e$*6-K;)avs`z^S@`82;Kv~RE%MJZ{=LsXJ0zj@287^@ z`>2Z@JWj}+QVrKmTt_cbvP%uug~e2>*d|t0{B5(COXL99hIWyn>blBn5^nPKbJx7K zAb06~gWb1gV{EdVVUpnCW^wc6=%wMe<YPXZ9s8|0;u_P{Pq|xD<uM<magES%pxu@w z@qPasHU#$>3=Di#>YxL@FG)<c_ou5tyZ(>K0+}~rDK4+|JZt6@Rp)Xvxu$;Y^!<z$ zcsi^oxA#I$evE#YPTPpRm%m#zzcQUFDO}(tdaReIh_4R3Pv*wPBmmyBmK~&$;Ji%n z)Z#udEHhW^e@2UviTGd?IFNq^3Ijm;kfAg&{ox0YK4tzNpCZ>jDZO|fWGKAZK)yAq zNlpy?DPU6!KxK9qIgd(Y4W694D4~f7Sbn11u2dhVhF?QeN@TuOcId#2umcPf{c`=` z(HH$#Nhc~m=qskKtC|B;m0dBo`RktwE(6>DXInb)4B6c#z|P+J!65jY#$OP8s|KCu zvWGYT`b$mclf&TIMtxm?w5__9^he=@>mP=AvpJd1rK7o2{7@rYor~%{Z*}XY8;TtZ zuNRVxGrFZVcG+Jh934kNaS0>({Ta}FlI2IC%9DRUL~oe5Q&6T;LMKbhfoMeTVAPPs zAAVtMm(X5wJ0%}fy@^CqU9CI+IVLghq0LRq*yTYk7yq?1I$8vYJCXmB`>+lch=BjE zKj&iXct7Z8d@`lqqRJ>Jn2M_OnN}@4s%7!XzZoq<8c;JhS>Mx8K)pWO&!hTAPgK_% zIxZO`Z0VeNr)OOM#Y;Ue2NhrL$;iAM3@nl_?O_}-%X(+XM8w$K#$Rd@iif$ErXcAs zJh)5ju3ItrwY}_Nsrgj5tK|VaicJ-oN=BMVght1oTCNY4{RDlAhdUW^zjhDaO09;B zl;ywPwe(n4O!b1g-ZpymVqA5efU%31T){&kx2www!<@T}n6Cw_xhrK~Wcd1C?{V9( zN6e2qr_}LXupitO`H!A{Gc{-s{xN+KNwhwmJNf8OL`R_g;F)(YR81+1y8BBX1WxT} zTMIg#Qy&}Ov8|doM_snRpaj02sk6C+!lc#8F<p0vFUI9UP0b<~LSOejKBj0^_U)=Z z+M~rt7(r+g?5!!OSF7g`|Lx!(u2^rxhV7QR0tavRN*zApz{w^iL$zMk1Zel)!yE3C zgdPQiYp=D}*89OIG41<-Jj|<}eF9-6k?SA5&y;RIhL_E)CED=!D!!b%JTA)})AlfY zb){rQwB59NSXokPGsxLnUsvw=<>D*Hu>57x14lkC0I#+9^r6+|7KUjLZ=oJhl7Ft8 z1YlW+=|p|;=6#BV=#a3198HBz7=~4lPs!sWXW>zaX;{){(nxs~M#8QVS@DBoi0jVZ zn7PE3izv@oMO93q6MgUal@^a#?f;ikH<=s>Hl0jM`5=9s=om_z@CS6XhMAZg%k4`P zbX2b7d-p%RYYTY{yy+t*-5w6T${p>{c)@W+)!UGeV%AHt$&zWXZf))(2T~FH0S>df zjp+c>&xznw(v#g%?1bs;LT)w}ZC!=({&)^r>Gwn5153}dj8(I>9>K>PAgy*stGUaT z{%L4CfTDXRv1SuFnVRy$BO}Yly~;EaN{6A>aXEq0t=Oi1A}9y-UOutM*>yP(_c=Rb zBhy<uu<_k0GAf&lW$2G6E3(Mu@`_R$)b~%V@{^fFc-P~lSE-LrztHrOo%u0JNUqpX z%5IPBpa4Vm_wau14G#Mm*X~TSJscJmq5|2st<Z<eB`sa_BWYJ}#3a^|>NaXDb}<8_ ze|4zu*Jc4{s%2y$)$>Hfx7ODE%*cbgIuH-TJQJQ+J@rWTd5i{2!V}$LG7s^r=9Z%> ztZ$`eGXsBU7Z!|1DWVH-#xk`U^20NX+;U}vCpZ+dj;8i?swA_*uR6M+sm3pUpMK;u zma)&)-N2y|B{CBq@48==%~GOV%%xf=sSl1@CXl;eaH)y(xGTq!zuLpMe;XKF^^w9{ z!(rXA65oCGppbcA)DjNbk9n3ls((oMUyDZI^BwsvhBHj~EPb?4N@|vKL#>;6dRb{W zkzCDI8k){%_b%h-Pk`RKF^W1e^^q_Mn17OYulEe4zZPIA;codx3>Ed9IJz+gem(x* zetlR~F7bWar(7bN^<ALpwzW@8$15X1jOdS3r))I3ht-(iXlcoRk0IKWD=+g(m%tz% zyu0a8<CWw&T|BNBqX`Jhw7Wuf3a3hBgW%+(tJSqecfPoNEh9}ir;4BZ;)&@r{t@SX z-=)^YPpo8N$IkT^pIg$ki%g3~pJs3F5nDaM3a%X~d@1(lq5FVC_vYFe5Et#EfURGd zomGo^PC9b-?G1}#=hLF?VXHAhC<hzsSoMb6^@6Av?S)m_wTp1YWjPUln<DzJsE*{U z(2#E?r@Lh*Ej{!x@oO~;WIMK-^@%lRe>?P*@(hXRBVW~g{#<txkoLysEzeaeRE1z4 zSIW?NN!v@DH}GAt+kMDOWF)Udm|JC)9NHnNnS!}9VVOg7=K`X>gi!|Z{!(gdYV(jK zd66uKl6Eus{RFMMx$d8RKM(j`mA=3Zt<O%4m5<MfML(~rqA&xyzT<fN<zJEMPSR_U zfoI-kV;9oH51yqjpx8Wy1+~JM_2Y{)uJQtej{?#e?`%#(>ub0zpQyZR-}2wz4lmGV z2IsB&R0aOkzt!C9RL@0dQrP%sEOYwH7P6rw{8ZIsQ&lvTCEGHyq5lzk7+J8ED>PxO z@zn!`Z*NPcj}OeKAH6F1VOVc`hh4UPlmotOdz!HyyWj9s<y~JAdnQYN+fRu+<tX_8 z(>Kani*=WmRc^<YckNSETP=1exwwSs6&*AtV-tgadGSh>Cf2yZeD(3)UK|CqV?Z-B zta9L=J)`$bl5un_m(Moduy=JOi~A3OJ>U`j1`ql2NR2~>t0<>HPpyC_84g$DrhO*w zH?n=4YXY_Dg@{Sq(gKWU@3Jk|(cpd*lTKte=6?Ob(PAd;i<X0}Q9(d0^zJmr=sOA> z>3p4LD(x&3W|cSV6!P2)jD(F%RSWVZaN4(P^gKtu2NyBYo<x68*2#%I!C6IH3fBO} z=)+D$!F1V1RR8Lsv%N!2tf^u}?CMEWZZ@aYU<beT#*04Yd<~`9iL9uMz9TtLRAF7H z9*<SGiz6?|)&R7MXf!XGC-uJ^p`n>81u{}<hYC*k!)VnVdi81FHggGcg?6YF36$BX z9PG1l9q`|L0!%V{J+fk4M!lq0eye<?_Fq9n+cF37c4^=nmzH4V|0C?n<Du;S_qA!W zJSxeS7RpZcol=DCTlPxGF!r562}LMt_K<DFWZwtL9<mHshsQF;zKvxV^E;#ZJoWwO zcmMHtJ^gW?bKd8D-ph4e=biu=dX%bSx&5l=m}POUb+REIg3t4E`wnxeOd{uWygDpu z{ZxWvOY&qj^}%#?8GT^n8dHQoaS=CyMbh^U0(q;WXqqe8;2>EX10x{45f;lhFJX&W z+m1+t%d8uk&CEB054kI1FGKSyCi@27Gb4ixfd5Wt3C;hw>n`J1ZZW&&g-TnQBH{7! zx(7FTvtG>X_P?GAQvSB*h&=~2D<2TBS*t%TFT5)1jU+zUI4RUer@pP*et?FVmXAQI z;6t>A!sZD<+e<vv$$T?}*MjW#^BMXD59_UfS>Bz8Lqiy17J6IeVdMs07h2Gt6HK17 z0u^nabhsZm%Y(mbVCUYo+Z~6{TQ3y!3o6jPu6CV#EaU32Wu2kkOje~lza33KCb4M! zRH|R=kZo`yBa3;%p1DIV{J@IrgmURuG3ou``$LN&9sA*v=S%S|szLC5ZR1a*;+4hk z66YGVb8~o^6di}A9!e4?qI0Zn>d)||kt{R2=Qn&(oN2x%H$bmDDeGX26yBVzwW_m1 zE}p)1xEOgo;%degvlvm7a2aesaKsIj$YE2@K!!oYbtSk4G6_FAtO^o^UAa*mVP(q{ za3Nud<;syyGBWyc2~<TROPuG<eX8~v`}B6=ky5X_jbB%X`Y-&!p9SPDf7V=U%xu<q z|Dze8Es~bl<EXr29J|}sH{O>N5z7c)H?u;|Rr`(T$+I0y#?6@Rj?Ry4E;|N6CJ<7~ z+)!g7-C}!0KFhd|a=i6TSl97t<0@k8GJY1vG2a_Gva4!?{`l^&-Mtj)v;PulxLeDb zdoPNd(<m#tJHB(oH*Rnt2B1WZUx#A{uU&7S9qp~QXi-z@eV5VV!nst!nrkqHkKJ&q zHYq*-FPoC&_F_!SRNI*PFRI1g48$R@gk2mDXmd{7dG;_TayCrYBiEs0zY*c9(fiSz zLU*@(J|;gDDd}tIof7rjd|*y97BjJ`H98;a?3A6_TSb(~Ahl7A`$~s__q?8vj`?z( zkxKRho#Lv}?ls<48<E5?;KpSBWHZ3s_XyPBT<cWnoG!I?3@j=dmBAc{dCX?JM)Q~` zgOJs|@NT9<Ig*M=;u?TSjs-`wF5rOUv2zN1!T3CA67(C8Nlr-v(ZFd#`xg>6VFj9l zD@vSn%xORU%eQlqqW4vKq|PngVF7fBIigCoKI{`FN&|)OUMNR#QO4{<p!E>_L5RAN zZwZu_>~qLZ-1br~(o<(HsD#Z!Hmry-gA3l~`T$@QvY4(bb@(C(r(rbzAmD&PTt)y4 zB!SeH`X5n28mCR&)OuPx<N|)dDYA>3n8MRK`Ia>>8MDy*K14I}<K~+;M4p|L-PGj( z6SWiKFMPW6+0E3zj+i3!>Eq)o*DHS=kyUk2c((SWS>5bA?Qg~?=J*O!0p{^+srPjQ zmIEkhck6oDzFg2Nd1X;HmCZtl+KH>2O8G2R9dc2BEb$~g{Pyjit=;nFT5tX9OUAfK z@$RpBulkd$Qu;p?DxI;~6*6<N9vVHYzbJkb+t&>o?1!@EYL9T~N=ZHFjZfWikcr0_ zv=fL;rom&p*zSn#Z%!)fCQNSo_KrU+i`(d@t55xceLk!L=a&oTsxH+7-7l7+o^MR3 zBG}N?-aJ0j>M6X-6%=lJ<DXs&{`&+}>BYT$z~ZTZ4VrJsRN*cTs#RnF^K~XwjIl0x z7o~sb?F}M8iE5~uH<yP+K=wcEf$O6imHZAbk5{`a#Q@6yDLw=62hUKMcdShcin))U zES<$yy!rO24n`o-c@WJ&u$978T-`w&*cEz!pJt`o2N&=TA0lX-{h2`L3h^AccAYF& zcUuHMxH`g9Y#X82X~&!e%3BIuT8gz>pmB|!&InT8?;9-y)pYW`kX%4?2SGIcVcuWz zhVhp~$uOf#ex?As@?7m=t`bPIkhGH`-_VlJZt6%?iEY~3M{$P*&U7&dpXr-#C<1A@ z;FrfFQa9cRwr(>ne>s@UwtH%6fklY!Ts(a`cFgSnF;#22LX`Q%$H+Zy>fSv1sHYHv zGQ^|RRjtT;GrTg6QznUh1w`z;8&M28S~l`P=g2uT@%D8ek8NHMTdW70DGfK)PC|T^ zT*Zs=<pd+yF0bZCv}e-C(0o11!l@huV>~2C9h6LEHJ3r_SC%IUHv%$s8NYYq4>!}& zdcR=6KOMG0ax#0cK~v~hp>|}nn}o><?|}{okdf1;oY-;TV^zJ|vIT=#`6INn^j871 z&5GUh^zH3juHEbQsTt#K%UWC%l$B-|?8vuOFJq!wC|Y4TN!32J)@oTySi0sA!>P-= zv+=LqFKVw|)-jWgEEIy9qK*2;M&j7&SrT^I|LNwmgJB(?W&g|aO|0kw*dA_2tFgIi z_da{DJ%fkU5Q!uh6>Za?JR^kAH<C@w^K>5=Y}XH(-z=1uQM_Z!EA27T`7@Lj1wL>6 zlId2;2{*hoe@M-N4}htvbnJEy4Gj$=oy*;p2=dii2WiZb+pSA7#r=tZHFaAa%1-v) z;t)vx#ESj??x_XAo?{2G#UizV^R5)goN@S}i?pRziX2%QXpmR*=~@}_(})Cat6Ox} zW7+q`FX!7o18`a&mqphw?D6`FRjo<o1WCQ75W3?3h+f@>^K>=<Cq&xir=26>S_XIw zYgb_%pO#evC{Q2xR}Y(L9a0lLP`6!FR4m}r^^%qn^?q+<AX49~pVk#ZpTo^$H~)R$ z=h=S6t*=LU-X>3pP$lCh4AtSo7~8r;CkW-_k-I|R3Z<MyL$*%UV|eI>NXK4g(gW0U zBF{#%9-Li?Q@iS82rXp{D`9nmFLncjs5;wWP9;wLs%R!E#S~b<uSI<Wpoo8jh-i6K z-;7Z5kxNr9;<&lRY#m;SF9O7^?9M7t>!LLH3l82Jz3clMbSmKVmy4T6PUAeBQkV-K z3D;t*1Maa?jAFAl|8JN4sy9;z+RxA9F=^e@a+fiOyCUQwN4kxXkmzAXKh_@2o0~UM zs?#FE<8uH(7sV^bab8t|)9C9m8<lH}84BwZ-F1ussU&i9vKLX}PCTO2i`}HC6?cCQ zFj>%cowGr`WgW5=LA}c3RKmM%h~yh?VAL-r5GT(i-xudlg6m6OMa$U#TB#+#^XnC# zd1wmPAu~aoJC)d()ese&3phRtBvGTta2p6{;EzIbHS`+%cC(Iv3gWOgTsI4LTj~$l z-QX@BHaXd9M=hZ9@(U|&)f7h9uk|YTGyfT&b;98vJf~Xb^0O~%KaKC*HGar%G6)Ye zRy$w@eTqL{`QA6tA&bgl?hU&^x9BlDknd56&KKuq2FH6}a@e!aJcWY_q|r;fd`G!g z7iyT};qjgo+d+%QHsuNm`S!X%$G56kIjZh>q6p|G;37Ba@&6JE(lMt0XR4v8RTxXN zG%<W=nQNV`o7Zs+{HAaa{7hEGk2A5D&3+wuwiAusQ!VXL1WZ`o)|Ko8G_j`P+69qA zv|gzk@*i3smX{TAv-X325VhvRo^-I5&!eM-$%p03PVS>PmB^>%21LxZK&A@Z4`Fn{ zko9h)ivUii%Vx<?M7KItl?MYANnEZg&gN8zjbqJBR_ivnruHfiK4QNVYnA$&bRss; z>X3Ei>J>}CHH4M@Y|&N{Ct5|9yj*n3Pui7zD;l*EUKF{TYmEhqD5$suc;MHK!4xqU zC`cQ!E?(T9g;^3WW=LN74sRpI-jrOhmpNA<_6t7H$yK^3yuAHUSw9y_D)X`JUa#@^ zQvJ=I5R}&wJR>+ZK@fuW6CYvS{7V3^0M_({`>hyt?HR`Rvf;kh!d&NCH7zVH+HNF* zdaT_}b~~8~6qqnCm%g?09LlOHQLHiCrpEW=L#LG_4|ju%jMx~4B<spE@6H2N*zOI0 ztB-AexpGKp%cEOxd&mH=l(L;-yG`i|=is!+7gM#El(O;p1qb-dL>%SCH2x6+;aq23 zc`lL(t$vewanp0mu6&_Nj|YHzLel*kddC6}7P6?IhgkLpe=hy35@2F|ou^+t<9vwl zyK4@*Z@3X5?`90ve|5)4DL~Zf%7aFPJBd~9Fb10ahT0`R)$veWlD?PcH~KUOJ`oDQ zKex(-ILaX9GvOp^Wutuj^S6Hy^Bmr9J2Ys{NQ1~6*V!|Q#FfmWf?e@Dk5jLAeYk?F zTsF*45jQD!n}2krx9$Ru*4^X;VFD)Lmqkc_rjG(@HAx>7qr%v)*Up|PKR2Vy3EFcY zJ$d*amkoD#CApx0=CMHv>S%qgA?|xr3JN->K;43e_r2i_*Nz{JkW{JTPD&rDwXt3@ zGLMOgop;W<fB&<>=2AYw)cYQDf{2I)mc{N_pB68Y=FEQ+c&iSI%GGj-t*T*{qi?P5 z+>wtKvU;N&&1D_Ww>zsC=CuZu*A0~a+>!eu$0>FQ!G*k~qy3pl)<r|bYQIGwZ+O=7 zMBoKMotJVXe4^AoqHl5hG~S}&spn|CjFs}sK<sV<_1u&aUykM-%40E>W6k-^|BdeN zLn>P8VgSgktPl;vUDFcPjRlI9QdvOY#Ipfd?76BV>hy3<DY!yhxs-R&m_)KyuZC*F z#=*<A_V)YTo@GNz5J}qvV1k6r=%@J!`}UnnM(SWUVh0!2#I@6G=?OQjUyj4v-jLK| z8u7&W!B_e&yQlub#>l>qW&wUqyg#?QG)vIm*!?&19_w>W_mI=had>^mE4p55(okxM zPDuKsZk7m%Z!-0)HEs%F<h=7i!t+ralF2V_77Yt@^V<eo&{y4%fqhI1Htgd&PVMx& zGIX<uM2QmN<p0)Bc8VVqeLITG-ljZ>V}Mw06&9tKD{zyRFtntPH-I~j$yrp5fpZbJ z^KfA)rEPDUo|B{EqPmynFSf;G>9Xh8BbuWI>s@9zY=$TV5PX0F=oIf3x}Q^!scqUD zN=>cR^Y*O|?>BEi_G-3pB><59zvuWR;D7rWku;h8A55+TXsY1ZKxUwwUkzZq);#+E zEmL$6+kKe^|AGO!%x(J-NY2LzWk5BxXqy#&OGi`~HcVzx&>rc19+p??@Q9JebN?dq z$Zp~xFbQQ8{=Pn#J-1f95)FtBjd;<javPpF!PY++mn-!k_e{KS!TJSYk53fos=Ogd zH=h<0JmpLEwIZ%|+Yn}xXTO|D+xc<7V`GKUR|K2@*v|aj%*>C|QX_zVU=i<oMB~t0 zfMUVcRwvFaU{*Be)1+k(l1y%{_Jf9bR%(5O^6_UM__xP;e+BAa>z5;uoAoD@Y{%qc zAYXx9cnvD&PLcXsaTB!;A5fN+I1H5o^CLin4MQgCBLu+UVBon7jwtTp5XxbWk9Q5^ z@71T)m_~^3?ILD3bMsKz!Cca8Lzp)mSRJC>Ab<v~s|sO^$6_ioG&>nWcv&9*sVw-% zADlmj20QxUK9{2oN&q5^5pw?osBNQJdmg;jPfmN17Bocdv7C1C(1R3<c@<pGbR17P zzTHy0MG-ARcRZ<Ss;fU}H%h45{RJTW_}uXvBx?WVT;Tx>w_6g2g5Q=t788g09UOme z|IrH|{_#F6?&8r&gG6H~Cep={ZZoXuMPAE$X#d`%So{vtwclER$BD}f!dNMmzz)p} z<$E2@dI~{lkzcNoSeP5gNAdS=nC1csDg|?$Ot7d|iv*D3)DQ{76&_Up0!S6i45b_F z0C?fa^S|&y(;A@p%bTJN1Ev3e&(9gX@3hk%+_MAmz&QH(`QRLo1!IQ}<l7)a&J}6t zU-)DOs&taQxQ8^9CfC|Z+LTof7GxC@ha<fD9#XHm_o_4Xv@20t+oA75_ncCuarmUy z;jg}rm`4g>us3yceO^9qKRdV*#Oox+^p}+9NC+qx=rWh`nRVbkfFG(qfn8fMg#e|8 zMQm(JnxV<%w=Gk*baZ!`njX@@A{NKYb3U%Nw%;Fo5tmZ@?HWW_cP$4V6yopawqDOm z(znb~KP!-y<(9<612JXET+>>@!H?^lx>DS!XNd;!k!<~?P_DlNQ8Nfcq5qz8n!|fn z15Wrr6Np?~I==fESS~Nx3RhwuXJ%zG!p~5w#bj`Idy5h*b3Qs4;G6wi_P^im_%zlU z9|Z9~>kgzmFoA!`Vf>pA=5g>#B(9*GyHN^(4D~B{xd9UJv>SbnRJpIH%R52#zYn87 z5Cl)8o4^$5NJNkexr6C{a+ATlu5GDI9?5Nb_!%b0!U0BDIk92@>_KGAyMhzvQ%b*) z6q;?yC`#HRbXG*XeaXZ@tRenuor_QR#X~l*05bfLYy3T&#(gWc(QYe(lkLkF7wzCO z1;+n8fTYo@zvmoS;j&~hnAk<u#ZjbuBFuwJi7FdM-h3n@d#=NN5SV~l7>M$=2V(#m z$>D?a@XiWf9<hlpWyEErF--LCBcHq*ug!ZGt6pK29lk%g;dMw6%zw}o%+50#T%fp+ z(u3eC-~9!xkcKB!`}J&CCwKkIJNp<#n`4m|OgW87LM|chegQvhXOoxtfq=a3b2iTO zk{2djNmif=CXAHRb8{M#s2XD6TC4$<(^W^LASLbEM6ZYR(C}v4gHEirBDz*YnLf9L zgnT72{Fu6t?_nMSy6ATZ7|8%CEpEH`?cYc)n8}1ODJCd|(DG&Fd6|KB5s3C2u|VLK zYwYsU;$U|^Rd}&7J_vqP-G?M8QyAuuXA2wzOx2Qeo_(UCsi@8|<CMj3E(EC+w$5b( zdD%|S+skkIWUN90gCO4s?hD0je7Oc=61%;q><-~GZflgPf7pM6G<aLpxL?Mh*vcO? z6PJCVAK`4x2D6ge%)P>dRDK=W_y2YoZc01ud<H?FBPu!HQ(e{~KITns8bHArIgj$1 zSq>|~i1?|5vFa?}y;WDwqA@@k#Bk<vTxS{ha=M%Ss>qFQ!!IF0^8;#28;gWL<Yg6? zKu)Z9n%N$ww~)9~IKaOW-s7GN)DW>lucNHt-eYn=&BP_s3}~8XgKA*uBcdx^Yr9q> zZaaPyD6&cn=#24}{|1l*ASAKqVF1YgCwB<wdx+tl#+ozj(_Zo`UHV)?tgM6R-}nhI zfximiY5Y5SVG}%{dCU_0r@jE0QCv`+ooEpoKciP$5D=XbZ;`|4kPORMSvC`8;N%#s zxg0SYUOcX6A_Y%4WT=i$7evdtJsZ-lCCS{D%!nWv_ZR5tvZ(o(Mk&gCT1~&_JhQ^c za4y|+(5*dY`wthqB1+1IMLIbQnOp@>JBedQIR7U<0m&GSIkhC|(XXNVNYcB<eSsPc zih+GSJ|8nb+p#C{rM?~sX$)8FnZ}T&EEKhdEYiLAg3Ax)4h41_Rj!*T8^p8GW83Yt z7hDYd>P(X*9TWe!3s8?Z9NX1z^<v-YQ*yV2xfb5hN3>a%kF$@Nw{942FSr5U?|fXI z=hSqn!<Imo3Iv4vU8D1RA1yBG$$&cv4vZXUQeg|o{ug^j^BcFy7rr8)GKi5SHxq9Q z!Tcm~Re5i;o02T_iV*AFT12gcsM8;t-YQJmbX(N9DV=f)K#`rg0^|TB@pa%!Lwge+ zr*&f<<E{KOPMy%#(TxX~xQi)^w#jPJ)}M1$_YNBG4VO9wSPZPEDS`MWHH(An4Q}A< z>Vgb!Ilk?Uq~2k2BtMbsj>#(pox<4oOhTyFo{?m!{==T{qwqhNvMVHA+ZBC>Jic`m z0Qiwm;@3`WJR9yZ#s#;cFbwb)tW8ZipQTb|;-BQOeg-$0qh~6g#j`hwtUSpfZ}kS3 zF~E0UWfPpeq4}QImEyB~{PItqrW$x_DqXTK8|A7RYDwHl0q8H@c=~sndU*17pM%U( znQqtN1@94Sa3Mb<{;LcQaqNlRji_7x&fI7wpc6=>BS9$AZjb8HBI}Emi`9MXaJ5d~ zJHV><r$}O7D_O))?YYg3>hm$l@ypIPY94AzOM`YC-+o;9L5}12c2%aiWX!3v9UaDh z9C_Z;pbl{AG%-K<UQO=m|B7EXQ28aGMZRg!9B>|dx`&o6vlrAk=W!_Pb$*t6O4oX9 zOoQ@moq$%vLN)ff@ZQ!ih<J%Vr9OPxhKQSC-}f=ixsWFI4ja;{U1u)Z{x__@AE>_M z3Ual|6AVYcw}VyZ{!e&PvPpr$3TO-sU6$9~$t$LVx!di4bU$H0oWTqO1j)i}rk;)x zMP~Vtc?>agez~v4mlC(v-h`3T7M4)nNM*^6SC@i2WhyI2f||1v`iF>+tgZ<ha%0q9 z57J32;DObLx7MKI^$M?P6zJ&M%4t)j<`QQ^Y0!3EbO&5~mc2eB=jjK<3K2z8!58>4 z=99e`;YYrS7rN)gh9gzaF5BlGW9%j@Xw=R-8m`ZWdRgpffU7G;GT`?q{`WXcf|&X? zk0eu0kla}tY?UTSOjf5KgD4{|2-3*H$u~W*$$J#BlZY=N7d3YU*m#QbNzLB*_r6B8 zT0jh6{w-mAqa=-?zNXP=!1`|)UuPEA0!r7TC!Ku$e?yXyRghYXR@ZWhTGh12X<33A zr~Z_fkc4C^`h=%BXE07%P$ZxPK}Si6I$kiOE^X&YMa7kCC^~ABL%vGwJ;06H_fEui zthr;SpC@O5k9qy?sbD`Gqe=NCw)u8>LYLeT{ZAgZ*gBc>fSkl&HtJw6%`_QTn8ul; z?gIo{qPT}ez;Vl9V}^wNU9FB!N_98ECLUNU6b*qy5v!+qP_D)zYb$Z`e<P6jpCvVC zQazbON={mXVc;b|8kVbBoTBlRc42*P(8jmtyVW?qPGFrgV6YXpmxOg*45_mjqyStS zKAta6dOs%aL{up#M%u+Zzq$O;{E`u0fph2ig?>>BLF4`&OkdbzonO~J`ceGSkl$VA zJsG>4Q^e^-lG3aE5@!RDPnT@<MQ|6B*9HME*w_A-CxDhoulLV>=GQy3aH>l>xe9Nv z6c_l33_XgSRVAOlsU<zoPF}do4+Ls7EQ}VO<A+%2{od;CH>FZ117E@?moh*GJ7BB1 zql>C3sQXhxK*oCt9MbhSopybsa|-6#`#%8(K%u=%PIB-__i51b-pz;f#A3|!Vdgo< zd*h8@bw)My0xC5YuYmK^39;~-id6q~D}s#fCCLbIx6mqO+p&6JV1L8T`8gyVxq;<n zgg$idO)oM)ky3Z^PBfpkRs*k9S22L+##QU+xnHo7uBFvnR_}7waClWvvA_{<&)@T% zs}WqQ&jt{n|2+;3q!WO_%k-FuRCl_N?>}s+ct)z~+=6lCnUX>3{RucD(ilxmdY`4N zQe>bx$Ndg5;?fC{gnRqs)8e%mmZQ<Y*I9hpT>c2!WORY5)MTCoT49$;k-5oOik;j; z3}yVMGWdU5s=!d7olCcG@3|hN>`+FkS1M71K$?y9Un37CbB3FtRM^ZRe>KMw>7;yM zw#ncaoYcVEN53jq@J}2`3yEzNh}})^uIqc><_u>2gmhK!uoe*;0YaHlpJmBdgZzcP z4iX@G{5{PDCO8*9;wM@A%O>^rK)ET0WT!PSG{K`ENgVV2YFUn*98}=Uvb5;%=?kx| z^880M{35HP6%T%S7n+fFE~%rM1W+a?Z`itvp`LsXB@gxAkMmfNKf_@<``1mJL#FVp zy&aQFUP#O-z<A5{_>ICK{e`bBNHLwkg~c}KR2(NSD50udml)*P#NtS(R)>MTp(RRk zjMw|0@=w?KFK`)Y;=Cw;I_$rFtY-sUsvPn(<yll+(6$J8^LKDCtMK7nu|wF+2dK*B z+m&M=W>;JQf^^iAYdpm)aXye7a?Hl~j-!*6<*d{Q^KFRmv~IvXxdUrJ--{<T{MCb1 zu#zH*elp%g50K}5^!z!X@SETJIu>hC){-$R9mKKwRSCRbCx%Obq%!X~4RlI<x%=C5 z_J>Mfbi(8KrqViHDt#JxFvKf6r<f-R?gxKiZaW+R^O)uWP0<lP3eaTA!w2%S()tuz zEz4)V0VzY3>}rXK-3atE1+WpgGrGH}6zfAkeW6R$)>H60)N&{KsS7_mKFt#>_>kwM zI(Ww)CbBp*QJ!&iNY&;F(6;S<B9Z1IR&QQ}KJ@d!zqK+QyxB3x0RJ*0;oY<Sqv2SP z@~S#%@@xq8@^A2xd0wk$K)!p$UU*K}xT#$aP!Ip-?fx|7(!ECDI-OARbDwhz7vUd0 z&1p^Bt2D%*%h_J811&-Dw~YUqgBzG9ebII~$LXH*e5LEELJby_HD(bz70FI$dpxxu z-BJ2G!Z3me^M+mP(<^)gBXG&x`ak$(v&v;rN}rGujW2kSMXo*Wm>?WDM_09?qHsOY z`rO6u!M8>@^+q*l-ijJh#&dhW?fWY##*w)3W}yYAOokGhrxM3JZ7057g`+-&Ta*EP zXK5`gI_=tYRs}$R$M(k{@@y3vED!#Nasf^8H-2F50yxx8E6^+duh8<A3xt+O{k7fH z(S1!}-hn990Ph??e*U~!w!H37dhw$;ZB3d?o?^6KK2Y(Ujfss+r#4G|7O!jT6LTmT zK0bZf>e($}#??=MnZ${bWD-v8v`==I@qB&st;h1K%6sa9(01__m1B?}&{t~7T_E|4 z>SX*WuBo`hQnMb}tEJ_X0>J*^h$QRJr&^iA@KOcewP^nG_rtoEzhDF=$_a;nTLrE6 zNTmU=O>F$&f^IM}V&U+v*VXc-)Y7>`ul@IF=ZrtSDG`G4WAAlv!%b}hW5b1XjvFI; zbr*8n%8&g0a$Rtk_`AR^68NNn(JQBkKdM(&+2LDZQ`?JK+y9)?I(3@ubej9^j{*Ma zFKB7cBDYLwZkuxd*t6l2J)8a_<YD3Cd$&Kn7Q)uLpUO=fL$mZuyd_imF>M>Uf~l(D z?T#7}->wpjdb+U~|5D*K1EH(d3BNZqABQF+S#}XSG&psFO8W1PcnoH#21S0jhV+>^ zVX-t0%XwrlFNo)He(patv3gb`Rnxw$Xb1PlRXvU3)i?(-nKbK`2RKHNdKU_&>{k*r z43gL*f%k%j<|7E`3$=tc>L9JOqK}zB7-6CaV>|ZKoY(jyjZ&pHUgpPsU%wmJl6^_} zxQ_AO<Lk7jD~&FH+~pvv2?w_>Wz2VA`kZCHN!Uv{SBPYOV}x-+h)RJ~o;txgTtOCB zmZp>Q02`b?SB;O@1=CMQ9@OcVxbKzu>2l-fo8ZVC(<cn&I*DhO`I&$7HsGZCE8ouG zBTJ>ZaPFg#>7~aK<ec?I+++J+P6=BlTjn7iRvQE$yuSm}lx2m@k2I@T9YDa;;aB+d zQ>6$M`4{7cG~X$OQL-IvZ<*ZG{%M=iKW!tpM(0Q-lWCo8$>1?$on`(ZDJTr7V?yp) zigH`&&`N9&rB{C0e$nWr)?`{k+3>I|kw2Qe#eCQZ!BPfC^jmFu$XolbTYER0x+mQF zbL#BnqoY!^7b>Eo67{o|&YnFR6P1{qG&-uR_G{q!!JT*@a|*6@S@aXaBpM7CI#y%Z z*#pMq_pDoSm>-Zz&s~V;FeRr0ErW7kdu(jvGe!(%`jYaCshRff!D&U7UcbwJRTX-o z`C(5OO1~GNLMd(>3+IL34jMM~$i`j*hRc~j?s;Z`A9c?P7z*~~3(q~D`5flOp6UDK z^%C_{=Kj6Z2dIH1$xxfg$7vEa8h&hS{ami$9NKlLNDHpe7PV|`SaoU+xYOpb7XK?^ zuIhdQ%qC{%B>7w{okD97cb}#MMZR|ls#N`l{t}N%HEO1YX1LHh6>RkxZ0_l@wdW?) z6l~8$ePkz9mxfDv^cIBIU4gmGi@AgGZ@g5fZl)RmsK%e(W&qkR-(B+wJ$vxjW<BPk zN%c15%gNMd<Ef!goV52gc6Sh6D7>qDud~ixZU4T_z=$8;hKH2bTIaT{DpIRw9%)A8 zH$kftJ43sF3zZP*fN)la4Cls^n~47aPJd6iIH+nP?3R-lHH>TRz62&qvD9P6%eg^= ztygO)@7&Ul&s`elJOZjeYp}@RKjiCWKXz`)D!mnbN~}r*gD!aA%%j=@Od-cpwo-qj za?DPt_w<tC0-i|Gmy?JXc&okFHp%XVm>x;B%&DK@^!*l`3d{fUCB2#@d31v{3^~I< zDNE!QPX=16y;L9Tk%Q_~E68?AZRE#U)jpR&RekJ$4X?KC17@Y(Z{i!Jo?Px<f3-aj z2?p4aoll|5mkV|p^(X`FUxkDY{CGWe;ljD6c@e%&H8R9Wcllh6m|pED+bNt%+$H6s z_Pd_F)uiq&e_)|Nlp^y;I5){X%v|DrxyNuxYd;6fdv17=F2_FNJS{y9Z%0u-ckSyg znfyA|wizeu?(uZV%S%Jm>XL3tv8*@=>~U9Hqs@lWuRCHUPUHU=#InV8WM=vy#uwH+ zN<4<nC}}~QBFU*2xq=(hCO*iS$Sg9QI6<x)Y1wI_k=gwVmXt$ffPLv+-`MWU=Nseb zcpM-8!teB%)4ini(9%Kk>SR0<F8dM8!Fo_sW<BmRqvAo4^+uzCfnLP4J!ompv`drd z$`f`PjmSnmIYM*I^<Xo9EITPy442tv&E>S7!$sqjn)2`m=0okm>mE`?+$u{(<)2|Z zX{NSooV6YLbTBe!Oo6n-`{e6N^Sy=nP;W5fi}BdVkEM(v7ZKdQ6-$<fE@abt!$iJ7 zw#9{FzjM-Mu1mC;J<~wm2sZG-qRMOWY>-yN%Qrz=v@kltW^EelY8Jh=O#dux2edTh zy6LTGa`xOli*0rZ;l9I|Igv8}9c3*a;pr&4a7knHYH8<4nM&jn^Z5&d2Rv70^dd`K z_tb!Ik)$->GCeqkN~dwkwy9cmbH^&gD?KINx_&N7`Q3K0$dQ7h=w|q1cxtSz1Uak8 z-d9z~SR*pzTkKLbYAU@a=v>3g{*Pkf#8QEG;JXtkP$SA4FUmbe?P`guVn#gI3g4YG zau)<H&YBBVFO|UD=(|O-q&a?V5Y494aQpcg>a#JdyW+`_I#M#m%7k?4{@K|X!q|k- zrnmbe|GNDoU$!#!H>Arq0MFMn^+gW;k9J2NhHeaIC0o*zk&P&4*9YyTA56*xVQvTl zK3xitne(!vG3fZ1J*>acDeX|NaZV@5AXSaSLKm%1nRz7S_`T+w?zy!rb5a0m5h9d} z1K~{^YpzZ9mXp|`eFKIijbl5tc|4tZz%aOs&p~NDx(KE@_1VH;eVc3Of5Nlb31&Gm z)Ey^<kRY^opeg-s4VJxBEAF<5>zW_YJg?F?5F$IRXJLV1P(GpEt92eaRSS@4<rnSi z%P=Bp$zGlNa&Qw{-tFuIL*m{bxptb!f}mH;i)-c&Na27i95UHEgZG@ZRnnU3C!g;x z(0vVEUq2gO72(I=K?J{($X?!Z9Ya$V7m@&bK3q`0H1MLfx(12<Cp$Iao`N^5&L6Sk z+-*1GeWn(PcI$DSnb<r0>VgL);P~NTN8(c8CuF+^KjjKOP|Vd$C{gR{<a_g(&;!0- zkwcu>e%5(|LCPj$vylN-USI+R*{@?1f&5<8bT+29#=<dwB)@whIZc%!>kbs<vx-uN zjQsY*ScGAQdL3RZ@&Y|gfwLOR!+AH53>3%IeQ!TMsC{AYpz(oe;GO+9%$mo6?*ptJ zV%FWQpUQh<!xgtu=LM_7PQLRhx8Xyq(5=#DT>LgLFv^5j*&d8i*Z$yI5|K+LhjYcS z)Y+_!OPiusxNatW{5p|AB!Nc|J`m4zxI_<DM8?GYD&3$%))LD3|HK)qyVtqb?H}8R z;%t^ZHTy8!BGG5EGD$VbAfMq=u(Uq!?FdxsYZlrFdGmAqIW6&qgg!+@&kGYKJ-PAo zPAK`GzM@#_gJOWKV)Y|GzMZ&Y;@YMmp1d_{tpB(N@>;wy6HRYTXy%Dz&2GHfru8_@ zC^8yorPHcEe?1VfAG>jQIKzhz-KW0VZDvNdJ($(luDehagyYhSq)myL`1~l$16HDt z>{floWV|l<0@dkIioPF8)a>bMFY^z65LJ5?qO$3gPnf-R`w@cdu<90wJ|1J;;Esl% zYAPY41u)0_1y}X&bD^A56sLOIwjV?{^3}Us0LGbk1@^^gbei$<Mfd`5wT7Bi8!g58 z`6dW<U6-UgJ7dhdyElYRKo>!QOsBx^O_Eyhzvc_dk;c4nWl(hP^vC1iHx$Y)j9GA8 zsW<D<+}gG~$k)tJu<+&mbnr`vymLclp8CVEl1*aThNAIP35BrP&F#K9_hsEX*S+O2 zqIF$^bJ^p-_{b~#^=2He3(JO6WqqyKDLF^Hr<#YG8+sg-7o1blgmRz~X1KT4q7vSR zllm$qP0gs4xX6z=t*1=fhdyg1`mp6%M=5{+%p0eo5|>{BgA$)}L&r>Aw&DHcI5s6$ z^K{ya4A+zritBxEG6S*ZJ-__702l5T|2GM|kMuyuNzS4oZzrahUsZaGIitC1GTtbr z=W3sxQK@epxru9C+TB%JYmP12muF0PE7vzDGjCfMNfB=HB=6?s56ld=P-NbQ_I}Xz z6P6_?|BP?f@$OLw3j>M0l7nIQ3IDRC9~OIYQHfkiA>ko9hbb6?KFA3(DpQVha@yD& z_{afdJYX65iK0B?R(&PSkssMQ^dQZPo=wi`2m3ZlBYtv`{aJwo!f*CXI09WLdV~yZ zZV+n+^ZaNhg;icc*P>mL7%b+P8~X|0Qp$$M2`5qbO-4$#7ko-8rHJ*UTKm*A)*Q~2 zQ9;8g<Uyea(*>Fg%YcInwp3zjgHBG{mwzKs-u;QcoqP^4(?nca^Vl4INv%A_%g--Y zZY&Hwk|8gzhRxQ$S;JR8l3#v9P1ECH4%Jg;?(s6`J&~q7Ap2^Qu7)(tmkyT`{e5>V zVnKrbu>ayH2!xRzr@wlX;;V06B7;=3?QPAi8}xyw6!l~Z_iRMX6#bLqm}v+Bhaev` z5mmUEcSYPCF3}7bd-2k)%TT%>klho!r4myLGu6f*HO3uw6z=vzw(O_j?Ql=$(pB*F zhf=k;2*GG_;p9G9jbqKKdUDTR9%k@*%@fCW;-Hd5`4Lpu>jB!vF5UYMKzf(p<L$oi z34E7#<g$%HY(e$n9hCa3I93bH^hMEK%Pir6CJd!`0fvlB__d-Ia%2hTcfzh5oBgxg z=E5J%88>vb$+#+-lo4^Tjl{B}OgDIWTpI<;hao_wI>uL{V&uMf3%L7@+Q*U58tbO@ z>$a~Gp7zRb=UQ}+H%<9}KUFHVK+co2{|RivYp>CR$ax`KI|<SN4i5tGxZV%Gwe5t8 zs#`r(GxL+AEVX|2%+oflJGBqRnKBV=j}2mZ=_T%ZZ!hWV0sSlOSY^&{EdYmvfL7Yo zhL#wXLw5&J^U%7rXP0Xpc1o1<GiMm8Jd4h$ZjOlQBYwxoN<{{Z<11!)3@msr`KaL^ zbKwhiosqz8l=EggQTz7DB9w%&K(huzzmDojQ}~VAZsEg*D(9S|tGSNsRZ~z<g#Vb{ zv)6n_15f=2fj_+_^qaaZr63t=i%Bh50V%Ffj;l146j|bD&K`c9b3Uyw>axatk5~CJ z__j5?$FM!vUH#0=VMZ7+LA(*9?ouV{@$9mj)a;k{P6or5PFxovjww=R-BHy9ZHije zn)Tt)1B>)GwD|FcMR(58+clNu;D}dcpOWcVHeVYLx6bpCYGOAl$JcIkwT^YXFNi4` zg5T%Peo#0SdS)=^^fu%!F;VBO*&_+HQks7*e5giOn>n`OY;kL;`yX1&h(9zqci^kv zA2r<#9D#6Qx<sPMb)jSb2I2`D>iyQ=>6=Q+=th+?_`;2V$B~Z`)0lh@vNC?!ovgHd zov=3@+mg5U=FF+p`2(L$Sm-P^ktY%4>Np8k-C&8rp9cUEWR5;hK?Z*v{Y}SYdy^;2 zT!%5%0=uQJn5(oPWCZI<kE!z6EGBusuuY^bBi-~YgYr@B8`2)B&_%jSAF1NPg@N<G zu*gOGp>^*+c!6d8H3ib29aa$U`q{_27jtjxQ;2}=uh>lKK&6@8G=h$F)k<JryaPqu zU}pA>;pUTWD<H3A*_sv_3(DZX>)F7%RD*gy+?aD{8&if1cKp?*`;bx>BuQnZ()iG? z8nY=YHg%HSQ2!Y5NQ$cSkeh&b0cEH4F)<9O1(;MbC8)bUf=%V>t}8g-<u8})fC?Z# zpH>Cltg^&g@w1HhJ#!xh(%YGW`_kUohilqueZsQK<hn+bRsGvw0~OW>O=dEzddtFs zQ8{q_%F<_Am?-aFhsL@0C4j$BB|b{eA8=YNE#mh5ba&|94Pni?!WE@h3yI%_E@>2* zuy6`8VXcQc6$+{q`UgkA&h11;TT;4W7|oxGQwi&NN?lI&LJ<s+Zs1owa;OfQAzEiE zM&+Y@H)OZof)1j|JUF#Zt>(Zn;I&5b@t}LyXhj)ax%(A|!RPl%cBDuf@Q@=uw`v({ z^q^&x{?=(%VYh$9P6QqwnimcCz9+lCl?{4awO(qY9`}Y4d(h)rlRg;~v4Vu=S)_Qy zGpWfKKhJR9*|n)Z#==o!8uHfwI%kEzDeI|99n#J=bqvB@Y6fq%UfiPwUy>fy^K<)x z@$&2)1aORmQaB>79%Mui<4deY^a5T#8dg-7x~A{zyY^#pQ@=bh_161SsN3C=rkb^u zH-F~fU(1jy1=Y7dgZ+-Qeh%1%Eb~iK4iYZFR64ReLwdx6a#`1rMg(a$ZY+I9`D{>K z7K%QOd@`67hWGtqRAz{8Yn)y^%O8CTS%4E4%~M)&K5Tw}8|i~#8o;i@w$(FiKwF)a zamjJ%ylBib7t?C%YI0-Wh_t&o;Z*jUW98=6peJI}rZPeeI*FmCw&Eymyg<Ow$a1xc zCjcw@{XXzlN0MX~+81|T2mxa^vGxlyXDTOqHj2+nm!#≫m%bCc6cI7Z(U<fi@Rv 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 }xd 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ä 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 SHZ&=l;(XBk0PXuTSN;tnrO4(0 diff --git a/x-pack/test/reporting/functional/reports/baseline/dashboard_print.pdf b/x-pack/test/reporting/functional/reports/baseline/dashboard_print.pdf deleted file mode 100644 index bf2bca54ca2d77f545192b3f89dfe7063863ea36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359189 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�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 diff --git a/x-pack/test/reporting/functional/reports/baseline/visualize_print.pdf b/x-pack/test/reporting/functional/reports/baseline/visualize_print.pdf deleted file mode 100644 index c11967c12ebf5af3288862358ef903a5a5ac053a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 124146 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ⅆF(fW>_>;(9~Q-{Sw`?C-s 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 From f9e8c1bfff15365c8e89c6843322b246db473e22 Mon Sep 17 00:00:00 2001 From: Steph Milovic <stephanie.milovic@elastic.co> Date: Tue, 14 Apr 2020 14:11:50 -0600 Subject: [PATCH 110/121] [SIEM] [Cases] Removed double pasted line (#63507) --- x-pack/legacy/plugins/siem/public/pages/case/case.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/legacy/plugins/siem/public/pages/case/case.tsx b/x-pack/legacy/plugins/siem/public/pages/case/case.tsx index aefb0a93366b8..2b613f6692df1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/case/case.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/case/case.tsx @@ -26,7 +26,6 @@ export const CasesPage = React.memo(() => { message={savedObjectReadOnly.description} /> )} - <CaseCallOut title={savedObjectReadOnly.title} message={savedObjectReadOnly.description} /> <AllCases userCanCrud={userPermissions?.crud ?? false} /> </WrapperPage> <SpyRoute /> From 7cd746bc2f24530ba8a3375798188e017747eddc Mon Sep 17 00:00:00 2001 From: Wylie Conlon <william.conlon@elastic.co> Date: Tue, 14 Apr 2020 17:20:18 -0400 Subject: [PATCH 111/121] [Lens] Fix missing formatting bug in "break down by" (#63288) * [Lens] Fix missing formatting bug in "break down by" * Stop showing UUIDs, make logic more explicit Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../xy_visualization/xy_expression.test.tsx | 294 ++++++++++++++---- .../public/xy_visualization/xy_expression.tsx | 23 +- 2 files changed, 254 insertions(+), 63 deletions(-) diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx index 54abc2c2bb667..0a6945dd0c1f0 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx @@ -633,70 +633,242 @@ describe('xy_expression', () => { expect(component.find(BarSeries).prop('enableHistogramMode')).toEqual(false); }); - test('it names the series for multiple accessors', () => { - const { data, args } = sampleArgs(); - - const component = shallow( - <XYChart - data={data} - args={args} - formatFactory={getFormatSpy} - timeZone="UTC" - chartTheme={{}} - executeTriggerActions={executeTriggerActions} - /> - ); - const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; - - expect( - nameFn( - { - seriesKeys: ['a', 'b', 'c', 'd'], - key: '', - specId: 'a', - yAccessor: '', - splitAccessors: new Map(), + describe('provides correct series naming', () => { + const dataWithoutFormats: LensMultiTable = { + type: 'lens_multitable', + tables: { + first: { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'a' }, + { id: 'b', name: 'b' }, + { id: 'c', name: 'c' }, + { id: 'd', name: 'd' }, + ], + rows: [ + { a: 1, b: 2, c: 'I', d: 'Row 1' }, + { a: 1, b: 5, c: 'J', d: 'Row 2' }, + ], }, - false - ) - ).toEqual('Label A - Label B - c - Label D'); - }); - - test('it names the series for a single accessor', () => { - const { data, args } = sampleArgs(); - - const component = shallow( - <XYChart - data={data} - args={{ - ...args, - layers: [ - { - ...args.layers[0], - accessors: ['a'], - }, + }, + }; + const dataWithFormats: LensMultiTable = { + type: 'lens_multitable', + tables: { + first: { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'a' }, + { id: 'b', name: 'b' }, + { id: 'c', name: 'c' }, + { id: 'd', name: 'd', formatHint: { id: 'custom' } }, + ], + rows: [ + { a: 1, b: 2, c: 'I', d: 'Row 1' }, + { a: 1, b: 5, c: 'J', d: 'Row 2' }, ], - }} - formatFactory={getFormatSpy} - timeZone="UTC" - chartTheme={{}} - executeTriggerActions={executeTriggerActions} - /> - ); - const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; - - expect( - nameFn( - { - seriesKeys: ['a', 'b', 'c', 'd'], - key: '', - specId: 'a', - yAccessor: '', - splitAccessors: new Map(), }, - false - ) - ).toEqual('Label A'); + }, + }; + + const nameFnArgs = { + seriesKeys: [], + key: '', + specId: 'a', + yAccessor: '', + splitAccessors: new Map(), + }; + + const getRenderedComponent = (data: LensMultiTable, args: XYArgs) => { + return shallow( + <XYChart + data={data} + args={args} + formatFactory={getFormatSpy} + timeZone="UTC" + chartTheme={{}} + executeTriggerActions={executeTriggerActions} + /> + ); + }; + + test('simplest xy chart without human-readable name', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a'], + splitAccessor: undefined, + columnToLabel: '', + }, + ], + }; + + const component = getRenderedComponent(dataWithoutFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + // In this case, the ID is used as the name. This shouldn't happen in practice + expect(nameFn({ ...nameFnArgs, seriesKeys: ['a'] }, false)).toEqual(''); + expect(nameFn({ ...nameFnArgs, seriesKeys: ['nonsense'] }, false)).toEqual(''); + }); + + test('simplest xy chart with empty name', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a'], + splitAccessor: undefined, + columnToLabel: '{"a":""}', + }, + ], + }; + + const component = getRenderedComponent(dataWithoutFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + // In this case, the ID is used as the name. This shouldn't happen in practice + expect(nameFn({ ...nameFnArgs, seriesKeys: ['a'] }, false)).toEqual(''); + expect(nameFn({ ...nameFnArgs, seriesKeys: ['nonsense'] }, false)).toEqual(''); + }); + + test('simplest xy chart with human-readable name', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a'], + splitAccessor: undefined, + columnToLabel: '{"a":"Column A"}', + }, + ], + }; + + const component = getRenderedComponent(dataWithoutFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + expect(nameFn({ ...nameFnArgs, seriesKeys: ['a'] }, false)).toEqual('Column A'); + }); + + test('multiple y accessors', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a', 'b'], + splitAccessor: undefined, + columnToLabel: '{"a": "Label A"}', + }, + ], + }; + + const component = getRenderedComponent(dataWithoutFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + // This accessor has a human-readable name + expect(nameFn({ ...nameFnArgs, seriesKeys: ['a'] }, false)).toEqual('Label A'); + // This accessor does not + expect(nameFn({ ...nameFnArgs, seriesKeys: ['b'] }, false)).toEqual(''); + expect(nameFn({ ...nameFnArgs, seriesKeys: ['nonsense'] }, false)).toEqual(''); + }); + + test('split series without formatting and single y accessor', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a'], + splitAccessor: 'd', + columnToLabel: '{"a": "Label A"}', + }, + ], + }; + + const component = getRenderedComponent(dataWithoutFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + expect(nameFn({ ...nameFnArgs, seriesKeys: ['split1', 'a'] }, false)).toEqual('split1'); + }); + + test('split series with formatting and single y accessor', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a'], + splitAccessor: 'd', + columnToLabel: '{"a": "Label A"}', + }, + ], + }; + + const component = getRenderedComponent(dataWithFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + convertSpy.mockReturnValueOnce('formatted'); + expect(nameFn({ ...nameFnArgs, seriesKeys: ['split1', 'a'] }, false)).toEqual('formatted'); + expect(getFormatSpy).toHaveBeenCalledWith({ id: 'custom' }); + }); + + test('split series without formatting with multiple y accessors', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a', 'b'], + splitAccessor: 'd', + columnToLabel: '{"a": "Label A","b": "Label B"}', + }, + ], + }; + + const component = getRenderedComponent(dataWithoutFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + expect(nameFn({ ...nameFnArgs, seriesKeys: ['split1', 'b'] }, false)).toEqual( + 'split1 - Label B' + ); + }); + + test('split series with formatting with multiple y accessors', () => { + const args = createArgsWithLayers(); + const newArgs = { + ...args, + layers: [ + { + ...args.layers[0], + accessors: ['a', 'b'], + splitAccessor: 'd', + columnToLabel: '{"a": "Label A","b": "Label B"}', + }, + ], + }; + + const component = getRenderedComponent(dataWithFormats, newArgs); + const nameFn = component.find(LineSeries).prop('name') as SeriesNameFn; + + convertSpy.mockReturnValueOnce('formatted1').mockReturnValueOnce('formatted2'); + expect(nameFn({ ...nameFnArgs, seriesKeys: ['split1', 'a'] }, false)).toEqual( + 'formatted1 - Label A' + ); + expect(nameFn({ ...nameFnArgs, seriesKeys: ['split1', 'b'] }, false)).toEqual( + 'formatted2 - Label B' + ); + }); }); test('it set the scale of the x axis according to the args prop', () => { diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx index f5798688badc5..527eedf1083c2 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx @@ -361,12 +361,31 @@ export function XYChart({ enableHistogramMode: isHistogram && (seriesType.includes('stacked') || !splitAccessor), timeZone, name(d) { + const splitHint = table.columns.find(col => col.id === splitAccessor)?.formatHint; + + // For multiple y series, the name of the operation is used on each, either: + // * Key - Y name + // * Formatted value - Y name if (accessors.length > 1) { return d.seriesKeys - .map((key: string | number) => columnToLabelMap[key] || key) + .map((key: string | number, i) => { + if (i === 0 && splitHint) { + return formatFactory(splitHint).convert(key); + } + return splitAccessor && i === 0 ? key : columnToLabelMap[key] ?? ''; + }) .join(' - '); } - return columnToLabelMap[d.seriesKeys[0]] ?? d.seriesKeys[0]; + + // For formatted split series, format the key + // This handles splitting by dates, for example + if (splitHint) { + return formatFactory(splitHint).convert(d.seriesKeys[0]); + } + // This handles both split and single-y cases: + // * If split series without formatting, show the value literally + // * If single Y, the seriesKey will be the acccessor, so we show the human-readable name + return splitAccessor ? d.seriesKeys[0] : columnToLabelMap[d.seriesKeys[0]] ?? ''; }, }; From 5aa93be77d7e03802a5cfc2dcd020e57d80a27dd Mon Sep 17 00:00:00 2001 From: Nathan Reese <reese.nathan@gmail.com> Date: Tue, 14 Apr 2020 15:41:50 -0600 Subject: [PATCH 112/121] [Maps] fix double fetch when filter pill is added (#63024) * [Maps] fix double fetch when filter pill is added * remove isDataSyncActive * set dataMetaAtStart to null instead of deleting Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../data_request_descriptor_types.d.ts | 2 +- x-pack/plugins/maps/public/layers/util/data_request.ts | 10 +++++++--- x-pack/plugins/maps/public/reducers/map.js | 5 +++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts index ceba2fe56db12..26044d28d53a3 100644 --- a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts +++ b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.d.ts @@ -65,7 +65,7 @@ export type DataMeta = Partial<VectorSourceRequestMeta> & export type DataRequestDescriptor = { dataId: string; - dataMetaAtStart?: DataMeta; + dataMetaAtStart?: DataMeta | null; dataRequestToken?: symbol; data?: object; dataMeta?: DataMeta; diff --git a/x-pack/plugins/maps/public/layers/util/data_request.ts b/x-pack/plugins/maps/public/layers/util/data_request.ts index eeef5c49c6ef8..44b7b2ffb6ae7 100644 --- a/x-pack/plugins/maps/public/layers/util/data_request.ts +++ b/x-pack/plugins/maps/public/layers/util/data_request.ts @@ -26,9 +26,13 @@ export class DataRequest { } getMeta(): DataMeta { - return this.hasData() - ? _.get(this._descriptor, 'dataMeta', {}) - : _.get(this._descriptor, 'dataMetaAtStart', {}); + if (this._descriptor.dataMetaAtStart) { + return this._descriptor.dataMetaAtStart; + } else if (this._descriptor.dataMeta) { + return this._descriptor.dataMeta; + } else { + return {}; + } } hasData(): boolean { diff --git a/x-pack/plugins/maps/public/reducers/map.js b/x-pack/plugins/maps/public/reducers/map.js index 7e07569b44b83..251a2304538ed 100644 --- a/x-pack/plugins/maps/public/reducers/map.js +++ b/x-pack/plugins/maps/public/reducers/map.js @@ -57,8 +57,13 @@ const updateLayerInList = (state, layerId, attribute, newValue) => { if (!layerId) { return state; } + const { layerList } = state; const layerIdx = getLayerIndex(layerList, layerId); + if (layerIdx === -1) { + return state; + } + const updatedLayer = { ...layerList[layerIdx], // Update layer w/ new value. If no value provided, toggle boolean value From 0abbb1d9c4b22904eed969b28778715eb3ea33fa Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:19:31 -0400 Subject: [PATCH 113/121] adding useMemo (#63504) --- .../view/policy/policy_forms/events/linux.tsx | 26 ++++++++++--------- .../view/policy/policy_forms/events/mac.tsx | 26 ++++++++++--------- .../policy/policy_forms/events/windows.tsx | 7 ++--- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx index 9d2ce03c20462..ca2215d3d0a59 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/linux.tsx @@ -8,18 +8,19 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; +import { ImmutableArray } from '../../../../../../../common/types'; +import { getIn, setIn } from '../../../../models/policy_details_config'; import { EventsCheckbox } from './checkbox'; import { OS, UIPolicyConfig } from '../../../../types'; import { usePolicyDetailsSelector } from '../../policy_hooks'; import { selectedLinuxEvents, totalLinuxEvents } from '../../../../store/policy_details/selectors'; import { ConfigForm } from '../config_form'; -import { getIn, setIn } from '../../../../models/policy_details_config'; export const LinuxEvents = React.memo(() => { const selected = usePolicyDetailsSelector(selectedLinuxEvents); const total = usePolicyDetailsSelector(totalLinuxEvents); - const checkboxes: Array<{ + const checkboxes: ImmutableArray<{ name: string; os: 'linux'; protectionField: keyof UIPolicyConfig['linux']['events']; @@ -50,7 +51,7 @@ export const LinuxEvents = React.memo(() => { [] ); - const renderCheckboxes = () => { + const renderCheckboxes = useMemo(() => { return ( <> <EuiTitle size="xxs"> @@ -76,9 +77,9 @@ export const LinuxEvents = React.memo(() => { })} </> ); - }; + }, [checkboxes]); - const collectionsEnabled = () => { + const collectionsEnabled = useMemo(() => { return ( <EuiText size="s" color="subdued"> <FormattedMessage @@ -88,19 +89,20 @@ export const LinuxEvents = React.memo(() => { /> </EuiText> ); - }; + }, [selected, total]); return ( <ConfigForm type={i18n.translate('xpack.endpoint.policy.details.eventCollection', { defaultMessage: 'Event Collection', })} - supportedOss={[ - i18n.translate('xpack.endpoint.policy.details.linux', { defaultMessage: 'Linux' }), - ]} - id="linuxEventingForm" - rightCorner={collectionsEnabled()} - children={renderCheckboxes()} + supportedOss={useMemo( + () => [i18n.translate('xpack.endpoint.policy.details.linux', { defaultMessage: 'Linux' })], + [] + )} + id="linuxEventsForm" + rightCorner={collectionsEnabled} + children={renderCheckboxes} /> ); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx index 3b69c21d2b150..5024d02603d77 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/mac.tsx @@ -8,18 +8,19 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; +import { ImmutableArray } from '../../../../../../../common/types'; +import { getIn, setIn } from '../../../../models/policy_details_config'; import { EventsCheckbox } from './checkbox'; import { OS, UIPolicyConfig } from '../../../../types'; import { usePolicyDetailsSelector } from '../../policy_hooks'; import { selectedMacEvents, totalMacEvents } from '../../../../store/policy_details/selectors'; import { ConfigForm } from '../config_form'; -import { getIn, setIn } from '../../../../models/policy_details_config'; export const MacEvents = React.memo(() => { const selected = usePolicyDetailsSelector(selectedMacEvents); const total = usePolicyDetailsSelector(totalMacEvents); - const checkboxes: Array<{ + const checkboxes: ImmutableArray<{ name: string; os: 'mac'; protectionField: keyof UIPolicyConfig['mac']['events']; @@ -50,7 +51,7 @@ export const MacEvents = React.memo(() => { [] ); - const renderCheckboxes = () => { + const renderCheckboxes = useMemo(() => { return ( <> <EuiTitle size="xxs"> @@ -76,9 +77,9 @@ export const MacEvents = React.memo(() => { })} </> ); - }; + }, [checkboxes]); - const collectionsEnabled = () => { + const collectionsEnabled = useMemo(() => { return ( <EuiText size="s" color="subdued"> <FormattedMessage @@ -88,19 +89,20 @@ export const MacEvents = React.memo(() => { /> </EuiText> ); - }; + }, [selected, total]); return ( <ConfigForm type={i18n.translate('xpack.endpoint.policy.details.eventCollection', { defaultMessage: 'Event Collection', })} - supportedOss={[ - i18n.translate('xpack.endpoint.policy.details.mac', { defaultMessage: 'Mac' }), - ]} - id="macEventingForm" - rightCorner={collectionsEnabled()} - children={renderCheckboxes()} + supportedOss={useMemo( + () => [i18n.translate('xpack.endpoint.policy.details.mac', { defaultMessage: 'Mac' })], + [] + )} + id="macEventsForm" + rightCorner={collectionsEnabled} + children={renderCheckboxes} /> ); }); diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx index da675dc1e2393..5b347ec387f48 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_forms/events/windows.tsx @@ -8,6 +8,8 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiText, EuiSpacer } from '@elastic/eui'; +import { ImmutableArray } from '../../../../../../../common/types'; +import { setIn, getIn } from '../../../../models/policy_details_config'; import { EventsCheckbox } from './checkbox'; import { OS, UIPolicyConfig } from '../../../../types'; import { usePolicyDetailsSelector } from '../../policy_hooks'; @@ -16,13 +18,12 @@ import { totalWindowsEvents, } from '../../../../store/policy_details/selectors'; import { ConfigForm } from '../config_form'; -import { setIn, getIn } from '../../../../models/policy_details_config'; export const WindowsEvents = React.memo(() => { const selected = usePolicyDetailsSelector(selectedWindowsEvents); const total = usePolicyDetailsSelector(totalWindowsEvents); - const checkboxes: Array<{ + const checkboxes: ImmutableArray<{ name: string; os: 'windows'; protectionField: keyof UIPolicyConfig['windows']['events']; @@ -132,7 +133,7 @@ export const WindowsEvents = React.memo(() => { ], [] )} - id="windowsEventingForm" + id="windowsEventsForm" rightCorner={collectionsEnabled} children={renderCheckboxes} /> From 7677764c6597d0920b7d14a2d0e5773f9c32d2b7 Mon Sep 17 00:00:00 2001 From: Patrick Mueller <pmuellr@gmail.com> Date: Tue, 14 Apr 2020 18:20:50 -0400 Subject: [PATCH 114/121] [Alerting] fixes to allow pre-configured actions to be executed (#63432) resolves https://github.com/elastic/kibana/issues/63162 Most of the support for pre-configured actions has already been added to Kibana, except for one small piece. The ability for them to be executed. This PR adds that support. --- .../server/create_execute_function.test.ts | 67 +++++++++++++ .../actions/server/create_execute_function.ts | 25 ++++- .../server/lib/action_executor.test.ts | 2 + .../actions/server/lib/action_executor.ts | 72 +++++++++++--- .../server/lib/task_runner_factory.test.ts | 1 + x-pack/plugins/actions/server/plugin.ts | 2 + .../alerting_api_integration/common/config.ts | 21 +++++ .../es_index_preconfigured.ts | 68 ++++++++++++++ .../tests/actions/get_all.ts | 66 +++++++++++++ .../tests/actions/index.ts | 1 + .../tests/alerting/alerts.ts | 94 +++++++++++++++++++ .../spaces_only/tests/actions/get_all.ts | 44 +++++++++ 12 files changed, 445 insertions(+), 18 deletions(-) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts diff --git a/x-pack/plugins/actions/server/create_execute_function.test.ts b/x-pack/plugins/actions/server/create_execute_function.test.ts index 68c3967359ff4..6bdd30848e4b7 100644 --- a/x-pack/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/plugins/actions/server/create_execute_function.test.ts @@ -23,6 +23,7 @@ describe('execute()', () => { actionTypeRegistry: actionTypeRegistryMock.create(), getScopedSavedObjectsClient: jest.fn().mockReturnValueOnce(savedObjectsClient), isESOUsingEphemeralEncryptionKey: false, + preconfiguredActions: [], }); savedObjectsClient.get.mockResolvedValueOnce({ id: '123', @@ -68,6 +69,68 @@ describe('execute()', () => { }); }); + test('schedules the action with all given parameters with a preconfigured action', async () => { + const executeFn = createExecuteFunction({ + getBasePath, + taskManager: mockTaskManager, + actionTypeRegistry: actionTypeRegistryMock.create(), + getScopedSavedObjectsClient: jest.fn().mockReturnValueOnce(savedObjectsClient), + isESOUsingEphemeralEncryptionKey: false, + preconfiguredActions: [ + { + id: '123', + actionTypeId: 'mock-action-preconfigured', + config: {}, + isPreconfigured: true, + name: 'x', + secrets: {}, + }, + ], + }); + savedObjectsClient.get.mockResolvedValueOnce({ + id: '123', + type: 'action', + attributes: { + actionTypeId: 'mock-action', + }, + references: [], + }); + savedObjectsClient.create.mockResolvedValueOnce({ + id: '234', + type: 'action_task_params', + attributes: {}, + references: [], + }); + await executeFn({ + id: '123', + params: { baz: false }, + spaceId: 'default', + apiKey: Buffer.from('123:abc').toString('base64'), + }); + expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); + expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "params": Object { + "actionTaskParamsId": "234", + "spaceId": "default", + }, + "scope": Array [ + "actions", + ], + "state": Object {}, + "taskType": "actions:mock-action-preconfigured", + }, + ] + `); + expect(savedObjectsClient.get).not.toHaveBeenCalled(); + expect(savedObjectsClient.create).toHaveBeenCalledWith('action_task_params', { + actionId: '123', + params: { baz: false }, + apiKey: Buffer.from('123:abc').toString('base64'), + }); + }); + test('uses API key when provided', async () => { const getScopedSavedObjectsClient = jest.fn().mockReturnValueOnce(savedObjectsClient); const executeFn = createExecuteFunction({ @@ -76,6 +139,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: false, actionTypeRegistry: actionTypeRegistryMock.create(), + preconfiguredActions: [], }); savedObjectsClient.get.mockResolvedValueOnce({ id: '123', @@ -125,6 +189,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: false, actionTypeRegistry: actionTypeRegistryMock.create(), + preconfiguredActions: [], }); savedObjectsClient.get.mockResolvedValueOnce({ id: '123', @@ -171,6 +236,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: true, actionTypeRegistry: actionTypeRegistryMock.create(), + preconfiguredActions: [], }); await expect( executeFn({ @@ -193,6 +259,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: false, actionTypeRegistry: mockedActionTypeRegistry, + preconfiguredActions: [], }); mockedActionTypeRegistry.ensureActionTypeEnabled.mockImplementation(() => { throw new Error('Fail'); diff --git a/x-pack/plugins/actions/server/create_execute_function.ts b/x-pack/plugins/actions/server/create_execute_function.ts index 4bbcda4cba7fc..4a9ddf412b7cc 100644 --- a/x-pack/plugins/actions/server/create_execute_function.ts +++ b/x-pack/plugins/actions/server/create_execute_function.ts @@ -6,7 +6,12 @@ import { SavedObjectsClientContract } from '../../../../src/core/server'; import { TaskManagerStartContract } from '../../task_manager/server'; -import { GetBasePathFunction, RawAction, ActionTypeRegistryContract } from './types'; +import { + GetBasePathFunction, + RawAction, + ActionTypeRegistryContract, + PreConfiguredAction, +} from './types'; interface CreateExecuteFunctionOptions { taskManager: TaskManagerStartContract; @@ -14,6 +19,7 @@ interface CreateExecuteFunctionOptions { getBasePath: GetBasePathFunction; isESOUsingEphemeralEncryptionKey: boolean; actionTypeRegistry: ActionTypeRegistryContract; + preconfiguredActions: PreConfiguredAction[]; } export interface ExecuteOptions { @@ -29,6 +35,7 @@ export function createExecuteFunction({ actionTypeRegistry, getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey, + preconfiguredActions, }: CreateExecuteFunctionOptions) { return async function execute({ id, params, spaceId, apiKey }: ExecuteOptions) { if (isESOUsingEphemeralEncryptionKey === true) { @@ -61,9 +68,9 @@ export function createExecuteFunction({ }; const savedObjectsClient = getScopedSavedObjectsClient(fakeRequest); - const actionSavedObject = await savedObjectsClient.get<RawAction>('action', id); + const actionTypeId = await getActionTypeId(id); - actionTypeRegistry.ensureActionTypeEnabled(actionSavedObject.attributes.actionTypeId); + actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); const actionTaskParamsRecord = await savedObjectsClient.create('action_task_params', { actionId: id, @@ -72,7 +79,7 @@ export function createExecuteFunction({ }); await taskManager.schedule({ - taskType: `actions:${actionSavedObject.attributes.actionTypeId}`, + taskType: `actions:${actionTypeId}`, params: { spaceId, actionTaskParamsId: actionTaskParamsRecord.id, @@ -80,5 +87,15 @@ export function createExecuteFunction({ state: {}, scope: ['actions'], }); + + async function getActionTypeId(actionId: string): Promise<string> { + const pcAction = preconfiguredActions.find(action => action.id === actionId); + if (pcAction) { + return pcAction.actionTypeId; + } + + const actionSO = await savedObjectsClient.get<RawAction>('action', actionId); + return actionSO.attributes.actionTypeId; + } }; } diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index bbcb0457fc1d1..124e5951c714b 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -43,6 +43,7 @@ actionExecutor.initialize({ actionTypeRegistry, encryptedSavedObjectsPlugin, eventLogger: eventLoggerMock.create(), + preconfiguredActions: [], }); beforeEach(() => { @@ -232,6 +233,7 @@ test('throws an error when passing isESOUsingEphemeralEncryptionKey with value o actionTypeRegistry, encryptedSavedObjectsPlugin, eventLogger: eventLoggerMock.create(), + preconfiguredActions: [], }); await expect( customActionExecutor.execute(executeParams) diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index ba8bb79170c63..a33fb8830a930 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -11,6 +11,8 @@ import { ActionTypeRegistryContract, GetServicesFunction, RawAction, + PreConfiguredAction, + Services, } from '../types'; import { EncryptedSavedObjectsPluginStart } from '../../../encrypted_saved_objects/server'; import { SpacesServiceSetup } from '../../../spaces/server'; @@ -24,6 +26,7 @@ export interface ActionExecutorContext { encryptedSavedObjectsPlugin: EncryptedSavedObjectsPluginStart; actionTypeRegistry: ActionTypeRegistryContract; eventLogger: IEventLogger; + preconfiguredActions: PreConfiguredAction[]; } export interface ExecuteOptions { @@ -72,28 +75,22 @@ export class ActionExecutor { encryptedSavedObjectsPlugin, actionTypeRegistry, eventLogger, + preconfiguredActions, } = this.actionExecutorContext!; const services = getServices(request); const spaceId = spaces && spaces.getSpaceId(request); const namespace = spaceId && spaceId !== 'default' ? { namespace: spaceId } : {}; - // Ensure user can read the action before processing - const { - attributes: { actionTypeId, config, name }, - } = await services.savedObjectsClient.get<RawAction>('action', actionId); - - actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); - - // Only get encrypted attributes here, the remaining attributes can be fetched in - // the savedObjectsClient call - const { - attributes: { secrets }, - } = await encryptedSavedObjectsPlugin.getDecryptedAsInternalUser<RawAction>( - 'action', + const { actionTypeId, name, config, secrets } = await getActionInfo( + services, + encryptedSavedObjectsPlugin, + preconfiguredActions, actionId, - namespace + namespace.namespace ); + + actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); const actionType = actionTypeRegistry.get(actionTypeId); let validatedParams: Record<string, any>; @@ -173,3 +170,50 @@ function actionErrorToMessage(result: ActionTypeExecutorResult): string { return message; } + +interface ActionInfo { + actionTypeId: string; + name: string; + config: any; + secrets: any; +} + +async function getActionInfo( + services: Services, + encryptedSavedObjectsPlugin: EncryptedSavedObjectsPluginStart, + preconfiguredActions: PreConfiguredAction[], + actionId: string, + namespace: string | undefined +): Promise<ActionInfo> { + // check to see if it's a pre-configured action first + const pcAction = preconfiguredActions.find( + preconfiguredAction => preconfiguredAction.id === actionId + ); + if (pcAction) { + return { + actionTypeId: pcAction.actionTypeId, + name: pcAction.name, + config: pcAction.config, + secrets: pcAction.secrets, + }; + } + + // if not pre-configured action, should be a saved object + // ensure user can read the action before processing + const { + attributes: { actionTypeId, config, name }, + } = await services.savedObjectsClient.get<RawAction>('action', actionId); + + const { + attributes: { secrets }, + } = await encryptedSavedObjectsPlugin.getDecryptedAsInternalUser<RawAction>('action', actionId, { + namespace: namespace === 'default' ? undefined : namespace, + }); + + return { + actionTypeId, + name, + config, + secrets, + }; +} diff --git a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts index 43882cef21170..f070f714ee508 100644 --- a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts @@ -61,6 +61,7 @@ const actionExecutorInitializerParams = { actionTypeRegistry, encryptedSavedObjectsPlugin: mockedEncryptedSavedObjectsPlugin, eventLogger: eventLoggerMock.create(), + preconfiguredActions: [], }; const taskRunnerFactoryInitializerParams = { spaceIdToNamespace, diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 34c9e7aa9e8b8..ef3716070ab04 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -245,6 +245,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi getServices: this.getServicesFactory(core.savedObjects), encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects, actionTypeRegistry: actionTypeRegistry!, + preconfiguredActions, }); taskRunnerFactory!.initialize({ @@ -265,6 +266,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi getScopedSavedObjectsClient: core.savedObjects.getScopedClient, getBasePath: this.getBasePath, isESOUsingEphemeralEncryptionKey: isESOUsingEphemeralEncryptionKey!, + preconfiguredActions, }), isActionTypeEnabled: id => { return this.actionTypeRegistry!.isActionTypeEnabled(id); diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index 4d32a5ae9f53c..457b7621e84bd 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -100,6 +100,27 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) xyzSecret2: 'credential2', }, }, + { + id: 'preconfigured-es-index-action', + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + }, + { + id: 'preconfigured.test.index-record', + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + secrets: { + encrypted: 'this-is-also-ignored-and-also-required', + }, + }, ])}`, ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts new file mode 100644 index 0000000000000..b04bc13ffc5e4 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// from: x-pack/test/alerting_api_integration/common/config.ts +const ACTION_ID = 'preconfigured-es-index-action'; +const ES_TEST_INDEX_NAME = 'functional-test-actions-index-preconfigured'; + +// eslint-disable-next-line import/no-default-export +export default function indexTest({ getService }: FtrProviderContext) { + const es = getService('legacyEs'); + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('preconfigured index action', () => { + after(() => esArchiver.unload('empty_kibana')); + beforeEach(() => clearTestIndex(es)); + + it('should execute successfully when expected for a single body', async () => { + const { body: result } = await supertest + .post(`/api/action/${ACTION_ID}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + documents: [{ testing: [4, 5, 6] }], + }, + }) + .expect(200); + expect(result.status).to.eql('ok'); + + const items = await getTestIndexItems(es); + expect(items.length).to.eql(1); + + // check document sans timestamp + const document = items[0]._source; + const timestamp = document.timestamp; + delete document.timestamp; + expect(document).to.eql({ testing: [4, 5, 6] }); + + // check timestamp + const timestampTime = new Date(timestamp).getTime(); + const timeNow = Date.now(); + const timeMinuteAgo = timeNow - 1000 * 60; + expect(timestampTime).to.be.within(timeMinuteAgo, timeNow); + }); + }); +} + +async function clearTestIndex(es: any) { + return await es.indices.delete({ + index: ES_TEST_INDEX_NAME, + ignoreUnavailable: true, + }); +} + +async function getTestIndexItems(es: any) { + const result = await es.search({ + index: ES_TEST_INDEX_NAME, + }); + + return result.hits.hits; +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts index 80b512f3fb5e3..0b637326d4667 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts @@ -68,6 +68,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -90,6 +102,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); break; default: @@ -167,6 +189,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 1, }, + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -189,6 +223,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); break; default: @@ -232,6 +276,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { case 'superuser at space1': expect(response.statusCode).to.eql(200); expect(response.body).to.eql([ + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -254,6 +310,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); break; default: diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts index d7ec2e78ccb30..8e002bcc8d3da 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts @@ -11,6 +11,7 @@ export default function actionsTests({ loadTestFile }: FtrProviderContext) { describe('Actions', () => { loadTestFile(require.resolve('./builtin_action_types/email')); loadTestFile(require.resolve('./builtin_action_types/es_index')); + loadTestFile(require.resolve('./builtin_action_types/es_index_preconfigured')); loadTestFile(require.resolve('./builtin_action_types/pagerduty')); loadTestFile(require.resolve('./builtin_action_types/server_log')); loadTestFile(require.resolve('./builtin_action_types/servicenow')); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts index 6eed28cc381dd..d8e4f808f5cd2 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts @@ -165,6 +165,100 @@ instanceStateValue: true } }); + it('should schedule task, run alert and schedule preconfigured actions when appropriate', async () => { + const testStart = new Date(); + const reference = alertUtils.generateReference(); + const response = await alertUtils.createAlwaysFiringAction({ + reference, + indexRecordActionId: 'preconfigured.test.index-record', + }); + + switch (scenario.id) { + case 'no_kibana_privileges at space1': + case 'global_read at space1': + case 'space_1_all at space2': + expect(response.statusCode).to.eql(404); + expect(response.body).to.eql({ + statusCode: 404, + error: 'Not Found', + message: 'Not Found', + }); + break; + case 'superuser at space1': + case 'space_1_all at space1': + expect(response.statusCode).to.eql(200); + + // Wait for the action to index a document before disabling the alert and waiting for tasks to finish + await esTestIndexTool.waitForDocs('action:test.index-record', reference); + + await taskManagerUtils.waitForAllTasksIdle(testStart); + + const alertId = response.body.id; + await alertUtils.disable(alertId); + await taskManagerUtils.waitForEmpty(testStart); + + // Ensure only 1 alert executed with proper params + const alertSearchResult = await esTestIndexTool.search( + 'alert:test.always-firing', + reference + ); + expect(alertSearchResult.hits.total.value).to.eql(1); + expect(alertSearchResult.hits.hits[0]._source).to.eql({ + source: 'alert:test.always-firing', + reference, + state: {}, + params: { + index: ES_TEST_INDEX_NAME, + reference, + }, + alertInfo: { + alertId, + spaceId: space.id, + namespace: space.id, + name: 'abc', + tags: ['tag-A', 'tag-B'], + createdBy: user.fullName, + updatedBy: user.fullName, + }, + }); + + // Ensure only 1 action executed with proper params + const actionSearchResult = await esTestIndexTool.search( + 'action:test.index-record', + reference + ); + expect(actionSearchResult.hits.total.value).to.eql(1); + expect(actionSearchResult.hits.hits[0]._source).to.eql({ + config: { + unencrypted: 'ignored-but-required', + }, + secrets: { + encrypted: 'this-is-also-ignored-and-also-required', + }, + params: { + index: ES_TEST_INDEX_NAME, + reference, + message: ` +alertId: ${alertId}, +alertName: abc, +spaceId: ${space.id}, +tags: tag-A,tag-B, +alertInstanceId: 1, +instanceContextValue: true, +instanceStateValue: true +`.trim(), + }, + reference, + source: 'action:test.index-record', + }); + + await taskManagerUtils.waitForActionTaskParamsToBeCleanedUp(testStart); + break; + default: + throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); + } + }); + it('should pass updated alert params to executor', async () => { const testStart = new Date(); // create an alert diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts index 517c64f178af5..ec59e56b08308 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts @@ -45,6 +45,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -67,6 +79,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); }); @@ -88,6 +110,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); await supertest.get(`${getUrlPrefix(Spaces.other.id)}/api/action/_getAll`).expect(200, [ + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -110,6 +144,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); }); }); From bf63b56f833c8657cb249c0a69805acc47608550 Mon Sep 17 00:00:00 2001 From: Phillip Burch <phillip.burch@live.com> Date: Tue, 14 Apr 2020 18:32:05 -0500 Subject: [PATCH 115/121] Disable adding conditions when in alert management context. (#63514) * Disable adding conditions when in alert manament context. * Fix typo * Change id for i18n string --- .../alerting/metrics/expression.tsx | 179 ++++++++++++------ 1 file changed, 117 insertions(+), 62 deletions(-) diff --git a/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx b/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx index 2430fe78e2053..6cf4e5bed2e6f 100644 --- a/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx +++ b/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx @@ -17,6 +17,9 @@ import { import { IFieldType } from 'src/plugins/data/public'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { EuiExpression } from '@elastic/eui'; +import { EuiCallOut } from '@elastic/eui'; +import { EuiLink } from '@elastic/eui'; import { MetricExpressionParams, Comparator, @@ -208,6 +211,37 @@ export const Expressions: React.FC<Props> = props => { } }, [alertsContext.metadata, defaultExpression, source]); // eslint-disable-line react-hooks/exhaustive-deps + // INFO: If there is metadata, you're in the metrics explorer context + const canAddConditions = !!alertsContext.metadata; + + if (!canAddConditions && !alertParams.criteria) { + return ( + <> + <EuiSpacer size={'m'} /> + <EuiCallOut + title={ + <> + <FormattedMessage + id="xpack.infra.metrics.alertFlyout.createAlertWarningBody" + defaultMessage="Create new metric threshold alerts from" + />{' '} + <EuiLink href={'../app/metrics/explorer'}> + <FormattedMessage + id="xpack.infra.homePage.metricsExplorerTabTitle" + defaultMessage="Metrics Explorer" + /> + </EuiLink> + . + </> + } + color="warning" + iconType="help" + /> + <EuiSpacer size={'m'} /> + </> + ); + } + return ( <> <EuiSpacer size={'m'} /> @@ -224,6 +258,7 @@ export const Expressions: React.FC<Props> = props => { alertParams.criteria.map((e, idx) => { return ( <ExpressionRow + canEditAggField={canAddConditions} canDelete={alertParams.criteria.length > 1} fields={derivedIndexPattern.fields} remove={removeExpression} @@ -246,62 +281,65 @@ export const Expressions: React.FC<Props> = props => { /> <div> - <EuiButtonEmpty - color={'primary'} - iconSide={'left'} - flush={'left'} - iconType={'plusInCircleFilled'} - onClick={addExpression} - > - <FormattedMessage - id="xpack.infra.metrics.alertFlyout.addCondition" - defaultMessage="Add condition" - /> - </EuiButtonEmpty> + {canAddConditions && ( + <EuiButtonEmpty + color={'primary'} + iconSide={'left'} + flush={'left'} + iconType={'plusInCircleFilled'} + onClick={addExpression} + > + <FormattedMessage + id="xpack.infra.metrics.alertFlyout.addCondition" + defaultMessage="Add condition" + /> + </EuiButtonEmpty> + )} </div> <EuiSpacer size={'m'} /> - <EuiFormRow - label={i18n.translate('xpack.infra.metrics.alertFlyout.filterLabel', { - defaultMessage: 'Filter (optional)', - })} - helpText={i18n.translate('xpack.infra.metrics.alertFlyout.filterHelpText', { - defaultMessage: 'Use a KQL expression to limit the scope of your alert trigger.', - })} - fullWidth - compressed - > - <MetricsExplorerKueryBar - derivedIndexPattern={derivedIndexPattern} - onSubmit={onFilterQuerySubmit} - value={alertParams.filterQuery} - /> - </EuiFormRow> - - <EuiSpacer size={'m'} /> - {alertsContext.metadata && ( - <EuiFormRow - label={i18n.translate('xpack.infra.metrics.alertFlyout.createAlertPerText', { - defaultMessage: 'Create alert per (optional)', - })} - helpText={i18n.translate('xpack.infra.metrics.alertFlyout.createAlertPerHelpText', { - defaultMessage: - 'Create an alert for every unique value. For example: "host.id" or "cloud.region".', - })} - fullWidth - compressed - > - <MetricsExplorerGroupBy - onChange={onGroupByChange} - fields={derivedIndexPattern.fields} - options={{ - ...options, - groupBy: alertParams.groupBy || undefined, - }} - /> - </EuiFormRow> + <> + <EuiFormRow + label={i18n.translate('xpack.infra.metrics.alertFlyout.filterLabel', { + defaultMessage: 'Filter (optional)', + })} + helpText={i18n.translate('xpack.infra.metrics.alertFlyout.filterHelpText', { + defaultMessage: 'Use a KQL expression to limit the scope of your alert trigger.', + })} + fullWidth + compressed + > + <MetricsExplorerKueryBar + derivedIndexPattern={derivedIndexPattern} + onSubmit={onFilterQuerySubmit} + value={alertParams.filterQuery} + /> + </EuiFormRow> + + <EuiSpacer size={'m'} /> + <EuiFormRow + label={i18n.translate('xpack.infra.metrics.alertFlyout.createAlertPerText', { + defaultMessage: 'Create alert per (optional)', + })} + helpText={i18n.translate('xpack.infra.metrics.alertFlyout.createAlertPerHelpText', { + defaultMessage: + 'Create an alert for every unique value. For example: "host.id" or "cloud.region".', + })} + fullWidth + compressed + > + <MetricsExplorerGroupBy + onChange={onGroupByChange} + fields={derivedIndexPattern.fields} + options={{ + ...options, + groupBy: alertParams.groupBy || undefined, + }} + /> + </EuiFormRow> + </> )} </> ); @@ -309,6 +347,7 @@ export const Expressions: React.FC<Props> = props => { interface ExpressionRowProps { fields: IFieldType[]; + canEditAggField: boolean; expressionId: number; expression: MetricExpression; errors: IErrorObject; @@ -379,17 +418,20 @@ export const ExpressionRow: React.FC<ExpressionRowProps> = props => { </StyledExpression> {aggType !== 'count' && ( <StyledExpression> - <OfExpression - customAggTypesOptions={aggregationType} - aggField={metric} - fields={fields.map(f => ({ - normalizedType: f.type, - name: f.name, - }))} - aggType={aggType} - errors={errors} - onChangeSelectedAggField={updateMetric} - /> + {!props.canEditAggField && <DisabledAggField text={metric || ''} />} + {props.canEditAggField && ( + <OfExpression + customAggTypesOptions={aggregationType} + aggField={metric} + fields={fields.map(f => ({ + normalizedType: f.type, + name: f.name, + }))} + aggType={aggType} + errors={errors} + onChangeSelectedAggField={updateMetric} + /> + )} </StyledExpression> )} <StyledExpression> @@ -421,6 +463,19 @@ export const ExpressionRow: React.FC<ExpressionRowProps> = props => { ); }; +export const DisabledAggField = ({ text }: { text: string }) => { + return ( + <EuiExpression + description={i18n.translate('xpack.infra.metrics.alertFlyout.of.buttonLabel', { + defaultMessage: 'of', + })} + value={text} + isActive={false} + color={'secondary'} + /> + ); +}; + export const aggregationType: { [key: string]: any } = { avg: { text: i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.avg', { From 8264352bbe27c527e2738aaf95bf9c4e51fa294b Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm <matthias.wilhelm@elastic.co> Date: Wed, 15 Apr 2020 08:33:10 +0200 Subject: [PATCH 116/121] [Discover] Fix broken setting of bucketInterval (#62939) * Fix broken setting of bucketInterval, remove $watch * Fix and adapt functional tests --- .../discover/np_ready/angular/discover.html | 1 + .../discover/np_ready/angular/discover.js | 14 +++---------- .../apps/discover/_discover_histogram.js | 20 +++++++++---------- test/functional/page_objects/discover_page.ts | 5 +++++ 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html index d068e824a3e0a..1221b01657e45 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.html @@ -140,6 +140,7 @@ <h1 class="euiScreenReaderOnly">{{screenTitle}}</h1> position="'top'" ></icon-tip> <span + data-test-subj="discoverIntervalSelectScaledToDesc" i18n-id="kbn.discover.scaledToDescription" i18n-default-message="Scaled to {bucketIntervalDescription}" i18n-values="{ diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index 630ba22d4f3a6..d770e8334b3af 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -675,17 +675,6 @@ function discoverController( } }); - $scope.$watch('vis.aggs', function() { - // no timefield, no vis, nothing to update - if (!getTimeField() || !$scope.vis) return; - - const buckets = $scope.vis.data.aggs.byTypeName('buckets'); - - if (buckets && buckets.length === 1) { - $scope.bucketInterval = buckets[0].buckets.getInterval(); - } - }); - $scope.$watchMulti( ['rows', 'fetchStatus'], (function updateResultState() { @@ -891,6 +880,9 @@ function discoverController( tabifiedData, getDimensions($scope.vis.data.aggs.aggs, $scope.timeRange) ); + if ($scope.vis.data.aggs.aggs[1]) { + $scope.bucketInterval = $scope.vis.data.aggs.aggs[1].buckets.getInterval(); + } } $scope.hits = resp.hits.total; diff --git a/test/functional/apps/discover/_discover_histogram.js b/test/functional/apps/discover/_discover_histogram.js index f815c505a8c27..eeef3333aab0f 100644 --- a/test/functional/apps/discover/_discover_histogram.js +++ b/test/functional/apps/discover/_discover_histogram.js @@ -66,9 +66,8 @@ export default function({ getService, getPageObjects }) { }); it('should visualize monthly data with different day intervals', async () => { - //Nov 1, 2017 @ 01:00:00.000 - Mar 21, 2018 @ 02:00:00.000 - const fromTime = '2017-11-01 00:00:00.000'; - const toTime = '2018-03-21 00:00:00.000'; + const fromTime = 'Nov 01, 2017 @ 00:00:00.000'; + const toTime = 'Mar 21, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.discover.setChartInterval('Monthly'); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -76,24 +75,25 @@ export default function({ getService, getPageObjects }) { expect(chartCanvasExist).to.be(true); }); it('should visualize weekly data with within DST changes', async () => { - //Nov 1, 2017 @ 01:00:00.000 - Mar 21, 2018 @ 02:00:00.000 - const fromTime = '2018-03-01 00:00:00.000'; - const toTime = '2018-05-01 00:00:00.000'; + const fromTime = 'Mar 01, 2018 @ 00:00:00.000'; + const toTime = 'May 01, 2018 @ 00:00:00.000'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.discover.setChartInterval('Weekly'); await PageObjects.header.waitUntilLoadingHasFinished(); const chartCanvasExist = await elasticChart.canvasExists(); expect(chartCanvasExist).to.be(true); }); - it('should visualize monthly data with different years Scaled to 30d', async () => { - //Nov 1, 2017 @ 01:00:00.000 - Mar 21, 2018 @ 02:00:00.000 - const fromTime = '2010-01-01 00:00:00.000'; - const toTime = '2018-03-21 00:00:00.000'; + it('should visualize monthly data with different years Scaled to 30 days', async () => { + const fromTime = 'Jan 01, 2010 @ 00:00:00.000'; + const toTime = 'Mar 21, 2019 @ 00:00:00.000'; + await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); await PageObjects.discover.setChartInterval('Daily'); await PageObjects.header.waitUntilLoadingHasFinished(); const chartCanvasExist = await elasticChart.canvasExists(); expect(chartCanvasExist).to.be(true); + const chartIntervalScaledDesc = await PageObjects.discover.getChartIntervalScaledToDesc(); + expect(chartIntervalScaledDesc).to.be('Scaled to 30 days'); }); }); } diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 00bf87621864a..e43a774940391 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -162,6 +162,11 @@ export function DiscoverPageProvider({ getService, getPageObjects }: FtrProvider return selectedOption.getVisibleText(); } + public async getChartIntervalScaledToDesc() { + await header.waitUntilLoadingHasFinished(); + return await testSubjects.getVisibleText('discoverIntervalSelectScaledToDesc'); + } + public async setChartInterval(interval: string) { const optionElement = await find.byCssSelector(`option[label="${interval}"]`, 5000); await optionElement.click(); From 18687a35312bb48d6c2ea021e6018e630dcd5e20 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa <Uladzislau_Lasitsa@epam.com> Date: Wed, 15 Apr 2020 11:16:36 +0300 Subject: [PATCH 117/121] [data.search.aggs] Remove service getters from agg types (AggConfig part) (#62548) * removed getFieldFormats from aggConfig * made new properties is private * Fixed ci * Fixed tests * Fixes clone method * move filedFotmats inside opt fro AggConfigs * Added readonly Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> --- .../new_platform/new_platform.karma_mock.js | 1 + src/plugins/data/public/plugin.ts | 2 +- .../public/search/aggs/agg_config.test.ts | 34 +++++++------- .../data/public/search/aggs/agg_config.ts | 19 +++++--- .../public/search/aggs/agg_configs.test.ts | 44 +++++++++++-------- .../data/public/search/aggs/agg_configs.ts | 17 +++++-- .../_terms_other_bucket_helper.test.ts | 5 ++- .../create_filter/date_histogram.test.ts | 5 ++- .../buckets/create_filter/date_range.test.ts | 5 ++- .../buckets/create_filter/filters.test.ts | 5 ++- .../buckets/create_filter/histogram.test.ts | 4 +- .../buckets/create_filter/ip_range.test.ts | 5 ++- .../aggs/buckets/create_filter/range.test.ts | 5 ++- .../aggs/buckets/create_filter/terms.test.ts | 1 + .../search/aggs/buckets/date_range.test.ts | 5 ++- .../search/aggs/buckets/geo_hash.test.ts | 5 ++- .../search/aggs/buckets/histogram.test.ts | 5 ++- .../public/search/aggs/buckets/range.test.ts | 5 ++- .../aggs/buckets/significant_terms.test.ts | 1 + .../public/search/aggs/buckets/terms.test.ts | 4 +- .../public/search/aggs/metrics/median.test.ts | 5 ++- .../aggs/metrics/parent_pipeline.test.ts | 2 +- .../aggs/metrics/percentile_ranks.test.ts | 2 +- .../search/aggs/metrics/percentiles.test.ts | 2 +- .../aggs/metrics/sibling_pipeline.test.ts | 2 +- .../search/aggs/metrics/std_deviation.test.ts | 2 +- .../search/aggs/metrics/top_hit.test.ts | 2 +- src/plugins/data/public/search/aggs/mocks.ts | 2 + .../search/expressions/create_filter.test.ts | 4 +- .../data/public/search/search_service.ts | 13 +++++- .../public/search/tabify/get_columns.test.ts | 3 ++ .../search/tabify/response_writer.test.ts | 3 ++ .../data/public/search/tabify/tabify.test.ts | 3 ++ 33 files changed, 156 insertions(+), 66 deletions(-) diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 33a7fdad065b4..f577a29ce90b9 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -453,6 +453,7 @@ export const npStart = { createAggConfigs: (indexPattern, configStates = []) => { return new AggConfigs(indexPattern, configStates, { typesRegistry: aggTypesRegistry.start(), + fieldFormats: getFieldFormatsRegistry(mockCoreStart), }); }, types: aggTypesRegistry.start(), diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 2ebe377b3b32f..1723545b32522 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -155,7 +155,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli const query = this.queryService.start(savedObjects); setQueryService(query); - const search = this.searchService.start(core, indexPatterns); + const search = this.searchService.start(core, { fieldFormats, indexPatterns }); setSearchService(search); uiActions.attachAction(APPLY_FILTER_TRIGGER, uiActions.getAction(ACTION_GLOBAL_APPLY_FILTER)); diff --git a/src/plugins/data/public/search/aggs/agg_config.test.ts b/src/plugins/data/public/search/aggs/agg_config.test.ts index 41d943ef0c94b..2813e3b9c5373 100644 --- a/src/plugins/data/public/search/aggs/agg_config.test.ts +++ b/src/plugins/data/public/search/aggs/agg_config.test.ts @@ -26,10 +26,12 @@ import { AggTypesRegistryStart } from './agg_types_registry'; import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; import { Field as IndexPatternField, IndexPattern } from '../../index_patterns'; import { stubIndexPatternWithFields } from '../../../public/stubs'; +import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('AggConfig', () => { let indexPattern: IndexPattern; let typesRegistry: AggTypesRegistryStart; + const fieldFormats = fieldFormatsServiceMock.createStartContract(); beforeEach(() => { jest.restoreAllMocks(); @@ -40,7 +42,7 @@ describe('AggConfig', () => { describe('#toDsl', () => { it('calls #write()', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); const configStates = { enabled: true, type: 'date_histogram', @@ -55,7 +57,7 @@ describe('AggConfig', () => { }); it('uses the type name as the agg name', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); const configStates = { enabled: true, type: 'date_histogram', @@ -70,7 +72,7 @@ describe('AggConfig', () => { }); it('uses the params from #write() output as the agg params', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); const configStates = { enabled: true, type: 'date_histogram', @@ -100,7 +102,7 @@ describe('AggConfig', () => { params: {}, }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const histoConfig = ac.byName('date_histogram')[0]; const avgConfig = ac.byName('avg')[0]; @@ -210,8 +212,8 @@ describe('AggConfig', () => { testsIdentical.forEach((configState, index) => { it(`identical aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry }); + const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats }); + const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); }); }); @@ -251,8 +253,8 @@ describe('AggConfig', () => { testsIdenticalDifferentOrder.forEach((test, index) => { it(`identical aggregations (${index}) - init json is in different order`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true); }); }); @@ -316,8 +318,8 @@ describe('AggConfig', () => { testsDifferent.forEach((test, index) => { it(`different aggregations (${index})`, () => { - const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry }); + const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats }); + const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats }); expect(ac1.jsonDataEquals(ac2.aggs)).toBe(false); }); }); @@ -325,7 +327,7 @@ describe('AggConfig', () => { describe('#toJSON', () => { it('includes the aggs id, params, type and schema', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); const configStates = { enabled: true, type: 'date_histogram', @@ -356,8 +358,8 @@ describe('AggConfig', () => { params: {}, }, ]; - const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry }); - const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); + const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); // this relies on the assumption that js-engines consistently loop over properties in insertion order. // most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications. @@ -369,7 +371,7 @@ describe('AggConfig', () => { let aggConfig: AggConfig; beforeEach(() => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); aggConfig = ac.createAggConfig({ type: 'count' } as CreateAggConfigParams); }); @@ -398,7 +400,7 @@ describe('AggConfig', () => { describe('#fieldFormatter - custom getFormat handler', () => { it('returns formatter from getFormat handler', () => { - const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats }); const configStates = { enabled: true, type: 'count', @@ -439,7 +441,7 @@ describe('AggConfig', () => { }, }, }; - const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry }); + const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry, fieldFormats }); aggConfig = ac.createAggConfig(configStates); }); diff --git a/src/plugins/data/public/search/aggs/agg_config.ts b/src/plugins/data/public/search/aggs/agg_config.ts index d6948aaade63d..6188849e0e6d4 100644 --- a/src/plugins/data/public/search/aggs/agg_config.ts +++ b/src/plugins/data/public/search/aggs/agg_config.ts @@ -25,7 +25,7 @@ import { IAggConfigs } from './agg_configs'; import { FetchOptions } from '../fetch'; import { ISearchSource } from '../search_source'; import { FieldFormatsContentType, KBN_FIELD_TYPES } from '../../../common'; -import { getFieldFormats } from '../../../public/services'; +import { FieldFormatsStart } from '../../field_formats'; export interface AggConfigOptions { type: IAggType; @@ -35,6 +35,10 @@ export interface AggConfigOptions { schema?: string; } +export interface AggConfigDependencies { + fieldFormats: FieldFormatsStart; +} + /** * @name AggConfig * @@ -93,8 +97,13 @@ export class AggConfig { private __type: IAggType; private __typeDecorations: any; private subAggs: AggConfig[] = []; + private readonly fieldFormats: FieldFormatsStart; - constructor(aggConfigs: IAggConfigs, opts: AggConfigOptions) { + constructor( + aggConfigs: IAggConfigs, + opts: AggConfigOptions, + { fieldFormats }: AggConfigDependencies + ) { this.aggConfigs = aggConfigs; this.id = String(opts.id || AggConfig.nextId(aggConfigs.aggs as any)); this.enabled = typeof opts.enabled === 'boolean' ? opts.enabled : true; @@ -115,6 +124,8 @@ export class AggConfig { // @ts-ignore this.__type = this.__type; + + this.fieldFormats = fieldFormats; } /** @@ -341,12 +352,10 @@ export class AggConfig { } fieldOwnFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) { - const fieldFormatsService = getFieldFormats(); - const field = this.getField(); let format = field && field.format; if (!format) format = defaultFormat; - if (!format) format = fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING); + if (!format) format = this.fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING); return format.getConverterFor(contentType); } diff --git a/src/plugins/data/public/search/aggs/agg_configs.test.ts b/src/plugins/data/public/search/aggs/agg_configs.test.ts index e20e6de6112a8..653bf6a266df6 100644 --- a/src/plugins/data/public/search/aggs/agg_configs.test.ts +++ b/src/plugins/data/public/search/aggs/agg_configs.test.ts @@ -24,10 +24,12 @@ import { AggTypesRegistryStart } from './agg_types_registry'; import { mockDataServices, mockAggTypesRegistry } from './test_helpers'; import { Field as IndexPatternField, IndexPattern } from '../../index_patterns'; import { stubIndexPattern, stubIndexPatternWithFields } from '../../../public/stubs'; +import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('AggConfigs', () => { let indexPattern: IndexPattern; let typesRegistry: AggTypesRegistryStart; + const fieldFormats = fieldFormatsServiceMock.createStartContract(); beforeEach(() => { mockDataServices(); @@ -45,7 +47,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); expect(ac.aggs).toHaveLength(1); }); @@ -70,7 +72,7 @@ describe('AggConfigs', () => { ]; const spy = jest.spyOn(AggConfig, 'ensureIds'); - new AggConfigs(indexPattern, configStates, { typesRegistry }); + new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); expect(spy).toHaveBeenCalledTimes(1); expect(spy.mock.calls[0]).toEqual([configStates]); spy.mockRestore(); @@ -92,16 +94,20 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); expect(ac.aggs).toHaveLength(2); ac.createAggConfig( - new AggConfig(ac, { - enabled: true, - type: typesRegistry.get('terms'), - params: {}, - schema: 'split', - }) + new AggConfig( + ac, + { + enabled: true, + type: typesRegistry.get('terms'), + params: {}, + schema: 'split', + }, + { fieldFormats } + ) ); expect(ac.aggs).toHaveLength(3); }); @@ -115,7 +121,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); expect(ac.aggs).toHaveLength(1); ac.createAggConfig({ @@ -136,7 +142,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); expect(ac.aggs).toHaveLength(1); ac.createAggConfig( @@ -164,7 +170,7 @@ describe('AggConfigs', () => { { type: 'percentiles', enabled: true, params: {}, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const sorted = ac.getRequestAggs(); const aggs = indexBy(ac.aggs, agg => agg.type.name); @@ -187,7 +193,7 @@ describe('AggConfigs', () => { { type: 'count', enabled: true, params: {}, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const sorted = ac.getResponseAggs(); const aggs = indexBy(ac.aggs, agg => agg.type.name); @@ -204,7 +210,7 @@ describe('AggConfigs', () => { { type: 'percentiles', enabled: true, params: { percents: [1, 2, 3] }, schema: 'metric' }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const sorted = ac.getResponseAggs(); const aggs = indexBy(ac.aggs, agg => agg.type.name); @@ -225,7 +231,7 @@ describe('AggConfigs', () => { it('uses the sorted aggs', () => { const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const spy = jest.spyOn(AggConfigs.prototype, 'getRequestAggs'); ac.toDsl(); expect(spy).toHaveBeenCalledTimes(1); @@ -241,6 +247,7 @@ describe('AggConfigs', () => { const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, + fieldFormats, }); const aggInfos = ac.aggs.map(aggConfig => { @@ -284,7 +291,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const dsl = ac.toDsl(); const histo = ac.byName('date_histogram')[0]; const count = ac.byName('count')[0]; @@ -311,6 +318,7 @@ describe('AggConfigs', () => { const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, + fieldFormats, }); const dsl = ac.toDsl(); const histo = ac.byName('date_histogram')[0]; @@ -336,7 +344,7 @@ describe('AggConfigs', () => { { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const topLevelDsl = ac.toDsl(true); const buckets = ac.bySchemaName('buckets'); const metrics = ac.bySchemaName('metrics'); @@ -406,7 +414,7 @@ describe('AggConfigs', () => { }, ]; - const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats }); const topLevelDsl = ac.toDsl(true)['2']; expect(Object.keys(topLevelDsl.aggs)).toContain('1'); diff --git a/src/plugins/data/public/search/aggs/agg_configs.ts b/src/plugins/data/public/search/aggs/agg_configs.ts index c441b2a0eb46f..5ad09f824d3e4 100644 --- a/src/plugins/data/public/search/aggs/agg_configs.ts +++ b/src/plugins/data/public/search/aggs/agg_configs.ts @@ -28,6 +28,7 @@ import { IndexPattern } from '../../index_patterns'; import { ISearchSource } from '../search_source'; import { FetchOptions } from '../fetch'; import { TimeRange } from '../../../common'; +import { FieldFormatsStart } from '../../field_formats'; function removeParentAggs(obj: any) { for (const prop in obj) { @@ -47,6 +48,7 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) { export interface AggConfigsOptions { typesRegistry: AggTypesRegistryStart; + fieldFormats: FieldFormatsStart; } export type CreateAggConfigParams = Assign<AggConfigOptions, { type: string | IAggType }>; @@ -68,6 +70,7 @@ export type IAggConfigs = AggConfigs; export class AggConfigs { public indexPattern: IndexPattern; public timeRange?: TimeRange; + private readonly fieldFormats: FieldFormatsStart; private readonly typesRegistry: AggTypesRegistryStart; aggs: IAggConfig[]; @@ -83,6 +86,7 @@ export class AggConfigs { this.aggs = []; this.indexPattern = indexPattern; + this.fieldFormats = opts.fieldFormats; configStates.forEach((params: any) => this.createAggConfig(params)); } @@ -113,6 +117,7 @@ export class AggConfigs { const aggConfigs = new AggConfigs(this.indexPattern, this.aggs.filter(filterAggs), { typesRegistry: this.typesRegistry, + fieldFormats: this.fieldFormats, }); return aggConfigs; @@ -129,10 +134,14 @@ export class AggConfigs { aggConfig = params; params.parent = this; } else { - aggConfig = new AggConfig(this, { - ...params, - type: typeof type === 'string' ? this.typesRegistry.get(type) : type, - }); + aggConfig = new AggConfig( + this, + { + ...params, + type: typeof type === 'string' ? this.typesRegistry.get(type) : type, + }, + { fieldFormats: this.fieldFormats } + ); } if (addToAggConfigs) { diff --git a/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts b/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts index c664325a168b1..44d99375bbd30 100644 --- a/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/_terms_other_bucket_helper.test.ts @@ -26,6 +26,7 @@ import { AggConfigs, CreateAggConfigParams } from '../agg_configs'; import { BUCKET_TYPES } from './bucket_agg_types'; import { IBucketAggConfig } from './bucket_agg_type'; import { mockAggTypesRegistry } from '../test_helpers'; +import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; const indexPattern = { id: '1234', @@ -219,8 +220,10 @@ const nestedOtherResponse = { describe('Terms Agg Other bucket helper', () => { const typesRegistry = mockAggTypesRegistry(); + const fieldFormats = fieldFormatsServiceMock.createStartContract(); + const getAggConfigs = (aggs: CreateAggConfigParams[] = []) => { - return new AggConfigs(indexPattern, [...aggs], { typesRegistry }); + return new AggConfigs(indexPattern, [...aggs], { typesRegistry, fieldFormats }); }; describe('buildOtherBucketAgg', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts index 97c940b4ff4b1..7778fcb36bcd6 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts @@ -78,7 +78,10 @@ describe('AggConfig Filters', () => { params: { field: field.name, interval, customInterval: '5d' }, }, ], - { typesRegistry: mockAggTypesRegistry([getDateHistogramBucketAgg(aggTypesDependencies)]) } + { + typesRegistry: mockAggTypesRegistry([getDateHistogramBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); const bucketKey = 1422579600000; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts index 8c0466b769a7e..4207fa92736f8 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts @@ -72,7 +72,10 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]) } + { + typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts index f5a0b5a7b9094..bf05f7463db6c 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts @@ -69,7 +69,10 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]) } + { + typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts index 18b388be74877..396d515f3b580 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts @@ -23,10 +23,12 @@ import { mockAggTypesRegistry } from '../../test_helpers'; import { BUCKET_TYPES } from '../bucket_agg_types'; import { IBucketAggConfig } from '../bucket_agg_type'; import { BytesFormat, FieldFormatsGetConfigFn } from '../../../../../common'; +import { fieldFormatsServiceMock } from '../../../../field_formats/mocks'; describe('AggConfig Filters', () => { describe('histogram', () => { const getConfig = (() => {}) as FieldFormatsGetConfigFn; + const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = () => { const field = { name: 'bytes', @@ -55,7 +57,7 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry() } + { typesRegistry: mockAggTypesRegistry(), fieldFormats } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts index b528313b080d0..d85576a0ccb14 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts @@ -29,10 +29,11 @@ import { notificationServiceMock } from '../../../../../../../core/public/mocks' describe('AggConfig Filters', () => { describe('IP range', () => { + const fieldFormats = fieldFormatsServiceMock.createStartContract(); const typesRegistry = mockAggTypesRegistry([ getIpRangeBucketAgg({ getInternalStartServices: () => ({ - fieldFormats: fieldFormatsServiceMock.createStartContract(), + fieldFormats, notifications: notificationServiceMock.createStartContract(), }), }), @@ -52,7 +53,7 @@ describe('AggConfig Filters', () => { }, } as any; - return new AggConfigs(indexPattern, aggs, { typesRegistry }); + return new AggConfigs(indexPattern, aggs, { typesRegistry, fieldFormats }); }; test('should return a range filter for ip_range agg', () => { diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts index 14a7538aa95a4..cadd8e9fe13ed 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/range.test.ts @@ -71,7 +71,10 @@ describe('AggConfig Filters', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]) } + { + typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts b/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts index c11a7d1a4e6b8..d9ff63613b640 100644 --- a/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts @@ -58,6 +58,7 @@ describe('AggConfig Filters', () => { return new AggConfigs(indexPattern, aggs, { typesRegistry: mockAggTypesRegistry([getTermsBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, }); }; diff --git a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts index c050620c3a856..f78f0cce732e7 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_range.test.ts @@ -74,7 +74,10 @@ describe('date_range params', () => { params, }, ], - { typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]) } + { + typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts index 24270dd33a576..226faefe43482 100644 --- a/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/geo_hash.test.ts @@ -77,7 +77,10 @@ describe('Geohash Agg', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry() } + { + typesRegistry: mockAggTypesRegistry(), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts index bbfc263df4268..a55c32951232a 100644 --- a/src/plugins/data/public/search/aggs/buckets/histogram.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/histogram.test.ts @@ -70,7 +70,10 @@ describe('Histogram Agg', () => { params, }, ], - { typesRegistry: mockAggTypesRegistry([getHistogramBucketAgg(aggTypesDependencies)]) } + { + typesRegistry: mockAggTypesRegistry([getHistogramBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/range.test.ts b/src/plugins/data/public/search/aggs/buckets/range.test.ts index a1f0ab6a2326a..144d2b779e950 100644 --- a/src/plugins/data/public/search/aggs/buckets/range.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/range.test.ts @@ -95,7 +95,10 @@ describe('Range Agg', () => { }, }, ], - { typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]) } + { + typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts index 761d0ced6a114..d0ace5a50c28d 100644 --- a/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/significant_terms.test.ts @@ -70,6 +70,7 @@ describe('Significant Terms Agg', () => { typesRegistry: mockAggTypesRegistry([ getSignificantTermsBucketAgg(aggTypesDependencies), ]), + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, } ); }; diff --git a/src/plugins/data/public/search/aggs/buckets/terms.test.ts b/src/plugins/data/public/search/aggs/buckets/terms.test.ts index 5afe7d0b0c35c..0dc052bd1fdf6 100644 --- a/src/plugins/data/public/search/aggs/buckets/terms.test.ts +++ b/src/plugins/data/public/search/aggs/buckets/terms.test.ts @@ -20,9 +20,11 @@ import { AggConfigs } from '../agg_configs'; import { mockAggTypesRegistry } from '../test_helpers'; import { BUCKET_TYPES } from './bucket_agg_types'; +import { fieldFormatsServiceMock } from '../../../field_formats/mocks'; describe('Terms Agg', () => { describe('order agg editor UI', () => { + const fieldFormats = fieldFormatsServiceMock.createStartContract(); const getAggConfigs = (params: Record<string, any> = {}) => { const indexPattern = { id: '1234', @@ -47,7 +49,7 @@ describe('Terms Agg', () => { type: BUCKET_TYPES.TERMS, }, ], - { typesRegistry: mockAggTypesRegistry() } + { typesRegistry: mockAggTypesRegistry(), fieldFormats } ); }; diff --git a/src/plugins/data/public/search/aggs/metrics/median.test.ts b/src/plugins/data/public/search/aggs/metrics/median.test.ts index f80c46026f50a..de3ca646ead9e 100644 --- a/src/plugins/data/public/search/aggs/metrics/median.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/median.test.ts @@ -59,7 +59,10 @@ describe('AggTypeMetricMedianProvider class', () => { }, }, ], - { typesRegistry } + { + typesRegistry, + fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats, + } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts b/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts index af983a50f6c23..3beb92a2fa000 100644 --- a/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts @@ -110,7 +110,7 @@ describe('parent pipeline aggs', function() { schema: 'metric', }, ], - { typesRegistry } + { typesRegistry, fieldFormats: getInternalStartServices().fieldFormats } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts index 2944fc8c11b23..1b94ecd602075 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts @@ -70,7 +70,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function() { }, }, ], - { typesRegistry } + { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts b/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts index 33bd42df74cc7..76da2fe3eb62c 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentiles.test.ts @@ -70,7 +70,7 @@ describe('AggTypesMetricsPercentilesProvider class', () => { }, }, ], - { typesRegistry } + { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } ); }); diff --git a/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts b/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts index ab480fe44227e..a47aa2c677ade 100644 --- a/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts @@ -111,7 +111,7 @@ describe('sibling pipeline aggs', () => { }, }, ], - { typesRegistry } + { typesRegistry, fieldFormats: getInternalStartServices().fieldFormats } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) diff --git a/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts b/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts index 6bbff3009cc11..d2370e1fed02c 100644 --- a/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/std_deviation.test.ts @@ -64,7 +64,7 @@ describe('AggTypeMetricStandardDeviationProvider class', () => { }, }, ], - { typesRegistry } + { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } ); }; diff --git a/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts b/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts index 8294ad09bae22..142b8e4c83301 100644 --- a/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts +++ b/src/plugins/data/public/search/aggs/metrics/top_hit.test.ts @@ -89,7 +89,7 @@ describe('Top hit metric', () => { params, }, ], - { typesRegistry } + { typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats } ); // Grab the aggConfig off the vis (we don't actually use the vis for anything else) diff --git a/src/plugins/data/public/search/aggs/mocks.ts b/src/plugins/data/public/search/aggs/mocks.ts index 7a5dcc9be4592..16544fd8f46b0 100644 --- a/src/plugins/data/public/search/aggs/mocks.ts +++ b/src/plugins/data/public/search/aggs/mocks.ts @@ -27,6 +27,7 @@ import { } from './'; import { SearchAggsSetup, SearchAggsStart } from './types'; import { mockAggTypesRegistry } from './test_helpers'; +import { fieldFormatsServiceMock } from '../../field_formats/mocks'; const aggTypeBaseParamMock = () => ({ name: 'some_param', @@ -72,6 +73,7 @@ export const searchAggsStartMock = (): SearchAggsStart => ({ createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => { return new AggConfigs(indexPattern, configStates, { typesRegistry: mockAggTypesRegistry(), + fieldFormats: fieldFormatsServiceMock.createStartContract(), }); }), types: mockAggTypesRegistry(), diff --git a/src/plugins/data/public/search/expressions/create_filter.test.ts b/src/plugins/data/public/search/expressions/create_filter.test.ts index 23da060cba203..51b5e175761bd 100644 --- a/src/plugins/data/public/search/expressions/create_filter.test.ts +++ b/src/plugins/data/public/search/expressions/create_filter.test.ts @@ -22,10 +22,12 @@ import { AggConfigs, IAggConfig } from '../aggs'; import { TabbedTable } from '../tabify'; import { isRangeFilter, BytesFormat, FieldFormatsGetConfigFn } from '../../../common'; import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; +import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('createFilter', () => { let table: TabbedTable; let aggConfig: IAggConfig; + const fieldFormats = fieldFormatsServiceMock.createStartContract(); const typesRegistry = mockAggTypesRegistry(); @@ -58,7 +60,7 @@ describe('createFilter', () => { params, }, ], - { typesRegistry } + { typesRegistry, fieldFormats } ); }; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 6124682184821..a539736991adb 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -44,12 +44,19 @@ import { siblingPipelineAggHelper, } from './aggs'; +import { FieldFormatsStart } from '../field_formats'; + interface SearchServiceSetupDependencies { packageInfo: PackageInfo; query: QuerySetup; getInternalStartServices: GetInternalStartServicesFn; } +interface SearchStartDependencies { + fieldFormats: FieldFormatsStart; + indexPatterns: IndexPatternsContract; +} + /** * The search plugin exposes two registration methods for other plugins: * - registerSearchStrategyProvider for plugins to add their own custom @@ -110,7 +117,10 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> { }; } - public start(core: CoreStart, indexPatterns: IndexPatternsContract): ISearchStart { + public start( + core: CoreStart, + { fieldFormats, indexPatterns }: SearchStartDependencies + ): ISearchStart { /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. @@ -131,6 +141,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> { createAggConfigs: (indexPattern, configStates = [], schemas) => { return new AggConfigs(indexPattern, configStates, { typesRegistry: aggTypesStart, + fieldFormats, }); }, types: aggTypesStart, diff --git a/src/plugins/data/public/search/tabify/get_columns.test.ts b/src/plugins/data/public/search/tabify/get_columns.test.ts index b7dadc3f65d82..1072e9318b40e 100644 --- a/src/plugins/data/public/search/tabify/get_columns.test.ts +++ b/src/plugins/data/public/search/tabify/get_columns.test.ts @@ -21,6 +21,7 @@ import { tabifyGetColumns } from './get_columns'; import { TabbedAggColumn } from './types'; import { AggConfigs } from '../aggs'; import { mockAggTypesRegistry, mockDataServices } from '../aggs/test_helpers'; +import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('get columns', () => { beforeEach(() => { @@ -28,6 +29,7 @@ describe('get columns', () => { }); const typesRegistry = mockAggTypesRegistry(); + const fieldFormats = fieldFormatsServiceMock.createStartContract(); const createAggConfigs = (aggs: any[] = []) => { const field = { @@ -45,6 +47,7 @@ describe('get columns', () => { return new AggConfigs(indexPattern, aggs, { typesRegistry, + fieldFormats, }); }; diff --git a/src/plugins/data/public/search/tabify/response_writer.test.ts b/src/plugins/data/public/search/tabify/response_writer.test.ts index 52338ae79ccbb..3334d858ce54e 100644 --- a/src/plugins/data/public/search/tabify/response_writer.test.ts +++ b/src/plugins/data/public/search/tabify/response_writer.test.ts @@ -21,6 +21,7 @@ import { TabbedAggResponseWriter } from './response_writer'; import { AggConfigs, BUCKET_TYPES } from '../aggs'; import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers'; import { TabbedResponseWriterOptions } from './types'; +import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('TabbedAggResponseWriter class', () => { beforeEach(() => { @@ -30,6 +31,7 @@ describe('TabbedAggResponseWriter class', () => { let responseWriter: TabbedAggResponseWriter; const typesRegistry = mockAggTypesRegistry(); + const fieldFormats = fieldFormatsServiceMock.createStartContract(); const splitAggConfig = [ { @@ -74,6 +76,7 @@ describe('TabbedAggResponseWriter class', () => { return new TabbedAggResponseWriter( new AggConfigs(indexPattern, aggs, { typesRegistry, + fieldFormats, }), { metricsAtAllLevels: false, diff --git a/src/plugins/data/public/search/tabify/tabify.test.ts b/src/plugins/data/public/search/tabify/tabify.test.ts index c9bf04ae9f0fc..63685cc87f5cf 100644 --- a/src/plugins/data/public/search/tabify/tabify.test.ts +++ b/src/plugins/data/public/search/tabify/tabify.test.ts @@ -22,9 +22,11 @@ import { IndexPattern } from '../../index_patterns'; import { AggConfigs, IAggConfig, IAggConfigs } from '../aggs'; import { mockAggTypesRegistry } from '../aggs/test_helpers'; import { metricOnly, threeTermBuckets } from 'fixtures/fake_hierarchical_data'; +import { fieldFormatsServiceMock } from '../../field_formats/mocks'; describe('tabifyAggResponse Integration', () => { const typesRegistry = mockAggTypesRegistry(); + const fieldFormats = fieldFormatsServiceMock.createStartContract(); const createAggConfigs = (aggs: IAggConfig[] = []) => { const field = { @@ -42,6 +44,7 @@ describe('tabifyAggResponse Integration', () => { return new AggConfigs(indexPattern, aggs, { typesRegistry, + fieldFormats, }); }; From cf87efb9d0856acea74c64803f858409fcbc5461 Mon Sep 17 00:00:00 2001 From: Thomas Watson <w@tson.dk> Date: Wed, 15 Apr 2020 10:20:01 +0200 Subject: [PATCH 118/121] Add test:jest_integration npm script (#62938) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 388e46aedf37d..c60cf5234c9f7 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "test:karma": "grunt test:karma", "test:karma:debug": "grunt test:karmaDebug", "test:jest": "node scripts/jest", + "test:jest_integration": "node scripts/jest_integration", "test:mocha": "node scripts/mocha", "test:mocha:coverage": "grunt test:mochaCoverage", "test:ftr": "node scripts/functional_tests", From ebbc062689e3b130b6ea7dbd585a976fde406036 Mon Sep 17 00:00:00 2001 From: Tim Roes <tim.roes@elastic.co> Date: Wed, 15 Apr 2020 12:22:37 +0200 Subject: [PATCH 119/121] Move Lens frontend to Kibana Platform (#62965) * Move Lens frontend to Kibana platform * Fix line breaks * Fix jest tests * Fix remaining test * Remove old Lens plugin entry * Fix i18n prefix * Add config schema * Address review --- .eslintrc.js | 4 +- .github/CODEOWNERS | 2 +- .sass-lint.yml | 2 +- x-pack/.i18nrc.json | 2 +- x-pack/index.js | 2 - x-pack/legacy/plugins/lens/index.ts | 38 ------------------ .../lens/public/app_plugin/_index.scss | 1 - .../datatable_visualization/_index.scss | 1 - .../plugins/lens/public/drag_drop/_index.scss | 1 - .../public/editor_frame_service/_index.scss | 1 - .../editor_frame/index.scss | 8 ---- .../indexpattern_datasource/_index.scss | 4 -- .../dimension_panel/_index.scss | 2 - x-pack/legacy/plugins/lens/public/legacy.ts | 17 -------- x-pack/legacy/plugins/lens/public/redirect.ts | 19 --------- .../lens/public/xy_visualization/_index.scss | 1 - x-pack/plugins/lens/config.ts | 13 ++++++ x-pack/plugins/lens/kibana.json | 12 +++++- .../plugins/lens/public/_mixins.scss | 0 .../plugins/lens/public/_variables.scss | 0 .../plugins/lens/public/app_plugin/_app.scss | 0 .../lens/public/app_plugin/_index.scss | 1 + .../lens/public/app_plugin/app.test.tsx | 28 +++++++------ .../plugins/lens/public/app_plugin/app.tsx | 14 ++++--- .../plugins/lens/public/app_plugin/index.ts | 0 .../plugins/lens/public/assets/chart_area.svg | 0 .../lens/public/assets/chart_area_stacked.svg | 0 .../plugins/lens/public/assets/chart_bar.svg | 0 .../public/assets/chart_bar_horizontal.svg | 0 .../assets/chart_bar_horizontal_stacked.svg | 0 .../lens/public/assets/chart_bar_stacked.svg | 0 .../lens/public/assets/chart_datatable.svg | 0 .../plugins/lens/public/assets/chart_line.svg | 0 .../lens/public/assets/chart_metric.svg | 0 .../lens/public/assets/chart_mixed_xy.svg | 0 .../assets/lens_app_graphic_dark_2x.png | Bin .../assets/lens_app_graphic_light_2x.png | Bin .../datatable_visualization/_index.scss | 1 + .../_visualization.scss | 0 .../datatable_visualization/expression.tsx | 2 +- .../public/datatable_visualization/index.ts | 4 +- .../visualization.test.tsx | 0 .../datatable_visualization/visualization.tsx | 0 .../debounced_component.test.tsx | 0 .../debounced_component.tsx | 0 .../lens/public/debounced_component/index.ts | 0 .../__snapshots__/drag_drop.test.tsx.snap | 0 .../lens/public/drag_drop/_drag_drop.scss | 0 .../plugins/lens/public/drag_drop/_index.scss | 1 + .../lens/public/drag_drop/drag_drop.test.tsx | 0 .../lens/public/drag_drop/drag_drop.tsx | 0 .../plugins/lens/public/drag_drop/index.ts | 0 .../lens/public/drag_drop/providers.test.tsx | 0 .../lens/public/drag_drop/providers.tsx | 0 .../plugins/lens/public/drag_drop/readme.md | 0 .../public/editor_frame_service/_index.scss | 1 + .../__mocks__/suggestion_helpers.ts | 0 .../editor_frame/_chart_switch.scss | 0 .../editor_frame/_config_panel_wrapper.scss | 0 .../editor_frame/_data_panel_wrapper.scss | 0 .../editor_frame/_expression_renderer.scss | 0 .../editor_frame/_frame_layout.scss | 0 .../editor_frame/_suggestion_panel.scss | 0 .../_workspace_panel_wrapper.scss | 0 .../editor_frame/chart_switch.test.tsx | 0 .../editor_frame/chart_switch.tsx | 0 .../editor_frame/config_panel_wrapper.tsx | 0 .../editor_frame/data_panel_wrapper.tsx | 5 +-- .../editor_frame/editor_frame.test.tsx | 0 .../editor_frame/editor_frame.tsx | 6 +-- .../editor_frame/expression_helpers.ts | 2 +- .../editor_frame/frame_layout.tsx | 0 .../editor_frame/index.scss | 8 ++++ .../editor_frame/index.ts | 0 .../editor_frame/layer_actions.test.ts | 0 .../editor_frame/layer_actions.ts | 0 .../editor_frame/save.test.ts | 2 +- .../editor_frame_service/editor_frame/save.ts | 0 .../editor_frame/state_management.test.ts | 2 +- .../editor_frame/state_management.ts | 2 +- .../editor_frame/suggestion_helpers.test.ts | 0 .../editor_frame/suggestion_helpers.ts | 0 .../editor_frame/suggestion_panel.test.tsx | 4 +- .../editor_frame/suggestion_panel.tsx | 2 +- .../editor_frame/workspace_panel.test.tsx | 4 +- .../editor_frame/workspace_panel.tsx | 4 +- .../editor_frame/workspace_panel_wrapper.tsx | 0 .../embeddable/embeddable.test.tsx | 4 +- .../embeddable/embeddable.tsx | 6 +-- .../embeddable/embeddable_factory.ts | 8 ++-- .../embeddable/expression_wrapper.tsx | 0 .../editor_frame_service/format_column.ts | 0 .../lens/public/editor_frame_service/index.ts | 0 .../editor_frame_service/merge_tables.test.ts | 2 - .../editor_frame_service/merge_tables.ts | 2 +- .../public/editor_frame_service/mocks.tsx | 8 ++-- .../editor_frame_service/service.test.tsx | 2 - .../public/editor_frame_service/service.tsx | 19 +++++---- .../plugins/lens/public/help_menu_util.tsx | 7 ++-- .../plugins/lens/public/helpers/index.ts | 0 .../lens/public/helpers/url_helper.test.ts | 2 +- .../plugins/lens/public/helpers/url_helper.ts | 2 +- .../public/id_generator/id_generator.test.ts | 0 .../lens/public/id_generator/id_generator.ts | 0 .../plugins/lens/public/id_generator/index.ts | 0 .../plugins/lens/public/index.scss | 11 ++--- .../{legacy => }/plugins/lens/public/index.ts | 0 .../__mocks__/loader.ts | 0 .../__mocks__/state_helpers.ts | 0 .../lens_field_icon.test.tsx.snap | 0 .../indexpattern_datasource/_datapanel.scss | 0 .../indexpattern_datasource/_field_item.scss | 2 +- .../indexpattern_datasource/_index.scss | 4 ++ .../indexpattern_datasource/auto_date.test.ts | 2 +- .../indexpattern_datasource/auto_date.ts | 4 +- .../change_indexpattern.tsx | 0 .../datapanel.test.tsx | 4 +- .../indexpattern_datasource/datapanel.tsx | 10 ++++- .../dimension_panel/_field_select.scss | 0 .../dimension_panel/_index.scss | 2 + .../dimension_panel/_popover.scss | 0 .../bucket_nesting_editor.test.tsx | 0 .../dimension_panel/bucket_nesting_editor.tsx | 0 .../dimension_panel/dimension_panel.test.tsx | 10 +---- .../dimension_panel/dimension_panel.tsx | 6 +-- .../dimension_panel/field_select.tsx | 0 .../dimension_panel/format_selector.tsx | 0 .../dimension_panel/index.ts | 0 .../dimension_panel/popover_editor.tsx | 0 .../indexpattern_datasource/document_field.ts | 0 .../field_item.test.tsx | 11 ++--- .../indexpattern_datasource/field_item.tsx | 19 ++++++--- .../public/indexpattern_datasource/index.ts | 8 ++-- .../indexpattern.test.ts | 6 +-- .../indexpattern_datasource/indexpattern.tsx | 11 ++--- .../indexpattern_suggestions.test.tsx | 1 - .../indexpattern_suggestions.ts | 0 .../layerpanel.test.tsx | 1 - .../indexpattern_datasource/layerpanel.tsx | 0 .../lens_field_icon.test.tsx | 0 .../lens_field_icon.tsx | 2 +- .../indexpattern_datasource/loader.test.ts | 2 - .../public/indexpattern_datasource/loader.ts | 10 ++--- .../public/indexpattern_datasource/mocks.ts | 0 .../operations/__mocks__/index.ts | 0 .../operations/definitions/cardinality.tsx | 2 +- .../operations/definitions/column_types.ts | 0 .../operations/definitions/count.tsx | 2 +- .../definitions/date_histogram.test.tsx | 8 ++-- .../operations/definitions/date_histogram.tsx | 7 +--- .../operations/definitions/index.ts | 6 +-- .../operations/definitions/metrics.tsx | 2 +- .../operations/definitions/terms.test.tsx | 8 ++-- .../operations/definitions/terms.tsx | 2 +- .../operations/index.ts | 0 .../operations/operations.test.ts | 3 +- .../operations/operations.ts | 0 .../pure_helpers.test.ts | 0 .../indexpattern_datasource/pure_helpers.ts | 0 .../rename_columns.test.ts | 4 +- .../indexpattern_datasource/rename_columns.ts | 0 .../state_helpers.test.ts | 1 - .../indexpattern_datasource/state_helpers.ts | 0 .../indexpattern_datasource/to_expression.ts | 0 .../public/indexpattern_datasource/types.ts | 2 +- .../public/indexpattern_datasource/utils.ts | 0 .../public/lens_ui_telemetry/factory.test.ts | 0 .../lens/public/lens_ui_telemetry/factory.ts | 4 +- .../lens/public/lens_ui_telemetry/index.ts | 0 .../plugins/lens/public/loader.test.tsx | 0 .../plugins/lens/public/loader.tsx | 0 .../metric_visualization/auto_scale.test.tsx | 0 .../metric_visualization/auto_scale.tsx | 0 .../public/metric_visualization/index.scss | 0 .../lens/public/metric_visualization/index.ts | 4 +- .../metric_expression.test.tsx | 4 +- .../metric_expression.tsx | 2 +- .../metric_suggestions.test.ts | 2 +- .../metric_suggestions.ts | 0 .../metric_visualization.test.ts | 0 .../metric_visualization.tsx | 0 .../lens/public/metric_visualization/types.ts | 0 .../lens/public/native_renderer/index.ts | 0 .../native_renderer/native_renderer.test.tsx | 0 .../native_renderer/native_renderer.tsx | 0 .../plugins/lens/public/persistence/index.ts | 0 .../persistence/saved_object_store.test.ts | 0 .../public/persistence/saved_object_store.ts | 4 +- .../plugins/lens/public/plugin.tsx | 23 ++++++----- .../{legacy => }/plugins/lens/public/types.ts | 11 ++--- .../plugins/lens/public/vis_type_alias.ts | 2 +- .../public/visualization_container.test.tsx | 0 .../lens/public/visualization_container.tsx | 0 .../__snapshots__/to_expression.test.ts.snap | 0 .../__snapshots__/xy_expression.test.tsx.snap | 0 .../lens/public/xy_visualization/_index.scss | 1 + .../xy_visualization/_xy_expression.scss | 0 .../lens/public/xy_visualization/index.ts | 6 +-- .../lens/public/xy_visualization/services.ts | 4 +- .../public/xy_visualization/state_helpers.ts | 0 .../xy_visualization/to_expression.test.ts | 0 .../public/xy_visualization/to_expression.ts | 0 .../lens/public/xy_visualization/types.ts | 2 +- .../xy_visualization/xy_config_panel.test.tsx | 0 .../xy_visualization/xy_config_panel.tsx | 0 .../xy_visualization/xy_expression.test.tsx | 7 +--- .../public/xy_visualization/xy_expression.tsx | 8 ++-- .../xy_visualization/xy_suggestions.test.ts | 0 .../public/xy_visualization/xy_suggestions.ts | 0 .../xy_visualization/xy_visualization.test.ts | 0 .../xy_visualization/xy_visualization.tsx | 0 x-pack/{legacy => }/plugins/lens/readme.md | 0 x-pack/plugins/lens/server/index.ts | 8 +++- 213 files changed, 249 insertions(+), 301 deletions(-) delete mode 100644 x-pack/legacy/plugins/lens/index.ts delete mode 100644 x-pack/legacy/plugins/lens/public/app_plugin/_index.scss delete mode 100644 x-pack/legacy/plugins/lens/public/datatable_visualization/_index.scss delete mode 100644 x-pack/legacy/plugins/lens/public/drag_drop/_index.scss delete mode 100644 x-pack/legacy/plugins/lens/public/editor_frame_service/_index.scss delete mode 100644 x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss delete mode 100644 x-pack/legacy/plugins/lens/public/indexpattern_datasource/_index.scss delete mode 100644 x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss delete mode 100644 x-pack/legacy/plugins/lens/public/legacy.ts delete mode 100644 x-pack/legacy/plugins/lens/public/redirect.ts delete mode 100644 x-pack/legacy/plugins/lens/public/xy_visualization/_index.scss create mode 100644 x-pack/plugins/lens/config.ts rename x-pack/{legacy => }/plugins/lens/public/_mixins.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/_variables.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/app_plugin/_app.scss (100%) create mode 100644 x-pack/plugins/lens/public/app_plugin/_index.scss rename x-pack/{legacy => }/plugins/lens/public/app_plugin/app.test.tsx (96%) rename x-pack/{legacy => }/plugins/lens/public/app_plugin/app.tsx (96%) rename x-pack/{legacy => }/plugins/lens/public/app_plugin/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_area.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_area_stacked.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_bar.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_bar_horizontal.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_bar_stacked.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_datatable.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_line.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_metric.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/chart_mixed_xy.svg (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/lens_app_graphic_dark_2x.png (100%) rename x-pack/{legacy => }/plugins/lens/public/assets/lens_app_graphic_light_2x.png (100%) create mode 100644 x-pack/plugins/lens/public/datatable_visualization/_index.scss rename x-pack/{legacy => }/plugins/lens/public/datatable_visualization/_visualization.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/datatable_visualization/expression.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/datatable_visualization/index.ts (89%) rename x-pack/{legacy => }/plugins/lens/public/datatable_visualization/visualization.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/datatable_visualization/visualization.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/debounced_component/debounced_component.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/debounced_component/debounced_component.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/debounced_component/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap (100%) rename x-pack/{legacy => }/plugins/lens/public/drag_drop/_drag_drop.scss (100%) create mode 100644 x-pack/plugins/lens/public/drag_drop/_index.scss rename x-pack/{legacy => }/plugins/lens/public/drag_drop/drag_drop.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/drag_drop/drag_drop.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/drag_drop/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/drag_drop/providers.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/drag_drop/providers.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/drag_drop/readme.md (100%) create mode 100644 x-pack/plugins/lens/public/editor_frame_service/_index.scss rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/suggestion_helpers.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/_chart_switch.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/_expression_renderer.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/_workspace_panel_wrapper.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx (94%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx (97%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts (97%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx (100%) create mode 100644 x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.scss rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts (98%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/save.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts (99%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts (99%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel_wrapper.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx (96%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx (94%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts (91%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/format_column.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/merge_tables.test.ts (98%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/merge_tables.ts (96%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/mocks.tsx (92%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/service.test.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/editor_frame_service/service.tsx (91%) rename x-pack/{legacy => }/plugins/lens/public/help_menu_util.tsx (63%) rename x-pack/{legacy => }/plugins/lens/public/helpers/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/helpers/url_helper.test.ts (96%) rename x-pack/{legacy => }/plugins/lens/public/helpers/url_helper.ts (95%) rename x-pack/{legacy => }/plugins/lens/public/id_generator/id_generator.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/id_generator/id_generator.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/id_generator/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/index.scss (54%) rename x-pack/{legacy => }/plugins/lens/public/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/__mocks__/state_helpers.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/__snapshots__/lens_field_icon.test.tsx.snap (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/_datapanel.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/_field_item.scss (98%) create mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/_index.scss rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/auto_date.test.ts (96%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/auto_date.ts (92%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/datapanel.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/_field_select.scss (100%) create mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx (97%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/document_field.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/field_item.test.tsx (95%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/field_item.tsx (97%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/index.ts (84%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts (98%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/indexpattern.tsx (96%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/layerpanel.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/lens_field_icon.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx (86%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/loader.test.ts (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/loader.ts (96%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/mocks.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx (97%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts (97%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/operations/operations.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/pure_helpers.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/pure_helpers.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts (96%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/rename_columns.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts (99%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/state_helpers.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/to_expression.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/types.ts (94%) rename x-pack/{legacy => }/plugins/lens/public/indexpattern_datasource/utils.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/lens_ui_telemetry/factory.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/lens_ui_telemetry/factory.ts (96%) rename x-pack/{legacy => }/plugins/lens/public/lens_ui_telemetry/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/loader.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/loader.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/auto_scale.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/auto_scale.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/index.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/index.ts (88%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/metric_expression.test.tsx (94%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/metric_expression.tsx (98%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/metric_suggestions.test.ts (98%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/metric_suggestions.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/metric_visualization.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/metric_visualization.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/metric_visualization/types.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/native_renderer/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/native_renderer/native_renderer.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/native_renderer/native_renderer.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/persistence/index.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/persistence/saved_object_store.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/persistence/saved_object_store.ts (94%) rename x-pack/{legacy => }/plugins/lens/public/plugin.tsx (90%) rename x-pack/{legacy => }/plugins/lens/public/types.ts (98%) rename x-pack/{legacy => }/plugins/lens/public/vis_type_alias.ts (95%) rename x-pack/{legacy => }/plugins/lens/public/visualization_container.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/visualization_container.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap (100%) create mode 100644 x-pack/plugins/lens/public/xy_visualization/_index.scss rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/_xy_expression.scss (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/index.ts (89%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/services.ts (70%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/state_helpers.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/to_expression.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/to_expression.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/types.ts (99%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_config_panel.tsx (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_expression.test.tsx (99%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_expression.tsx (97%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_suggestions.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_suggestions.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_visualization.test.ts (100%) rename x-pack/{legacy => }/plugins/lens/public/xy_visualization/xy_visualization.tsx (100%) rename x-pack/{legacy => }/plugins/lens/readme.md (100%) diff --git a/.eslintrc.js b/.eslintrc.js index 2ce6d279d93a9..246702aedf863 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -109,7 +109,7 @@ module.exports = { }, }, { - files: ['x-pack/legacy/plugins/lens/**/*.{js,ts,tsx}'], + files: ['x-pack/plugins/lens/**/*.{js,ts,tsx}'], rules: { 'react-hooks/exhaustive-deps': 'off', 'react-hooks/rules-of-hooks': 'off', @@ -728,7 +728,7 @@ module.exports = { * Lens overrides */ { - files: ['x-pack/legacy/plugins/lens/**/*.{ts,tsx}', 'x-pack/plugins/lens/**/*.{ts,tsx}'], + files: ['x-pack/plugins/lens/**/*.{ts,tsx}'], rules: { '@typescript-eslint/no-explicit-any': 'error', }, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 267f3dde0b66f..71d857c1c9041 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,7 +3,7 @@ # For more info, see https://help.github.com/articles/about-codeowners/ # App -/x-pack/legacy/plugins/lens/ @elastic/kibana-app +/x-pack/plugins/lens/ @elastic/kibana-app /x-pack/legacy/plugins/graph/ @elastic/kibana-app /src/legacy/server/url_shortening/ @elastic/kibana-app /src/legacy/server/sample_data/ @elastic/kibana-app diff --git a/.sass-lint.yml b/.sass-lint.yml index dd7bc0576692b..0c33eaf794c69 100644 --- a/.sass-lint.yml +++ b/.sass-lint.yml @@ -8,9 +8,9 @@ files: - 'x-pack/legacy/plugins/security/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/canvas/**/*.s+(a|c)ss' - 'x-pack/plugins/triggers_actions_ui/**/*.s+(a|c)ss' + - 'x-pack/plugins/lens/**/*.s+(a|c)ss' ignore: - 'x-pack/legacy/plugins/canvas/shareable_runtime/**/*.s+(a|c)ss' - - 'x-pack/legacy/plugins/lens/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/maps/**/*.s+(a|c)ss' rules: quotes: diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index b3744f7cf93ab..50f36ddd21c97 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -21,7 +21,7 @@ "xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management", "xpack.infra": "plugins/infra", "xpack.ingestManager": "plugins/ingest_manager", - "xpack.lens": "legacy/plugins/lens", + "xpack.lens": "plugins/lens", "xpack.licenseMgmt": "plugins/license_management", "xpack.licensing": "plugins/licensing", "xpack.logstash": ["plugins/logstash", "legacy/plugins/logstash"], diff --git a/x-pack/index.js b/x-pack/index.js index 3126dc17a7107..61fd4f1752316 100644 --- a/x-pack/index.js +++ b/x-pack/index.js @@ -29,7 +29,6 @@ import { uptime } from './legacy/plugins/uptime'; import { encryptedSavedObjects } from './legacy/plugins/encrypted_saved_objects'; import { actions } from './legacy/plugins/actions'; import { alerting } from './legacy/plugins/alerting'; -import { lens } from './legacy/plugins/lens'; import { ingestManager } from './legacy/plugins/ingest_manager'; import { triggersActionsUI } from './legacy/plugins/triggers_actions_ui'; @@ -58,7 +57,6 @@ module.exports = function(kibana) { upgradeAssistant(kibana), uptime(kibana), encryptedSavedObjects(kibana), - lens(kibana), actions(kibana), alerting(kibana), ingestManager(kibana), diff --git a/x-pack/legacy/plugins/lens/index.ts b/x-pack/legacy/plugins/lens/index.ts deleted file mode 100644 index e9a901c58cd90..0000000000000 --- a/x-pack/legacy/plugins/lens/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import * as Joi from 'joi'; -import { resolve } from 'path'; -import { LegacyPluginInitializer } from 'src/legacy/types'; -import { PLUGIN_ID, NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../../plugins/lens/common'; - -export const lens: LegacyPluginInitializer = kibana => { - return new kibana.Plugin({ - id: PLUGIN_ID, - configPrefix: `xpack.${PLUGIN_ID}`, - // task_manager could be required, but is only used for telemetry - require: ['kibana', 'elasticsearch', 'xpack_main', 'interpreter'], - publicDir: resolve(__dirname, 'public'), - - uiExports: { - app: { - title: NOT_INTERNATIONALIZED_PRODUCT_NAME, - description: 'Explore and visualize data.', - main: `plugins/${PLUGIN_ID}/redirect`, - listed: false, - }, - visualize: [`plugins/${PLUGIN_ID}/legacy`], - embeddableFactories: [`plugins/${PLUGIN_ID}/legacy`], - styleSheetPaths: resolve(__dirname, 'public/index.scss'), - }, - - config: () => { - return Joi.object({ - enabled: Joi.boolean().default(true), - }).default(); - }, - }); -}; diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/_index.scss b/x-pack/legacy/plugins/lens/public/app_plugin/_index.scss deleted file mode 100644 index 2ac86f0e58a61..0000000000000 --- a/x-pack/legacy/plugins/lens/public/app_plugin/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './app'; diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/_index.scss b/x-pack/legacy/plugins/lens/public/datatable_visualization/_index.scss deleted file mode 100644 index 99c357b53952f..0000000000000 --- a/x-pack/legacy/plugins/lens/public/datatable_visualization/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './visualization'; diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/_index.scss b/x-pack/legacy/plugins/lens/public/drag_drop/_index.scss deleted file mode 100644 index 1b3d0cf0a3c2a..0000000000000 --- a/x-pack/legacy/plugins/lens/public/drag_drop/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './drag_drop' diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/_index.scss b/x-pack/legacy/plugins/lens/public/editor_frame_service/_index.scss deleted file mode 100644 index 4d7e054ff03c3..0000000000000 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './editor_frame/index'; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss b/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss deleted file mode 100644 index 6c6a63c8c7eb6..0000000000000 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.scss +++ /dev/null @@ -1,8 +0,0 @@ -@import './chart_switch'; -@import './config_panel_wrapper'; -@import './data_panel_wrapper'; -@import './expression_renderer'; -@import './frame_layout'; -@import './suggestion_panel'; -@import './workspace_panel_wrapper'; - diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/_index.scss b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/_index.scss deleted file mode 100644 index a283198d6cf73..0000000000000 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/_index.scss +++ /dev/null @@ -1,4 +0,0 @@ -@import './datapanel'; -@import './field_item'; - -@import './dimension_panel/index'; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss b/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss deleted file mode 100644 index 26f805fe735f0..0000000000000 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './field_select'; -@import './popover'; diff --git a/x-pack/legacy/plugins/lens/public/legacy.ts b/x-pack/legacy/plugins/lens/public/legacy.ts deleted file mode 100644 index 3b7b6a7a1b510..0000000000000 --- a/x-pack/legacy/plugins/lens/public/legacy.ts +++ /dev/null @@ -1,17 +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 { npSetup, npStart } from 'ui/new_platform'; - -export * from './types'; - -import { plugin } from './index'; - -const pluginInstance = plugin(); -pluginInstance.setup(npSetup.core, { - ...npSetup.plugins, -}); -pluginInstance.start(npStart.core, npStart.plugins); diff --git a/x-pack/legacy/plugins/lens/public/redirect.ts b/x-pack/legacy/plugins/lens/public/redirect.ts deleted file mode 100644 index 25b0188214c5e..0000000000000 --- a/x-pack/legacy/plugins/lens/public/redirect.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// This file redirects lens urls starting with app/lens#... to their counterpart on app/kibana#lens/... to -// make sure it's compatible with the 7.5 release - -import { npSetup } from 'ui/new_platform'; -import chrome from 'ui/chrome'; - -chrome.setRootController('lens', () => { - // prefix the path in the hash with lens/ - const prefixedHashRoute = window.location.hash.replace(/^#\//, '#/lens/'); - - // redirect to the new lens url `app/kibana#/lens/...` - window.location.href = npSetup.core.http.basePath.prepend('/app/kibana' + prefixedHashRoute); -}); diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/_index.scss b/x-pack/legacy/plugins/lens/public/xy_visualization/_index.scss deleted file mode 100644 index 794ed4aed82ec..0000000000000 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './_xy_expression'; diff --git a/x-pack/plugins/lens/config.ts b/x-pack/plugins/lens/config.ts new file mode 100644 index 0000000000000..84cf02a7ea541 --- /dev/null +++ b/x-pack/plugins/lens/config.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 { schema, TypeOf } from '@kbn/config-schema'; + +export const configSchema = schema.object({ + enabled: schema.boolean({ defaultValue: true }), +}); + +export type ConfigSchema = TypeOf<typeof configSchema>; diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index 6abdaad7903be..ce544b31b88ef 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -3,7 +3,15 @@ "version": "8.0.0", "kibanaVersion": "kibana", "server": true, - "ui": false, - "optionalPlugins": ["usageCollection", "taskManager"], + "ui": true, + "requiredPlugins": [ + "data", + "expressions", + "navigation", + "kibanaLegacy", + "uiActions", + "visualizations" + ], + "optionalPlugins": ["embeddable", "usageCollection", "taskManager"], "configPath": ["xpack", "lens"] } diff --git a/x-pack/legacy/plugins/lens/public/_mixins.scss b/x-pack/plugins/lens/public/_mixins.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/_mixins.scss rename to x-pack/plugins/lens/public/_mixins.scss diff --git a/x-pack/legacy/plugins/lens/public/_variables.scss b/x-pack/plugins/lens/public/_variables.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/_variables.scss rename to x-pack/plugins/lens/public/_variables.scss diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/_app.scss b/x-pack/plugins/lens/public/app_plugin/_app.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/app_plugin/_app.scss rename to x-pack/plugins/lens/public/app_plugin/_app.scss diff --git a/x-pack/plugins/lens/public/app_plugin/_index.scss b/x-pack/plugins/lens/public/app_plugin/_index.scss new file mode 100644 index 0000000000000..e72e824224956 --- /dev/null +++ b/x-pack/plugins/lens/public/app_plugin/_index.scss @@ -0,0 +1 @@ +@import 'app'; diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx similarity index 96% rename from x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx rename to x-pack/plugins/lens/public/app_plugin/app.test.tsx index be72dd4b4edef..d49c128dff604 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -9,7 +9,7 @@ import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { App } from './app'; import { EditorFrameInstance } from '../types'; -import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; +import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { Document, SavedObjectStore } from '../persistence'; import { mount } from 'enzyme'; import { @@ -17,25 +17,24 @@ import { FilterManager, IFieldType, IIndexPattern, -} from '../../../../../../src/plugins/data/public'; -import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; +} from '../../../../../src/plugins/data/public'; +import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; const dataStartMock = dataPluginMock.createStartContract(); -import { TopNavMenuData } from '../../../../../../src/plugins/navigation/public'; +import { navigationPluginMock } from '../../../../../src/plugins/navigation/public/mocks'; +import { TopNavMenuData } from '../../../../../src/plugins/navigation/public'; import { coreMock } from 'src/core/public/mocks'; -jest.mock('ui/new_platform'); jest.mock('../persistence'); jest.mock('src/core/public'); -import { npStart } from 'ui/new_platform'; -jest - .spyOn(npStart.plugins.navigation.ui.TopNavMenu.prototype, 'constructor') - .mockImplementation(() => { - return <div className="topNavMenu" />; - }); +const navigationStartMock = navigationPluginMock.createStartContract(); + +jest.spyOn(navigationStartMock.ui.TopNavMenu.prototype, 'constructor').mockImplementation(() => { + return <div className="topNavMenu" />; +}); -const { TopNavMenu } = npStart.plugins.navigation.ui; +const { TopNavMenu } = navigationStartMock.ui; function createMockFrame(): jest.Mocked<EditorFrameInstance> { return { @@ -99,6 +98,7 @@ describe('Lens App', () => { function makeDefaultArgs(): jest.Mocked<{ editorFrame: EditorFrameInstance; data: typeof dataStartMock; + navigation: typeof navigationStartMock; core: typeof core; storage: Storage; docId?: string; @@ -107,6 +107,7 @@ describe('Lens App', () => { addToDashboardMode?: boolean; }> { return ({ + navigation: navigationStartMock, editorFrame: createMockFrame(), core: { ...core, @@ -140,6 +141,7 @@ describe('Lens App', () => { }, redirectTo: jest.fn(id => {}), } as unknown) as jest.Mocked<{ + navigation: typeof navigationStartMock; editorFrame: EditorFrameInstance; data: typeof dataStartMock; core: typeof core; @@ -338,6 +340,7 @@ describe('Lens App', () => { let defaultArgs: jest.Mocked<{ editorFrame: EditorFrameInstance; + navigation: typeof navigationStartMock; data: typeof dataStartMock; core: typeof core; storage: Storage; @@ -654,6 +657,7 @@ describe('Lens App', () => { let defaultArgs: jest.Mocked<{ editorFrame: EditorFrameInstance; data: typeof dataStartMock; + navigation: typeof navigationStartMock; core: typeof core; storage: Storage; docId?: string; diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx similarity index 96% rename from x-pack/legacy/plugins/lens/public/app_plugin/app.tsx rename to x-pack/plugins/lens/public/app_plugin/app.tsx index dfea2e39fcbc5..2d8f1650e4008 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -9,12 +9,12 @@ 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 { AppMountContext, NotificationsStart } from 'src/core/public'; +import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; +import { AppMountContext, NotificationsStart } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { npStart } from 'ui/new_platform'; import { FormattedMessage } from '@kbn/i18n/react'; -import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; -import { SavedObjectSaveModal } from '../../../../../../src/plugins/saved_objects/public'; +import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { SavedObjectSaveModal } from '../../../../../src/plugins/saved_objects/public'; import { Document, SavedObjectStore } from '../persistence'; import { EditorFrameInstance } from '../types'; import { NativeRenderer } from '../native_renderer'; @@ -25,7 +25,7 @@ import { IndexPattern as IndexPatternInstance, IndexPatternsContract, SavedQuery, -} from '../../../../../../src/plugins/data/public'; +} from '../../../../../src/plugins/data/public'; interface State { isLoading: boolean; @@ -53,9 +53,11 @@ export function App({ docStorage, redirectTo, addToDashboardMode, + navigation, }: { editorFrame: EditorFrameInstance; data: DataPublicPluginStart; + navigation: NavigationPublicPluginStart; core: AppMountContext['core']; storage: IStorageWrapper; docId?: string; @@ -188,7 +190,7 @@ export function App({ [] ); - const { TopNavMenu } = npStart.plugins.navigation.ui; + const { TopNavMenu } = navigation.ui; const confirmButton = addToDashboardMode ? ( <FormattedMessage diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/index.ts b/x-pack/plugins/lens/public/app_plugin/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/app_plugin/index.ts rename to x-pack/plugins/lens/public/app_plugin/index.ts diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_area.svg b/x-pack/plugins/lens/public/assets/chart_area.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_area.svg rename to x-pack/plugins/lens/public/assets/chart_area.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_area_stacked.svg b/x-pack/plugins/lens/public/assets/chart_area_stacked.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_area_stacked.svg rename to x-pack/plugins/lens/public/assets/chart_area_stacked.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_bar.svg b/x-pack/plugins/lens/public/assets/chart_bar.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_bar.svg rename to x-pack/plugins/lens/public/assets/chart_bar.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_bar_horizontal.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_bar_horizontal.svg rename to x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg rename to x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_bar_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_bar_stacked.svg rename to x-pack/plugins/lens/public/assets/chart_bar_stacked.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_datatable.svg b/x-pack/plugins/lens/public/assets/chart_datatable.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_datatable.svg rename to x-pack/plugins/lens/public/assets/chart_datatable.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_line.svg b/x-pack/plugins/lens/public/assets/chart_line.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_line.svg rename to x-pack/plugins/lens/public/assets/chart_line.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_metric.svg b/x-pack/plugins/lens/public/assets/chart_metric.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_metric.svg rename to x-pack/plugins/lens/public/assets/chart_metric.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/chart_mixed_xy.svg b/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/chart_mixed_xy.svg rename to x-pack/plugins/lens/public/assets/chart_mixed_xy.svg diff --git a/x-pack/legacy/plugins/lens/public/assets/lens_app_graphic_dark_2x.png b/x-pack/plugins/lens/public/assets/lens_app_graphic_dark_2x.png similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/lens_app_graphic_dark_2x.png rename to x-pack/plugins/lens/public/assets/lens_app_graphic_dark_2x.png diff --git a/x-pack/legacy/plugins/lens/public/assets/lens_app_graphic_light_2x.png b/x-pack/plugins/lens/public/assets/lens_app_graphic_light_2x.png similarity index 100% rename from x-pack/legacy/plugins/lens/public/assets/lens_app_graphic_light_2x.png rename to x-pack/plugins/lens/public/assets/lens_app_graphic_light_2x.png diff --git a/x-pack/plugins/lens/public/datatable_visualization/_index.scss b/x-pack/plugins/lens/public/datatable_visualization/_index.scss new file mode 100644 index 0000000000000..532e8106b023f --- /dev/null +++ b/x-pack/plugins/lens/public/datatable_visualization/_index.scss @@ -0,0 +1 @@ +@import 'visualization'; diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/_visualization.scss b/x-pack/plugins/lens/public/datatable_visualization/_visualization.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/datatable_visualization/_visualization.scss rename to x-pack/plugins/lens/public/datatable_visualization/_visualization.scss diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/expression.tsx b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/datatable_visualization/expression.tsx rename to x-pack/plugins/lens/public/datatable_visualization/expression.tsx index 050f294d0b964..cbdc0617e8568 100644 --- a/x-pack/legacy/plugins/lens/public/datatable_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx @@ -13,7 +13,7 @@ import { ExpressionFunctionDefinition, ExpressionRenderDefinition, IInterpreterRenderHandlers, -} from '../../../../../../src/plugins/expressions/public'; +} from '../../../../../src/plugins/expressions/public'; import { VisualizationContainer } from '../visualization_container'; export interface DatatableColumns { diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/index.ts b/x-pack/plugins/lens/public/datatable_visualization/index.ts similarity index 89% rename from x-pack/legacy/plugins/lens/public/datatable_visualization/index.ts rename to x-pack/plugins/lens/public/datatable_visualization/index.ts index 7a54a5daa3095..ff036aadfd4cf 100644 --- a/x-pack/legacy/plugins/lens/public/datatable_visualization/index.ts +++ b/x-pack/plugins/lens/public/datatable_visualization/index.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup } from 'src/core/public'; +import { CoreSetup } from 'kibana/public'; import { datatableVisualization } from './visualization'; -import { ExpressionsSetup } from '../../../../../../src/plugins/expressions/public'; +import { ExpressionsSetup } from '../../../../../src/plugins/expressions/public'; import { datatable, datatableColumns, getDatatableRenderer } from './expression'; import { EditorFrameSetup, FormatFactory } from '../types'; diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.test.tsx b/x-pack/plugins/lens/public/datatable_visualization/visualization.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.test.tsx rename to x-pack/plugins/lens/public/datatable_visualization/visualization.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.tsx b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/datatable_visualization/visualization.tsx rename to x-pack/plugins/lens/public/datatable_visualization/visualization.tsx diff --git a/x-pack/legacy/plugins/lens/public/debounced_component/debounced_component.test.tsx b/x-pack/plugins/lens/public/debounced_component/debounced_component.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/debounced_component/debounced_component.test.tsx rename to x-pack/plugins/lens/public/debounced_component/debounced_component.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/debounced_component/debounced_component.tsx b/x-pack/plugins/lens/public/debounced_component/debounced_component.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/debounced_component/debounced_component.tsx rename to x-pack/plugins/lens/public/debounced_component/debounced_component.tsx diff --git a/x-pack/legacy/plugins/lens/public/debounced_component/index.ts b/x-pack/plugins/lens/public/debounced_component/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/debounced_component/index.ts rename to x-pack/plugins/lens/public/debounced_component/index.ts diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap b/x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap rename to x-pack/plugins/lens/public/drag_drop/__snapshots__/drag_drop.test.tsx.snap diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/_drag_drop.scss b/x-pack/plugins/lens/public/drag_drop/_drag_drop.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/_drag_drop.scss rename to x-pack/plugins/lens/public/drag_drop/_drag_drop.scss diff --git a/x-pack/plugins/lens/public/drag_drop/_index.scss b/x-pack/plugins/lens/public/drag_drop/_index.scss new file mode 100644 index 0000000000000..ddf9b9aa3e429 --- /dev/null +++ b/x-pack/plugins/lens/public/drag_drop/_index.scss @@ -0,0 +1 @@ +@import 'drag_drop'; diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/drag_drop.test.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/drag_drop.test.tsx rename to x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/drag_drop.tsx b/x-pack/plugins/lens/public/drag_drop/drag_drop.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/drag_drop.tsx rename to x-pack/plugins/lens/public/drag_drop/drag_drop.tsx diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/index.ts b/x-pack/plugins/lens/public/drag_drop/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/index.ts rename to x-pack/plugins/lens/public/drag_drop/index.ts diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/providers.test.tsx b/x-pack/plugins/lens/public/drag_drop/providers.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/providers.test.tsx rename to x-pack/plugins/lens/public/drag_drop/providers.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/providers.tsx b/x-pack/plugins/lens/public/drag_drop/providers.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/providers.tsx rename to x-pack/plugins/lens/public/drag_drop/providers.tsx diff --git a/x-pack/legacy/plugins/lens/public/drag_drop/readme.md b/x-pack/plugins/lens/public/drag_drop/readme.md similarity index 100% rename from x-pack/legacy/plugins/lens/public/drag_drop/readme.md rename to x-pack/plugins/lens/public/drag_drop/readme.md diff --git a/x-pack/plugins/lens/public/editor_frame_service/_index.scss b/x-pack/plugins/lens/public/editor_frame_service/_index.scss new file mode 100644 index 0000000000000..199cbe35e25fa --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/_index.scss @@ -0,0 +1 @@ +@import 'editor_frame/index'; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/suggestion_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/suggestion_helpers.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/suggestion_helpers.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/suggestion_helpers.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_chart_switch.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_chart_switch.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_chart_switch.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/_chart_switch.scss diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/_config_panel_wrapper.scss diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/_data_panel_wrapper.scss diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_expression_renderer.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_expression_renderer.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_expression_renderer.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/_expression_renderer.scss diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/_frame_layout.scss diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_workspace_panel_wrapper.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_workspace_panel_wrapper.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/_workspace_panel_wrapper.scss rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/_workspace_panel_wrapper.scss diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/chart_switch.tsx diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel_wrapper.tsx diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx similarity index 94% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx index 2a9499077f3c1..cd0aee732793e 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx @@ -7,12 +7,11 @@ import React, { useMemo, memo, useContext, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiPopover, EuiButtonIcon, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui'; -import { DatasourceDataPanelProps, Datasource } from '../../../public'; import { NativeRenderer } from '../../native_renderer'; import { Action } from './state_management'; import { DragContext } from '../../drag_drop'; -import { StateSetter, FramePublicAPI } from '../../types'; -import { Query, Filter } from '../../../../../../../src/plugins/data/public'; +import { StateSetter, FramePublicAPI, DatasourceDataPanelProps, Datasource } from '../../types'; +import { Query, Filter } from '../../../../../../src/plugins/data/public'; interface DataPanelWrapperProps { datasourceState: unknown; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx similarity index 97% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx index 082519d9a8feb..b72d9081bbc91 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx @@ -5,8 +5,8 @@ */ import React, { useEffect, useReducer } from 'react'; -import { CoreSetup, CoreStart } from 'src/core/public'; -import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; +import { CoreSetup, CoreStart } from 'kibana/public'; +import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; import { Datasource, DatasourcePublicAPI, @@ -25,7 +25,7 @@ import { RootDragDropProvider } from '../../drag_drop'; import { getSavedObjectFormat } from './save'; import { WorkspacePanelWrapper } from './workspace_panel_wrapper'; import { generateId } from '../../id_generator'; -import { Filter, Query, SavedQuery } from '../../../../../../../src/plugins/data/public'; +import { Filter, Query, SavedQuery } from '../../../../../../src/plugins/data/public'; export interface EditorFrameProps { doc?: Document; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts similarity index 97% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts index d264e6d0da3ad..9d4f8587577a3 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts @@ -6,7 +6,7 @@ import { Ast, fromExpression, ExpressionFunctionAST } from '@kbn/interpreter/common'; import { Visualization, Datasource, FramePublicAPI } from '../../types'; -import { Filter, TimeRange, Query } from '../../../../../../../src/plugins/data/public'; +import { Filter, TimeRange, Query } from '../../../../../../src/plugins/data/public'; export function prependDatasourceExpression( visualizationExpression: Ast | string | null, diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.scss new file mode 100644 index 0000000000000..d4b27c6c98b3c --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.scss @@ -0,0 +1,8 @@ +@import 'chart_switch'; +@import 'config_panel_wrapper'; +@import 'data_panel_wrapper'; +@import 'expression_renderer'; +@import 'frame_layout'; +@import 'suggestion_panel'; +@import 'workspace_panel_wrapper'; + diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/index.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.test.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.test.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.test.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/layer_actions.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts similarity index 98% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts index 60bfbc493f61c..9c7ed265f3539 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts @@ -6,7 +6,7 @@ import { getSavedObjectFormat, Props } from './save'; import { createMockDatasource, createMockVisualization } from '../mocks'; -import { esFilters, IIndexPattern, IFieldType } from '../../../../../../../src/plugins/data/public'; +import { esFilters, IIndexPattern, IFieldType } from '../../../../../../src/plugins/data/public'; describe('save editor frame state', () => { const mockVisualization = createMockVisualization(); diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/save.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts diff --git a/x-pack/legacy/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 similarity index 99% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts index 4aaf2a3ee9e81..1f62929783b63 100644 --- a/x-pack/legacy/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 @@ -5,7 +5,7 @@ */ import { getInitialState, reducer } from './state_management'; -import { EditorFrameProps } from '.'; +import { EditorFrameProps } from './index'; import { Datasource, Visualization } from '../../types'; import { createExpressionRendererMock } from '../mocks'; import { coreMock } from 'src/core/public/mocks'; diff --git a/x-pack/legacy/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 similarity index 99% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts index 7d763bcac2cc9..bb6daf5641a64 100644 --- a/x-pack/legacy/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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EditorFrameProps } from '../editor_frame'; +import { EditorFrameProps } from './index'; import { Document } from '../../persistence/saved_object_store'; export interface PreviewState { diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx index 0e32f1f053b9d..240bdff40b51c 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx @@ -15,8 +15,8 @@ import { createMockFramePublicAPI, } from '../mocks'; import { act } from 'react-dom/test-utils'; -import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; -import { esFilters, IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public'; +import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; +import { esFilters, IFieldType, IIndexPattern } from '../../../../../../src/plugins/data/public'; import { SuggestionPanel, SuggestionPanelProps } from './suggestion_panel'; import { getSuggestions, Suggestion } from './suggestion_helpers'; import { EuiIcon, EuiPanel, EuiToolTip } from '@elastic/eui'; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index 76443027ab88a..867214d15578a 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -24,7 +24,7 @@ import classNames from 'classnames'; import { Action, PreviewState } from './state_management'; import { Datasource, Visualization, FramePublicAPI, DatasourcePublicAPI } from '../../types'; import { getSuggestions, switchToSuggestion } from './suggestion_helpers'; -import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; +import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; import { prependDatasourceExpression, prependKibanaContext } from './expression_helpers'; import { debouncedComponent } from '../../debounced_component'; import { trackUiEvent, trackSuggestionEvent } from '../../lens_ui_telemetry'; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx index 748e5b876da95..33ecee53fa3bc 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.test.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { ReactExpressionRendererProps } from '../../../../../../../src/plugins/expressions/public'; +import { ReactExpressionRendererProps } from '../../../../../../src/plugins/expressions/public'; import { FramePublicAPI, TableSuggestion, Visualization } from '../../types'; import { createMockVisualization, @@ -21,7 +21,7 @@ import { ReactWrapper } from 'enzyme'; import { DragDrop, ChildDragDropProvider } from '../../drag_drop'; import { Ast } from '@kbn/interpreter/common'; import { coreMock } from 'src/core/public/mocks'; -import { esFilters, IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public'; +import { esFilters, IFieldType, IIndexPattern } from '../../../../../../src/plugins/data/public'; describe('workspace_panel', () => { let mockVisualization: jest.Mocked<Visualization>; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.tsx index c2a5c16e405a2..1f741ca37934f 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel.tsx @@ -16,8 +16,8 @@ import { EuiBetaBadge, EuiButtonEmpty, } from '@elastic/eui'; -import { CoreStart, CoreSetup } from 'src/core/public'; -import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; +import { CoreStart, CoreSetup } from 'kibana/public'; +import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; import { Action } from './state_management'; import { Datasource, Visualization, FramePublicAPI } from '../../types'; import { DragDrop, DragContext } from '../../drag_drop'; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel_wrapper.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel_wrapper.tsx rename to x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel_wrapper.tsx diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx similarity index 96% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx rename to x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx index 55363ebe4d8f3..aeae64514b0fd 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx @@ -9,9 +9,9 @@ import { Embeddable } from './embeddable'; import { ReactExpressionRendererProps } from 'src/plugins/expressions/public'; import { Query, TimeRange, Filter, TimefilterContract } from 'src/plugins/data/public'; import { Document } from '../../persistence'; -import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; +import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; -jest.mock('../../../../../../../src/plugins/inspector/public/', () => ({ +jest.mock('../../../../../../src/plugins/inspector/public/', () => ({ isAvailable: false, open: false, })); diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx similarity index 94% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx rename to x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx index c2ab1c72af545..0ef5f6d1a5470 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx @@ -16,15 +16,15 @@ import { } from 'src/plugins/data/public'; import { Subscription } from 'rxjs'; -import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; -import { VIS_EVENT_TO_TRIGGER } from '../../../../../../../src/plugins/visualizations/public'; +import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; +import { VIS_EVENT_TO_TRIGGER } from '../../../../../../src/plugins/visualizations/public'; import { Embeddable as AbstractEmbeddable, EmbeddableOutput, IContainer, EmbeddableInput, -} from '../../../../../../../src/plugins/embeddable/public'; +} from '../../../../../../src/plugins/embeddable/public'; import { Document, DOC_TYPE } from '../../persistence'; import { ExpressionWrapper } from './expression_wrapper'; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts similarity index 91% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts rename to x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts index 99a59c756e228..68dbff263f60d 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts @@ -15,17 +15,17 @@ import { IndexPatternsContract, IndexPattern, TimefilterContract, -} from '../../../../../../../src/plugins/data/public'; -import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; +} from '../../../../../../src/plugins/data/public'; +import { ReactExpressionRendererType } from '../../../../../../src/plugins/expressions/public'; import { EmbeddableFactoryDefinition, ErrorEmbeddable, EmbeddableInput, IContainer, -} from '../../../../../../../src/plugins/embeddable/public'; +} from '../../../../../../src/plugins/embeddable/public'; import { Embeddable } from './embeddable'; import { SavedObjectIndexStore, DOC_TYPE } from '../../persistence'; -import { getEditPath } from '../../../../../../plugins/lens/common'; +import { getEditPath } from '../../../common'; interface StartServices { timefilter: TimefilterContract; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx rename to x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/format_column.ts b/x-pack/plugins/lens/public/editor_frame_service/format_column.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/format_column.ts rename to x-pack/plugins/lens/public/editor_frame_service/format_column.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/index.ts b/x-pack/plugins/lens/public/editor_frame_service/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/index.ts rename to x-pack/plugins/lens/public/editor_frame_service/index.ts diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/merge_tables.test.ts b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts similarity index 98% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/merge_tables.test.ts rename to x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts index 9368674de31c5..243441f2c8ab3 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/merge_tables.test.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts @@ -8,8 +8,6 @@ import moment from 'moment'; import { mergeTables } from './merge_tables'; import { KibanaDatatable } from 'src/plugins/expressions'; -jest.mock('ui/new_platform'); - describe('lens_merge_tables', () => { it('should produce a row with the nested table as defined', () => { const sampleTable1: KibanaDatatable = { diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/merge_tables.ts b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts similarity index 96% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/merge_tables.ts rename to x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts index c06640fb25de6..7c10ee4a57fad 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/merge_tables.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts @@ -10,7 +10,7 @@ import { ExpressionValueSearchContext, KibanaDatatable, } from 'src/plugins/expressions/public'; -import { search } from '../../../../../../src/plugins/data/public'; +import { search } from '../../../../../src/plugins/data/public'; const { toAbsoluteDates } = search.aggs; import { LensMultiTable } from '../types'; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx b/x-pack/plugins/lens/public/editor_frame_service/mocks.tsx similarity index 92% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx rename to x-pack/plugins/lens/public/editor_frame_service/mocks.tsx index 5d2f68a5567eb..50cd1ad8bd53a 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/mocks.tsx @@ -9,12 +9,12 @@ import { ReactExpressionRendererProps, ExpressionsSetup, ExpressionsStart, -} from '../../../../../../src/plugins/expressions/public'; -import { embeddablePluginMock } from '../../../../../../src/plugins/embeddable/public/mocks'; -import { expressionsPluginMock } from '../../../../../../src/plugins/expressions/public/mocks'; +} from '../../../../../src/plugins/expressions/public'; +import { embeddablePluginMock } from '../../../../../src/plugins/embeddable/public/mocks'; +import { expressionsPluginMock } from '../../../../../src/plugins/expressions/public/mocks'; import { DatasourcePublicAPI, FramePublicAPI, Datasource, Visualization } from '../types'; import { EditorFrameSetupPlugins, EditorFrameStartPlugins } from './service'; -import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; +import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; export function createMockVisualization(): jest.Mocked<Visualization> { return { diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/service.test.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx rename to x-pack/plugins/lens/public/editor_frame_service/service.test.tsx index 42a1fcc055a1e..fbd65c5044d51 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/service.test.tsx @@ -14,8 +14,6 @@ import { } from './mocks'; import { CoreSetup } from 'kibana/public'; -jest.mock('ui/new_platform'); - // mock away actual dependencies to prevent all of it being loaded jest.mock('./embeddable/embeddable_factory', () => ({ EmbeddableFactory: class Mock {}, diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.tsx b/x-pack/plugins/lens/public/editor_frame_service/service.tsx similarity index 91% rename from x-pack/legacy/plugins/lens/public/editor_frame_service/service.tsx rename to x-pack/plugins/lens/public/editor_frame_service/service.tsx index 1375c60060ca8..15fe449d6563b 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/service.tsx @@ -7,16 +7,13 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { I18nProvider } from '@kbn/i18n/react'; -import { CoreSetup, CoreStart } from 'src/core/public'; -import { - ExpressionsSetup, - ExpressionsStart, -} from '../../../../../../src/plugins/expressions/public'; -import { EmbeddableSetup, EmbeddableStart } from '../../../../../../src/plugins/embeddable/public'; +import { CoreSetup, CoreStart } from 'kibana/public'; +import { ExpressionsSetup, ExpressionsStart } from '../../../../../src/plugins/expressions/public'; +import { EmbeddableSetup, EmbeddableStart } from '../../../../../src/plugins/embeddable/public'; import { DataPublicPluginSetup, DataPublicPluginStart, -} from '../../../../../../src/plugins/data/public'; +} from '../../../../../src/plugins/data/public'; import { Datasource, Visualization, @@ -32,13 +29,13 @@ import { getActiveDatasourceIdFromDoc } from './editor_frame/state_management'; export interface EditorFrameSetupPlugins { data: DataPublicPluginSetup; - embeddable: EmbeddableSetup; + embeddable?: EmbeddableSetup; expressions: ExpressionsSetup; } export interface EditorFrameStartPlugins { data: DataPublicPluginStart; - embeddable: EmbeddableStart; + embeddable?: EmbeddableStart; expressions: ExpressionsStart; } @@ -79,7 +76,9 @@ export class EditorFrameService { }; }; - plugins.embeddable.registerEmbeddableFactory('lens', new EmbeddableFactory(getStartServices)); + if (plugins.embeddable) { + plugins.embeddable.registerEmbeddableFactory('lens', new EmbeddableFactory(getStartServices)); + } return { registerDatasource: datasource => { diff --git a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx b/x-pack/plugins/lens/public/help_menu_util.tsx similarity index 63% rename from x-pack/legacy/plugins/lens/public/help_menu_util.tsx rename to x-pack/plugins/lens/public/help_menu_util.tsx index 9ead31690e854..333a90df4731b 100644 --- a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx +++ b/x-pack/plugins/lens/public/help_menu_util.tsx @@ -4,16 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; -import { ChromeStart } from 'kibana/public'; +import { ChromeStart, DocLinksStart } from 'kibana/public'; -export function addHelpMenuToAppChrome(chrome: ChromeStart) { +export function addHelpMenuToAppChrome(chrome: ChromeStart, docLinks: DocLinksStart) { chrome.setHelpExtension({ appName: 'Lens', links: [ { linkType: 'documentation', - href: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/lens.html`, + href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/lens.html`, }, { linkType: 'github', diff --git a/x-pack/legacy/plugins/lens/public/helpers/index.ts b/x-pack/plugins/lens/public/helpers/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/helpers/index.ts rename to x-pack/plugins/lens/public/helpers/index.ts diff --git a/x-pack/legacy/plugins/lens/public/helpers/url_helper.test.ts b/x-pack/plugins/lens/public/helpers/url_helper.test.ts similarity index 96% rename from x-pack/legacy/plugins/lens/public/helpers/url_helper.test.ts rename to x-pack/plugins/lens/public/helpers/url_helper.test.ts index ef960fb52952b..37e35ca17e0b3 100644 --- a/x-pack/legacy/plugins/lens/public/helpers/url_helper.test.ts +++ b/x-pack/plugins/lens/public/helpers/url_helper.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../../../../src/plugins/dashboard/public', () => ({ +jest.mock('../../../../../src/plugins/dashboard/public', () => ({ DashboardConstants: { ADD_EMBEDDABLE_ID: 'addEmbeddableId', ADD_EMBEDDABLE_TYPE: 'addEmbeddableType', diff --git a/x-pack/legacy/plugins/lens/public/helpers/url_helper.ts b/x-pack/plugins/lens/public/helpers/url_helper.ts similarity index 95% rename from x-pack/legacy/plugins/lens/public/helpers/url_helper.ts rename to x-pack/plugins/lens/public/helpers/url_helper.ts index 3495c15118ce7..0a97ba4b2edf7 100644 --- a/x-pack/legacy/plugins/lens/public/helpers/url_helper.ts +++ b/x-pack/plugins/lens/public/helpers/url_helper.ts @@ -5,7 +5,7 @@ */ import { parseUrl, stringify } from 'query-string'; -import { DashboardConstants } from '../../../../../../src/plugins/dashboard/public'; +import { DashboardConstants } from '../../../../../src/plugins/dashboard/public'; type UrlVars = Record<string, string>; diff --git a/x-pack/legacy/plugins/lens/public/id_generator/id_generator.test.ts b/x-pack/plugins/lens/public/id_generator/id_generator.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/id_generator/id_generator.test.ts rename to x-pack/plugins/lens/public/id_generator/id_generator.test.ts diff --git a/x-pack/legacy/plugins/lens/public/id_generator/id_generator.ts b/x-pack/plugins/lens/public/id_generator/id_generator.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/id_generator/id_generator.ts rename to x-pack/plugins/lens/public/id_generator/id_generator.ts diff --git a/x-pack/legacy/plugins/lens/public/id_generator/index.ts b/x-pack/plugins/lens/public/id_generator/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/id_generator/index.ts rename to x-pack/plugins/lens/public/id_generator/index.ts diff --git a/x-pack/legacy/plugins/lens/public/index.scss b/x-pack/plugins/lens/public/index.scss similarity index 54% rename from x-pack/legacy/plugins/lens/public/index.scss rename to x-pack/plugins/lens/public/index.scss index 2f91d14c397c7..67bbac12be8c3 100644 --- a/x-pack/legacy/plugins/lens/public/index.scss +++ b/x-pack/plugins/lens/public/index.scss @@ -1,12 +1,13 @@ // Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; +@import '@elastic/eui/src/global_styling/variables/index'; +@import '@elastic/eui/src/global_styling/mixins/index'; -@import './variables'; -@import './mixins'; +@import 'variables'; +@import 'mixins'; -@import './app_plugin/index'; +@import 'app_plugin/index'; @import 'datatable_visualization/index'; -@import './drag_drop/index'; +@import 'drag_drop/index'; @import 'editor_frame_service/index'; @import 'indexpattern_datasource/index'; @import 'xy_visualization/index'; diff --git a/x-pack/legacy/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/index.ts rename to x-pack/plugins/lens/public/index.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts b/x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/__mocks__/state_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/state_helpers.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/__mocks__/state_helpers.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/state_helpers.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/__snapshots__/lens_field_icon.test.tsx.snap b/x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/lens_field_icon.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/__snapshots__/lens_field_icon.test.tsx.snap rename to x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/lens_field_icon.test.tsx.snap diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/_datapanel.scss b/x-pack/plugins/lens/public/indexpattern_datasource/_datapanel.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/_datapanel.scss rename to x-pack/plugins/lens/public/indexpattern_datasource/_datapanel.scss diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/_field_item.scss b/x-pack/plugins/lens/public/indexpattern_datasource/_field_item.scss similarity index 98% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/_field_item.scss rename to x-pack/plugins/lens/public/indexpattern_datasource/_field_item.scss index 89f6bbf908419..41919b900c71f 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/_field_item.scss +++ b/x-pack/plugins/lens/public/indexpattern_datasource/_field_item.scss @@ -14,7 +14,7 @@ } .lnsFieldItem--missing { - background: lightOrDarkTheme(transparentize($euiColorMediumShade, 0.9), $euiColorEmptyShade); + background: lightOrDarkTheme(transparentize($euiColorMediumShade, .9), $euiColorEmptyShade); color: $euiColorDarkShade; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/_index.scss b/x-pack/plugins/lens/public/indexpattern_datasource/_index.scss new file mode 100644 index 0000000000000..e5d8b408e33e5 --- /dev/null +++ b/x-pack/plugins/lens/public/indexpattern_datasource/_index.scss @@ -0,0 +1,4 @@ +@import 'datapanel'; +@import 'field_item'; + +@import 'dimension_panel/index'; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/auto_date.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.test.ts similarity index 96% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/auto_date.test.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/auto_date.test.ts index cc1a74a1854ce..5f35ef650a08c 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/auto_date.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; +import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; import { getAutoDate } from './auto_date'; describe('auto_date', () => { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/auto_date.ts b/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.ts similarity index 92% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/auto_date.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/auto_date.ts index 063cbb4d217a7..97a46f4a3e176 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/auto_date.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.ts @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { DataPublicPluginSetup } from '../../../../../../src/plugins/data/public'; +import { DataPublicPluginSetup } from '../../../../../src/plugins/data/public'; import { ExpressionFunctionDefinition, KibanaContext, -} from '../../../../../../src/plugins/expressions/public'; +} from '../../../../../src/plugins/expressions/public'; interface LensAutoDateProps { aggConfigs: string; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx index 3066ac0e11325..c396f0efee42e 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx @@ -6,6 +6,7 @@ import React, { ChangeEvent } from 'react'; import { createMockedDragDropContext } from './mocks'; +import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; import { InnerIndexPatternDataPanel, IndexPatternDataPanel, MemoizedDataPanel } from './datapanel'; import { FieldItem } from './field_item'; import { act } from 'react-dom/test-utils'; @@ -16,8 +17,6 @@ import { ChangeIndexPattern } from './change_indexpattern'; import { EuiProgress } from '@elastic/eui'; import { documentField } from './document_field'; -jest.mock('ui/new_platform'); - const initialState: IndexPatternPrivateState = { indexPatternRefs: [], existingFields: {}, @@ -218,6 +217,7 @@ describe('IndexPattern Data Panel', () => { defaultProps = { indexPatternRefs: [], existingFields: {}, + data: dataPluginMock.createStartContract(), dragDropContext: createMockedDragDropContext(), currentIndexPatternId: '1', indexPatterns: initialState.indexPatterns, diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/datapanel.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx index 7a3c04b67fbc4..79dcdafd916b4 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx @@ -27,6 +27,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { DatasourceDataPanelProps, DataType, StateSetter } from '../types'; import { ChildDragDropProvider, DragContextState } from '../drag_drop'; import { FieldItem } from './field_item'; @@ -40,9 +41,10 @@ import { trackUiEvent } from '../lens_ui_telemetry'; import { syncExistingFields } from './loader'; import { fieldExists } from './pure_helpers'; import { Loader } from '../loader'; -import { esQuery, IIndexPattern } from '../../../../../../src/plugins/data/public'; +import { esQuery, IIndexPattern } from '../../../../../src/plugins/data/public'; export type Props = DatasourceDataPanelProps<IndexPatternPrivateState> & { + data: DataPublicPluginStart; changeIndexPattern: ( id: string, state: IndexPatternPrivateState, @@ -78,6 +80,7 @@ export function IndexPatternDataPanel({ state, dragDropContext, core, + data, query, filters, dateRange, @@ -152,6 +155,7 @@ export function IndexPatternDataPanel({ showEmptyFields={state.showEmptyFields} onToggleEmptyFields={onToggleEmptyFields} core={core} + data={data} onChangeIndexPattern={onChangeIndexPattern} existingFields={state.existingFields} /> @@ -177,8 +181,10 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ showEmptyFields, onToggleEmptyFields, core, + data, existingFields, }: Pick<DatasourceDataPanelProps, Exclude<keyof DatasourceDataPanelProps, 'state' | 'setState'>> & { + data: DataPublicPluginStart; currentIndexPatternId: string; indexPatternRefs: IndexPatternRef[]; indexPatterns: Record<string, IndexPattern>; @@ -441,6 +447,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ {specialFields.map(field => ( <FieldItem core={core} + data={data} key={field.name} indexPattern={currentIndexPattern} field={field} @@ -468,6 +475,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ return ( <FieldItem core={core} + data={data} indexPattern={currentIndexPattern} key={field.name} field={field} diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_field_select.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_field_select.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_field_select.scss rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_field_select.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss new file mode 100644 index 0000000000000..085a00a2c33c5 --- /dev/null +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_index.scss @@ -0,0 +1,2 @@ +@import 'field_select'; +@import 'popover'; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/_popover.scss diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx diff --git a/x-pack/legacy/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 similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx index f4485774bc942..074c40759f8d8 100644 --- a/x-pack/legacy/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 @@ -8,7 +8,7 @@ import { ReactWrapper, ShallowWrapper } from 'enzyme'; import React from 'react'; import { act } from 'react-dom/test-utils'; import { EuiComboBox, EuiSideNav, EuiSideNavItemType, EuiFieldNumber } from '@elastic/eui'; -import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public'; +import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; import { changeColumn } from '../state_helpers'; import { IndexPatternDimensionEditorComponent, @@ -19,18 +19,12 @@ import { import { DragContextState } from '../../drag_drop'; import { createMockedDragDropContext } from '../mocks'; import { mountWithIntl as mount, shallowWithIntl as shallow } from 'test_utils/enzyme_helpers'; -import { - IUiSettingsClient, - SavedObjectsClientContract, - HttpSetup, - CoreSetup, -} from 'src/core/public'; +import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup, CoreSetup } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { IndexPatternPrivateState } from '../types'; import { documentField } from '../document_field'; import { OperationMetadata } from '../../types'; -jest.mock('ui/new_platform'); jest.mock('../loader'); jest.mock('../state_helpers'); diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx similarity index 97% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx index 5d87137db3d39..8b03a879da431 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx @@ -8,7 +8,7 @@ import _ from 'lodash'; import React, { memo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiLink } from '@elastic/eui'; -import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'src/core/public'; +import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { DatasourceDimensionTriggerProps, @@ -16,7 +16,7 @@ import { DatasourceDimensionDropProps, DatasourceDimensionDropHandlerProps, } from '../../types'; -import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public'; +import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; import { IndexPatternColumn, OperationType } from '../indexpattern'; import { getAvailableOperationsByMetadata, buildColumn, changeField } from '../operations'; import { PopoverEditor } from './popover_editor'; @@ -24,7 +24,7 @@ import { changeColumn } from '../state_helpers'; import { isDraggedField, hasField } from '../utils'; import { IndexPatternPrivateState, IndexPatternField } from '../types'; import { trackUiEvent } from '../../lens_ui_telemetry'; -import { DateRange } from '../../../../../../plugins/lens/common'; +import { DateRange } from '../../../common'; export type IndexPatternDimensionTriggerProps = DatasourceDimensionTriggerProps< IndexPatternPrivateState diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/document_field.ts b/x-pack/plugins/lens/public/indexpattern_datasource/document_field.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/document_field.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/document_field.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/field_item.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx similarity index 95% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/field_item.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx index 77f7f8cdab358..6a4a2bd2ba77b 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/field_item.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx @@ -10,16 +10,15 @@ import { EuiLoadingSpinner, EuiPopover } from '@elastic/eui'; import { FieldItem, FieldItemProps } from './field_item'; import { coreMock } from 'src/core/public/mocks'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { npStart } from 'ui/new_platform'; -import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; +import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; +import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; import { IndexPattern } from './types'; -jest.mock('ui/new_platform'); - describe('IndexPattern Field Item', () => { let defaultProps: FieldItemProps; let indexPattern: IndexPattern; let core: ReturnType<typeof coreMock['createSetup']>; + let data: DataPublicPluginStart; beforeEach(() => { indexPattern = { @@ -61,9 +60,11 @@ describe('IndexPattern Field Item', () => { } as IndexPattern; core = coreMock.createSetup(); + data = dataPluginMock.createStartContract(); core.http.post.mockClear(); defaultProps = { indexPattern, + data, core, highlight: '', dateRange: { @@ -81,7 +82,7 @@ describe('IndexPattern Field Item', () => { exists: true, }; - npStart.plugins.data.fieldFormats = ({ + data.fieldFormats = ({ getDefaultInstance: jest.fn(() => ({ convert: jest.fn((s: unknown) => JSON.stringify(s)), })), diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx similarity index 97% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/field_item.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx index b98f589bc5b98..c4d2a6f8780c6 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -20,7 +20,6 @@ import { EuiText, EuiToolTip, } from '@elastic/eui'; -import { npStart } from 'ui/new_platform'; import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; import { Axis, @@ -33,6 +32,7 @@ import { TooltipType, } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { Query, KBN_FIELD_TYPES, @@ -40,17 +40,18 @@ import { Filter, esQuery, IIndexPattern, -} from '../../../../../../src/plugins/data/public'; +} from '../../../../../src/plugins/data/public'; import { DraggedField } from './indexpattern'; import { DragDrop } from '../drag_drop'; import { DatasourceDataPanelProps, DataType } from '../types'; -import { BucketedAggregation, FieldStatsResponse } from '../../../../../plugins/lens/common'; +import { BucketedAggregation, FieldStatsResponse } from '../../common'; import { IndexPattern, IndexPatternField } from './types'; import { LensFieldIcon } from './lens_field_icon'; import { trackUiEvent } from '../lens_ui_telemetry'; export interface FieldItemProps { core: DatasourceDataPanelProps['core']; + data: DataPublicPluginStart; field: IndexPatternField; indexPattern: IndexPattern; highlight?: string; @@ -237,8 +238,16 @@ export function FieldItem(props: FieldItemProps) { } function FieldItemPopoverContents(props: State & FieldItemProps) { - const fieldFormats = npStart.plugins.data.fieldFormats; - const { histogram, topValues, indexPattern, field, dateRange, core, sampledValues } = props; + const { + histogram, + topValues, + indexPattern, + field, + dateRange, + core, + sampledValues, + data: { fieldFormats }, + } = props; const IS_DARK_THEME = core.uiSettings.get('theme:darkMode'); const chartTheme = IS_DARK_THEME ? EUI_CHARTS_THEME_DARK.theme : EUI_CHARTS_THEME_LIGHT.theme; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/index.ts similarity index 84% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/index.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/index.ts index 8a5c562ebd455..fe14f472341af 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/index.ts @@ -4,16 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup } from 'src/core/public'; -import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; +import { CoreSetup } from 'kibana/public'; +import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { getIndexPatternDatasource } from './indexpattern'; import { renameColumns } from './rename_columns'; import { getAutoDate } from './auto_date'; -import { ExpressionsSetup } from '../../../../../../src/plugins/expressions/public'; +import { ExpressionsSetup } from '../../../../../src/plugins/expressions/public'; import { DataPublicPluginSetup, DataPublicPluginStart, -} from '../../../../../../src/plugins/data/public'; +} from '../../../../../src/plugins/data/public'; import { Datasource, EditorFrameSetup } from '../types'; export interface IndexPatternDatasourceSetupPlugins { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts similarity index 98% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index 76e59a170a9e9..dbdbe4e3f9442 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -8,13 +8,11 @@ import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { getIndexPatternDatasource, IndexPatternColumn, uniqueLabels } from './indexpattern'; import { DatasourcePublicAPI, Operation, Datasource } from '../types'; import { coreMock } from 'src/core/public/mocks'; -import { pluginsMock } from 'ui/new_platform/__mocks__/helpers'; import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; +import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; jest.mock('./loader'); jest.mock('../id_generator'); -// Contains old and new platform data plugins, used for interpreter and filter ratio -jest.mock('ui/new_platform'); const expectedIndexPatterns = { 1: { @@ -140,7 +138,7 @@ describe('IndexPattern Data Source', () => { indexPatternDatasource = getIndexPatternDatasource({ storage: {} as IStorageWrapper, core: coreMock.createStart(), - data: pluginsMock.createStart().data, + data: dataPluginMock.createStartContract(), }); persistedState = { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx similarity index 96% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index 9c2a9c9bf4a09..b8f0460f2a9ab 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -8,7 +8,7 @@ import _ from 'lodash'; import React from 'react'; import { render } from 'react-dom'; import { I18nProvider } from '@kbn/i18n/react'; -import { CoreStart } from 'src/core/public'; +import { CoreStart } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { @@ -42,10 +42,10 @@ import { IndexPatternPrivateState, IndexPatternPersistedState, } from './types'; -import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; -import { Plugin as DataPlugin } from '../../../../../../src/plugins/data/public'; +import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; import { deleteColumn } from './state_helpers'; -import { Datasource, StateSetter } from '..'; +import { Datasource, StateSetter } from '../index'; export { OperationType, IndexPatternColumn } from './operations'; @@ -105,7 +105,7 @@ export function getIndexPatternDatasource({ }: { core: CoreStart; storage: IStorageWrapper; - data: ReturnType<DataPlugin['start']>; + data: DataPublicPluginStart; }) { const savedObjectsClient = core.savedObjects.client; const uiSettings = core.uiSettings; @@ -209,6 +209,7 @@ export function getIndexPatternDatasource({ onError: onIndexPatternLoadError, }); }} + data={data} {...props} /> </I18nProvider>, diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx index fe14e5de5c1e3..2008b326a539c 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx @@ -12,7 +12,6 @@ import { getDatasourceSuggestionsFromCurrentState, } from './indexpattern_suggestions'; -jest.mock('ui/new_platform'); jest.mock('./loader'); jest.mock('../id_generator'); diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx index 219a6d935e436..4dd29d7925916 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx @@ -12,7 +12,6 @@ import { ShallowWrapper } from 'enzyme'; import { EuiSelectable, EuiSelectableList } from '@elastic/eui'; import { ChangeIndexPattern } from './change_indexpattern'; -jest.mock('ui/new_platform'); jest.mock('./state_helpers'); const initialState: IndexPatternPrivateState = { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/layerpanel.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/lens_field_icon.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/lens_field_icon.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx similarity index 86% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx index 06eda73748cef..bcc83e799d889 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { FieldIcon, FieldIconProps } from '../../../../../../src/plugins/kibana_react/public'; +import { FieldIcon, FieldIconProps } from '../../../../../src/plugins/kibana_react/public'; import { DataType } from '../types'; import { normalizeOperationDataType } from './utils'; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/loader.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/loader.test.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts index ea9c8213ba909..cacf729ba0caf 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/loader.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts @@ -16,8 +16,6 @@ import { import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; import { documentField } from './document_field'; -// TODO: This should not be necessary -jest.mock('ui/new_platform'); jest.mock('./operations'); const sampleIndexPatterns = { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/loader.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts similarity index 96% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/loader.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/loader.ts index f4d5857f4826d..23faab768eba6 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/loader.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts @@ -5,8 +5,8 @@ */ import _ from 'lodash'; -import { SavedObjectsClientContract, SavedObjectAttributes, HttpSetup } from 'src/core/public'; -import { SimpleSavedObject } from 'src/core/public'; +import { SavedObjectsClientContract, SavedObjectAttributes, HttpSetup } from 'kibana/public'; +import { SimpleSavedObject } from 'kibana/public'; import { StateSetter } from '../types'; import { IndexPattern, @@ -16,14 +16,14 @@ import { IndexPatternField, } from './types'; import { updateLayerIndexPattern } from './state_helpers'; -import { DateRange, ExistingFields } from '../../../../../plugins/lens/common/types'; -import { BASE_API_URL } from '../../../../../plugins/lens/common'; +import { DateRange, ExistingFields } from '../../common/types'; +import { BASE_API_URL } from '../../common'; import { documentField } from './document_field'; import { indexPatterns as indexPatternsUtils, IFieldType, IndexPatternTypeMeta, -} from '../../../../../../src/plugins/data/public'; +} from '../../../../../src/plugins/data/public'; interface SavedIndexPatternAttributes extends SavedObjectAttributes { title: string; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/mocks.ts b/x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/mocks.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx index 33325016deaeb..9491ca9ea3787 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { OperationDefinition } from '.'; +import { OperationDefinition } from './index'; import { FormattedIndexPatternColumn } from './column_types'; const supportedTypes = new Set(['string', 'boolean', 'number', 'ip', 'date']); diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx similarity index 97% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx index 1592b1049f666..1dcaf78b58a6c 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { OperationDefinition } from '.'; +import { OperationDefinition } from './index'; import { FormattedIndexPatternColumn } from './column_types'; import { IndexPatternField } from '../../types'; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx index dc279fca82d4b..e3b6061248f3b 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx @@ -6,21 +6,19 @@ import React from 'react'; import { DateHistogramIndexPatternColumn } from './date_histogram'; -import { dateHistogramOperation } from '.'; +import { dateHistogramOperation } from './index'; import { shallow } from 'enzyme'; import { EuiSwitch, EuiSwitchEvent } from '@elastic/eui'; -import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'src/core/public'; +import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'kibana/public'; import { coreMock } from 'src/core/public/mocks'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { dataPluginMock, getCalculateAutoTimeExpression, -} from '../../../../../../../../src/plugins/data/public/mocks'; +} from '../../../../../../../src/plugins/data/public/mocks'; import { createMockedIndexPattern } from '../../mocks'; import { IndexPatternPrivateState } from '../../types'; -jest.mock('ui/new_platform'); - const dataStart = dataPluginMock.createStartContract(); dataStart.search.aggs.calculateAutoTimeExpression = getCalculateAutoTimeExpression({ ...coreMock.createStart().uiSettings, diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx index 452d5c9140868..7a36d52ad897b 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx @@ -21,12 +21,9 @@ import { EuiSpacer, } from '@elastic/eui'; import { updateColumnParam } from '../../state_helpers'; -import { OperationDefinition } from '.'; +import { OperationDefinition } from './index'; import { FieldBasedIndexPatternColumn } from './column_types'; -import { - IndexPatternAggRestrictions, - search, -} from '../../../../../../../../src/plugins/data/public'; +import { IndexPatternAggRestrictions, search } from '../../../../../../../src/plugins/data/public'; const { isValidInterval } = search.aggs; const autoInterval = 'auto'; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts similarity index 97% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts index 2db5296905000..ef12fca690f0c 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'src/core/public'; +import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { termsOperation } from './terms'; import { cardinalityOperation } from './cardinality'; @@ -14,8 +14,8 @@ import { countOperation } from './count'; import { DimensionPriority, StateSetter, OperationMetadata } from '../../../types'; import { BaseIndexPatternColumn } from './column_types'; import { IndexPatternPrivateState, IndexPattern, IndexPatternField } from '../../types'; -import { DateRange } from '../../../../../../../plugins/lens/common'; -import { DataPublicPluginStart } from '../../../../../../../../src/plugins/data/public'; +import { DateRange } from '../../../../common'; +import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public'; // List of all operation definitions registered to this data source. // If you want to implement a new operation, add it to this array and diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx index c2d9478c6ea15..3da635dc13d10 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { OperationDefinition } from '.'; +import { OperationDefinition } from './index'; import { FormattedIndexPatternColumn } from './column_types'; type MetricColumn<T> = FormattedIndexPatternColumn & { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx index fc0c9746b2f98..8f6130e74b5b8 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx @@ -7,16 +7,14 @@ import React from 'react'; import { shallow } from 'enzyme'; import { EuiRange, EuiSelect } from '@elastic/eui'; -import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'src/core/public'; +import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { dataPluginMock } from '../../../../../../../../src/plugins/data/public/mocks'; +import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; import { createMockedIndexPattern } from '../../mocks'; import { TermsIndexPatternColumn } from './terms'; -import { termsOperation } from '.'; +import { termsOperation } from './index'; import { IndexPatternPrivateState } from '../../types'; -jest.mock('ui/new_platform'); - const defaultProps = { storage: {} as IStorageWrapper, uiSettings: {} as IUiSettingsClient, diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx index 387b197c9235c..29e5787fa4f54 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx @@ -10,7 +10,7 @@ import { EuiForm, EuiFormRow, EuiRange, EuiSelect } from '@elastic/eui'; import { IndexPatternColumn } from '../../indexpattern'; import { updateColumnParam } from '../../state_helpers'; import { DataType } from '../../../types'; -import { OperationDefinition } from '.'; +import { OperationDefinition } from './index'; import { FieldBasedIndexPatternColumn } from './column_types'; type PropType<C> = C extends React.ComponentType<infer P> ? P : unknown; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/index.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts index 3602491c6eb2c..111b1040de989 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts @@ -4,13 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getOperationTypesForField, getAvailableOperationsByMetadata, buildColumn } from '.'; +import { getOperationTypesForField, getAvailableOperationsByMetadata, buildColumn } from './index'; import { AvgIndexPatternColumn, MinIndexPatternColumn } from './definitions/metrics'; import { CountIndexPatternColumn } from './definitions/count'; import { IndexPatternPrivateState } from '../types'; import { documentField } from '../document_field'; -jest.mock('ui/new_platform'); jest.mock('../loader'); const expectedIndexPatterns = { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/operations.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/operations/operations.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/pure_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/pure_helpers.test.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.test.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/pure_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/pure_helpers.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts similarity index 96% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts index 9da7591305a6c..4bfd6a4f93c75 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts @@ -5,8 +5,8 @@ */ import { renameColumns } from './rename_columns'; -import { KibanaDatatable } from '../../../../../../src/plugins/expressions/public'; -import { createMockExecutionContext } from '../../../../../../src/plugins/expressions/common/mocks'; +import { KibanaDatatable } from '../../../../../src/plugins/expressions/public'; +import { createMockExecutionContext } from '../../../../../src/plugins/expressions/common/mocks'; describe('rename_columns', () => { it('should rename columns of a given datatable', () => { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/rename_columns.ts b/x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/rename_columns.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts similarity index 99% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts index 0a58853f1ef4f..1e3251a8dedd8 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts @@ -17,7 +17,6 @@ import { DateHistogramIndexPatternColumn } from './operations/definitions/date_h import { AvgIndexPatternColumn } from './operations/definitions/metrics'; import { IndexPattern, IndexPatternPrivateState, IndexPatternLayer } from './types'; -jest.mock('ui/new_platform'); jest.mock('./operations'); describe('state_helpers', () => { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/state_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/state_helpers.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/to_expression.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts similarity index 94% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/types.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/types.ts index 3820ff3b387bb..563af40ed2720 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts @@ -5,7 +5,7 @@ */ import { IndexPatternColumn } from './operations'; -import { IndexPatternAggRestrictions } from '../../../../../../src/plugins/data/public'; +import { IndexPatternAggRestrictions } from '../../../../../src/plugins/data/public'; export interface IndexPattern { id: string; diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_datasource/utils.ts b/x-pack/plugins/lens/public/indexpattern_datasource/utils.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/indexpattern_datasource/utils.ts rename to x-pack/plugins/lens/public/indexpattern_datasource/utils.ts diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts b/x-pack/plugins/lens/public/lens_ui_telemetry/factory.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts rename to x-pack/plugins/lens/public/lens_ui_telemetry/factory.test.ts diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts b/x-pack/plugins/lens/public/lens_ui_telemetry/factory.ts similarity index 96% rename from x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts rename to x-pack/plugins/lens/public/lens_ui_telemetry/factory.ts index 73750a65c50b8..10b052c66efed 100644 --- a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts +++ b/x-pack/plugins/lens/public/lens_ui_telemetry/factory.ts @@ -5,10 +5,10 @@ */ import moment from 'moment'; -import { HttpSetup } from 'src/core/public'; +import { HttpSetup } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { BASE_API_URL } from '../../../../../plugins/lens/common'; +import { BASE_API_URL } from '../../common'; const STORAGE_KEY = 'lens-ui-telemetry'; diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/index.ts b/x-pack/plugins/lens/public/lens_ui_telemetry/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/lens_ui_telemetry/index.ts rename to x-pack/plugins/lens/public/lens_ui_telemetry/index.ts diff --git a/x-pack/legacy/plugins/lens/public/loader.test.tsx b/x-pack/plugins/lens/public/loader.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/loader.test.tsx rename to x-pack/plugins/lens/public/loader.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/loader.tsx b/x-pack/plugins/lens/public/loader.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/loader.tsx rename to x-pack/plugins/lens/public/loader.tsx diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/auto_scale.test.tsx b/x-pack/plugins/lens/public/metric_visualization/auto_scale.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/metric_visualization/auto_scale.test.tsx rename to x-pack/plugins/lens/public/metric_visualization/auto_scale.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/auto_scale.tsx b/x-pack/plugins/lens/public/metric_visualization/auto_scale.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/metric_visualization/auto_scale.tsx rename to x-pack/plugins/lens/public/metric_visualization/auto_scale.tsx diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/index.scss b/x-pack/plugins/lens/public/metric_visualization/index.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/metric_visualization/index.scss rename to x-pack/plugins/lens/public/metric_visualization/index.scss diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/index.ts b/x-pack/plugins/lens/public/metric_visualization/index.ts similarity index 88% rename from x-pack/legacy/plugins/lens/public/metric_visualization/index.ts rename to x-pack/plugins/lens/public/metric_visualization/index.ts index 65f064258a5e2..2960da52191e4 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization/index.ts +++ b/x-pack/plugins/lens/public/metric_visualization/index.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup } from 'src/core/public'; +import { CoreSetup } from 'kibana/public'; import { metricVisualization } from './metric_visualization'; -import { ExpressionsSetup } from '../../../../../../src/plugins/expressions/public'; +import { ExpressionsSetup } from '../../../../../src/plugins/expressions/public'; import { metricChart, getMetricChartRenderer } from './metric_expression'; import { EditorFrameSetup, FormatFactory } from '../types'; diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.test.tsx b/x-pack/plugins/lens/public/metric_visualization/metric_expression.test.tsx similarity index 94% rename from x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.test.tsx rename to x-pack/plugins/lens/public/metric_visualization/metric_expression.test.tsx index 3da38d486aecd..2406e7cd42ebc 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.test.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/metric_expression.test.tsx @@ -9,8 +9,8 @@ import { LensMultiTable } from '../types'; import React from 'react'; import { shallow } from 'enzyme'; import { MetricConfig } from './types'; -import { createMockExecutionContext } from '../../../../../../src/plugins/expressions/common/mocks'; -import { IFieldFormat } from '../../../../../../src/plugins/data/public'; +import { createMockExecutionContext } from '../../../../../src/plugins/expressions/common/mocks'; +import { IFieldFormat } from '../../../../../src/plugins/data/public'; function sampleArgs() { const data: LensMultiTable = { diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx b/x-pack/plugins/lens/public/metric_visualization/metric_expression.tsx similarity index 98% rename from x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx rename to x-pack/plugins/lens/public/metric_visualization/metric_expression.tsx index a80552e57a9e0..3484837f65b43 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_expression.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/metric_expression.tsx @@ -10,7 +10,7 @@ import { ExpressionFunctionDefinition, ExpressionRenderDefinition, IInterpreterRenderHandlers, -} from '../../../../../../src/plugins/expressions/public'; +} from '../../../../../src/plugins/expressions/public'; import { MetricConfig } from './types'; import { FormatFactory, LensMultiTable } from '../types'; import { AutoScale } from './auto_scale'; diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_suggestions.test.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts similarity index 98% rename from x-pack/legacy/plugins/lens/public/metric_visualization/metric_suggestions.test.ts rename to x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts index c9bfadbefaf5f..ef93f0b5bf064 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_suggestions.test.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts @@ -5,7 +5,7 @@ */ import { getSuggestions } from './metric_suggestions'; -import { TableSuggestionColumn, TableSuggestion } from '..'; +import { TableSuggestionColumn, TableSuggestion } from '../index'; describe('metric_suggestions', () => { function numCol(columnId: string): TableSuggestionColumn { diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_suggestions.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/metric_visualization/metric_suggestions.ts rename to x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.test.ts b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.test.ts rename to x-pack/plugins/lens/public/metric_visualization/metric_visualization.test.ts diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.tsx b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/metric_visualization/metric_visualization.tsx rename to x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization/types.ts b/x-pack/plugins/lens/public/metric_visualization/types.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/metric_visualization/types.ts rename to x-pack/plugins/lens/public/metric_visualization/types.ts diff --git a/x-pack/legacy/plugins/lens/public/native_renderer/index.ts b/x-pack/plugins/lens/public/native_renderer/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/native_renderer/index.ts rename to x-pack/plugins/lens/public/native_renderer/index.ts diff --git a/x-pack/legacy/plugins/lens/public/native_renderer/native_renderer.test.tsx b/x-pack/plugins/lens/public/native_renderer/native_renderer.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/native_renderer/native_renderer.test.tsx rename to x-pack/plugins/lens/public/native_renderer/native_renderer.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/native_renderer/native_renderer.tsx b/x-pack/plugins/lens/public/native_renderer/native_renderer.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/native_renderer/native_renderer.tsx rename to x-pack/plugins/lens/public/native_renderer/native_renderer.tsx diff --git a/x-pack/legacy/plugins/lens/public/persistence/index.ts b/x-pack/plugins/lens/public/persistence/index.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/persistence/index.ts rename to x-pack/plugins/lens/public/persistence/index.ts diff --git a/x-pack/legacy/plugins/lens/public/persistence/saved_object_store.test.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/persistence/saved_object_store.test.ts rename to x-pack/plugins/lens/public/persistence/saved_object_store.test.ts diff --git a/x-pack/legacy/plugins/lens/public/persistence/saved_object_store.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.ts similarity index 94% rename from x-pack/legacy/plugins/lens/public/persistence/saved_object_store.ts rename to x-pack/plugins/lens/public/persistence/saved_object_store.ts index ac0b3322b400e..015f4b9b825f4 100644 --- a/x-pack/legacy/plugins/lens/public/persistence/saved_object_store.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.ts @@ -5,8 +5,8 @@ */ // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { SavedObjectAttributes } from 'src/core/server'; -import { Query, Filter } from '../../../../../../src/plugins/data/public'; +import { SavedObjectAttributes } from 'kibana/server'; +import { Query, Filter } from '../../../../../src/plugins/data/public'; export interface Document { id?: string; diff --git a/x-pack/legacy/plugins/lens/public/plugin.tsx b/x-pack/plugins/lens/public/plugin.tsx similarity index 90% rename from x-pack/legacy/plugins/lens/public/plugin.tsx rename to x-pack/plugins/lens/public/plugin.tsx index b426a12d07f9b..8d760eb0df501 100644 --- a/x-pack/legacy/plugins/lens/public/plugin.tsx +++ b/x-pack/plugins/lens/public/plugin.tsx @@ -11,14 +11,15 @@ import { render, unmountComponentAtNode } from 'react-dom'; import rison, { RisonObject, RisonValue } from 'rison-node'; import { isObject } from 'lodash'; -import { AppMountParameters, CoreSetup, CoreStart } from 'src/core/public'; +import { AppMountParameters, CoreSetup, CoreStart } from 'kibana/public'; import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public'; import { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public'; import { ExpressionsSetup, ExpressionsStart } from 'src/plugins/expressions/public'; import { VisualizationsSetup } from 'src/plugins/visualizations/public'; +import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; import { KibanaLegacySetup } from 'src/plugins/kibana_legacy/public'; -import { DashboardConstants } from '../../../../../src/plugins/dashboard/public'; -import { Storage } from '../../../../../src/plugins/kibana_utils/public'; +import { DashboardConstants } from '../../../../src/plugins/dashboard/public'; +import { Storage } from '../../../../src/plugins/kibana_utils/public'; import { EditorFrameService } from './editor_frame_service'; import { IndexPatternDatasource } from './indexpattern_datasource'; import { addHelpMenuToAppChrome } from './help_menu_util'; @@ -34,17 +35,19 @@ import { trackUiEvent, } from './lens_ui_telemetry'; -import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; -import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../../../plugins/lens/common'; +import { UiActionsStart } from '../../../../src/plugins/ui_actions/public'; +import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../common'; import { addEmbeddableToDashboardUrl, getUrlVars } from './helpers'; import { EditorFrameStart } from './types'; import { getLensAliasConfig } from './vis_type_alias'; +import './index.scss'; + export interface LensPluginSetupDependencies { kibanaLegacy: KibanaLegacySetup; expressions: ExpressionsSetup; data: DataPublicPluginSetup; - embeddable: EmbeddableSetup; + embeddable?: EmbeddableSetup; visualizations: VisualizationsSetup; } @@ -52,6 +55,7 @@ export interface LensPluginStartDependencies { data: DataPublicPluginStart; embeddable: EmbeddableStart; expressions: ExpressionsStart; + navigation: NavigationPublicPluginStart; uiActions: UiActionsStart; } @@ -75,7 +79,7 @@ export class LensPlugin { } setup( - core: CoreSetup<LensPluginStartDependencies>, + core: CoreSetup<LensPluginStartDependencies, void>, { kibanaLegacy, expressions, data, embeddable, visualizations }: LensPluginSetupDependencies ) { const editorFrameSetupInterface = this.editorFrameService.setup(core, { @@ -103,9 +107,9 @@ export class LensPlugin { title: NOT_INTERNATIONALIZED_PRODUCT_NAME, mount: async (params: AppMountParameters) => { const [coreStart, startDependencies] = await core.getStartServices(); - const dataStart = startDependencies.data; + const { data: dataStart, navigation } = startDependencies; const savedObjectsClient = coreStart.savedObjects.client; - addHelpMenuToAppChrome(coreStart.chrome); + addHelpMenuToAppChrome(coreStart.chrome, coreStart.docLinks); const instance = await this.createEditorFrame!(); @@ -157,6 +161,7 @@ export class LensPlugin { <App core={coreStart} data={dataStart} + navigation={navigation} editorFrame={instance} storage={new Storage(localStorage)} docId={routeProps.match.params.id} diff --git a/x-pack/legacy/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts similarity index 98% rename from x-pack/legacy/plugins/lens/public/types.ts rename to x-pack/plugins/lens/public/types.ts index 3d67b7b2da460..0b432c0c70727 100644 --- a/x-pack/legacy/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -6,15 +6,12 @@ import { Ast } from '@kbn/interpreter/common'; import { IconType } from '@elastic/eui/src/components/icon/icon'; -import { CoreSetup } from 'src/core/public'; -import { - KibanaDatatable, - SerializedFieldFormat, -} from '../../../../../src/plugins/expressions/public'; +import { CoreSetup } from 'kibana/public'; +import { KibanaDatatable, SerializedFieldFormat } from '../../../../src/plugins/expressions/public'; import { DragContextState } from './drag_drop'; import { Document } from './persistence'; -import { DateRange } from '../../../../plugins/lens/common'; -import { Query, Filter, SavedQuery, IFieldFormat } from '../../../../../src/plugins/data/public'; +import { DateRange } from '../common'; +import { Query, Filter, SavedQuery, IFieldFormat } from '../../../../src/plugins/data/public'; export type ErrorCallback = (e: { message: string }) => void; diff --git a/x-pack/legacy/plugins/lens/public/vis_type_alias.ts b/x-pack/plugins/lens/public/vis_type_alias.ts similarity index 95% rename from x-pack/legacy/plugins/lens/public/vis_type_alias.ts rename to x-pack/plugins/lens/public/vis_type_alias.ts index 123b994e6ccce..807504ee2b9c2 100644 --- a/x-pack/legacy/plugins/lens/public/vis_type_alias.ts +++ b/x-pack/plugins/lens/public/vis_type_alias.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { VisTypeAlias } from 'src/plugins/visualizations/public'; -import { getBasePath, getEditPath } from '../../../../plugins/lens/common'; +import { getBasePath, getEditPath } from '../common'; export const getLensAliasConfig = (): VisTypeAlias => ({ aliasUrl: getBasePath(), diff --git a/x-pack/legacy/plugins/lens/public/visualization_container.test.tsx b/x-pack/plugins/lens/public/visualization_container.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/visualization_container.test.tsx rename to x-pack/plugins/lens/public/visualization_container.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/visualization_container.tsx b/x-pack/plugins/lens/public/visualization_container.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/visualization_container.tsx rename to x-pack/plugins/lens/public/visualization_container.tsx diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap rename to x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap rename to x-pack/plugins/lens/public/xy_visualization/__snapshots__/xy_expression.test.tsx.snap diff --git a/x-pack/plugins/lens/public/xy_visualization/_index.scss b/x-pack/plugins/lens/public/xy_visualization/_index.scss new file mode 100644 index 0000000000000..110a9589a6fb4 --- /dev/null +++ b/x-pack/plugins/lens/public/xy_visualization/_index.scss @@ -0,0 +1 @@ +@import 'xy_expression'; diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/_xy_expression.scss b/x-pack/plugins/lens/public/xy_visualization/_xy_expression.scss similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/_xy_expression.scss rename to x-pack/plugins/lens/public/xy_visualization/_xy_expression.scss diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/index.ts b/x-pack/plugins/lens/public/xy_visualization/index.ts similarity index 89% rename from x-pack/legacy/plugins/lens/public/xy_visualization/index.ts rename to x-pack/plugins/lens/public/xy_visualization/index.ts index 8cc5abb44d6e1..5dfae097be834 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/index.ts +++ b/x-pack/plugins/lens/public/xy_visualization/index.ts @@ -5,14 +5,14 @@ */ import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; -import { CoreSetup, IUiSettingsClient, CoreStart } from 'src/core/public'; +import { CoreSetup, IUiSettingsClient, CoreStart } from 'kibana/public'; import moment from 'moment-timezone'; -import { ExpressionsSetup } from '../../../../../../src/plugins/expressions/public'; +import { ExpressionsSetup } from '../../../../../src/plugins/expressions/public'; import { xyVisualization } from './xy_visualization'; import { xyChart, getXyChartRenderer } from './xy_expression'; import { legendConfig, xConfig, layerConfig } from './types'; import { EditorFrameSetup, FormatFactory } from '../types'; -import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public'; +import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; import { setExecuteTriggerActions } from './services'; export interface XyVisualizationPluginSetupPlugins { diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/services.ts b/x-pack/plugins/lens/public/xy_visualization/services.ts similarity index 70% rename from x-pack/legacy/plugins/lens/public/xy_visualization/services.ts rename to x-pack/plugins/lens/public/xy_visualization/services.ts index af683efb86534..51289fe0c63e7 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/services.ts +++ b/x-pack/plugins/lens/public/xy_visualization/services.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createGetterSetter } from '../../../../../../src/plugins/kibana_utils/public'; -import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public'; +import { createGetterSetter } from '../../../../../src/plugins/kibana_utils/public'; +import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; export const [getExecuteTriggerActions, setExecuteTriggerActions] = createGetterSetter< UiActionsStart['executeTriggerActions'] diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/state_helpers.ts b/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/state_helpers.ts rename to x-pack/plugins/lens/public/xy_visualization/state_helpers.ts diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/to_expression.test.ts rename to x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/to_expression.ts rename to x-pack/plugins/lens/public/xy_visualization/to_expression.ts diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts similarity index 99% rename from x-pack/legacy/plugins/lens/public/xy_visualization/types.ts rename to x-pack/plugins/lens/public/xy_visualization/types.ts index f7b4afc76ec4b..7a5837d382c7b 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/types.ts +++ b/x-pack/plugins/lens/public/xy_visualization/types.ts @@ -15,7 +15,7 @@ import chartBarHorizontalSVG from '../assets/chart_bar_horizontal.svg'; import chartBarHorizontalStackedSVG from '../assets/chart_bar_horizontal_stacked.svg'; import chartLineSVG from '../assets/chart_line.svg'; -import { VisualizationType } from '..'; +import { VisualizationType } from '../index'; export interface LegendConfig { isVisible: boolean; diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx rename to x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_config_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_config_panel.tsx rename to x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_expression.test.tsx similarity index 99% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx rename to x-pack/plugins/lens/public/xy_visualization/xy_expression.test.tsx index 0a6945dd0c1f0..80d33d1b95b61 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_expression.test.tsx @@ -18,14 +18,11 @@ import { } from '@elastic/charts'; import { xyChart, XYChart } from './xy_expression'; import { LensMultiTable } from '../types'; -import { - KibanaDatatable, - KibanaDatatableRow, -} from '../../../../../../src/plugins/expressions/public'; +import { KibanaDatatable, KibanaDatatableRow } from '../../../../../src/plugins/expressions/public'; import React from 'react'; import { shallow } from 'enzyme'; import { XYArgs, LegendConfig, legendConfig, layerConfig, LayerArgs } from './types'; -import { createMockExecutionContext } from '../../../../../../src/plugins/expressions/common/mocks'; +import { createMockExecutionContext } from '../../../../../src/plugins/expressions/common/mocks'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; const executeTriggerActions = jest.fn(); diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx similarity index 97% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx rename to x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx index 527eedf1083c2..f12a0e5b907c7 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx @@ -28,14 +28,14 @@ import { import { EuiIcon, EuiText, IconType, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { EmbeddableVisTriggerContext } from '../../../../../../src/plugins/embeddable/public'; -import { VIS_EVENT_TO_TRIGGER } from '../../../../../../src/plugins/visualizations/public'; +import { EmbeddableVisTriggerContext } from '../../../../../src/plugins/embeddable/public'; +import { VIS_EVENT_TO_TRIGGER } from '../../../../../src/plugins/visualizations/public'; import { LensMultiTable, FormatFactory } from '../types'; import { XYArgs, SeriesType, visualizationTypes } from './types'; import { VisualizationContainer } from '../visualization_container'; import { isHorizontalChart } from './state_helpers'; -import { UiActionsStart } from '../../../../../../src/plugins/ui_actions/public'; -import { parseInterval } from '../../../../../../src/plugins/data/common'; +import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; +import { parseInterval } from '../../../../../src/plugins/data/common'; import { getExecuteTriggerActions } from './services'; type InferPropType<T> = T extends React.FunctionComponent<infer P> ? P : T; diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_suggestions.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_suggestions.test.ts rename to x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_suggestions.ts rename to x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_visualization.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_visualization.test.ts rename to x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization/xy_visualization.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx similarity index 100% rename from x-pack/legacy/plugins/lens/public/xy_visualization/xy_visualization.tsx rename to x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx diff --git a/x-pack/legacy/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md similarity index 100% rename from x-pack/legacy/plugins/lens/readme.md rename to x-pack/plugins/lens/readme.md diff --git a/x-pack/plugins/lens/server/index.ts b/x-pack/plugins/lens/server/index.ts index 3b9e94986d247..8aeeeab4539b6 100644 --- a/x-pack/plugins/lens/server/index.ts +++ b/x-pack/plugins/lens/server/index.ts @@ -4,10 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PluginInitializerContext } from 'kibana/server'; +import { PluginInitializerContext, PluginConfigDescriptor } from 'kibana/server'; import { LensServerPlugin } from './plugin'; export * from './plugin'; +import { configSchema, ConfigSchema } from '../config'; + +export const config: PluginConfigDescriptor<ConfigSchema> = { + schema: configSchema, +}; + export const plugin = (initializerContext: PluginInitializerContext) => new LensServerPlugin(initializerContext); From d1134c551e63cf7efa28b966e68d2a3ce71ddf1b Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris <github@gidi.io> Date: Wed, 15 Apr 2020 12:34:16 +0100 Subject: [PATCH 120/121] [Alerting] Handle when an Alerting Task fails due to its Alert object being deleted mid flight (#63093) Detects if a task run failed due to the task SO being deleted mid flight and if so writes debug logs instead of warnings. Detects if an Alerting task run failed due to the alert SO being deleted mid flight of the task and if so ensures the task doesn't reschedule itself (as it usually would with other types of tasks). Ensures that the operation of deleting or disabling an Alert won't fail if it fails to delete an already deleted task (a task might preemptively self delete if its underlying alert object was deleted, even if the overall delete operation wasn't deleted). --- .../plugins/alerting/server/alerts_client.ts | 7 ++- .../lib/delete_task_if_it_exists.test.ts | 44 +++++++++++++++++++ .../server/lib/delete_task_if_it_exists.ts | 17 +++++++ .../lib/is_alert_not_found_error.test.ts | 31 +++++++++++++ .../server/lib/is_alert_not_found_error.ts | 11 +++++ .../server/task_runner/task_runner.test.ts | 33 ++++++++++++++ .../server/task_runner/task_runner.ts | 30 ++++++++----- .../tasks/visualizations/task_runner.test.ts | 8 +--- .../lib/is_task_not_found_error.test.ts | 31 +++++++++++++ .../server/lib/is_task_not_found_error.ts | 11 +++++ .../task_manager/server/task_pool.test.ts | 25 +++++++++++ .../plugins/task_manager/server/task_pool.ts | 13 +++++- 12 files changed, 240 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.test.ts create mode 100644 x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.ts create mode 100644 x-pack/plugins/alerting/server/lib/is_alert_not_found_error.test.ts create mode 100644 x-pack/plugins/alerting/server/lib/is_alert_not_found_error.ts create mode 100644 x-pack/plugins/task_manager/server/lib/is_task_not_found_error.test.ts create mode 100644 x-pack/plugins/task_manager/server/lib/is_task_not_found_error.ts diff --git a/x-pack/plugins/alerting/server/alerts_client.ts b/x-pack/plugins/alerting/server/alerts_client.ts index 6f8478df58a53..3e4c26d3444c9 100644 --- a/x-pack/plugins/alerting/server/alerts_client.ts +++ b/x-pack/plugins/alerting/server/alerts_client.ts @@ -34,6 +34,7 @@ import { import { EncryptedSavedObjectsPluginStart } from '../../../plugins/encrypted_saved_objects/server'; import { TaskManagerStartContract } from '../../../plugins/task_manager/server'; import { taskInstanceToAlertTaskInstance } from './task_runner/alert_task_instance'; +import { deleteTaskIfItExists } from './lib/delete_task_if_it_exists'; type NormalizedAlertAction = Omit<AlertAction, 'actionTypeId'>; export type CreateAPIKeyResult = @@ -268,7 +269,7 @@ export class AlertsClient { const removeResult = await this.savedObjectsClient.delete('alert', id); await Promise.all([ - taskIdToRemove ? this.taskManager.remove(taskIdToRemove) : null, + taskIdToRemove ? deleteTaskIfItExists(this.taskManager, taskIdToRemove) : null, apiKeyToInvalidate ? this.invalidateApiKey({ apiKey: apiKeyToInvalidate }) : null, ]); @@ -510,7 +511,9 @@ export class AlertsClient { ); await Promise.all([ - attributes.scheduledTaskId ? this.taskManager.remove(attributes.scheduledTaskId) : null, + attributes.scheduledTaskId + ? deleteTaskIfItExists(this.taskManager, attributes.scheduledTaskId) + : null, apiKeyToInvalidate ? this.invalidateApiKey({ apiKey: apiKeyToInvalidate }) : null, ]); } diff --git a/x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.test.ts b/x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.test.ts new file mode 100644 index 0000000000000..84a1743387c9c --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.test.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 uuid from 'uuid'; +import { taskManagerMock } from '../../../task_manager/server/mocks'; +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; +import { deleteTaskIfItExists } from './delete_task_if_it_exists'; + +describe('deleteTaskIfItExists', () => { + test('removes the task by its ID', async () => { + const tm = taskManagerMock.createStart(); + const id = uuid.v4(); + + expect(await deleteTaskIfItExists(tm, id)).toBe(undefined); + + expect(tm.remove).toHaveBeenCalledWith(id); + }); + + test('handles 404 errors caused by the task not existing', async () => { + const tm = taskManagerMock.createStart(); + const id = uuid.v4(); + + tm.remove.mockRejectedValue(SavedObjectsErrorHelpers.createGenericNotFoundError('task', id)); + + expect(await deleteTaskIfItExists(tm, id)).toBe(undefined); + + expect(tm.remove).toHaveBeenCalledWith(id); + }); + + test('throws if any other errro is caused by task removal', async () => { + const tm = taskManagerMock.createStart(); + const id = uuid.v4(); + + const error = SavedObjectsErrorHelpers.createInvalidVersionError(uuid.v4()); + tm.remove.mockRejectedValue(error); + + expect(deleteTaskIfItExists(tm, id)).rejects.toBe(error); + + expect(tm.remove).toHaveBeenCalledWith(id); + }); +}); diff --git a/x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.ts b/x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.ts new file mode 100644 index 0000000000000..53bb1b5cb5d53 --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/delete_task_if_it_exists.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 { TaskManagerStartContract } from '../../../task_manager/server'; +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; + +export async function deleteTaskIfItExists(taskManager: TaskManagerStartContract, taskId: string) { + try { + await taskManager.remove(taskId); + } catch (err) { + if (!SavedObjectsErrorHelpers.isNotFoundError(err)) { + throw err; + } + } +} diff --git a/x-pack/plugins/alerting/server/lib/is_alert_not_found_error.test.ts b/x-pack/plugins/alerting/server/lib/is_alert_not_found_error.test.ts new file mode 100644 index 0000000000000..46ceee3ce420b --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/is_alert_not_found_error.test.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 { isAlertSavedObjectNotFoundError } from './is_alert_not_found_error'; +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; +import uuid from 'uuid'; + +describe('isAlertSavedObjectNotFoundError', () => { + test('identifies SavedObjects Not Found errors', () => { + const id = uuid.v4(); + // ensure the error created by SO parses as a string with the format we expect + expect( + `${SavedObjectsErrorHelpers.createGenericNotFoundError('alert', id)}`.includes(`alert/${id}`) + ).toBe(true); + + const errorBySavedObjectsHelper = SavedObjectsErrorHelpers.createGenericNotFoundError( + 'alert', + id + ); + + expect(isAlertSavedObjectNotFoundError(errorBySavedObjectsHelper, id)).toBe(true); + }); + + test('identifies generic errors', () => { + const id = uuid.v4(); + expect(isAlertSavedObjectNotFoundError(new Error(`not found`), id)).toBe(false); + }); +}); diff --git a/x-pack/plugins/alerting/server/lib/is_alert_not_found_error.ts b/x-pack/plugins/alerting/server/lib/is_alert_not_found_error.ts new file mode 100644 index 0000000000000..0aa83ad0e883c --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/is_alert_not_found_error.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. + */ + +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; + +export function isAlertSavedObjectNotFoundError(err: Error, alertId: string) { + return SavedObjectsErrorHelpers.isNotFoundError(err) && `${err}`.includes(alertId); +} diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 4e6d959f0ce60..31cc893f785cb 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -16,6 +16,7 @@ import { PluginStartContract as ActionsPluginStart } from '../../../actions/serv import { actionsMock } from '../../../actions/server/mocks'; import { eventLoggerMock } from '../../../event_log/server/event_logger.mock'; import { IEventLogger } from '../../../event_log/server'; +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; const alertType = { id: 'test', @@ -665,4 +666,36 @@ describe('Task Runner', () => { } `); }); + + test('avoids rescheduling a failed Alert Task Runner when it throws due to failing to fetch the alert', async () => { + savedObjectsClient.get.mockImplementation(() => { + throw SavedObjectsErrorHelpers.createGenericNotFoundError('task', '1'); + }); + + const taskRunner = new TaskRunner( + alertType, + mockedTaskInstance, + taskRunnerFactoryInitializerParams + ); + + encryptedSavedObjectsPlugin.getDecryptedAsInternalUser.mockResolvedValueOnce({ + id: '1', + type: 'alert', + attributes: { + apiKey: Buffer.from('123:abc').toString('base64'), + }, + references: [], + }); + + const runnerResult = await taskRunner.run(); + + expect(runnerResult).toMatchInlineSnapshot(` + Object { + "runAt": undefined, + "state": Object { + "previousStartedAt": 1970-01-01T00:00:00.000Z, + }, + } + `); + }); }); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index 190cdc184930c..1d4b12e96bc76 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -26,12 +26,13 @@ import { taskInstanceToAlertTaskInstance } from './alert_task_instance'; import { AlertInstances } from '../alert_instance/alert_instance'; import { EVENT_LOG_ACTIONS } from '../plugin'; import { IEvent, IEventLogger } from '../../../event_log/server'; +import { isAlertSavedObjectNotFoundError } from '../lib/is_alert_not_found_error'; const FALLBACK_RETRY_INTERVAL: IntervalSchedule = { interval: '5m' }; interface AlertTaskRunResult { state: AlertTaskState; - runAt: Date; + runAt: Date | undefined; } interface AlertTaskInstance extends ConcreteTaskInstance { @@ -328,22 +329,29 @@ export class TaskRunner { }; }, (err: Error) => { - this.logger.error(`Executing Alert "${alertId}" has resulted in Error: ${err.message}`); + const message = `Executing Alert "${alertId}" has resulted in Error: ${err.message}`; + if (isAlertSavedObjectNotFoundError(err, alertId)) { + this.logger.debug(message); + } else { + this.logger.error(message); + } return { ...originalState, previousStartedAt, }; } ), - runAt: resolveErr<Date, Error>(runAt, () => - getNextRunAt( - new Date(), - // if we fail at this point we wish to recover but don't have access to the Alert's - // attributes, so we'll use a default interval to prevent the underlying task from - // falling into a failed state - FALLBACK_RETRY_INTERVAL - ) - ), + runAt: resolveErr<Date | undefined, Error>(runAt, err => { + return isAlertSavedObjectNotFoundError(err, alertId) + ? undefined + : getNextRunAt( + new Date(), + // if we fail at this point we wish to recover but don't have access to the Alert's + // attributes, so we'll use a default interval to prevent the underlying task from + // falling into a failed state + FALLBACK_RETRY_INTERVAL + ); + }), }; } } diff --git a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts index dff5e24db3c6e..6a47983a6f4d9 100644 --- a/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts +++ b/x-pack/plugins/oss_telemetry/server/lib/tasks/visualizations/task_runner.test.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import moment from 'moment'; import { getMockCallWithInternal, getMockConfig, @@ -13,6 +12,7 @@ import { } from '../../../test_utils'; import { visualizationsTaskRunner } from './task_runner'; import { TaskInstance } from '../../../../../task_manager/server'; +import { getNextMidnight } from '../../get_next_midnight'; describe('visualizationsTaskRunner', () => { let mockTaskInstance: TaskInstance; @@ -41,12 +41,6 @@ describe('visualizationsTaskRunner', () => { }); test('Summarizes visualization response data', async () => { - const getNextMidnight = () => - moment() - .add(1, 'days') - .startOf('day') - .toDate(); - const runner = visualizationsTaskRunner(mockTaskInstance, getMockConfig(), getMockEs()); const result = await runner(); diff --git a/x-pack/plugins/task_manager/server/lib/is_task_not_found_error.test.ts b/x-pack/plugins/task_manager/server/lib/is_task_not_found_error.test.ts new file mode 100644 index 0000000000000..65922ea8e6de7 --- /dev/null +++ b/x-pack/plugins/task_manager/server/lib/is_task_not_found_error.test.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 { isTaskSavedObjectNotFoundError } from './is_task_not_found_error'; +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; +import uuid from 'uuid'; + +describe('isTaskSavedObjectNotFoundError', () => { + test('identifies SavedObjects Not Found errors', () => { + const id = uuid.v4(); + // ensure the error created by SO parses as a string with the format we expect + expect( + `${SavedObjectsErrorHelpers.createGenericNotFoundError('task', id)}`.includes(`task/${id}`) + ).toBe(true); + + const errorBySavedObjectsHelper = SavedObjectsErrorHelpers.createGenericNotFoundError( + 'task', + id + ); + + expect(isTaskSavedObjectNotFoundError(errorBySavedObjectsHelper, id)).toBe(true); + }); + + test('identifies generic errors', () => { + const id = uuid.v4(); + expect(isTaskSavedObjectNotFoundError(new Error(`not found`), id)).toBe(false); + }); +}); diff --git a/x-pack/plugins/task_manager/server/lib/is_task_not_found_error.ts b/x-pack/plugins/task_manager/server/lib/is_task_not_found_error.ts new file mode 100644 index 0000000000000..8cc1c08f2a967 --- /dev/null +++ b/x-pack/plugins/task_manager/server/lib/is_task_not_found_error.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. + */ + +import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; + +export function isTaskSavedObjectNotFoundError(err: Error, taskId: string) { + return SavedObjectsErrorHelpers.isNotFoundError(err) && `${err}`.includes(taskId); +} diff --git a/x-pack/plugins/task_manager/server/task_pool.test.ts b/x-pack/plugins/task_manager/server/task_pool.test.ts index a827c1436c9bd..fb87b6290a3da 100644 --- a/x-pack/plugins/task_manager/server/task_pool.test.ts +++ b/x-pack/plugins/task_manager/server/task_pool.test.ts @@ -8,6 +8,7 @@ import sinon from 'sinon'; import { TaskPool, TaskPoolRunResult } from './task_pool'; import { mockLogger, resolvable, sleep } from './test_utils'; import { asOk } from './lib/result_type'; +import { SavedObjectsErrorHelpers } from '../../../../src/core/server'; describe('TaskPool', () => { test('occupiedWorkers are a sum of running tasks', async () => { @@ -101,6 +102,30 @@ describe('TaskPool', () => { expect(result).toEqual(TaskPoolRunResult.RunningAllClaimedTasks); }); + test('should not log when running a Task fails due to the Task SO having been deleted while in flight', async () => { + const logger = mockLogger(); + const pool = new TaskPool({ + maxWorkers: 3, + logger, + }); + + const taskFailedToRun = mockTask(); + taskFailedToRun.run.mockImplementation(async () => { + throw SavedObjectsErrorHelpers.createGenericNotFoundError('task', taskFailedToRun.id); + }); + + const result = await pool.run([mockTask(), taskFailedToRun, mockTask()]); + + expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "Task TaskType \\"shooooo\\" failed in attempt to run: Saved object [task/foo] not found", + ] + `); + expect(logger.warn).not.toHaveBeenCalled(); + + expect(result).toEqual(TaskPoolRunResult.RunningAllClaimedTasks); + }); + test('Running a task which fails still takes up capacity', async () => { const logger = mockLogger(); const pool = new TaskPool({ diff --git a/x-pack/plugins/task_manager/server/task_pool.ts b/x-pack/plugins/task_manager/server/task_pool.ts index 90f1880a159da..8999fb48680ce 100644 --- a/x-pack/plugins/task_manager/server/task_pool.ts +++ b/x-pack/plugins/task_manager/server/task_pool.ts @@ -11,6 +11,7 @@ import { performance } from 'perf_hooks'; import { Logger } from './types'; import { TaskRunner } from './task_runner'; +import { isTaskSavedObjectNotFoundError } from './lib/is_task_not_found_error'; interface Opts { maxWorkers: number; @@ -125,7 +126,17 @@ export class TaskPool { taskRunner .run() .catch(err => { - this.logger.warn(`Task ${taskRunner.toString()} failed in attempt to run: ${err.message}`); + // If a task Saved Object can't be found by an in flight task runner + // we asssume the underlying task has been deleted while it was running + // so we will log this as a debug, rather than a warn + const errorLogLine = `Task ${taskRunner.toString()} failed in attempt to run: ${ + err.message + }`; + if (isTaskSavedObjectNotFoundError(err, taskRunner.id)) { + this.logger.debug(errorLogLine); + } else { + this.logger.warn(errorLogLine); + } }) .then(() => this.running.delete(taskRunner)); } From c885ea53792456383fb145414b891c134f97593e Mon Sep 17 00:00:00 2001 From: Phillip Burch <phillip.burch@live.com> Date: Wed, 15 Apr 2020 06:43:03 -0500 Subject: [PATCH 121/121] Because onThreshold is changed even when it hasn't changed add a check (#63555) * Because onThreshold is changed even when it hasn't changed add a check * Fix join --- .../infra/public/components/alerting/metrics/expression.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx b/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx index 6cf4e5bed2e6f..7de52840777f9 100644 --- a/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx +++ b/x-pack/plugins/infra/public/components/alerting/metrics/expression.tsx @@ -399,7 +399,9 @@ export const ExpressionRow: React.FC<ExpressionRowProps> = props => { const updateThreshold = useCallback( t => { - setAlertParams(expressionId, { ...expression, threshold: t }); + if (t.join() !== expression.threshold.join()) { + setAlertParams(expressionId, { ...expression, threshold: t }); + } }, [expressionId, expression, setAlertParams] );

kCbAFrnrvi1y$?L2<5~xtW^1 zQ6b)p@`naH;H&fqaL%-Qp27`tO;^2`(vh5ZorS5p69?mgNB{3Vp}ZR z*n9{XBbycrgf`#c4}d|;k#%5oT7j+7v3Q`ARQTn0t%>F<($ZH8eB{3OS7bB(?OgXr zoI(0j;(D^%GAQpdE=9wOQ(rKn@0{h{p>yjeuaYm`5s8VuP_zB?ffT{uckbDuVlUas zj)w%rpollU#YUF-ifor>!#j;$Y2R}1k^T=&;is_+PXXzNaQD_v9&G~-@MzvU+v7>k z=xmcS&0ClLRKfknBSf9KpY`27>y8e=WDNCeIs9De)64E&fZqbGU)sxq?$ZI@TOY&j z^wpVVdkUj{JMM0{Rmbr16Izp%#g)vP>)0us%3FN450CRy+iMkj)z$e{U!J8%pZgXD z{w^hbCG>z#pu!9|EO@wt?ZI~s8V@XS>-tw}h7g|&Cg+c+x2~7B$}V2KXl);TWZTpgTQP_IP+0R5aO8HBhv*V5~N)%A>&}ARYbV1tGjuKr$pn^HlIsc z8>M3+vI$htt+ntU7=8fIh`zUj8A5d*zRKTgeW5CZ`RvuKn&5#`2V7vIba3Dc8WM zlV>*N^Z3<&>W&x#9>|f8?VS|uYl+abz;%7eXY1U=vYm#OLn1h?SgNy-(bv?8=oU1~ zoBU5mV2mN^DoNqS4w6H^6T3=PtIPkVj#ec=YvVs2$V>~JETYD!+Eu+7 zgd^v#Y-j-@y^Z%LbpRoT-Pye%6<@vrL#X^N+rU=;*kJo~(fT!86UySL?V%E|gqecX zhvFEnCr!V?bdFf4}*Oh;4XnZWe|t8}BhS8~%0D@aYx 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 Q1@I#&CMQ}btn2gt0O?oeDF6Tf literal 0 HcmV?d00001 diff --git a/docs/apm/using-the-apm-ui.asciidoc b/docs/apm/using-the-apm-ui.asciidoc index b1b7ed7307986..904718999069d 100644 --- a/docs/apm/using-the-apm-ui.asciidoc +++ b/docs/apm/using-the-apm-ui.asciidoc @@ -15,6 +15,7 @@ APM is available via the navigation sidebar in {Kib}. * <> * <> * <> +* <> * <> * <> * <> @@ -37,6 +38,8 @@ include::errors.asciidoc[] include::metrics.asciidoc[] +include::apm-alerts.asciidoc[] + include::agent-configuration.asciidoc[] include::custom-links.asciidoc[] From 13fe738b2a59c5117e15aca4af1c155e00129a37 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Thu, 9 Apr 2020 08:55:29 -0700 Subject: [PATCH 010/121] [UI COPY] Fixes typo in max_shingle_size for search_as_you_type (#63071) --- .../field_parameters/max_shingle_size_parameter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx index bc1917b2da966..cec97fb925eef 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx @@ -23,7 +23,7 @@ export const MaxShingleSizeParameter = ({ defaultToggleValue }: Props) => ( })} description={i18n.translate('xpack.idxMgmt.mappingsEditor.maxShingleSizeFieldDescription', { defaultMessage: - 'The default is three shingle subfields. More subfields enables more specific queries, but increases index size.', + 'The default is three shingle subfields. More subfields enable more specific queries, but increase index size.', })} defaultToggleValue={defaultToggleValue} > From 5e1c0be501b672174b2553dbca74d4eba16295f6 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Thu, 9 Apr 2020 11:56:03 -0400 Subject: [PATCH 011/121] [Endpoint] Add link to Logs UI to the Host Details view (#62852) * Add LinktoApp to host details for logs * initial setup for testing link on details * Export interface AppContextTestRender for reference in tests * Refactor hosts tests to use AppContextTestRender * Render full details and validate link to logs * one more test to ensure we navigate to app (not full page refresh) * Fixes post master merge --- .../endpoint/components/link_to_app.tsx | 2 +- .../endpoint/mocks/app_context_render.tsx | 2 +- .../store/hosts/mock_host_result_list.ts | 13 ++- .../endpoint/view/hosts/details.tsx | 28 +++++ .../endpoint/view/hosts/index.test.tsx | 106 +++++++++++++----- 5 files changed, 119 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx index b110d32442c2c..858dac864b58a 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/components/link_to_app.tsx @@ -12,7 +12,7 @@ import { useNavigateToAppEventHandler } from '../hooks/use_navigate_to_app_event export type LinkToAppProps = EuiLinkProps & { /** the app id - normally the value of the `id` in that plugin's `kibana.json` */ appId: string; - /** Any app specic path (route) */ + /** Any app specific path (route) */ appPath?: string; appState?: any; onClick?: MouseEventHandler; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/mocks/app_context_render.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/mocks/app_context_render.tsx index af34205e2310f..7cb1031ef9a09 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/mocks/app_context_render.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/mocks/app_context_render.tsx @@ -18,7 +18,7 @@ type UiRender = (ui: React.ReactElement, options?: RenderOptions) => RenderResul /** * Mocked app root context renderer */ -interface AppContextTestRender { +export interface AppContextTestRender { store: ReturnType; history: ReturnType; coreStart: ReturnType; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/store/hosts/mock_host_result_list.ts b/x-pack/plugins/endpoint/public/applications/endpoint/store/hosts/mock_host_result_list.ts index d4c2602e34387..20aa973ffc93d 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/store/hosts/mock_host_result_list.ts +++ b/x-pack/plugins/endpoint/public/applications/endpoint/store/hosts/mock_host_result_list.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HostResultList, HostStatus } from '../../../../../common/types'; +import { HostInfo, HostResultList, HostStatus } from '../../../../../common/types'; import { EndpointDocGenerator } from '../../../../../common/generate_data'; export const mockHostResultList: (options?: { @@ -40,3 +40,14 @@ export const mockHostResultList: (options?: { }; return mock; }; + +/** + * returns a mocked API response for retrieving a single host metadata + */ +export const mockHostDetailsApiResult = (): HostInfo => { + const generator = new EndpointDocGenerator('seed'); + return { + metadata: generator.generateHostMetadata(), + host_status: HostStatus.ERROR, + }; +}; diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx index 37080e8568350..90829f7ad4cbe 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/hosts/details.tsx @@ -28,6 +28,7 @@ import { useHostListSelector } from './hooks'; import { urlFromQueryParams } from './url_from_query_params'; import { FormattedDateAndTime } from '../formatted_date_time'; import { uiQueryParams, detailsData, detailsError } from './../../store/hosts/selectors'; +import { LinkToApp } from '../../components/link_to_app'; const HostIds = styled(EuiListGroupItem)` margin-top: 0; @@ -37,6 +38,7 @@ const HostIds = styled(EuiListGroupItem)` `; const HostDetails = memo(({ details }: { details: HostMetadata }) => { + const { appId, appPath, url } = useHostLogsUrl(details.host.id); const detailsResultsUpper = useMemo(() => { return [ { @@ -113,6 +115,20 @@ const HostDetails = memo(({ details }: { details: HostMetadata }) => { listItems={detailsResultsLower} data-test-subj="hostDetailsLowerList" /> + +